From 31993dfa6b47e11c7a6ef67cfa8af90892b9bd1c Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 5 Mar 2024 09:58:22 -0800 Subject: [PATCH] Revert Optimize Google Test process startup PiperOrigin-RevId: 612878184 Change-Id: Ia8e23da1ad09c2e0ce635a855f0c250f368f6878 --- googletest/include/gtest/gtest.h | 6 +- .../include/gtest/internal/gtest-filepath.h | 8 +- .../include/gtest/internal/gtest-internal.h | 29 ++-- .../include/gtest/internal/gtest-param-util.h | 142 +++++++++--------- googletest/src/gtest-internal-inl.h | 20 +-- googletest/src/gtest.cc | 117 +++++++++------ 6 files changed, 162 insertions(+), 160 deletions(-) diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index c899669520..2b70e49c47 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -607,7 +607,7 @@ class GTEST_API_ TestInfo { friend class internal::UnitTestImpl; friend class internal::StreamingListenerTest; friend TestInfo* internal::MakeAndRegisterTestInfo( - std::string test_suite_name, const char* name, const char* type_param, + const char* test_suite_name, const char* name, const char* type_param, const char* value_param, internal::CodeLocation code_location, internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc, internal::TearDownTestSuiteFunc tear_down_tc, @@ -615,7 +615,7 @@ class GTEST_API_ TestInfo { // Constructs a TestInfo object. The newly constructed instance assumes // ownership of the factory object. - TestInfo(std::string test_suite_name, std::string name, + TestInfo(const std::string& test_suite_name, const std::string& name, const char* a_type_param, // NULL if not a type-parameterized test const char* a_value_param, // NULL if not a value-parameterized test internal::CodeLocation a_code_location, @@ -683,7 +683,7 @@ class GTEST_API_ TestSuite { // this is not a type-parameterized test. // set_up_tc: pointer to the function that sets up the test suite // tear_down_tc: pointer to the function that tears down the test suite - TestSuite(const std::string& name, const char* a_type_param, + TestSuite(const char* name, const char* a_type_param, internal::SetUpTestSuiteFunc set_up_tc, internal::TearDownTestSuiteFunc tear_down_tc); diff --git a/googletest/include/gtest/internal/gtest-filepath.h b/googletest/include/gtest/internal/gtest-filepath.h index 7ffb492386..5189c81dab 100644 --- a/googletest/include/gtest/internal/gtest-filepath.h +++ b/googletest/include/gtest/internal/gtest-filepath.h @@ -43,7 +43,6 @@ #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #include -#include #include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-string.h" @@ -71,9 +70,8 @@ class GTEST_API_ FilePath { public: FilePath() : pathname_("") {} FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {} - FilePath(FilePath&& rhs) : pathname_(std::move(rhs.pathname_)) {} - explicit FilePath(std::string pathname) : pathname_(std::move(pathname)) { + explicit FilePath(const std::string& pathname) : pathname_(pathname) { Normalize(); } @@ -81,10 +79,6 @@ class GTEST_API_ FilePath { Set(rhs); return *this; } - FilePath& operator=(FilePath&& rhs) { - pathname_ = std::move(rhs.pathname_); - return *this; - } void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; } diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index 4661248f7d..806b08624c 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -474,8 +474,8 @@ using SetUpTestSuiteFunc = void (*)(); using TearDownTestSuiteFunc = void (*)(); struct CodeLocation { - CodeLocation(std::string a_file, int a_line) - : file(std::move(a_file)), line(a_line) {} + CodeLocation(const std::string& a_file, int a_line) + : file(a_file), line(a_line) {} std::string file; int line; @@ -564,7 +564,7 @@ struct SuiteApiResolver : T { // The newly created TestInfo instance will assume // ownership of the factory object. GTEST_API_ TestInfo* MakeAndRegisterTestInfo( - std::string test_suite_name, const char* name, const char* type_param, + const char* test_suite_name, const char* name, const char* type_param, const char* value_param, CodeLocation code_location, TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory); @@ -595,7 +595,8 @@ class GTEST_API_ TypedTestSuitePState { fflush(stderr); posix::Abort(); } - registered_tests_.emplace(test_name, CodeLocation(file, line)); + registered_tests_.insert( + ::std::make_pair(test_name, CodeLocation(file, line))); return true; } @@ -699,7 +700,7 @@ class TypeParameterizedTest { // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite, // Types). Valid values for 'index' are [0, N - 1] where N is the // length of Types. - static bool Register(const char* prefix, CodeLocation code_location, + static bool Register(const char* prefix, const CodeLocation& code_location, const char* case_name, const char* test_names, int index, const std::vector& type_names = GenerateNames()) { @@ -711,7 +712,8 @@ class TypeParameterizedTest { // list. MakeAndRegisterTestInfo( (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + - "/" + type_names[static_cast(index)]), + "/" + type_names[static_cast(index)]) + .c_str(), StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(), GetTypeName().c_str(), nullptr, // No value parameter. @@ -723,9 +725,13 @@ class TypeParameterizedTest { new TestFactoryImpl); // Next, recurses (at compile time) with the tail of the type list. - return TypeParameterizedTest:: - Register(prefix, std::move(code_location), case_name, test_names, - index + 1, type_names); + return TypeParameterizedTest::Register(prefix, + code_location, + case_name, + test_names, + index + 1, + type_names); } }; @@ -733,7 +739,7 @@ class TypeParameterizedTest { template class TypeParameterizedTest { public: - static bool Register(const char* /*prefix*/, CodeLocation, + static bool Register(const char* /*prefix*/, const CodeLocation&, const char* /*case_name*/, const char* /*test_names*/, int /*index*/, const std::vector& = @@ -780,8 +786,7 @@ class TypeParameterizedTestSuite { // Next, recurses (at compile time) with the tail of the test list. return TypeParameterizedTestSuite::Register(prefix, - std::move(code_location), + Types>::Register(prefix, code_location, state, case_name, SkipComma(test_names), type_names); diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h index 1fc500f97d..b04f702063 100644 --- a/googletest/include/gtest/internal/gtest-param-util.h +++ b/googletest/include/gtest/internal/gtest-param-util.h @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -86,7 +85,7 @@ namespace internal { // TEST_P macro is used to define two tests with the same name // but in different namespaces. GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name, - const CodeLocation& code_location); + CodeLocation code_location); template class ParamGeneratorInterface; @@ -380,7 +379,9 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { // integer test parameter index. template std::string DefaultParamName(const TestParamInfo& info) { - return std::to_string(info.index); + Message name_stream; + name_stream << info.index; + return name_stream.GetString(); } template @@ -512,10 +513,9 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { typedef ParamGenerator(GeneratorCreationFunc)(); using ParamNameGeneratorFunc = std::string(const TestParamInfo&); - explicit ParameterizedTestSuiteInfo(std::string name, + explicit ParameterizedTestSuiteInfo(const char* name, CodeLocation code_location) - : test_suite_name_(std::move(name)), - code_location_(std::move(code_location)) {} + : test_suite_name_(name), code_location_(code_location) {} // Test suite base name for display purposes. const std::string& GetTestSuiteName() const override { @@ -529,21 +529,20 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // prefix). test_base_name is the name of an individual test without // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is // test suite base name and DoBar is test base name. - void AddTestPattern(const char*, - const char* test_base_name, + void AddTestPattern(const char* test_suite_name, const char* test_base_name, TestMetaFactoryBase* meta_factory, CodeLocation code_location) { - tests_.emplace_back( - new TestInfo(test_base_name, meta_factory, std::move(code_location))); + tests_.push_back(std::shared_ptr(new TestInfo( + test_suite_name, test_base_name, meta_factory, code_location))); } // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information // about a generator. - int AddTestSuiteInstantiation(std::string instantiation_name, + int AddTestSuiteInstantiation(const std::string& instantiation_name, GeneratorCreationFunc* func, ParamNameGeneratorFunc* name_func, const char* file, int line) { - instantiations_.emplace_back(std::move(instantiation_name), func, name_func, - file, line); + instantiations_.push_back( + InstantiationInfo(instantiation_name, func, name_func, file, line)); return 0; // Return value used only to run this method in namespace scope. } // UnitTest class invokes this method to register tests in this test suite @@ -554,31 +553,34 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { void RegisterTests() override { bool generated_instantiations = false; - std::string test_suite_name; - std::string test_name; - for (const std::shared_ptr& test_info : tests_) { - for (const InstantiationInfo& instantiation : instantiations_) { - const std::string& instantiation_name = instantiation.name; - ParamGenerator generator((*instantiation.generator)()); - ParamNameGeneratorFunc* name_func = instantiation.name_func; - const char* file = instantiation.file; - int line = instantiation.line; - + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + std::shared_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); + gen_it != instantiations_.end(); ++gen_it) { + const std::string& instantiation_name = gen_it->name; + ParamGenerator generator((*gen_it->generator)()); + ParamNameGeneratorFunc* name_func = gen_it->name_func; + const char* file = gen_it->file; + int line = gen_it->line; + + std::string test_suite_name; if (!instantiation_name.empty()) test_suite_name = instantiation_name + "/"; - else - test_suite_name.clear(); - test_suite_name += test_suite_name_; + test_suite_name += test_info->test_suite_base_name; size_t i = 0; std::set test_param_names; - for (const auto& param : generator) { + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { generated_instantiations = true; - test_name.clear(); + Message test_name_stream; std::string param_name = - name_func(TestParamInfo(param, i)); + name_func(TestParamInfo(*param_it, i)); GTEST_CHECK_(IsValidParamName(param_name)) << "Parameterized test name '" << param_name @@ -590,25 +592,23 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { << "Duplicate parameterized test name '" << param_name << "', in " << file << " line " << line << std::endl; + test_param_names.insert(param_name); + if (!test_info->test_base_name.empty()) { - test_name.append(test_info->test_base_name).append("/"); + test_name_stream << test_info->test_base_name << "/"; } - test_name += param_name; - - test_param_names.insert(std::move(param_name)); - + test_name_stream << param_name; MakeAndRegisterTestInfo( - test_suite_name, test_name.c_str(), + test_suite_name.c_str(), test_name_stream.GetString().c_str(), nullptr, // No type parameter. - PrintToString(param).c_str(), test_info->code_location, + PrintToString(*param_it).c_str(), test_info->code_location, GetTestSuiteTypeId(), SuiteApiResolver::GetSetUpCaseOrSuite(file, line), SuiteApiResolver::GetTearDownCaseOrSuite(file, line), - test_info->test_meta_factory->CreateTestFactory(param)); - ++i; - } // for param - } // for instantiation - } // for test_info + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it if (!generated_instantiations) { // There are no generaotrs, or they all generate nothing ... @@ -621,13 +621,15 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // LocalTestInfo structure keeps information about a single test registered // with TEST_P macro. struct TestInfo { - TestInfo(const char* a_test_base_name, + TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, TestMetaFactoryBase* a_test_meta_factory, CodeLocation a_code_location) - : test_base_name(a_test_base_name), + : test_suite_base_name(a_test_suite_base_name), + test_base_name(a_test_base_name), test_meta_factory(a_test_meta_factory), - code_location(std::move(a_code_location)) {} + code_location(a_code_location) {} + const std::string test_suite_base_name; const std::string test_base_name; const std::unique_ptr> test_meta_factory; const CodeLocation code_location; @@ -637,10 +639,11 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // struct InstantiationInfo { - InstantiationInfo(std::string name_in, GeneratorCreationFunc* generator_in, + InstantiationInfo(const std::string& name_in, + GeneratorCreationFunc* generator_in, ParamNameGeneratorFunc* name_func_in, const char* file_in, int line_in) - : name(std::move(name_in)), + : name(name_in), generator(generator_in), name_func(name_func_in), file(file_in), @@ -701,32 +704,29 @@ class ParameterizedTestSuiteRegistry { // tests and instantiations of a particular test suite. template ParameterizedTestSuiteInfo* GetTestSuitePatternHolder( - std::string test_suite_name, CodeLocation code_location) { + const char* test_suite_name, CodeLocation code_location) { ParameterizedTestSuiteInfo* typed_test_info = nullptr; - - auto item_it = suite_name_to_info_index_.find(test_suite_name); - if (item_it != suite_name_to_info_index_.end()) { - auto* test_suite_info = test_suite_infos_[item_it->second]; - if (test_suite_info->GetTestSuiteTypeId() != GetTypeId()) { - // Complain about incorrect usage of Google Test facilities - // and terminate the program since we cannot guaranty correct - // test suite setup and tear-down in this case. - ReportInvalidTestSuiteType(test_suite_name.c_str(), code_location); - posix::Abort(); - } else { - // At this point we are sure that the object we found is of the same - // type we are looking for, so we downcast it to that type - // without further checks. - typed_test_info = - CheckedDowncastToActualType>( - test_suite_info); + for (auto& test_suite_info : test_suite_infos_) { + if (test_suite_info->GetTestSuiteName() == test_suite_name) { + if (test_suite_info->GetTestSuiteTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test suite setup and tear-down in this case. + ReportInvalidTestSuiteType(test_suite_name, code_location); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestSuiteInfo>(test_suite_info); + } + break; } } if (typed_test_info == nullptr) { typed_test_info = new ParameterizedTestSuiteInfo( - test_suite_name, std::move(code_location)); - suite_name_to_info_index_.emplace(std::move(test_suite_name), - test_suite_infos_.size()); + test_suite_name, code_location); test_suite_infos_.push_back(typed_test_info); } return typed_test_info; @@ -740,9 +740,8 @@ class ParameterizedTestSuiteRegistry { #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ template ParameterizedTestCaseInfo* GetTestCasePatternHolder( - std::string test_case_name, CodeLocation code_location) { - return GetTestSuitePatternHolder(std::move(test_case_name), - std::move(code_location)); + const char* test_case_name, CodeLocation code_location) { + return GetTestSuitePatternHolder(test_case_name, code_location); } #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ @@ -751,7 +750,6 @@ class ParameterizedTestSuiteRegistry { using TestSuiteInfoContainer = ::std::vector; TestSuiteInfoContainer test_suite_infos_; - ::std::unordered_map suite_name_to_info_index_; ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) = delete; @@ -778,7 +776,7 @@ class TypeParameterizedTestSuiteRegistry { private: struct TypeParameterizedTestSuiteInfo { explicit TypeParameterizedTestSuiteInfo(CodeLocation c) - : code_location(std::move(c)), instantiated(false) {} + : code_location(c), instantiated(false) {} CodeLocation code_location; bool instantiated; diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h index 6a7f4dd937..6dea34f8f9 100644 --- a/googletest/src/gtest-internal-inl.h +++ b/googletest/src/gtest-internal-inl.h @@ -46,7 +46,6 @@ #include #include #include -#include #include #include "gtest/internal/gtest-port.h" @@ -650,15 +649,13 @@ class GTEST_API_ UnitTestImpl { // this is not a typed or a type-parameterized test. // set_up_tc: pointer to the function that sets up the test suite // tear_down_tc: pointer to the function that tears down the test suite - TestSuite* GetTestSuite(const std::string& test_suite_name, - const char* type_param, + TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param, internal::SetUpTestSuiteFunc set_up_tc, internal::TearDownTestSuiteFunc tear_down_tc); // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - TestCase* GetTestCase(const std::string& test_case_name, - const char* type_param, + TestCase* GetTestCase(const char* test_case_name, const char* type_param, internal::SetUpTestSuiteFunc set_up_tc, internal::TearDownTestSuiteFunc tear_down_tc) { return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc); @@ -684,13 +681,13 @@ class GTEST_API_ UnitTestImpl { // AddTestInfo(), which is called to register a TEST or TEST_F // before main() is reached. if (original_working_dir_.IsEmpty()) { - original_working_dir_ = FilePath::GetCurrentDir(); + original_working_dir_.Set(FilePath::GetCurrentDir()); GTEST_CHECK_(!original_working_dir_.IsEmpty()) << "Failed to get the current working directory."; } #endif // GTEST_HAS_FILE_SYSTEM - GetTestSuite(test_info->test_suite_name_, test_info->type_param(), + GetTestSuite(test_info->test_suite_name(), test_info->type_param(), set_up_tc, tear_down_tc) ->AddTestInfo(test_info); } @@ -826,12 +823,6 @@ class GTEST_API_ UnitTestImpl { bool catch_exceptions() const { return catch_exceptions_; } private: - struct CompareTestSuitesByPointer { - bool operator()(const TestSuite* lhs, const TestSuite* rhs) const { - return lhs->name_ < rhs->name_; - }; - }; - friend class ::testing::UnitTest; // Used by UnitTest::Run() to capture the state of @@ -882,9 +873,6 @@ class GTEST_API_ UnitTestImpl { // elements in the vector. std::vector test_suites_; - // The set of TestSuites by name. - std::unordered_map test_suites_by_name_; - // Provides a level of indirection for the test suite list to allow // easy shuffling and restoring the test suite order. The i-th // element of this vector is the index of the i-th test suite in the diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index ca9f524e4a..c5f22bb7f2 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -578,7 +578,7 @@ 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, std::move(code_location)); + test_suite_name, code_location); } void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) { @@ -589,7 +589,7 @@ void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) { void TypeParameterizedTestSuiteRegistry::RegisterTestSuite( const char* test_suite_name, CodeLocation code_location) { suites_.emplace(std::string(test_suite_name), - TypeParameterizedTestSuiteInfo(std::move(code_location))); + TypeParameterizedTestSuiteInfo(code_location)); } void TypeParameterizedTestSuiteRegistry::RegisterInstantiation( @@ -801,7 +801,7 @@ class UnitTestFilter { // Returns true if and only if name matches at least one of the patterns in // the filter. bool MatchesName(const std::string& name) const { - return exact_match_patterns_.find(name) != exact_match_patterns_.end() || + return exact_match_patterns_.count(name) > 0 || std::any_of(glob_patterns_.begin(), glob_patterns_.end(), [&name](const std::string& pattern) { return PatternMatchesString( @@ -2740,16 +2740,18 @@ bool Test::IsSkipped() { // Constructs a TestInfo object. It assumes ownership of the test factory // object. -TestInfo::TestInfo(std::string a_test_suite_name, std::string a_name, - const char* a_type_param, const char* a_value_param, +TestInfo::TestInfo(const std::string& a_test_suite_name, + const std::string& a_name, const char* a_type_param, + const char* a_value_param, internal::CodeLocation a_code_location, internal::TypeId fixture_class_id, internal::TestFactoryBase* factory) - : test_suite_name_(std::move(a_test_suite_name)), - name_(std::move(a_name)), + : test_suite_name_(a_test_suite_name), + // begin()/end() is MSVC 17.3.3 ASAN crash workaround (GitHub issue #3997) + name_(a_name.begin(), a_name.end()), type_param_(a_type_param ? new std::string(a_type_param) : nullptr), value_param_(a_value_param ? new std::string(a_value_param) : nullptr), - location_(std::move(a_code_location)), + location_(a_code_location), fixture_class_id_(fixture_class_id), should_run_(false), is_disabled_(false), @@ -2782,19 +2784,19 @@ namespace internal { // The newly created TestInfo instance will assume // ownership of the factory object. TestInfo* MakeAndRegisterTestInfo( - std::string test_suite_name, const char* name, const char* type_param, + const char* test_suite_name, const char* name, const char* type_param, const char* value_param, CodeLocation code_location, TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) { TestInfo* const test_info = - new TestInfo(std::move(test_suite_name), name, type_param, value_param, - std::move(code_location), fixture_class_id, factory); + new TestInfo(test_suite_name, name, type_param, value_param, + code_location, fixture_class_id, factory); GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); return test_info; } void ReportInvalidTestSuiteType(const char* test_suite_name, - const CodeLocation& code_location) { + CodeLocation code_location) { Message errors; errors << "Attempted redefinition of test suite " << test_suite_name << ".\n" @@ -2946,7 +2948,7 @@ int TestSuite::total_test_count() const { // this is not a typed or a type-parameterized test suite. // set_up_tc: pointer to the function that sets up the test suite // tear_down_tc: pointer to the function that tears down the test suite -TestSuite::TestSuite(const std::string& a_name, const char* a_type_param, +TestSuite::TestSuite(const char* a_name, const char* a_type_param, internal::SetUpTestSuiteFunc set_up_tc, internal::TearDownTestSuiteFunc tear_down_tc) : name_(a_name), @@ -3834,10 +3836,11 @@ void TestEventRepeater::Append(TestEventListener* listener) { } TestEventListener* TestEventRepeater::Release(TestEventListener* listener) { - auto iter = std::find(listeners_.begin(), listeners_.end(), listener); - if (iter != listeners_.end()) { - listeners_.erase(iter); - return listener; + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + static_cast(i)); + return listener; + } } return nullptr; @@ -3848,21 +3851,20 @@ TestEventListener* TestEventRepeater::Release(TestEventListener* listener) { #define GTEST_REPEATER_METHOD_(Name, Type) \ void TestEventRepeater::Name(const Type& parameter) { \ if (forwarding_enabled_) { \ - for (auto* listener : listeners_) { \ - listener->Name(parameter); \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ } \ } \ } // This defines a member that forwards the call to all listeners in reverse // order. -#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ - void TestEventRepeater::Name(const Type& parameter) { \ - if (forwarding_enabled_) { \ - const auto end = listeners_.rend(); \ - for (auto scan = listeners_.rbegin(); scan != end; ++scan) { \ - (*scan)->Name(parameter); \ - } \ - } \ +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ + void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = listeners_.size(); i != 0; i--) { \ + listeners_[i - 1]->Name(parameter); \ + } \ + } \ } GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) @@ -3892,8 +3894,8 @@ GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, int iteration) { if (forwarding_enabled_) { - for (auto* listener : listeners_) { - listener->OnTestIterationStart(unit_test, iteration); + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); } } } @@ -3901,9 +3903,8 @@ void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, int iteration) { if (forwarding_enabled_) { - const auto end = listeners_.rend(); - for (auto scan = listeners_.rbegin(); scan != end; ++scan) { - (*scan)->OnTestIterationEnd(unit_test, iteration); + for (size_t i = listeners_.size(); i > 0; i--) { + listeners_[i - 1]->OnTestIterationEnd(unit_test, iteration); } } } @@ -5745,6 +5746,29 @@ void UnitTestImpl::PostFlagParsingInit() { } } +// A predicate that checks the name of a TestSuite against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestSuiteNameIs is copyable. +class TestSuiteNameIs { + public: + // Constructor. + explicit TestSuiteNameIs(const std::string& name) : name_(name) {} + + // Returns true if and only if the name of test_suite matches name_. + bool operator()(const TestSuite* test_suite) const { + return test_suite != nullptr && + strcmp(test_suite->name(), name_.c_str()) == 0; + } + + private: + std::string name_; +}; + // Finds and returns a TestSuite with the given name. If one doesn't // exist, creates one and returns it. It's the CALLER'S // RESPONSIBILITY to ensure that this function is only called WHEN THE @@ -5758,27 +5782,19 @@ void UnitTestImpl::PostFlagParsingInit() { // set_up_tc: pointer to the function that sets up the test suite // tear_down_tc: pointer to the function that tears down the test suite TestSuite* UnitTestImpl::GetTestSuite( - const std::string& test_suite_name, const char* type_param, + const char* test_suite_name, const char* type_param, internal::SetUpTestSuiteFunc set_up_tc, internal::TearDownTestSuiteFunc tear_down_tc) { - // During initialization, all TestInfos for a given suite are added in - // sequence. To optimize this case, see if the most recently added suite is - // the one being requested now. - if (!test_suites_.empty() && - (*test_suites_.rbegin())->name_ == test_suite_name) { - return *test_suites_.rbegin(); - } + // Can we find a TestSuite with the given name? + const auto test_suite = + std::find_if(test_suites_.rbegin(), test_suites_.rend(), + TestSuiteNameIs(test_suite_name)); - // Fall back to searching the collection. - auto item_it = test_suites_by_name_.find(test_suite_name); - if (item_it != test_suites_by_name_.end()) { - return item_it->second; - } + if (test_suite != test_suites_.rend()) return *test_suite; - // Not found. Create a new instance. + // No. Let's create one. auto* const new_test_suite = new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc); - test_suites_by_name_.emplace(test_suite_name, new_test_suite); const UnitTestFilter death_test_suite_filter(kDeathTestSuiteFilter); // Is this a death test suite? @@ -6130,11 +6146,12 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { int num_runnable_tests = 0; int num_selected_tests = 0; for (auto* test_suite : test_suites_) { - const std::string& test_suite_name = test_suite->name_; + const std::string& test_suite_name = test_suite->name(); test_suite->set_should_run(false); - for (TestInfo* test_info : test_suite->test_info_list()) { - const std::string& test_name = test_info->name_; + for (size_t j = 0; j < test_suite->test_info_list().size(); j++) { + TestInfo* const test_info = test_suite->test_info_list()[j]; + const std::string test_name(test_info->name()); // A test is disabled if test suite name or test name matches // kDisableTestFilter. const bool is_disabled =