diff options
author | Abseil Team <absl-team@google.com> | 2019-12-19 17:36:47 (GMT) |
---|---|---|
committer | Andy Soffer <asoffer@google.com> | 2020-01-02 21:48:59 (GMT) |
commit | a13a0626188b4e7d22d63a4c9fcfe9f441c81e4a (patch) | |
tree | 29e7ba132b7ec3acf8943cf3195cadb5c287a703 /googletest/src | |
parent | 008629ae2163035dabd428d581379fa5aac4b7bb (diff) | |
download | googletest-a13a0626188b4e7d22d63a4c9fcfe9f441c81e4a.zip googletest-a13a0626188b4e7d22d63a4c9fcfe9f441c81e4a.tar.gz googletest-a13a0626188b4e7d22d63a4c9fcfe9f441c81e4a.tar.bz2 |
Googletest export
Add option (default to disabled) to make C++ type parameterized tests (TYPED_TEST_P) fail when they're not instantiated.
When an un-instantiated TYPED_TEST_P is found, a new test will be inserted that emits a suitable message. For now, that is just a notice, but the hope it to flip the bit to make it fail by default.
PiperOrigin-RevId: 286408038
Diffstat (limited to 'googletest/src')
-rw-r--r-- | googletest/src/gtest-internal-inl.h | 9 | ||||
-rw-r--r-- | googletest/src/gtest-typed-test.cc | 5 | ||||
-rw-r--r-- | googletest/src/gtest.cc | 59 |
3 files changed, 72 insertions, 1 deletions
diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h index c3575ee..d0ebe0c 100644 --- a/googletest/src/gtest-internal-inl.h +++ b/googletest/src/gtest-internal-inl.h @@ -698,6 +698,13 @@ class GTEST_API_ UnitTestImpl { return parameterized_test_registry_; } + // Returns TypeParameterizedTestSuiteRegistry object used to keep track of + // type-parameterized tests and instantiations of them. + internal::TypeParameterizedTestSuiteRegistry& + type_parameterized_test_registry() { + 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; @@ -874,6 +881,8 @@ class GTEST_API_ UnitTestImpl { // ParameterizedTestRegistry object used to register value-parameterized // tests. internal::ParameterizedTestSuiteRegistry parameterized_test_registry_; + internal::TypeParameterizedTestSuiteRegistry + type_parameterized_test_registry_; // Indicates whether RegisterParameterizedTests() has been called already. bool parameterized_tests_registered_; diff --git a/googletest/src/gtest-typed-test.cc b/googletest/src/gtest-typed-test.cc index 8677caf..1b1cfb0 100644 --- a/googletest/src/gtest-typed-test.cc +++ b/googletest/src/gtest-typed-test.cc @@ -58,7 +58,10 @@ static std::vector<std::string> SplitIntoTestNames(const char* src) { // registered_tests_; returns registered_tests if successful, or // aborts the program otherwise. const char* TypedTestSuitePState::VerifyRegisteredTestNames( - const char* file, int line, const char* registered_tests) { + const char* test_suite_name, const char* file, int line, + const char* registered_tests) { + RegisterTypeParameterizedTestSuite(test_suite_name, CodeLocation(file, line)); + typedef RegisteredTestsMap::const_iterator RegisteredTestIter; registered_ = true; diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index f6466b9..07015cb 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -415,6 +415,7 @@ namespace { // // This configuration bit will likely be removed at some point. constexpr bool kErrorOnUninstantiatedParameterizedTest = false; +constexpr bool kErrorOnUninstantiatedTypeParameterizedTest = false; // A test that fails at a given file/line location with a given message. class FailureTest : public Test { @@ -467,6 +468,63 @@ void InsertSyntheticTestCase(const std::string &name, CodeLocation location) { }); } +void RegisterTypeParameterizedTestSuite(const char* test_suite_name, + CodeLocation code_location) { + GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite( + test_suite_name, code_location); +} + +void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) { + GetUnitTestImpl() + ->type_parameterized_test_registry() + .RegisterInstantiation(case_name); +} + +void TypeParameterizedTestSuiteRegistry::RegisterTestSuite( + const char* test_suite_name, CodeLocation code_location) { + suites_.emplace(std::string(test_suite_name), + TypeParameterizedTestSuiteInfo(code_location)); +} + +void TypeParameterizedTestSuiteRegistry::RegisterInstantiation( + const char* test_suite_name) { + auto it = suites_.find(std::string(test_suite_name)); + if (it != suites_.end()) { + it->second.instantiated = true; + } else { + GTEST_LOG_(ERROR) << "Unknown type parameterized test suit '" + << test_suite_name << "'"; + } +} + +void TypeParameterizedTestSuiteRegistry::CheckForInstantiations() { + for (const auto& testcase : suites_) { + if (testcase.second.instantiated) continue; + + std::string message = + "Type paramaterized test suite " + testcase.first + + " is defined via REGISTER_TYPED_TEST_SUITE_P, but never instantiated " + "via INSTANTIATE_TYPED_TEST_SUITE_P. None of the test cases will run." + "\n\n" + "Ideally, TYPED_TEST_P definitions should only ever be included as " + "part of binaries that intend to use them. (As opposed to, for " + "example, being placed in a library that may be linked in to get other " + "utilities.)"; + + std::string full_name = + "UninstantiatedTypeParamaterizedTestSuite<" + testcase.first + ">"; + RegisterTest( // + "GoogleTestVerification", full_name.c_str(), + nullptr, // No type parameter. + nullptr, // No value parameter. + testcase.second.code_location.file.c_str(), + testcase.second.code_location.line, [message, testcase] { + return new FailureTest(testcase.second.code_location, message, + kErrorOnUninstantiatedTypeParameterizedTest); + }); + } +} + // A copy of all command line arguments. Set by InitGoogleTest(). static ::std::vector<std::string> g_argvs; @@ -2710,6 +2768,7 @@ namespace internal { void UnitTestImpl::RegisterParameterizedTests() { if (!parameterized_tests_registered_) { parameterized_test_registry_.RegisterTests(); + type_parameterized_test_registry_.CheckForInstantiations(); parameterized_tests_registered_ = true; } } |