From 0b024bd91a14a77a7e7d6072ccd88e09c86ddeaa Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 14 Jan 2020 00:41:46 -0500 Subject: Googletest export Add GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST to mark a paramaterized test as allowed to be un-instantiated. This allows test suites, that are defined in libraries and, for other reasons, get linked in (which should probably be avoided, but isn't always possible) to be marked as allowed to go uninstantiated. This can also be used to grandfather existing issues and expedite adoption of the checks with regards to new cases before they can be fixed. PiperOrigin-RevId: 289581573 --- googletest/docs/advanced.md | 11 +++++++++++ googletest/include/gtest/gtest-param-test.h | 7 +++++++ googletest/include/gtest/gtest.h | 2 ++ googletest/include/gtest/internal/gtest-param-util.h | 8 ++++++++ googletest/src/gtest-internal-inl.h | 8 ++++++++ googletest/src/gtest.cc | 19 ++++++++++++++++++- googletest/test/googletest-output-test-golden-lin.txt | 4 ++++ googletest/test/googletest-param-test-test.cc | 11 +++++++++++ 8 files changed, 69 insertions(+), 1 deletion(-) diff --git a/googletest/docs/advanced.md b/googletest/docs/advanced.md index 10af769..5631e8e 100644 --- a/googletest/docs/advanced.md +++ b/googletest/docs/advanced.md @@ -1377,6 +1377,17 @@ function scope. NOTE: Don't forget this step! If you do your test will silently pass, but none of its suites will ever run! +There is work in progress to make omitting `INSTANTIATE_TEST_SUITE_P` show up +under the `GoogleTestVerification` test suite and to then make that an error. +If you have a test suite where that omission is not an error, for example it is +in a library that may be linked in for other reason or where the list of test +cases is dynamic and may be empty, then this check can be suppressed by tagging +the test suite: + +```c++ +GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(FooTest); +``` + To distinguish different instances of the pattern (yes, you can instantiate it more than once), the first argument to `INSTANTIATE_TEST_SUITE_P` is a prefix that will be added to the actual test suite name. Remember to pick unique diff --git a/googletest/include/gtest/gtest-param-test.h b/googletest/include/gtest/gtest-param-test.h index 70593da..37417a9 100644 --- a/googletest/include/gtest/gtest-param-test.h +++ b/googletest/include/gtest/gtest-param-test.h @@ -491,6 +491,13 @@ internal::CartesianProductHolder Combine(const Generator&... g) { >est_##prefix##test_suite_name##_EvalGenerateName_, \ __FILE__, __LINE__) + +// Allow Marking a Parameterized test class as not needing to be instantiated. +#define GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(T) \ + namespace gtest_do_not_use_outside_namespace_scope {} \ + static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \ + GTEST_STRINGIFY_(T)) + // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #define INSTANTIATE_TEST_CASE_P \ diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index eb44c4c..464b316 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -177,6 +177,7 @@ class FuchsiaDeathTest; class UnitTestImpl* GetUnitTestImpl(); void ReportFailureInUnknownLocation(TestPartResult::Type result_type, const std::string& message); +std::set* GetIgnoredParameterizedTestSuites(); } // namespace internal @@ -1418,6 +1419,7 @@ class GTEST_API_ UnitTest { friend class internal::StreamingListenerTest; friend class internal::UnitTestRecordPropertyTestHelper; friend Environment* AddGlobalTestEnvironment(Environment* env); + friend std::set* internal::GetIgnoredParameterizedTestSuites(); friend internal::UnitTestImpl* internal::GetUnitTestImpl(); friend void internal::ReportFailureInUnknownLocation( TestPartResult::Type result_type, diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h index ffa7d72..65aa956 100644 --- a/googletest/include/gtest/internal/gtest-param-util.h +++ b/googletest/include/gtest/internal/gtest-param-util.h @@ -474,6 +474,14 @@ class ParameterizedTestSuiteInfoBase { GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); }; +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Report a the name of a test_suit as safe to ignore +// as the side effect of construction of this type. +struct MarkAsIgnored { + explicit MarkAsIgnored(const char* test_suite); +}; + GTEST_API_ void InsertSyntheticTestCase(const std::string& name, CodeLocation location); diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h index d0ebe0c..e42ff47 100644 --- a/googletest/src/gtest-internal-inl.h +++ b/googletest/src/gtest-internal-inl.h @@ -698,6 +698,10 @@ class GTEST_API_ UnitTestImpl { return parameterized_test_registry_; } + std::set* ignored_parameterized_test_suites() { + return &ignored_parameterized_test_suites_; + } + // Returns TypeParameterizedTestSuiteRegistry object used to keep track of // type-parameterized tests and instantiations of them. internal::TypeParameterizedTestSuiteRegistry& @@ -884,6 +888,10 @@ class GTEST_API_ UnitTestImpl { internal::TypeParameterizedTestSuiteRegistry type_parameterized_test_registry_; + // The set holding the name of parameterized + // test suites that may go uninstantiated. + std::set ignored_parameterized_test_suites_; + // Indicates whether RegisterParameterizedTests() has been called already. bool parameterized_tests_registered_; diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index 2df647b..1abc664 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -444,9 +444,21 @@ class FailureTest : public Test { } // namespace +std::set* GetIgnoredParameterizedTestSuites() { + return UnitTest::GetInstance()->impl()->ignored_parameterized_test_suites(); +} + +// Add a given test_suit to the list of them allow to go un-instantiated. +MarkAsIgnored::MarkAsIgnored(const char* test_suite) { + GetIgnoredParameterizedTestSuites()->insert(test_suite); +} + // If this parameterized test suite has no instantiations (and that // has not been marked as okay), emit a test case reporting that. void InsertSyntheticTestCase(const std::string &name, CodeLocation location) { + const auto& ignored = *GetIgnoredParameterizedTestSuites(); + if (ignored.find(name) != ignored.end()) return; + std::string message = "Paramaterized test suite " + name + " is defined via TEST_P, but never instantiated. None of the test cases " @@ -455,7 +467,12 @@ void InsertSyntheticTestCase(const std::string &name, CodeLocation location) { "\n\n" "Ideally, 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.)"; + "placed in a library that may be linked in to get other utilities.)" + "\n\n" + "To suppress this error for this test suite, insert the following line " + "(in a non-header) in the namespace it is defined in:" + "\n\n" + "GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(" + name + ");"; std::string full_name = "UninstantiatedParamaterizedTestSuite<" + name + ">"; RegisterTest( // diff --git a/googletest/test/googletest-output-test-golden-lin.txt b/googletest/test/googletest-output-test-golden-lin.txt index c1db004..7249081 100644 --- a/googletest/test/googletest-output-test-golden-lin.txt +++ b/googletest/test/googletest-output-test-golden-lin.txt @@ -987,6 +987,10 @@ Stack trace: (omitted) Paramaterized test suite DetectNotInstantiatedTest is defined via TEST_P, but never instantiated. None of the test cases will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only ones provided expand to nothing. Ideally, 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.) + +To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in: + +GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(DetectNotInstantiatedTest); [ OK ] GoogleTestVerification.UninstantiatedParamaterizedTestSuite [ RUN ] GoogleTestVerification.UninstantiatedTypeParamaterizedTestSuite Type paramaterized test suite DetectNotInstantiatedTypesTest is defined via REGISTER_TYPED_TEST_SUITE_P, but never instantiated via INSTANTIATE_TYPED_TEST_SUITE_P. None of the test cases will run. diff --git a/googletest/test/googletest-param-test-test.cc b/googletest/test/googletest-param-test-test.cc index f92eb31..b3b8140 100644 --- a/googletest/test/googletest-param-test-test.cc +++ b/googletest/test/googletest-param-test-test.cc @@ -1077,6 +1077,17 @@ class NotUsedTest : public testing::TestWithParam {}; template class NotUsedTypeTest : public testing::Test {}; TYPED_TEST_SUITE_P(NotUsedTypeTest); + +// Used but not instantiated, this would fail. but... +class NotInstantiatedTest : public testing::TestWithParam {}; +// ... we mark is as allowed. +GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(NotInstantiatedTest); + +TEST_P(NotInstantiatedTest, Used) { } + +using OtherName = NotInstantiatedTest; +GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(OtherName); +TEST_P(OtherName, Used) { } } // namespace works_here int main(int argc, char **argv) { -- cgit v0.12