update gtest on windx64

This commit is contained in:
Bassem Girgis
2020-01-19 14:18:22 -06:00
parent 320a1eeb10
commit bedc944f48
53 changed files with 4996 additions and 17751 deletions

View File

@@ -37,18 +37,19 @@
#include <ctype.h>
#include <cassert>
#include <iterator>
#include <memory>
#include <set>
#include <tuple>
#include <utility>
#include <vector>
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-linked_ptr.h"
#include "gtest/internal/gtest-port.h"
#include "gtest/gtest-printers.h"
namespace testing {
// Input to a parameterized test name generator, describing a test parameter.
// Consists of the parameter value and the integer parameter index.
template <class ParamType>
@@ -72,13 +73,14 @@ struct PrintToStringParamName {
namespace internal {
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Utility Functions
// Outputs a message explaining invalid registration of different
// fixture class for the same test case. This may happen when
// fixture class for the same test suite. This may happen when
// TEST_P macro is used to define two tests with the same name
// but in different namespaces.
GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
CodeLocation code_location);
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
CodeLocation code_location);
template <typename> class ParamGeneratorInterface;
template <typename> class ParamGenerator;
@@ -153,7 +155,7 @@ class ParamIterator {
private:
friend class ParamGenerator<T>;
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
scoped_ptr<ParamIteratorInterface<T> > impl_;
std::unique_ptr<ParamIteratorInterface<T> > impl_;
};
// ParamGeneratorInterface<T> is the binary interface to access generators
@@ -192,7 +194,7 @@ class ParamGenerator {
iterator end() const { return iterator(impl_->End()); }
private:
linked_ptr<const ParamGeneratorInterface<T> > impl_;
std::shared_ptr<const ParamGeneratorInterface<T> > impl_;
};
// Generates values from a range of two comparable values. Can be used to
@@ -205,12 +207,12 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
RangeGenerator(T begin, T end, IncrementT step)
: begin_(begin), end_(end),
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
virtual ~RangeGenerator() {}
~RangeGenerator() override {}
virtual ParamIteratorInterface<T>* Begin() const {
ParamIteratorInterface<T>* Begin() const override {
return new Iterator(this, begin_, 0, step_);
}
virtual ParamIteratorInterface<T>* End() const {
ParamIteratorInterface<T>* End() const override {
return new Iterator(this, end_, end_index_, step_);
}
@@ -220,20 +222,20 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
IncrementT step)
: base_(base), value_(value), index_(index), step_(step) {}
virtual ~Iterator() {}
~Iterator() override {}
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
const ParamGeneratorInterface<T>* BaseGenerator() const override {
return base_;
}
virtual void Advance() {
void Advance() override {
value_ = static_cast<T>(value_ + step_);
index_++;
}
virtual ParamIteratorInterface<T>* Clone() const {
ParamIteratorInterface<T>* Clone() const override {
return new Iterator(*this);
}
virtual const T* Current() const { return &value_; }
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
const T* Current() const override { return &value_; }
bool Equals(const ParamIteratorInterface<T>& other) const override {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
@@ -290,12 +292,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
template <typename ForwardIterator>
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
: container_(begin, end) {}
virtual ~ValuesInIteratorRangeGenerator() {}
~ValuesInIteratorRangeGenerator() override {}
virtual ParamIteratorInterface<T>* Begin() const {
ParamIteratorInterface<T>* Begin() const override {
return new Iterator(this, container_.begin());
}
virtual ParamIteratorInterface<T>* End() const {
ParamIteratorInterface<T>* End() const override {
return new Iterator(this, container_.end());
}
@@ -307,16 +309,16 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
Iterator(const ParamGeneratorInterface<T>* base,
typename ContainerType::const_iterator iterator)
: base_(base), iterator_(iterator) {}
virtual ~Iterator() {}
~Iterator() override {}
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
const ParamGeneratorInterface<T>* BaseGenerator() const override {
return base_;
}
virtual void Advance() {
void Advance() override {
++iterator_;
value_.reset();
}
virtual ParamIteratorInterface<T>* Clone() const {
ParamIteratorInterface<T>* Clone() const override {
return new Iterator(*this);
}
// We need to use cached value referenced by iterator_ because *iterator_
@@ -326,12 +328,11 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
// can advance iterator_ beyond the end of the range, and we cannot
// detect that fact. The client code, on the other hand, is
// responsible for not calling Current() on an out-of-range iterator.
virtual const T* Current() const {
if (value_.get() == NULL)
value_.reset(new T(*iterator_));
const T* Current() const override {
if (value_.get() == nullptr) value_.reset(new T(*iterator_));
return value_.get();
}
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
bool Equals(const ParamIteratorInterface<T>& other) const override {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
@@ -354,9 +355,9 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
// A cached value of *iterator_. We keep it here to allow access by
// pointer in the wrapping iterator's operator->().
// value_ needs to be mutable to be accessed in Current().
// Use of scoped_ptr helps manage cached value's lifetime,
// Use of std::unique_ptr helps manage cached value's lifetime,
// which is bound by the lifespan of the iterator itself.
mutable scoped_ptr<const T> value_;
mutable std::unique_ptr<const T> value_;
}; // class ValuesInIteratorRangeGenerator::Iterator
// No implementation - assignment is unsupported.
@@ -376,25 +377,12 @@ std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
return name_stream.GetString();
}
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Parameterized test name overload helpers, which help the
// INSTANTIATE_TEST_CASE_P macro choose between the default parameterized
// test name generator and user param name generator.
template <class ParamType, class ParamNameGenFunctor>
ParamNameGenFunctor GetParamNameGen(ParamNameGenFunctor func) {
return func;
}
template <class ParamType>
struct ParamNameGenFunc {
typedef std::string Type(const TestParamInfo<ParamType>&);
};
template <class ParamType>
typename ParamNameGenFunc<ParamType>::Type *GetParamNameGen() {
return DefaultParamName;
template <typename T = int>
void TestNotEmpty() {
static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
}
template <typename T = int>
void TestNotEmpty(const T&) {}
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
@@ -406,7 +394,7 @@ class ParameterizedTestFactory : public TestFactoryBase {
typedef typename TestClass::ParamType ParamType;
explicit ParameterizedTestFactory(ParamType parameter) :
parameter_(parameter) {}
virtual Test* CreateTest() {
Test* CreateTest() override {
TestClass::SetParam(&parameter_);
return new TestClass();
}
@@ -434,19 +422,19 @@ class TestMetaFactoryBase {
// TestMetaFactory creates test factories for passing into
// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
// ownership of test factory pointer, same factory object cannot be passed
// into that method twice. But ParameterizedTestCaseInfo is going to call
// into that method twice. But ParameterizedTestSuiteInfo is going to call
// it for each Test/Parameter value combination. Thus it needs meta factory
// creator class.
template <class TestCase>
template <class TestSuite>
class TestMetaFactory
: public TestMetaFactoryBase<typename TestCase::ParamType> {
: public TestMetaFactoryBase<typename TestSuite::ParamType> {
public:
typedef typename TestCase::ParamType ParamType;
using ParamType = typename TestSuite::ParamType;
TestMetaFactory() {}
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
return new ParameterizedTestFactory<TestCase>(parameter);
TestFactoryBase* CreateTestFactory(ParamType parameter) override {
return new ParameterizedTestFactory<TestSuite>(parameter);
}
private:
@@ -455,93 +443,93 @@ class TestMetaFactory
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestCaseInfoBase is a generic interface
// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
// ParameterizedTestSuiteInfoBase is a generic interface
// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
// accumulates test information provided by TEST_P macro invocations
// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations
// and uses that information to register all resulting test instances
// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
// a collection of pointers to the ParameterizedTestCaseInfo objects
// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
// a collection of pointers to the ParameterizedTestSuiteInfo objects
// and calls RegisterTests() on each of them when asked.
class ParameterizedTestCaseInfoBase {
class ParameterizedTestSuiteInfoBase {
public:
virtual ~ParameterizedTestCaseInfoBase() {}
virtual ~ParameterizedTestSuiteInfoBase() {}
// Base part of test case name for display purposes.
virtual const std::string& GetTestCaseName() const = 0;
// Base part of test suite name for display purposes.
virtual const std::string& GetTestSuiteName() const = 0;
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const = 0;
virtual TypeId GetTestSuiteTypeId() const = 0;
// UnitTest class invokes this method to register tests in this
// test case right before running them in RUN_ALL_TESTS macro.
// This method should not be called more then once on any single
// instance of a ParameterizedTestCaseInfoBase derived class.
// test suite right before running them in RUN_ALL_TESTS macro.
// This method should not be called more than once on any single
// instance of a ParameterizedTestSuiteInfoBase derived class.
virtual void RegisterTests() = 0;
protected:
ParameterizedTestCaseInfoBase() {}
ParameterizedTestSuiteInfoBase() {}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
// macro invocations for a particular test case and generators
// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
// test case. It registers tests with all values generated by all
// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
// macro invocations for a particular test suite and generators
// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
// test suite. It registers tests with all values generated by all
// generators when asked.
template <class TestCase>
class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
template <class TestSuite>
class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
public:
// ParamType and GeneratorCreationFunc are private types but are required
// for declarations of public methods AddTestPattern() and
// AddTestCaseInstantiation().
typedef typename TestCase::ParamType ParamType;
// AddTestSuiteInstantiation().
using ParamType = typename TestSuite::ParamType;
// A function that returns an instance of appropriate generator type.
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
typedef typename ParamNameGenFunc<ParamType>::Type ParamNameGeneratorFunc;
using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
explicit ParameterizedTestCaseInfo(
const char* name, CodeLocation code_location)
: test_case_name_(name), code_location_(code_location) {}
explicit ParameterizedTestSuiteInfo(const char* name,
CodeLocation code_location)
: test_suite_name_(name), code_location_(code_location) {}
// Test case base name for display purposes.
virtual const std::string& GetTestCaseName() const { return test_case_name_; }
const std::string& GetTestSuiteName() const override {
return test_suite_name_;
}
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
// TEST_P macro uses AddTestPattern() to record information
// about a single test in a LocalTestInfo structure.
// test_case_name is the base name of the test case (without invocation
// test_suite_name is the base name of the test suite (without invocation
// prefix). test_base_name is the name of an individual test without
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
// test case base name and DoBar is test base name.
void AddTestPattern(const char* test_case_name,
const char* test_base_name,
// test suite base name and DoBar is test base name.
void AddTestPattern(const char* test_suite_name, const char* test_base_name,
TestMetaFactoryBase<ParamType>* meta_factory) {
tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
test_base_name,
meta_factory)));
tests_.push_back(std::shared_ptr<TestInfo>(
new TestInfo(test_suite_name, test_base_name, meta_factory)));
}
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
// about a generator.
int AddTestCaseInstantiation(const std::string& instantiation_name,
GeneratorCreationFunc* func,
ParamNameGeneratorFunc* name_func,
const char* file, int line) {
int AddTestSuiteInstantiation(const std::string& instantiation_name,
GeneratorCreationFunc* func,
ParamNameGeneratorFunc* name_func,
const char* file, int 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 case
// test cases right before running tests in RUN_ALL_TESTS macro.
// This method should not be called more then once on any single
// instance of a ParameterizedTestCaseInfoBase derived class.
// UnitTest has a guard to prevent from calling this method more then once.
virtual void RegisterTests() {
// UnitTest class invokes this method to register tests in this test suite
// test suites right before running tests in RUN_ALL_TESTS macro.
// This method should not be called more than once on any single
// instance of a ParameterizedTestSuiteInfoBase derived class.
// UnitTest has a guard to prevent from calling this method more than once.
void RegisterTests() override {
for (typename TestInfoContainer::iterator test_it = tests_.begin();
test_it != tests_.end(); ++test_it) {
linked_ptr<TestInfo> test_info = *test_it;
std::shared_ptr<TestInfo> test_info = *test_it;
for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it != instantiations_.end();
++gen_it) {
@@ -551,10 +539,10 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
const char* file = gen_it->file;
int line = gen_it->line;
std::string test_case_name;
std::string test_suite_name;
if ( !instantiation_name.empty() )
test_case_name = instantiation_name + "/";
test_case_name += test_info->test_case_base_name;
test_suite_name = instantiation_name + "/";
test_suite_name += test_info->test_suite_base_name;
size_t i = 0;
std::set<std::string> test_param_names;
@@ -577,39 +565,39 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
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_case_name.c_str(),
test_name_stream.GetString().c_str(),
NULL, // No type parameter.
PrintToString(*param_it).c_str(),
code_location_,
GetTestCaseTypeId(),
TestCase::SetUpTestCase,
TestCase::TearDownTestCase,
test_suite_name.c_str(), test_name_stream.GetString().c_str(),
nullptr, // No type parameter.
PrintToString(*param_it).c_str(), code_location_,
GetTestSuiteTypeId(),
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
test_info->test_meta_factory->CreateTestFactory(*param_it));
} // for param_it
} // for gen_it
} // for test_it
} // RegisterTests
} // RegisterTests
private:
// LocalTestInfo structure keeps information about a single test registered
// with TEST_P macro.
struct TestInfo {
TestInfo(const char* a_test_case_base_name,
const char* a_test_base_name,
TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
test_case_base_name(a_test_case_base_name),
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {}
TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
TestMetaFactoryBase<ParamType>* a_test_meta_factory)
: test_suite_base_name(a_test_suite_base_name),
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {}
const std::string test_case_base_name;
const std::string test_suite_base_name;
const std::string test_base_name;
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
};
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
// Records data received from INSTANTIATE_TEST_CASE_P macros:
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
// Records data received from INSTANTIATE_TEST_SUITE_P macros:
// <Instantiation name, Sequence generator creation function,
// Name generator function, Source file, Source line>
struct InstantiationInfo {
@@ -646,76 +634,247 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
return true;
}
const std::string test_case_name_;
const std::string test_suite_name_;
CodeLocation code_location_;
TestInfoContainer tests_;
InstantiationContainer instantiations_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
}; // class ParameterizedTestCaseInfo
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
}; // class ParameterizedTestSuiteInfo
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
template <class TestCase>
using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
// macros use it to locate their corresponding ParameterizedTestCaseInfo
// descriptors.
class ParameterizedTestCaseRegistry {
// ParameterizedTestSuiteRegistry contains a map of
// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
// ParameterizedTestSuiteInfo descriptors.
class ParameterizedTestSuiteRegistry {
public:
ParameterizedTestCaseRegistry() {}
~ParameterizedTestCaseRegistry() {
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
it != test_case_infos_.end(); ++it) {
delete *it;
ParameterizedTestSuiteRegistry() {}
~ParameterizedTestSuiteRegistry() {
for (auto& test_suite_info : test_suite_infos_) {
delete test_suite_info;
}
}
// Looks up or creates and returns a structure containing information about
// tests and instantiations of a particular test case.
template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
const char* test_case_name,
CodeLocation code_location) {
ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
it != test_case_infos_.end(); ++it) {
if ((*it)->GetTestCaseName() == test_case_name) {
if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
// tests and instantiations of a particular test suite.
template <class TestSuite>
ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
const char* test_suite_name, CodeLocation code_location) {
ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
for (auto& test_suite_info : test_suite_infos_) {
if (test_suite_info->GetTestSuiteName() == test_suite_name) {
if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
// Complain about incorrect usage of Google Test facilities
// and terminate the program since we cannot guaranty correct
// test case setup and tear-down in this case.
ReportInvalidTestCaseType(test_case_name, code_location);
// 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<
ParameterizedTestCaseInfo<TestCase> >(*it);
ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
}
break;
}
}
if (typed_test_info == NULL) {
typed_test_info = new ParameterizedTestCaseInfo<TestCase>(
test_case_name, code_location);
test_case_infos_.push_back(typed_test_info);
if (typed_test_info == nullptr) {
typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
test_suite_name, code_location);
test_suite_infos_.push_back(typed_test_info);
}
return typed_test_info;
}
void RegisterTests() {
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
it != test_case_infos_.end(); ++it) {
(*it)->RegisterTests();
for (auto& test_suite_info : test_suite_infos_) {
test_suite_info->RegisterTests();
}
}
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
const char* test_case_name, CodeLocation code_location) {
return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
}
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
private:
using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
TestSuiteInfoContainer test_suite_infos_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
};
} // namespace internal
// Forward declarations of ValuesIn(), which is implemented in
// include/gtest/gtest-param-test.h.
template <class Container>
internal::ParamGenerator<typename Container::value_type> ValuesIn(
const Container& container);
namespace internal {
// Used in the Values() function to provide polymorphic capabilities.
template <typename... Ts>
class ValueArray {
public:
ValueArray(Ts... v) : v_{std::move(v)...} {}
template <typename T>
operator ParamGenerator<T>() const { // NOLINT
return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
}
private:
typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
template <typename T, size_t... I>
std::vector<T> MakeVector(IndexSequence<I...>) const {
return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
}
TestCaseInfoContainer test_case_infos_;
FlatTuple<Ts...> v_;
};
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
template <typename... T>
class CartesianProductGenerator
: public ParamGeneratorInterface<::std::tuple<T...>> {
public:
typedef ::std::tuple<T...> ParamType;
CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
: generators_(g) {}
~CartesianProductGenerator() override {}
ParamIteratorInterface<ParamType>* Begin() const override {
return new Iterator(this, generators_, false);
}
ParamIteratorInterface<ParamType>* End() const override {
return new Iterator(this, generators_, true);
}
private:
template <class I>
class IteratorImpl;
template <size_t... I>
class IteratorImpl<IndexSequence<I...>>
: public ParamIteratorInterface<ParamType> {
public:
IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
: base_(base),
begin_(std::get<I>(generators).begin()...),
end_(std::get<I>(generators).end()...),
current_(is_end ? end_ : begin_) {
ComputeCurrentValue();
}
~IteratorImpl() override {}
const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
return base_;
}
// Advance should not be called on beyond-of-range iterators
// so no component iterators must be beyond end of range, either.
void Advance() override {
assert(!AtEnd());
// Advance the last iterator.
++std::get<sizeof...(T) - 1>(current_);
// if that reaches end, propagate that up.
AdvanceIfEnd<sizeof...(T) - 1>();
ComputeCurrentValue();
}
ParamIteratorInterface<ParamType>* Clone() const override {
return new IteratorImpl(*this);
}
const ParamType* Current() const override { return current_value_.get(); }
bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "The program attempted to compare iterators "
<< "from different generators." << std::endl;
const IteratorImpl* typed_other =
CheckedDowncastToActualType<const IteratorImpl>(&other);
// We must report iterators equal if they both point beyond their
// respective ranges. That can happen in a variety of fashions,
// so we have to consult AtEnd().
if (AtEnd() && typed_other->AtEnd()) return true;
bool same = true;
bool dummy[] = {
(same = same && std::get<I>(current_) ==
std::get<I>(typed_other->current_))...};
(void)dummy;
return same;
}
private:
template <size_t ThisI>
void AdvanceIfEnd() {
if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;
bool last = ThisI == 0;
if (last) {
// We are done. Nothing else to propagate.
return;
}
constexpr size_t NextI = ThisI - (ThisI != 0);
std::get<ThisI>(current_) = std::get<ThisI>(begin_);
++std::get<NextI>(current_);
AdvanceIfEnd<NextI>();
}
void ComputeCurrentValue() {
if (!AtEnd())
current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
}
bool AtEnd() const {
bool at_end = false;
bool dummy[] = {
(at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
(void)dummy;
return at_end;
}
const ParamGeneratorInterface<ParamType>* const base_;
std::tuple<typename ParamGenerator<T>::iterator...> begin_;
std::tuple<typename ParamGenerator<T>::iterator...> end_;
std::tuple<typename ParamGenerator<T>::iterator...> current_;
std::shared_ptr<ParamType> current_value_;
};
using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
std::tuple<ParamGenerator<T>...> generators_;
};
template <class... Gen>
class CartesianProductHolder {
public:
CartesianProductHolder(const Gen&... g) : generators_(g...) {}
template <typename... T>
operator ParamGenerator<::std::tuple<T...>>() const {
return ParamGenerator<::std::tuple<T...>>(
new CartesianProductGenerator<T...>(generators_));
}
private:
std::tuple<Gen...> generators_;
};
} // namespace internal