diff options
-rw-r--r-- | googletest/include/gtest/gtest-param-test.h | 20 | ||||
-rw-r--r-- | googletest/include/gtest/gtest-typed-test.h | 2 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-internal.h | 22 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-param-util.h | 33 | ||||
-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 | ||||
-rw-r--r-- | googletest/test/googletest-output-test-golden-lin.txt | 16 | ||||
-rw-r--r-- | googletest/test/googletest-output-test_.cc | 23 | ||||
-rw-r--r-- | googletest/test/googletest-param-test-test.cc | 5 | ||||
-rw-r--r-- | googletest/test/gtest-typed-test_test.cc | 12 | ||||
-rw-r--r-- | googletest/test/gtest_unittest.cc | 2 |
12 files changed, 176 insertions, 32 deletions
diff --git a/googletest/include/gtest/gtest-param-test.h b/googletest/include/gtest/gtest-param-test.h index f61e3c5d..70593da5 100644 --- a/googletest/include/gtest/gtest-param-test.h +++ b/googletest/include/gtest/gtest-param-test.h @@ -58,9 +58,7 @@ class FooTest : public ::testing::TestWithParam<const char*> { // Then, use the TEST_P macro to define as many parameterized tests // for this fixture as you want. The _P suffix is for "parameterized" -// or "pattern", whichever you prefer to think. The arguments to the -// TEST_P macro are the test_suite_name and test_case (both which must be -// non-empty) that will form the test name. +// or "pattern", whichever you prefer to think. TEST_P(FooTest, DoesBlah) { // Inside a test, access the test parameter with the GetParam() method @@ -103,10 +101,10 @@ INSTANTIATE_TEST_SUITE_P(InstantiationName, // To distinguish different instances of the pattern, (yes, you // can instantiate it more than once) the first argument to the -// INSTANTIATE_TEST_SUITE_P macro is a prefix (which must be non-empty) that -// will be added to the actual test suite name. Remember to pick unique prefixes -// for different instantiations. The tests from the instantiation above will -// have these names: +// INSTANTIATE_TEST_SUITE_P macro is a prefix that will be added to the +// actual test suite name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: // // * InstantiationName/FooTest.DoesBlah/0 for "meeny" // * InstantiationName/FooTest.DoesBlah/1 for "miny" @@ -414,10 +412,6 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) { } #define TEST_P(test_suite_name, test_name) \ - static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ - "test_suite_name must not be empty"); \ - static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \ - "test_name must not be empty"); \ class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ : public test_suite_name { \ public: \ @@ -464,10 +458,6 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) { #define GTEST_GET_SECOND_(first, second, ...) second #define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \ - static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ - "test_suite_name must not be empty"); \ - static_assert(sizeof(GTEST_STRINGIFY_(prefix)) > 1, \ - "prefix must not be empty"); \ static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \ gtest_##prefix##test_suite_name##_EvalGenerator_() { \ return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \ diff --git a/googletest/include/gtest/gtest-typed-test.h b/googletest/include/gtest/gtest-typed-test.h index 6f635c87..3ffa50b7 100644 --- a/googletest/include/gtest/gtest-typed-test.h +++ b/googletest/include/gtest/gtest-typed-test.h @@ -297,7 +297,7 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); static const char* const GTEST_REGISTERED_TEST_NAMES_( \ SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ - __FILE__, __LINE__, #__VA_ARGS__) + GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__) // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index ff2ff4ba..41c94f44 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -79,7 +79,16 @@ #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar // Stringifies its argument. -#define GTEST_STRINGIFY_(name) #name +// Work around a bug in visual studio which doesn't accept code like this: +// +// #define GTEST_STRINGIFY_(name) #name +// #define MACRO(a, b, c) ... GTEST_STRINGIFY_(a) ... +// MACRO(, x, y) +// +// Complaining about the argument to GTEST_STRINGIFY_ being empty. +// This is allowed by the spec. +#define GTEST_STRINGIFY_HELPER_(name, ...) #name +#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, ) namespace proto2 { class Message; } @@ -608,8 +617,9 @@ class GTEST_API_ TypedTestSuitePState { // Verifies that registered_tests match the test names in // defined_test_names_; returns registered_tests if successful, or // aborts the program otherwise. - const char* VerifyRegisteredTestNames( - const char* file, int line, const char* registered_tests); + const char* VerifyRegisteredTestNames(const char* test_suite_name, + const char* file, int line, + const char* registered_tests); private: typedef ::std::map<std::string, CodeLocation> RegisteredTestsMap; @@ -741,6 +751,11 @@ class TypeParameterizedTest<Fixture, TestSel, internal::None> { } }; +GTEST_API_ void RegisterTypeParameterizedTestSuite(const char* test_suite_name, + CodeLocation code_location); +GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation( + const char* case_name); + // TypeParameterizedTestSuite<Fixture, Tests, Types>::Register() // registers *all combinations* of 'Tests' and 'Types' with Google // Test. The return value is insignificant - we just need to return @@ -753,6 +768,7 @@ class TypeParameterizedTestSuite { const char* test_names, const std::vector<std::string>& type_names = GenerateNames<DefaultNameGenerator, Types>()) { + RegisterTypeParameterizedTestSuiteInstantiation(case_name); std::string test_name = StripTrailingSpaces( GetPrefixUntilComma(test_names)); if (!state->TestExists(test_name)) { diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h index 70c43354..ffa7d72c 100644 --- a/googletest/include/gtest/internal/gtest-param-util.h +++ b/googletest/include/gtest/internal/gtest-param-util.h @@ -574,7 +574,10 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { test_param_names.insert(param_name); - test_name_stream << test_info->test_base_name << "/" << param_name; + if (!test_info->test_base_name.empty()) { + test_name_stream << test_info->test_base_name << "/"; + } + test_name_stream << param_name; MakeAndRegisterTestInfo( test_suite_name.c_str(), test_name_stream.GetString().c_str(), nullptr, // No type parameter. @@ -728,6 +731,34 @@ class ParameterizedTestSuiteRegistry { GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry); }; +// Keep track of what type-parameterized test suite are defined and +// where as well as which are intatiated. This allows susequently +// identifying suits that are defined but never used. +class TypeParameterizedTestSuiteRegistry { + public: + // Add a suite definition + void RegisterTestSuite(const char* test_suite_name, + CodeLocation code_location); + + // Add an instantiation of a suit. + void RegisterInstantiation(const char* test_suite_name); + + // For each suit repored as defined but not reported as instantiation, + // emit a test that reports that fact (configurably, as an error). + void CheckForInstantiations(); + + private: + struct TypeParameterizedTestSuiteInfo { + explicit TypeParameterizedTestSuiteInfo(CodeLocation c) + : code_location(c), instantiated(false) {} + + CodeLocation code_location; + bool instantiated; + }; + + std::map<std::string, TypeParameterizedTestSuiteInfo> suites_; +}; + } // namespace internal // Forward declarations of ValuesIn(), which is implemented in diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h index c3575ee3..d0ebe0c5 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 8677caf7..1b1cfb0d 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 f6466b92..07015cba 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; } } diff --git a/googletest/test/googletest-output-test-golden-lin.txt b/googletest/test/googletest-output-test-golden-lin.txt index 27f9d489..c1db004c 100644 --- a/googletest/test/googletest-output-test-golden-lin.txt +++ b/googletest/test/googletest-output-test-golden-lin.txt @@ -12,7 +12,7 @@ Expected equality of these values: 3 Stack trace: (omitted) -[0;32m[==========] [mRunning 85 tests from 40 test suites. +[0;32m[==========] [mRunning 87 tests from 41 test suites. [0;32m[----------] [mGlobal test environment set-up. FooEnvironment::SetUp() called. BarEnvironment::SetUp() called. @@ -966,6 +966,9 @@ Expected equality of these values: Stack trace: (omitted) [0;31m[ FAILED ] [mPrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2 +[0;32m[----------] [m1 test from EmptyBasenameParamInst +[0;32m[ RUN ] [mEmptyBasenameParamInst.Passes/0 +[0;32m[ OK ] [mEmptyBasenameParamInst.Passes/0 [0;32m[----------] [m2 tests from PrintingStrings/ParamTest [0;32m[ RUN ] [mPrintingStrings/ParamTest.Success/a [0;32m[ OK ] [mPrintingStrings/ParamTest.Success/a @@ -979,12 +982,17 @@ Expected failure Stack trace: (omitted) [0;31m[ FAILED ] [mPrintingStrings/ParamTest.Failure/a, where GetParam() = "a" -[0;32m[----------] [m1 test from GoogleTestVerification +[0;32m[----------] [m2 tests from GoogleTestVerification [0;32m[ RUN ] [mGoogleTestVerification.UninstantiatedParamaterizedTestSuite<DetectNotInstantiatedTest> 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.) [0;32m[ OK ] [mGoogleTestVerification.UninstantiatedParamaterizedTestSuite<DetectNotInstantiatedTest> +[0;32m[ RUN ] [mGoogleTestVerification.UninstantiatedTypeParamaterizedTestSuite<DetectNotInstantiatedTypesTest> +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. + +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.) +[0;32m[ OK ] [mGoogleTestVerification.UninstantiatedTypeParamaterizedTestSuite<DetectNotInstantiatedTypesTest> [0;32m[----------] [mGlobal test environment tear-down BarEnvironment::TearDown() called. googletest-output-test_.cc:#: Failure @@ -998,8 +1006,8 @@ Failed Expected fatal failure. Stack trace: (omitted) -[0;32m[==========] [m85 tests from 40 test suites ran. -[0;32m[ PASSED ] [m31 tests. +[0;32m[==========] [m87 tests from 41 test suites ran. +[0;32m[ PASSED ] [m33 tests. [0;31m[ FAILED ] [m54 tests, listed below: [0;31m[ FAILED ] [mNonfatalFailureTest.EscapesStringOperands [0;31m[ FAILED ] [mNonfatalFailureTest.DiffForLongStrings diff --git a/googletest/test/googletest-output-test_.cc b/googletest/test/googletest-output-test_.cc index fe0d83f4..b1d66f9f 100644 --- a/googletest/test/googletest-output-test_.cc +++ b/googletest/test/googletest-output-test_.cc @@ -96,6 +96,14 @@ INSTANTIATE_TEST_SUITE_P(PrintingFailingParams, FailingParamTest, testing::Values(2)); +// Tests that an empty value for the test suite basename yields just +// the test name without any prior / +class EmptyBasenameParamInst : public testing::TestWithParam<int> {}; + +TEST_P(EmptyBasenameParamInst, Passes) { EXPECT_EQ(1, GetParam()); } + +INSTANTIATE_TEST_SUITE_P(, EmptyBasenameParamInst, testing::Values(1)); + static const char kGoldenString[] = "\"Line\0 1\"\nLine 2"; TEST(NonfatalFailureTest, EscapesStringOperands) { @@ -868,6 +876,21 @@ class TypedTestPNames { INSTANTIATE_TYPED_TEST_SUITE_P(UnsignedCustomName, TypedTestP, UnsignedTypes, TypedTestPNames); +template <typename T> +class DetectNotInstantiatedTypesTest : public testing::Test {}; +TYPED_TEST_SUITE_P(DetectNotInstantiatedTypesTest); +TYPED_TEST_P(DetectNotInstantiatedTypesTest, Used) { + TypeParam instantiate; + (void)instantiate; +} +REGISTER_TYPED_TEST_SUITE_P(DetectNotInstantiatedTypesTest, Used); + +// kErrorOnUninstantiatedTypeParameterizedTest=true would make the above fail. +// Adding the following would make that test failure go away. +// +// typedef ::testing::Types<char, int, unsigned int> MyTypes; +// INSTANTIATE_TYPED_TEST_SUITE_P(All, DetectNotInstantiatedTypesTest, MyTypes); + #endif // GTEST_HAS_TYPED_TEST_P #if GTEST_HAS_DEATH_TEST diff --git a/googletest/test/googletest-param-test-test.cc b/googletest/test/googletest-param-test-test.cc index 85c76c34..f92eb316 100644 --- a/googletest/test/googletest-param-test-test.cc +++ b/googletest/test/googletest-param-test-test.cc @@ -1072,6 +1072,11 @@ namespace works_here { // Never used not instantiated, this should work. class NotUsedTest : public testing::TestWithParam<int> {}; +/////// +// Never used not instantiated, this should work. +template <typename T> +class NotUsedTypeTest : public testing::Test {}; +TYPED_TEST_SUITE_P(NotUsedTypeTest); } // namespace works_here int main(int argc, char **argv) { diff --git a/googletest/test/gtest-typed-test_test.cc b/googletest/test/gtest-typed-test_test.cc index 5411832a..0c1f660f 100644 --- a/googletest/test/gtest-typed-test_test.cc +++ b/googletest/test/gtest-typed-test_test.cc @@ -228,7 +228,7 @@ class TypedTestSuitePStateTest : public Test { TEST_F(TypedTestSuitePStateTest, SucceedsForMatchingList) { const char* tests = "A, B, C"; EXPECT_EQ(tests, - state_.VerifyRegisteredTestNames("foo.cc", 1, tests)); + state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, tests)); } // Makes sure that the order of the tests and spaces around the names @@ -236,33 +236,33 @@ TEST_F(TypedTestSuitePStateTest, SucceedsForMatchingList) { TEST_F(TypedTestSuitePStateTest, IgnoresOrderAndSpaces) { const char* tests = "A,C, B"; EXPECT_EQ(tests, - state_.VerifyRegisteredTestNames("foo.cc", 1, tests)); + state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, tests)); } using TypedTestSuitePStateDeathTest = TypedTestSuitePStateTest; TEST_F(TypedTestSuitePStateDeathTest, DetectsDuplicates) { EXPECT_DEATH_IF_SUPPORTED( - state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, A, C"), + state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, A, C"), "foo\\.cc.1.?: Test A is listed more than once\\."); } TEST_F(TypedTestSuitePStateDeathTest, DetectsExtraTest) { EXPECT_DEATH_IF_SUPPORTED( - state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C, D"), + state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, C, D"), "foo\\.cc.1.?: No test named D can be found in this test suite\\."); } TEST_F(TypedTestSuitePStateDeathTest, DetectsMissedTest) { EXPECT_DEATH_IF_SUPPORTED( - state_.VerifyRegisteredTestNames("foo.cc", 1, "A, C"), + state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, C"), "foo\\.cc.1.?: You forgot to list test B\\."); } // Tests that defining a test for a parameterized test case generates // a run-time error if the test case has been registered. TEST_F(TypedTestSuitePStateDeathTest, DetectsTestAfterRegistration) { - state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C"); + state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, C"); EXPECT_DEATH_IF_SUPPORTED( state_.AddTestName("foo.cc", 2, "FooTest", "D"), "foo\\.cc.2.?: Test D must be defined before REGISTER_TYPED_TEST_SUITE_P" diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index d4cb0a1b..06c5e671 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -5337,7 +5337,7 @@ TEST_P(CodeLocationForTESTP, Verify) { VERIFY_CODE_LOCATION; } -INSTANTIATE_TEST_SUITE_P(All, CodeLocationForTESTP, Values(0)); +INSTANTIATE_TEST_SUITE_P(, CodeLocationForTESTP, Values(0)); template <typename T> class CodeLocationForTYPEDTEST : public Test { |