Merge pull request #4466 from danfabo:fix-fetch-content-uses-gtest
PiperOrigin-RevId: 612560830
Change-Id: Ib639603d34258909cf0e0d6fceb297dd8c983d54
diff --git a/BUILD.bazel b/BUILD.bazel
index b1e3b7f..e407ae2 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -56,6 +56,12 @@
constraint_values = ["@platforms//os:openbsd"],
)
+# NOTE: Fuchsia is not an officially supported platform.
+config_setting(
+ name = "fuchsia",
+ constraint_values = ["@platforms//os:fuchsia"],
+)
+
config_setting(
name = "msvc_compiler",
flag_values = {
@@ -147,6 +153,17 @@
"@com_googlesource_code_re2//:re2",
],
"//conditions:default": [],
+ }) + select({
+ # `gtest-death-test.cc` has `EXPECT_DEATH` that spawns a process,
+ # expects it to crash and inspects its logs with the given matcher,
+ # so that's why these libraries are needed.
+ # Otherwise, builds targeting Fuchsia would fail to compile.
+ ":fuchsia": [
+ "@fuchsia_sdk//pkg/fdio",
+ "@fuchsia_sdk//pkg/syslog",
+ "@fuchsia_sdk//pkg/zx",
+ ],
+ "//conditions:default": [],
}),
)
diff --git a/MODULE.bazel b/MODULE.bazel
index d4ad2b3..b81ebf0 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -53,5 +53,9 @@
bazel_dep(name = "rules_python",
version = "0.29.0")
+
+fake_fuchsia_sdk = use_repo_rule("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
+fake_fuchsia_sdk(name = "fuchsia_sdk")
+
# https://github.com/bazelbuild/rules_python/blob/main/BZLMOD_SUPPORT.md#default-toolchain-is-not-the-local-system-python
register_toolchains("@bazel_tools//tools/python:autodetecting_toolchain")
diff --git a/docs/gmock_for_dummies.md b/docs/gmock_for_dummies.md
index 9f24dca..ed2297c 100644
--- a/docs/gmock_for_dummies.md
+++ b/docs/gmock_for_dummies.md
@@ -261,6 +261,8 @@
when you allocate mocks on the heap. You get that automatically if you use the
`gtest_main` library already.
+###### Expectation Ordering
+
**Important note:** gMock requires expectations to be set **before** the mock
functions are called, otherwise the behavior is **undefined**. Do not alternate
between calls to `EXPECT_CALL()` and calls to the mock functions, and do not set
diff --git a/docs/reference/mocking.md b/docs/reference/mocking.md
index 3ad4952..ab37ebf 100644
--- a/docs/reference/mocking.md
+++ b/docs/reference/mocking.md
@@ -81,8 +81,8 @@
.Times(cardinality) // Can be used at most once
.InSequence(sequences...) // Can be used any number of times
.After(expectations...) // Can be used any number of times
- .WillRepeatedly(action) // Can be used any number of times
- .WillOnce(action) // Can be used at most once
+ .WillOnce(action) // Can be used any number of times
+ .WillRepeatedly(action) // Can be used at most once
.RetiresOnSaturation(); // Can be used at most once
```
diff --git a/fake_fuchsia_sdk.bzl b/fake_fuchsia_sdk.bzl
new file mode 100644
index 0000000..2024dc6
--- /dev/null
+++ b/fake_fuchsia_sdk.bzl
@@ -0,0 +1,33 @@
+"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available.
+
+This is needed since bazel queries on targets that depend on //:gtest (eg:
+`bazel query "deps(set(//googletest/test:gtest_all_test))"`) will fail if @fuchsia_sdk is not
+defined when bazel is evaluating the transitive closure of the query target.
+
+See https://github.com/google/googletest/issues/4472.
+"""
+
+def _fake_fuchsia_sdk_impl(repo_ctx):
+ for stub_target in repo_ctx.attr._stub_build_targets:
+ stub_package = stub_target
+ stub_target_name = stub_target.split("/")[-1]
+ repo_ctx.file("%s/BUILD.bazel" % stub_package, """
+filegroup(
+ name = "%s",
+)
+""" % stub_target_name)
+
+fake_fuchsia_sdk = repository_rule(
+ doc = "Used to create a fake @fuchsia_sdk repository with stub build targets.",
+ implementation = _fake_fuchsia_sdk_impl,
+ attrs = {
+ "_stub_build_targets": attr.string_list(
+ doc = "The stub build targets to initialize.",
+ default = [
+ "pkg/fdio",
+ "pkg/syslog",
+ "pkg/zx",
+ ],
+ ),
+ },
+)
diff --git a/googlemock/include/gmock/gmock-more-actions.h b/googlemock/include/gmock/gmock-more-actions.h
index dd90e31..e341d47 100644
--- a/googlemock/include/gmock/gmock-more-actions.h
+++ b/googlemock/include/gmock/gmock-more-actions.h
@@ -592,8 +592,9 @@
// Overloads for other custom-callables are provided in the
// internal/custom/gmock-generated-actions.h header.
template <typename F, typename... Args>
-auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) {
- return f(args...);
+auto InvokeArgument(F &&f,
+ Args... args) -> decltype(std::forward<F>(f)(args...)) {
+ return std::forward<F>(f)(args...);
}
template <std::size_t index, typename... Params>
diff --git a/googlemock/test/gmock-more-actions_test.cc b/googlemock/test/gmock-more-actions_test.cc
index 16af689..7ed89a9 100644
--- a/googlemock/test/gmock-more-actions_test.cc
+++ b/googlemock/test/gmock-more-actions_test.cc
@@ -91,6 +91,10 @@
UnaryMoveOnlyFunctor(UnaryMoveOnlyFunctor&&) = default;
};
+struct OneShotUnaryFunctor {
+ int operator()(bool x) && { return x ? 1 : -1; }
+};
+
const char* Binary(const char* input, short n) { return input + n; } // NOLINT
int Ternary(int x, char y, short z) { return x + y + z; } // NOLINT
@@ -716,6 +720,12 @@
EXPECT_EQ(1, a.Perform(std::make_tuple(UnaryMoveOnlyFunctor())));
}
+// Tests using InvokeArgument with a one-shot unary functor.
+TEST(InvokeArgumentTest, OneShotFunctor1) {
+ Action<int(OneShotUnaryFunctor)> a = InvokeArgument<0>(true); // NOLINT
+ EXPECT_EQ(1, a.Perform(std::make_tuple(OneShotUnaryFunctor())));
+}
+
// Tests using InvokeArgument with a 5-ary function.
TEST(InvokeArgumentTest, Function5) {
Action<int(int (*)(int, int, int, int, int))> a = // NOLINT
diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h
index 15d0539..2b70e49 100644
--- a/googletest/include/gtest/gtest.h
+++ b/googletest/include/gtest/gtest.h
@@ -60,16 +60,16 @@
#include <type_traits>
#include <vector>
-#include "gtest/gtest-assertion-result.h"
-#include "gtest/gtest-death-test.h"
-#include "gtest/gtest-matchers.h"
-#include "gtest/gtest-message.h"
-#include "gtest/gtest-param-test.h"
-#include "gtest/gtest-printers.h"
-#include "gtest/gtest-test-part.h"
-#include "gtest/gtest-typed-test.h"
-#include "gtest/gtest_pred_impl.h"
-#include "gtest/gtest_prod.h"
+#include "gtest/gtest-assertion-result.h" // IWYU pragma: export
+#include "gtest/gtest-death-test.h" // IWYU pragma: export
+#include "gtest/gtest-matchers.h" // IWYU pragma: export
+#include "gtest/gtest-message.h" // IWYU pragma: export
+#include "gtest/gtest-param-test.h" // IWYU pragma: export
+#include "gtest/gtest-printers.h" // IWYU pragma: export
+#include "gtest/gtest-test-part.h" // IWYU pragma: export
+#include "gtest/gtest-typed-test.h" // IWYU pragma: export
+#include "gtest/gtest_pred_impl.h" // IWYU pragma: export
+#include "gtest/gtest_prod.h" // IWYU pragma: export
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-string.h"
@@ -1262,6 +1262,20 @@
// total_test_suite_count() - 1. If i is not in that range, returns NULL.
TestSuite* GetMutableTestSuite(int i);
+ // Invokes OsStackTrackGetterInterface::UponLeavingGTest. UponLeavingGTest()
+ // should be called immediately before Google Test calls user code. It saves
+ // some information about the current stack that CurrentStackTrace() will use
+ // to find and hide Google Test stack frames.
+ void UponLeavingGTest();
+
+ // Sets the TestSuite object for the test that's currently running.
+ void set_current_test_suite(TestSuite* a_current_test_suite)
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
+ // Sets the TestInfo object for the test that's currently running.
+ void set_current_test_info(TestInfo* a_current_test_info)
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
// Accessors for the implementation object.
internal::UnitTestImpl* impl() { return impl_; }
const internal::UnitTestImpl* impl() const { return impl_; }
@@ -1270,6 +1284,8 @@
// members of UnitTest.
friend class ScopedTrace;
friend class Test;
+ friend class TestInfo;
+ friend class TestSuite;
friend class internal::AssertHelper;
friend class internal::StreamingListenerTest;
friend class internal::UnitTestRecordPropertyTestHelper;
diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc
index f914db5..15472f1 100644
--- a/googletest/src/gtest-death-test.cc
+++ b/googletest/src/gtest-death-test.cc
@@ -630,13 +630,13 @@
#ifndef GTEST_OS_WINDOWS
// Note: The return value points into args, so the return value's lifetime is
// bound to that of args.
-static std::unique_ptr<char*[]> CreateArgvFromArgs(
- std::vector<std::string>& args) {
- auto result = std::make_unique<char*[]>(args.size() + 1);
- for (size_t i = 0; i < args.size(); ++i) {
- result[i] = &args[i][0];
+static std::vector<char*> CreateArgvFromArgs(std::vector<std::string>& args) {
+ std::vector<char*> result;
+ result.reserve(args.size() + 1);
+ for (auto& arg : args) {
+ result.push_back(&arg[0]);
}
- result[args.size()] = nullptr; // extra null terminator
+ result.push_back(nullptr); // Extra null terminator.
return result;
}
#endif
@@ -1036,8 +1036,8 @@
// "Fuchsia Test Component" which contains a "Fuchsia Component Manifest")
// Launching processes is a privileged operation in Fuchsia, and the
// declaration indicates that the ability is required for the component.
- std::unique_ptr<char*[]> argv = CreateArgvFromArgs(args);
- status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, argv[0], argv.get(),
+ std::vector<char*> argv = CreateArgvFromArgs(args);
+ status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, argv[0], argv.data(),
nullptr, 2, spawn_actions,
child_process_.reset_and_get_address(), nullptr);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
@@ -1388,8 +1388,8 @@
// is necessary.
FlushInfoLog();
- std::unique_ptr<char*[]> argv = CreateArgvFromArgs(args);
- const pid_t child_pid = ExecDeathTestSpawnChild(argv.get(), pipe_fd[0]);
+ std::vector<char*> argv = CreateArgvFromArgs(args);
+ const pid_t child_pid = ExecDeathTestSpawnChild(argv.data(), pipe_fd[0]);
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
set_child_pid(child_pid);
set_read_fd(pipe_fd[0]);
diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h
index 4799a1e..6dea34f 100644
--- a/googletest/src/gtest-internal-inl.h
+++ b/googletest/src/gtest-internal-inl.h
@@ -709,18 +709,6 @@
return type_parameterized_test_registry_;
}
- // Sets the TestSuite object for the test that's currently running.
- void set_current_test_suite(TestSuite* a_current_test_suite) {
- current_test_suite_ = a_current_test_suite;
- }
-
- // Sets the TestInfo object for the test that's currently running. If
- // current_test_info is NULL, the assertion results will be stored in
- // ad_hoc_test_result_.
- void set_current_test_info(TestInfo* a_current_test_info) {
- current_test_info_ = a_current_test_info;
- }
-
// Registers all parameterized tests defined using TEST_P and
// INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
// combination. This method can be called more then once; it has guards
@@ -841,6 +829,18 @@
// GTEST_FLAG(catch_exceptions) at the moment it starts.
void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+ // Sets the TestSuite object for the test that's currently running.
+ void set_current_test_suite(TestSuite* a_current_test_suite) {
+ current_test_suite_ = a_current_test_suite;
+ }
+
+ // Sets the TestInfo object for the test that's currently running. If
+ // current_test_info is NULL, the assertion results will be stored in
+ // ad_hoc_test_result_.
+ void set_current_test_info(TestInfo* a_current_test_info) {
+ current_test_info_ = a_current_test_info;
+ }
+
// The UnitTest object that owns this implementation object.
UnitTest* const parent_;
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index d25f5c4..c5f22bb 100644
--- a/googletest/src/gtest.cc
+++ b/googletest/src/gtest.cc
@@ -2836,14 +2836,13 @@
}
// Tells UnitTest where to store test result.
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_info(this);
+ UnitTest::GetInstance()->set_current_test_info(this);
// Notifies the unit test event listeners that a test is about to start.
repeater->OnTestStart(*this);
result_.set_start_timestamp(internal::GetTimeInMillis());
internal::Timer timer;
- impl->os_stack_trace_getter()->UponLeavingGTest();
+ UnitTest::GetInstance()->UponLeavingGTest();
// Creates the test object.
Test* const test = internal::HandleExceptionsInMethodIfSupported(
@@ -2861,7 +2860,7 @@
if (test != nullptr) {
// Deletes the test object.
- impl->os_stack_trace_getter()->UponLeavingGTest();
+ UnitTest::GetInstance()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported(
test, &Test::DeleteSelf_, "the test fixture's destructor");
}
@@ -2873,15 +2872,14 @@
// Tells UnitTest to stop associating assertion results to this
// test.
- impl->set_current_test_info(nullptr);
+ UnitTest::GetInstance()->set_current_test_info(nullptr);
}
// Skip and records a skipped test result for this object.
void TestInfo::Skip() {
if (!should_run_) return;
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_info(this);
+ UnitTest::GetInstance()->set_current_test_info(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
@@ -2890,12 +2888,13 @@
const TestPartResult test_part_result =
TestPartResult(TestPartResult::kSkip, this->file(), this->line(), "");
- impl->GetTestPartResultReporterForCurrentThread()->ReportTestPartResult(
- test_part_result);
+ internal::GetUnitTestImpl()
+ ->GetTestPartResultReporterForCurrentThread()
+ ->ReportTestPartResult(test_part_result);
// Notifies the unit test event listener that a test has just finished.
repeater->OnTestEnd(*this);
- impl->set_current_test_info(nullptr);
+ UnitTest::GetInstance()->set_current_test_info(nullptr);
}
// class TestSuite
@@ -2991,8 +2990,7 @@
void TestSuite::Run() {
if (!should_run_) return;
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_suite(this);
+ UnitTest::GetInstance()->set_current_test_suite(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
@@ -3022,7 +3020,7 @@
repeater->OnTestCaseStart(*this);
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- impl->os_stack_trace_getter()->UponLeavingGTest();
+ UnitTest::GetInstance()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported(
this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");
@@ -3047,7 +3045,7 @@
}
elapsed_time_ = timer.Elapsed();
- impl->os_stack_trace_getter()->UponLeavingGTest();
+ UnitTest::GetInstance()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported(
this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");
@@ -3058,15 +3056,14 @@
repeater->OnTestCaseEnd(*this);
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- impl->set_current_test_suite(nullptr);
+ UnitTest::GetInstance()->set_current_test_suite(nullptr);
}
// Skips all tests under this TestSuite.
void TestSuite::Skip() {
if (!should_run_) return;
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_suite(this);
+ UnitTest::GetInstance()->set_current_test_suite(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
@@ -3088,7 +3085,7 @@
repeater->OnTestCaseEnd(*this);
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- impl->set_current_test_suite(nullptr);
+ UnitTest::GetInstance()->set_current_test_suite(nullptr);
}
// Clears the results of all tests in this test suite.
@@ -5304,6 +5301,22 @@
return impl()->GetMutableSuiteCase(i);
}
+void UnitTest::UponLeavingGTest() {
+ impl()->os_stack_trace_getter()->UponLeavingGTest();
+}
+
+// Sets the TestSuite object for the test that's currently running.
+void UnitTest::set_current_test_suite(TestSuite* a_current_test_suite) {
+ internal::MutexLock lock(&mutex_);
+ impl_->set_current_test_suite(a_current_test_suite);
+}
+
+// Sets the TestInfo object for the test that's currently running.
+void UnitTest::set_current_test_info(TestInfo* a_current_test_info) {
+ internal::MutexLock lock(&mutex_);
+ impl_->set_current_test_info(a_current_test_info);
+}
+
// Returns the list of event listeners that can be used to track events
// inside Google Test.
TestEventListeners& UnitTest::listeners() { return *impl()->listeners(); }
diff --git a/googletest_deps.bzl b/googletest_deps.bzl
index 8958890..1b7d2c8 100644
--- a/googletest_deps.bzl
+++ b/googletest_deps.bzl
@@ -1,6 +1,7 @@
"""Load dependencies needed to use the googletest library as a 3rd-party consumer."""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
def googletest_deps():
"""Loads common dependencies needed to use the googletest library."""
@@ -20,3 +21,8 @@
strip_prefix = "abseil-cpp-20240116.0",
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20240116.0/abseil-cpp-20240116.0.tar.gz"],
)
+
+ if not native.existing_rule("fuchsia_sdk"):
+ fake_fuchsia_sdk(
+ name = "fuchsia_sdk",
+ )