ref: 9a25e3169b59ca822558024423c5675790ffcf5b
dir: /third_party/googletest/src/include/gtest/internal/gtest-param-util.h/
// Copyright 2008 Google Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Type and function utilities for implementing parameterized tests. // GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #include <ctype.h> #include <cassert> #include <iterator> #include <memory> #include <set> #include <tuple> #include <type_traits> #include <utility> #include <vector> #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" #include "gtest/gtest-printers.h" #include "gtest/gtest-test-part.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> struct TestParamInfo { TestParamInfo(const ParamType& a_param, size_t an_index) : param(a_param), index(an_index) {} ParamType param; size_t index; }; // A builtin parameterized test name generator which returns the result of // testing::PrintToString. struct PrintToStringParamName { template <class ParamType> std::string operator()(const TestParamInfo<ParamType>& info) const { return PrintToString(info.param); } }; 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 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 ReportInvalidTestSuiteType(const char* test_suite_name, CodeLocation code_location); template <typename> class ParamGeneratorInterface; template <typename> class ParamGenerator; // Interface for iterating over elements provided by an implementation // of ParamGeneratorInterface<T>. template <typename T> class ParamIteratorInterface { public: virtual ~ParamIteratorInterface() {} // A pointer to the base generator instance. // Used only for the purposes of iterator comparison // to make sure that two iterators belong to the same generator. virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0; // Advances iterator to point to the next element // provided by the generator. The caller is responsible // for not calling Advance() on an iterator equal to // BaseGenerator()->End(). virtual void Advance() = 0; // Clones the iterator object. Used for implementing copy semantics // of ParamIterator<T>. virtual ParamIteratorInterface* Clone() const = 0; // Dereferences the current iterator and provides (read-only) access // to the pointed value. It is the caller's responsibility not to call // Current() on an iterator equal to BaseGenerator()->End(). // Used for implementing ParamGenerator<T>::operator*(). virtual const T* Current() const = 0; // Determines whether the given iterator and other point to the same // element in the sequence generated by the generator. // Used for implementing ParamGenerator<T>::operator==(). virtual bool Equals(const ParamIteratorInterface& other) const = 0; }; // Class iterating over elements provided by an implementation of // ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T> // and implements the const forward iterator concept. template <typename T> class ParamIterator { public: typedef T value_type; typedef const T& reference; typedef ptrdiff_t difference_type; // ParamIterator assumes ownership of the impl_ pointer. ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} ParamIterator& operator=(const ParamIterator& other) { if (this != &other) impl_.reset(other.impl_->Clone()); return *this; } const T& operator*() const { return *impl_->Current(); } const T* operator->() const { return impl_->Current(); } // Prefix version of operator++. ParamIterator& operator++() { impl_->Advance(); return *this; } // Postfix version of operator++. ParamIterator operator++(int /*unused*/) { ParamIteratorInterface<T>* clone = impl_->Clone(); impl_->Advance(); return ParamIterator(clone); } bool operator==(const ParamIterator& other) const { return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); } bool operator!=(const ParamIterator& other) const { return !(*this == other); } private: friend class ParamGenerator<T>; explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {} std::unique_ptr<ParamIteratorInterface<T> > impl_; }; // ParamGeneratorInterface<T> is the binary interface to access generators // defined in other translation units. template <typename T> class ParamGeneratorInterface { public: typedef T ParamType; virtual ~ParamGeneratorInterface() {} // Generator interface definition virtual ParamIteratorInterface<T>* Begin() const = 0; virtual ParamIteratorInterface<T>* End() const = 0; }; // Wraps ParamGeneratorInterface<T> and provides general generator syntax // compatible with the STL Container concept. // This class implements copy initialization semantics and the contained // ParamGeneratorInterface<T> instance is shared among all copies // of the original object. This is possible because that instance is immutable. template<typename T> class ParamGenerator { public: typedef ParamIterator<T> iterator; explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {} ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} ParamGenerator& operator=(const ParamGenerator& other) { impl_ = other.impl_; return *this; } iterator begin() const { return iterator(impl_->Begin()); } iterator end() const { return iterator(impl_->End()); } private: std::shared_ptr<const ParamGeneratorInterface<T> > impl_; }; // Generates values from a range of two comparable values. Can be used to // generate sequences of user-defined types that implement operator+() and // operator<(). // This class is used in the Range() function. template <typename T, typename IncrementT> class RangeGenerator : public ParamGeneratorInterface<T> { public: RangeGenerator(T begin, T end, IncrementT step) : begin_(begin), end_(end), step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} ~RangeGenerator() override {} ParamIteratorInterface<T>* Begin() const override { return new Iterator(this, begin_, 0, step_); } ParamIteratorInterface<T>* End() const override { return new Iterator(this, end_, end_index_, step_); } private: class Iterator : public ParamIteratorInterface<T> { public: Iterator(const ParamGeneratorInterface<T>* base, T value, int index, IncrementT step) : base_(base), value_(value), index_(index), step_(step) {} ~Iterator() override {} const ParamGeneratorInterface<T>* BaseGenerator() const override { return base_; } void Advance() override { value_ = static_cast<T>(value_ + step_); index_++; } ParamIteratorInterface<T>* Clone() const override { return new Iterator(*this); } 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()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const int other_index = CheckedDowncastToActualType<const Iterator>(&other)->index_; return index_ == other_index; } private: Iterator(const Iterator& other) : ParamIteratorInterface<T>(), base_(other.base_), value_(other.value_), index_(other.index_), step_(other.step_) {} // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface<T>* const base_; T value_; int index_; const IncrementT step_; }; // class RangeGenerator::Iterator static int CalculateEndIndex(const T& begin, const T& end, const IncrementT& step) { int end_index = 0; for (T i = begin; i < end; i = static_cast<T>(i + step)) end_index++; return end_index; } // No implementation - assignment is unsupported. void operator=(const RangeGenerator& other); const T begin_; const T end_; const IncrementT step_; // The index for the end() iterator. All the elements in the generated // sequence are indexed (0-based) to aid iterator comparison. const int end_index_; }; // class RangeGenerator // Generates values from a pair of STL-style iterators. Used in the // ValuesIn() function. The elements are copied from the source range // since the source can be located on the stack, and the generator // is likely to persist beyond that stack frame. template <typename T> class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> { public: template <typename ForwardIterator> ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) : container_(begin, end) {} ~ValuesInIteratorRangeGenerator() override {} ParamIteratorInterface<T>* Begin() const override { return new Iterator(this, container_.begin()); } ParamIteratorInterface<T>* End() const override { return new Iterator(this, container_.end()); } private: typedef typename ::std::vector<T> ContainerType; class Iterator : public ParamIteratorInterface<T> { public: Iterator(const ParamGeneratorInterface<T>* base, typename ContainerType::const_iterator iterator) : base_(base), iterator_(iterator) {} ~Iterator() override {} const ParamGeneratorInterface<T>* BaseGenerator() const override { return base_; } void Advance() override { ++iterator_; value_.reset(); } ParamIteratorInterface<T>* Clone() const override { return new Iterator(*this); } // We need to use cached value referenced by iterator_ because *iterator_ // can return a temporary object (and of type other then T), so just // having "return &*iterator_;" doesn't work. // value_ is updated here and not in Advance() because Advance() // 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. const T* Current() const override { if (value_.get() == nullptr) value_.reset(new T(*iterator_)); return value_.get(); } 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()) << "The program attempted to compare iterators " << "from different generators." << std::endl; return iterator_ == CheckedDowncastToActualType<const Iterator>(&other)->iterator_; } private: Iterator(const Iterator& other) // The explicit constructor call suppresses a false warning // emitted by gcc when supplied with the -Wextra option. : ParamIteratorInterface<T>(), base_(other.base_), iterator_(other.iterator_) {} const ParamGeneratorInterface<T>* const base_; typename ContainerType::const_iterator iterator_; // 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 std::unique_ptr helps manage cached value's lifetime, // which is bound by the lifespan of the iterator itself. mutable std::unique_ptr<const T> value_; }; // class ValuesInIteratorRangeGenerator::Iterator // No implementation - assignment is unsupported. void operator=(const ValuesInIteratorRangeGenerator& other); const ContainerType container_; }; // class ValuesInIteratorRangeGenerator // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Default parameterized test name generator, returns a string containing the // integer test parameter index. template <class ParamType> std::string DefaultParamName(const TestParamInfo<ParamType>& info) { Message name_stream; name_stream << info.index; return name_stream.GetString(); } 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. // // Stores a parameter value and later creates tests parameterized with that // value. template <class TestClass> class ParameterizedTestFactory : public TestFactoryBase { public: typedef typename TestClass::ParamType ParamType; explicit ParameterizedTestFactory(ParamType parameter) : parameter_(parameter) {} Test* CreateTest() override { TestClass::SetParam(¶meter_); return new TestClass(); } private: const ParamType parameter_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // TestMetaFactoryBase is a base class for meta-factories that create // test factories for passing into MakeAndRegisterTestInfo function. template <class ParamType> class TestMetaFactoryBase { public: virtual ~TestMetaFactoryBase() {} virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // 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 ParameterizedTestSuiteInfo is going to call // it for each Test/Parameter value combination. Thus it needs meta factory // creator class. template <class TestSuite> class TestMetaFactory : public TestMetaFactoryBase<typename TestSuite::ParamType> { public: using ParamType = typename TestSuite::ParamType; TestMetaFactory() {} TestFactoryBase* CreateTestFactory(ParamType parameter) override { return new ParameterizedTestFactory<TestSuite>(parameter); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // ParameterizedTestSuiteInfoBase is a generic interface // to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase // accumulates test information provided by TEST_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 ParameterizeTestSuiteRegistry class holds // a collection of pointers to the ParameterizedTestSuiteInfo objects // and calls RegisterTests() on each of them when asked. class ParameterizedTestSuiteInfoBase { public: virtual ~ParameterizedTestSuiteInfoBase() {} // Base part of test suite name for display purposes. virtual const std::string& GetTestSuiteName() const = 0; // Test case id to verify identity. virtual TypeId GetTestSuiteTypeId() const = 0; // UnitTest class invokes this method to register tests in this // 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: ParameterizedTestSuiteInfoBase() {} private: GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Report a the name of a test_suit as safe to ignore // as the side effect of construction of this type. struct MarkAsIgnored { explicit MarkAsIgnored(const char* test_suite); }; GTEST_API_ void InsertSyntheticTestCase(const std::string& name, CodeLocation location, bool has_test_p); // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // 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 TestSuite> class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { public: // ParamType and GeneratorCreationFunc are private types but are required // for declarations of public methods AddTestPattern() and // AddTestSuiteInstantiation(). using ParamType = typename TestSuite::ParamType; // A function that returns an instance of appropriate generator type. typedef ParamGenerator<ParamType>(GeneratorCreationFunc)(); using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&); explicit ParameterizedTestSuiteInfo(const char* name, CodeLocation code_location) : test_suite_name_(name), code_location_(code_location) {} // Test case base name for display purposes. const std::string& GetTestSuiteName() const override { return test_suite_name_; } // Test case id to verify identity. TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); } // TEST_P macro uses AddTestPattern() to record information // about a single test in a LocalTestInfo structure. // 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 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(std::shared_ptr<TestInfo>( new TestInfo(test_suite_name, test_base_name, meta_factory))); } // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information // about a generator. 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 suite // 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 { bool generated_instantiations = false; for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { std::shared_ptr<TestInfo> 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<ParamType> 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 + "/"; test_suite_name += test_info->test_suite_base_name; size_t i = 0; std::set<std::string> test_param_names; for (typename ParamGenerator<ParamType>::iterator param_it = generator.begin(); param_it != generator.end(); ++param_it, ++i) { generated_instantiations = true; Message test_name_stream; std::string param_name = name_func( TestParamInfo<ParamType>(*param_it, i)); GTEST_CHECK_(IsValidParamName(param_name)) << "Parameterized test name '" << param_name << "' is invalid, in " << file << " line " << line << std::endl; GTEST_CHECK_(test_param_names.count(param_name) == 0) << "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_stream << test_info->test_base_name << "/"; } test_name_stream << param_name; MakeAndRegisterTestInfo( test_suite_name.c_str(), test_name_stream.GetString().c_str(), nullptr, // No type parameter. 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 if (!generated_instantiations) { // There are no generaotrs, or they all generate nothing ... InsertSyntheticTestCase(GetTestSuiteName(), code_location_, !tests_.empty()); } } // RegisterTests private: // LocalTestInfo structure keeps information about a single test registered // with TEST_P macro. struct TestInfo { 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_suite_base_name; const std::string test_base_name; const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory; }; 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 { InstantiationInfo(const std::string &name_in, GeneratorCreationFunc* generator_in, ParamNameGeneratorFunc* name_func_in, const char* file_in, int line_in) : name(name_in), generator(generator_in), name_func(name_func_in), file(file_in), line(line_in) {} std::string name; GeneratorCreationFunc* generator; ParamNameGeneratorFunc* name_func; const char* file; int line; }; typedef ::std::vector<InstantiationInfo> InstantiationContainer; static bool IsValidParamName(const std::string& name) { // Check for empty string if (name.empty()) return false; // Check for invalid characters for (std::string::size_type index = 0; index < name.size(); ++index) { if (!isalnum(name[index]) && name[index] != '_') return false; } return true; } const std::string test_suite_name_; CodeLocation code_location_; TestInfoContainer tests_; InstantiationContainer instantiations_; 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. // // 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: 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 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 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<TestSuite> >(test_suite_info); } break; } } 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 (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); }; // Keep track of what type-parameterized test suite are defined and // where as well as which are intatiated. This allows susequently // identifying suits that are defined but never used. class TypeParameterizedTestSuiteRegistry { public: // Add a suite definition void RegisterTestSuite(const char* test_suite_name, CodeLocation code_location); // Add an instantiation of a suit. void RegisterInstantiation(const char* test_suite_name); // For each suit repored as defined but not reported as instantiation, // emit a test that reports that fact (configurably, as an error). void CheckForInstantiations(); private: struct TypeParameterizedTestSuiteInfo { explicit TypeParameterizedTestSuiteInfo(CodeLocation c) : code_location(c), instantiated(false) {} CodeLocation code_location; bool instantiated; }; std::map<std::string, TypeParameterizedTestSuiteInfo> suites_; }; } // namespace internal // Forward declarations of ValuesIn(), which is implemented in // 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: template <typename T, size_t... I> std::vector<T> MakeVector(IndexSequence<I...>) const { return std::vector<T>{static_cast<T>(v_.template Get<I>())...}; } FlatTuple<Ts...> v_; }; 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 } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_