Revert Optimize Google Test process startup

PiperOrigin-RevId: 612878184
Change-Id: Ia8e23da1ad09c2e0ce635a855f0c250f368f6878
This commit is contained in:
Abseil Team 2024-03-05 09:58:22 -08:00 committed by Copybara-Service
parent b9059aaa4c
commit 31993dfa6b
6 changed files with 161 additions and 159 deletions

View File

@ -607,7 +607,7 @@ class GTEST_API_ TestInfo {
friend class internal::UnitTestImpl; friend class internal::UnitTestImpl;
friend class internal::StreamingListenerTest; friend class internal::StreamingListenerTest;
friend TestInfo* internal::MakeAndRegisterTestInfo( 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, const char* value_param, internal::CodeLocation code_location,
internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc, internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc, internal::TearDownTestSuiteFunc tear_down_tc,
@ -615,7 +615,7 @@ class GTEST_API_ TestInfo {
// Constructs a TestInfo object. The newly constructed instance assumes // Constructs a TestInfo object. The newly constructed instance assumes
// ownership of the factory object. // 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_type_param, // NULL if not a type-parameterized test
const char* a_value_param, // NULL if not a value-parameterized test const char* a_value_param, // NULL if not a value-parameterized test
internal::CodeLocation a_code_location, internal::CodeLocation a_code_location,
@ -683,7 +683,7 @@ class GTEST_API_ TestSuite {
// this is not a type-parameterized test. // this is not a type-parameterized test.
// set_up_tc: pointer to the function that sets up the 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 // 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::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc); internal::TearDownTestSuiteFunc tear_down_tc);

View File

@ -43,7 +43,6 @@
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#include <string> #include <string>
#include <utility>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
@ -71,9 +70,8 @@ class GTEST_API_ FilePath {
public: public:
FilePath() : pathname_("") {} FilePath() : pathname_("") {}
FilePath(const FilePath& rhs) : pathname_(rhs.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(); Normalize();
} }
@ -81,10 +79,6 @@ class GTEST_API_ FilePath {
Set(rhs); Set(rhs);
return *this; return *this;
} }
FilePath& operator=(FilePath&& rhs) {
pathname_ = std::move(rhs.pathname_);
return *this;
}
void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; } void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; }

View File

@ -474,8 +474,8 @@ using SetUpTestSuiteFunc = void (*)();
using TearDownTestSuiteFunc = void (*)(); using TearDownTestSuiteFunc = void (*)();
struct CodeLocation { struct CodeLocation {
CodeLocation(std::string a_file, int a_line) CodeLocation(const std::string& a_file, int a_line)
: file(std::move(a_file)), line(a_line) {} : file(a_file), line(a_line) {}
std::string file; std::string file;
int line; int line;
@ -564,7 +564,7 @@ struct SuiteApiResolver : T {
// The newly created TestInfo instance will assume // The newly created TestInfo instance will assume
// ownership of the factory object. // ownership of the factory object.
GTEST_API_ TestInfo* MakeAndRegisterTestInfo( 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, const char* value_param, CodeLocation code_location,
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory); TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
@ -595,7 +595,8 @@ class GTEST_API_ TypedTestSuitePState {
fflush(stderr); fflush(stderr);
posix::Abort(); posix::Abort();
} }
registered_tests_.emplace(test_name, CodeLocation(file, line)); registered_tests_.insert(
::std::make_pair(test_name, CodeLocation(file, line)));
return true; return true;
} }
@ -699,7 +700,7 @@ class TypeParameterizedTest {
// specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite, // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
// Types). Valid values for 'index' are [0, N - 1] where N is the // Types). Valid values for 'index' are [0, N - 1] where N is the
// length of Types. // 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 char* case_name, const char* test_names, int index,
const std::vector<std::string>& type_names = const std::vector<std::string>& type_names =
GenerateNames<DefaultNameGenerator, Types>()) { GenerateNames<DefaultNameGenerator, Types>()) {
@ -711,7 +712,8 @@ class TypeParameterizedTest {
// list. // list.
MakeAndRegisterTestInfo( MakeAndRegisterTestInfo(
(std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
"/" + type_names[static_cast<size_t>(index)]), "/" + type_names[static_cast<size_t>(index)])
.c_str(),
StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(), StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
GetTypeName<Type>().c_str(), GetTypeName<Type>().c_str(),
nullptr, // No value parameter. nullptr, // No value parameter.
@ -723,9 +725,13 @@ class TypeParameterizedTest {
new TestFactoryImpl<TestClass>); new TestFactoryImpl<TestClass>);
// Next, recurses (at compile time) with the tail of the type list. // Next, recurses (at compile time) with the tail of the type list.
return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>:: return TypeParameterizedTest<Fixture, TestSel,
Register(prefix, std::move(code_location), case_name, test_names, typename Types::Tail>::Register(prefix,
index + 1, type_names); code_location,
case_name,
test_names,
index + 1,
type_names);
} }
}; };
@ -733,7 +739,7 @@ class TypeParameterizedTest {
template <GTEST_TEMPLATE_ Fixture, class TestSel> template <GTEST_TEMPLATE_ Fixture, class TestSel>
class TypeParameterizedTest<Fixture, TestSel, internal::None> { class TypeParameterizedTest<Fixture, TestSel, internal::None> {
public: public:
static bool Register(const char* /*prefix*/, CodeLocation, static bool Register(const char* /*prefix*/, const CodeLocation&,
const char* /*case_name*/, const char* /*test_names*/, const char* /*case_name*/, const char* /*test_names*/,
int /*index*/, int /*index*/,
const std::vector<std::string>& = const std::vector<std::string>& =
@ -780,8 +786,7 @@ class TypeParameterizedTestSuite {
// Next, recurses (at compile time) with the tail of the test list. // Next, recurses (at compile time) with the tail of the test list.
return TypeParameterizedTestSuite<Fixture, typename Tests::Tail, return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
Types>::Register(prefix, Types>::Register(prefix, code_location,
std::move(code_location),
state, case_name, state, case_name,
SkipComma(test_names), SkipComma(test_names),
type_names); type_names);

View File

@ -47,7 +47,6 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -86,7 +85,7 @@ namespace internal {
// TEST_P macro is used to define two tests with the same name // TEST_P macro is used to define two tests with the same name
// but in different namespaces. // but in different namespaces.
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name, GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
const CodeLocation& code_location); CodeLocation code_location);
template <typename> template <typename>
class ParamGeneratorInterface; class ParamGeneratorInterface;
@ -380,7 +379,9 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
// integer test parameter index. // integer test parameter index.
template <class ParamType> template <class ParamType>
std::string DefaultParamName(const TestParamInfo<ParamType>& info) { std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
return std::to_string(info.index); Message name_stream;
name_stream << info.index;
return name_stream.GetString();
} }
template <typename T = int> template <typename T = int>
@ -512,10 +513,9 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)(); typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&); using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
explicit ParameterizedTestSuiteInfo(std::string name, explicit ParameterizedTestSuiteInfo(const char* name,
CodeLocation code_location) CodeLocation code_location)
: test_suite_name_(std::move(name)), : test_suite_name_(name), code_location_(code_location) {}
code_location_(std::move(code_location)) {}
// Test suite base name for display purposes. // Test suite base name for display purposes.
const std::string& GetTestSuiteName() const override { 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 // prefix). test_base_name is the name of an individual test without
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
// test suite base name and DoBar is test base name. // test suite base name and DoBar is test base name.
void AddTestPattern(const char*, void AddTestPattern(const char* test_suite_name, const char* test_base_name,
const char* test_base_name,
TestMetaFactoryBase<ParamType>* meta_factory, TestMetaFactoryBase<ParamType>* meta_factory,
CodeLocation code_location) { CodeLocation code_location) {
tests_.emplace_back( tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo(
new TestInfo(test_base_name, meta_factory, std::move(code_location))); test_suite_name, test_base_name, meta_factory, code_location)));
} }
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
// about a generator. // about a generator.
int AddTestSuiteInstantiation(std::string instantiation_name, int AddTestSuiteInstantiation(const std::string& instantiation_name,
GeneratorCreationFunc* func, GeneratorCreationFunc* func,
ParamNameGeneratorFunc* name_func, ParamNameGeneratorFunc* name_func,
const char* file, int line) { const char* file, int line) {
instantiations_.emplace_back(std::move(instantiation_name), func, name_func, instantiations_.push_back(
file, line); InstantiationInfo(instantiation_name, func, name_func, file, line));
return 0; // Return value used only to run this method in namespace scope. 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 // UnitTest class invokes this method to register tests in this test suite
@ -554,31 +553,34 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
void RegisterTests() override { void RegisterTests() override {
bool generated_instantiations = false; bool generated_instantiations = false;
std::string test_suite_name; for (typename TestInfoContainer::iterator test_it = tests_.begin();
std::string test_name; test_it != tests_.end(); ++test_it) {
for (const std::shared_ptr<TestInfo>& test_info : tests_) { std::shared_ptr<TestInfo> test_info = *test_it;
for (const InstantiationInfo& instantiation : instantiations_) { for (typename InstantiationContainer::iterator gen_it =
const std::string& instantiation_name = instantiation.name; instantiations_.begin();
ParamGenerator<ParamType> generator((*instantiation.generator)()); gen_it != instantiations_.end(); ++gen_it) {
ParamNameGeneratorFunc* name_func = instantiation.name_func; const std::string& instantiation_name = gen_it->name;
const char* file = instantiation.file; ParamGenerator<ParamType> generator((*gen_it->generator)());
int line = instantiation.line; 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()) if (!instantiation_name.empty())
test_suite_name = instantiation_name + "/"; test_suite_name = instantiation_name + "/";
else test_suite_name += test_info->test_suite_base_name;
test_suite_name.clear();
test_suite_name += test_suite_name_;
size_t i = 0; size_t i = 0;
std::set<std::string> test_param_names; std::set<std::string> test_param_names;
for (const auto& param : generator) { for (typename ParamGenerator<ParamType>::iterator param_it =
generator.begin();
param_it != generator.end(); ++param_it, ++i) {
generated_instantiations = true; generated_instantiations = true;
test_name.clear(); Message test_name_stream;
std::string param_name = std::string param_name =
name_func(TestParamInfo<ParamType>(param, i)); name_func(TestParamInfo<ParamType>(*param_it, i));
GTEST_CHECK_(IsValidParamName(param_name)) GTEST_CHECK_(IsValidParamName(param_name))
<< "Parameterized test name '" << param_name << "Parameterized test name '" << param_name
@ -590,25 +592,23 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
<< "Duplicate parameterized test name '" << param_name << "', in " << "Duplicate parameterized test name '" << param_name << "', in "
<< file << " line " << line << std::endl; << file << " line " << line << std::endl;
test_param_names.insert(param_name);
if (!test_info->test_base_name.empty()) { 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_name_stream << param_name;
test_param_names.insert(std::move(param_name));
MakeAndRegisterTestInfo( MakeAndRegisterTestInfo(
test_suite_name, test_name.c_str(), test_suite_name.c_str(), test_name_stream.GetString().c_str(),
nullptr, // No type parameter. nullptr, // No type parameter.
PrintToString(param).c_str(), test_info->code_location, PrintToString(*param_it).c_str(), test_info->code_location,
GetTestSuiteTypeId(), GetTestSuiteTypeId(),
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line), SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line), SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
test_info->test_meta_factory->CreateTestFactory(param)); test_info->test_meta_factory->CreateTestFactory(*param_it));
++i; } // for param_it
} // for param } // for gen_it
} // for instantiation } // for test_it
} // for test_info
if (!generated_instantiations) { if (!generated_instantiations) {
// There are no generaotrs, or they all generate nothing ... // 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 // LocalTestInfo structure keeps information about a single test registered
// with TEST_P macro. // with TEST_P macro.
struct TestInfo { struct TestInfo {
TestInfo(const char* a_test_base_name, TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
TestMetaFactoryBase<ParamType>* a_test_meta_factory, TestMetaFactoryBase<ParamType>* a_test_meta_factory,
CodeLocation a_code_location) 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), 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::string test_base_name;
const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory; const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
const CodeLocation code_location; const CodeLocation code_location;
@ -637,10 +639,11 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
// <Instantiation name, Sequence generator creation function, // <Instantiation name, Sequence generator creation function,
// Name generator function, Source file, Source line> // Name generator function, Source file, Source line>
struct InstantiationInfo { 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, ParamNameGeneratorFunc* name_func_in, const char* file_in,
int line_in) int line_in)
: name(std::move(name_in)), : name(name_in),
generator(generator_in), generator(generator_in),
name_func(name_func_in), name_func(name_func_in),
file(file_in), file(file_in),
@ -701,32 +704,29 @@ class ParameterizedTestSuiteRegistry {
// tests and instantiations of a particular test suite. // tests and instantiations of a particular test suite.
template <class TestSuite> template <class TestSuite>
ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder( ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
std::string test_suite_name, CodeLocation code_location) { const char* test_suite_name, CodeLocation code_location) {
ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr; ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
for (auto& test_suite_info : test_suite_infos_) {
auto item_it = suite_name_to_info_index_.find(test_suite_name); if (test_suite_info->GetTestSuiteName() == test_suite_name) {
if (item_it != suite_name_to_info_index_.end()) { if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
auto* test_suite_info = test_suite_infos_[item_it->second]; // Complain about incorrect usage of Google Test facilities
if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) { // and terminate the program since we cannot guaranty correct
// Complain about incorrect usage of Google Test facilities // test suite setup and tear-down in this case.
// and terminate the program since we cannot guaranty correct ReportInvalidTestSuiteType(test_suite_name, code_location);
// test suite setup and tear-down in this case. posix::Abort();
ReportInvalidTestSuiteType(test_suite_name.c_str(), code_location); } else {
posix::Abort(); // At this point we are sure that the object we found is of the same
} else { // type we are looking for, so we downcast it to that type
// At this point we are sure that the object we found is of the same // without further checks.
// type we are looking for, so we downcast it to that type typed_test_info = CheckedDowncastToActualType<
// without further checks. ParameterizedTestSuiteInfo<TestSuite>>(test_suite_info);
typed_test_info = }
CheckedDowncastToActualType<ParameterizedTestSuiteInfo<TestSuite>>( break;
test_suite_info);
} }
} }
if (typed_test_info == nullptr) { if (typed_test_info == nullptr) {
typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>( typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
test_suite_name, std::move(code_location)); test_suite_name, code_location);
suite_name_to_info_index_.emplace(std::move(test_suite_name),
test_suite_infos_.size());
test_suite_infos_.push_back(typed_test_info); test_suite_infos_.push_back(typed_test_info);
} }
return typed_test_info; return typed_test_info;
@ -740,9 +740,8 @@ class ParameterizedTestSuiteRegistry {
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
template <class TestCase> template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder( ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
std::string test_case_name, CodeLocation code_location) { const char* test_case_name, CodeLocation code_location) {
return GetTestSuitePatternHolder<TestCase>(std::move(test_case_name), return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
std::move(code_location));
} }
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
@ -751,7 +750,6 @@ class ParameterizedTestSuiteRegistry {
using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>; using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
TestSuiteInfoContainer test_suite_infos_; TestSuiteInfoContainer test_suite_infos_;
::std::unordered_map<std::string, size_t> suite_name_to_info_index_;
ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) = ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) =
delete; delete;
@ -778,7 +776,7 @@ class TypeParameterizedTestSuiteRegistry {
private: private:
struct TypeParameterizedTestSuiteInfo { struct TypeParameterizedTestSuiteInfo {
explicit TypeParameterizedTestSuiteInfo(CodeLocation c) explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
: code_location(std::move(c)), instantiated(false) {} : code_location(c), instantiated(false) {}
CodeLocation code_location; CodeLocation code_location;
bool instantiated; bool instantiated;

View File

@ -46,7 +46,6 @@
#include <memory> #include <memory>
#include <set> #include <set>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
@ -650,15 +649,13 @@ class GTEST_API_ UnitTestImpl {
// this is not a typed or a type-parameterized test. // this is not a typed or a type-parameterized test.
// set_up_tc: pointer to the function that sets up the 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 // tear_down_tc: pointer to the function that tears down the test suite
TestSuite* GetTestSuite(const std::string& test_suite_name, TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
const char* type_param,
internal::SetUpTestSuiteFunc set_up_tc, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc); internal::TearDownTestSuiteFunc tear_down_tc);
// Legacy API is deprecated but still available // Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
TestCase* GetTestCase(const std::string& test_case_name, TestCase* GetTestCase(const char* test_case_name, const char* type_param,
const char* type_param,
internal::SetUpTestSuiteFunc set_up_tc, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc) { internal::TearDownTestSuiteFunc tear_down_tc) {
return GetTestSuite(test_case_name, type_param, set_up_tc, 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 // AddTestInfo(), which is called to register a TEST or TEST_F
// before main() is reached. // before main() is reached.
if (original_working_dir_.IsEmpty()) { if (original_working_dir_.IsEmpty()) {
original_working_dir_ = FilePath::GetCurrentDir(); original_working_dir_.Set(FilePath::GetCurrentDir());
GTEST_CHECK_(!original_working_dir_.IsEmpty()) GTEST_CHECK_(!original_working_dir_.IsEmpty())
<< "Failed to get the current working directory."; << "Failed to get the current working directory.";
} }
#endif // GTEST_HAS_FILE_SYSTEM #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) set_up_tc, tear_down_tc)
->AddTestInfo(test_info); ->AddTestInfo(test_info);
} }
@ -826,12 +823,6 @@ class GTEST_API_ UnitTestImpl {
bool catch_exceptions() const { return catch_exceptions_; } bool catch_exceptions() const { return catch_exceptions_; }
private: private:
struct CompareTestSuitesByPointer {
bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
return lhs->name_ < rhs->name_;
};
};
friend class ::testing::UnitTest; friend class ::testing::UnitTest;
// Used by UnitTest::Run() to capture the state of // Used by UnitTest::Run() to capture the state of
@ -882,9 +873,6 @@ class GTEST_API_ UnitTestImpl {
// elements in the vector. // elements in the vector.
std::vector<TestSuite*> test_suites_; std::vector<TestSuite*> test_suites_;
// The set of TestSuites by name.
std::unordered_map<std::string, TestSuite*> test_suites_by_name_;
// Provides a level of indirection for the test suite list to allow // Provides a level of indirection for the test suite list to allow
// easy shuffling and restoring the test suite order. The i-th // 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 // element of this vector is the index of the i-th test suite in the

View File

@ -578,7 +578,7 @@ void InsertSyntheticTestCase(const std::string& name, CodeLocation location,
void RegisterTypeParameterizedTestSuite(const char* test_suite_name, void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
CodeLocation code_location) { CodeLocation code_location) {
GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite( GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite(
test_suite_name, std::move(code_location)); test_suite_name, code_location);
} }
void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) { void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) {
@ -589,7 +589,7 @@ void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) {
void TypeParameterizedTestSuiteRegistry::RegisterTestSuite( void TypeParameterizedTestSuiteRegistry::RegisterTestSuite(
const char* test_suite_name, CodeLocation code_location) { const char* test_suite_name, CodeLocation code_location) {
suites_.emplace(std::string(test_suite_name), suites_.emplace(std::string(test_suite_name),
TypeParameterizedTestSuiteInfo(std::move(code_location))); TypeParameterizedTestSuiteInfo(code_location));
} }
void TypeParameterizedTestSuiteRegistry::RegisterInstantiation( void TypeParameterizedTestSuiteRegistry::RegisterInstantiation(
@ -801,7 +801,7 @@ class UnitTestFilter {
// Returns true if and only if name matches at least one of the patterns in // Returns true if and only if name matches at least one of the patterns in
// the filter. // the filter.
bool MatchesName(const std::string& name) const { 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(), std::any_of(glob_patterns_.begin(), glob_patterns_.end(),
[&name](const std::string& pattern) { [&name](const std::string& pattern) {
return PatternMatchesString( return PatternMatchesString(
@ -2740,16 +2740,18 @@ bool Test::IsSkipped() {
// Constructs a TestInfo object. It assumes ownership of the test factory // Constructs a TestInfo object. It assumes ownership of the test factory
// object. // object.
TestInfo::TestInfo(std::string a_test_suite_name, std::string a_name, TestInfo::TestInfo(const std::string& a_test_suite_name,
const char* a_type_param, const char* a_value_param, const std::string& a_name, const char* a_type_param,
const char* a_value_param,
internal::CodeLocation a_code_location, internal::CodeLocation a_code_location,
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory) internal::TestFactoryBase* factory)
: test_suite_name_(std::move(a_test_suite_name)), : test_suite_name_(a_test_suite_name),
name_(std::move(a_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), type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
value_param_(a_value_param ? new std::string(a_value_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), fixture_class_id_(fixture_class_id),
should_run_(false), should_run_(false),
is_disabled_(false), is_disabled_(false),
@ -2782,19 +2784,19 @@ namespace internal {
// The newly created TestInfo instance will assume // The newly created TestInfo instance will assume
// ownership of the factory object. // ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo( 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, const char* value_param, CodeLocation code_location,
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) { TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
TestInfo* const test_info = TestInfo* const test_info =
new TestInfo(std::move(test_suite_name), name, type_param, value_param, new TestInfo(test_suite_name, name, type_param, value_param,
std::move(code_location), fixture_class_id, factory); code_location, fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info; return test_info;
} }
void ReportInvalidTestSuiteType(const char* test_suite_name, void ReportInvalidTestSuiteType(const char* test_suite_name,
const CodeLocation& code_location) { CodeLocation code_location) {
Message errors; Message errors;
errors errors
<< "Attempted redefinition of test suite " << test_suite_name << ".\n" << "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. // this is not a typed or a type-parameterized test suite.
// set_up_tc: pointer to the function that sets up the 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 // 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::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc) internal::TearDownTestSuiteFunc tear_down_tc)
: name_(a_name), : name_(a_name),
@ -3834,10 +3836,11 @@ void TestEventRepeater::Append(TestEventListener* listener) {
} }
TestEventListener* TestEventRepeater::Release(TestEventListener* listener) { TestEventListener* TestEventRepeater::Release(TestEventListener* listener) {
auto iter = std::find(listeners_.begin(), listeners_.end(), listener); for (size_t i = 0; i < listeners_.size(); ++i) {
if (iter != listeners_.end()) { if (listeners_[i] == listener) {
listeners_.erase(iter); listeners_.erase(listeners_.begin() + static_cast<int>(i));
return listener; return listener;
}
} }
return nullptr; return nullptr;
@ -3848,21 +3851,20 @@ TestEventListener* TestEventRepeater::Release(TestEventListener* listener) {
#define GTEST_REPEATER_METHOD_(Name, Type) \ #define GTEST_REPEATER_METHOD_(Name, Type) \
void TestEventRepeater::Name(const Type& parameter) { \ void TestEventRepeater::Name(const Type& parameter) { \
if (forwarding_enabled_) { \ if (forwarding_enabled_) { \
for (auto* listener : listeners_) { \ for (size_t i = 0; i < listeners_.size(); i++) { \
listener->Name(parameter); \ listeners_[i]->Name(parameter); \
} \ } \
} \ } \
} }
// This defines a member that forwards the call to all listeners in reverse // This defines a member that forwards the call to all listeners in reverse
// order. // order.
#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ #define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
void TestEventRepeater::Name(const Type& parameter) { \ void TestEventRepeater::Name(const Type& parameter) { \
if (forwarding_enabled_) { \ if (forwarding_enabled_) { \
const auto end = listeners_.rend(); \ for (size_t i = listeners_.size(); i != 0; i--) { \
for (auto scan = listeners_.rbegin(); scan != end; ++scan) { \ listeners_[i - 1]->Name(parameter); \
(*scan)->Name(parameter); \ } \
} \ } \
} \
} }
GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
@ -3892,8 +3894,8 @@ GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
int iteration) { int iteration) {
if (forwarding_enabled_) { if (forwarding_enabled_) {
for (auto* listener : listeners_) { for (size_t i = 0; i < listeners_.size(); i++) {
listener->OnTestIterationStart(unit_test, iteration); listeners_[i]->OnTestIterationStart(unit_test, iteration);
} }
} }
} }
@ -3901,9 +3903,8 @@ void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
int iteration) { int iteration) {
if (forwarding_enabled_) { if (forwarding_enabled_) {
const auto end = listeners_.rend(); for (size_t i = listeners_.size(); i > 0; i--) {
for (auto scan = listeners_.rbegin(); scan != end; ++scan) { listeners_[i - 1]->OnTestIterationEnd(unit_test, iteration);
(*scan)->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 // Finds and returns a TestSuite with the given name. If one doesn't
// exist, creates one and returns it. It's the CALLER'S // exist, creates one and returns it. It's the CALLER'S
// RESPONSIBILITY to ensure that this function is only called WHEN THE // 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 // 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 // tear_down_tc: pointer to the function that tears down the test suite
TestSuite* UnitTestImpl::GetTestSuite( 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::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc) { internal::TearDownTestSuiteFunc tear_down_tc) {
// During initialization, all TestInfos for a given suite are added in // Can we find a TestSuite with the given name?
// sequence. To optimize this case, see if the most recently added suite is const auto test_suite =
// the one being requested now. std::find_if(test_suites_.rbegin(), test_suites_.rend(),
if (!test_suites_.empty() && TestSuiteNameIs(test_suite_name));
(*test_suites_.rbegin())->name_ == test_suite_name) {
return *test_suites_.rbegin();
}
// Fall back to searching the collection. if (test_suite != test_suites_.rend()) return *test_suite;
auto item_it = test_suites_by_name_.find(test_suite_name);
if (item_it != test_suites_by_name_.end()) {
return item_it->second;
}
// Not found. Create a new instance. // No. Let's create one.
auto* const new_test_suite = auto* const new_test_suite =
new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc); 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); const UnitTestFilter death_test_suite_filter(kDeathTestSuiteFilter);
// Is this a death test suite? // Is this a death test suite?
@ -6130,11 +6146,12 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
int num_runnable_tests = 0; int num_runnable_tests = 0;
int num_selected_tests = 0; int num_selected_tests = 0;
for (auto* test_suite : test_suites_) { 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); test_suite->set_should_run(false);
for (TestInfo* test_info : test_suite->test_info_list()) { for (size_t j = 0; j < test_suite->test_info_list().size(); j++) {
const std::string& test_name = test_info->name_; 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 // A test is disabled if test suite name or test name matches
// kDisableTestFilter. // kDisableTestFilter.
const bool is_disabled = const bool is_disabled =