1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030 |
- // 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.
- // IWYU pragma: private, include "gtest/gtest.h"
- // IWYU pragma: friend gtest/.*
- // IWYU pragma: friend gmock/.*
- #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
- #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
- #include <ctype.h>
- #include <cassert>
- #include <iterator>
- #include <map>
- #include <memory>
- #include <ostream>
- #include <set>
- #include <string>
- #include <tuple>
- #include <type_traits>
- #include <unordered_map>
- #include <utility>
- #include <vector>
- #include "gtest/gtest-printers.h"
- #include "gtest/gtest-test-part.h"
- #include "gtest/internal/gtest-internal.h"
- #include "gtest/internal/gtest-port.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,
- const 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() = default;
- // 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() = default;
- // 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 = default;
- 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 = default;
- 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 = default;
- 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 = default;
- 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) {
- return std::to_string(info.index);
- }
- 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_;
- ParameterizedTestFactory(const ParameterizedTestFactory&) = delete;
- ParameterizedTestFactory& operator=(const ParameterizedTestFactory&) = delete;
- };
- // 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() = default;
- 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() = default;
- TestFactoryBase* CreateTestFactory(ParamType parameter) override {
- return new ParameterizedTestFactory<TestSuite>(parameter);
- }
- private:
- TestMetaFactory(const TestMetaFactory&) = delete;
- TestMetaFactory& operator=(const TestMetaFactory&) = delete;
- };
- // 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() = default;
- // Base part of test suite name for display purposes.
- virtual const std::string& GetTestSuiteName() const = 0;
- // Test suite 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:
- ParameterizedTestSuiteInfoBase(const ParameterizedTestSuiteInfoBase&) =
- delete;
- ParameterizedTestSuiteInfoBase& operator=(
- const ParameterizedTestSuiteInfoBase&) = delete;
- };
- // 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 GTEST_API_ 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(std::string name,
- CodeLocation code_location)
- : test_suite_name_(std::move(name)),
- code_location_(std::move(code_location)) {}
- // Test suite base name for display purposes.
- const std::string& GetTestSuiteName() const override {
- return test_suite_name_;
- }
- // Test suite 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*,
- const char* test_base_name,
- TestMetaFactoryBase<ParamType>* meta_factory,
- CodeLocation code_location) {
- tests_.emplace_back(
- new TestInfo(test_base_name, meta_factory, std::move(code_location)));
- }
- // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
- // about a generator.
- int AddTestSuiteInstantiation(std::string instantiation_name,
- GeneratorCreationFunc* func,
- ParamNameGeneratorFunc* name_func,
- const char* file, int line) {
- instantiations_.emplace_back(std::move(instantiation_name), func, name_func,
- file, line);
- 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;
- std::string test_suite_name;
- std::string test_name;
- for (const std::shared_ptr<TestInfo>& test_info : tests_) {
- for (const InstantiationInfo& instantiation : instantiations_) {
- const std::string& instantiation_name = instantiation.name;
- ParamGenerator<ParamType> generator((*instantiation.generator)());
- ParamNameGeneratorFunc* name_func = instantiation.name_func;
- const char* file = instantiation.file;
- int line = instantiation.line;
- if (!instantiation_name.empty())
- test_suite_name = instantiation_name + "/";
- else
- test_suite_name.clear();
- test_suite_name += test_suite_name_;
- size_t i = 0;
- std::set<std::string> test_param_names;
- for (const auto& param : generator) {
- generated_instantiations = true;
- test_name.clear();
- std::string param_name =
- name_func(TestParamInfo<ParamType>(param, i));
- GTEST_CHECK_(IsValidParamName(param_name))
- << "Parameterized test name '" << param_name
- << "' is invalid (contains spaces, dashes, or any "
- "non-alphanumeric characters other than underscores), 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;
- if (!test_info->test_base_name.empty()) {
- test_name.append(test_info->test_base_name).append("/");
- }
- test_name += param_name;
- test_param_names.insert(std::move(param_name));
- MakeAndRegisterTestInfo(
- test_suite_name, test_name.c_str(),
- nullptr, // No type parameter.
- PrintToString(param).c_str(), test_info->code_location,
- GetTestSuiteTypeId(),
- SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
- SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
- test_info->test_meta_factory->CreateTestFactory(param));
- ++i;
- } // for param
- } // for instantiation
- } // for test_info
- 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_base_name,
- TestMetaFactoryBase<ParamType>* a_test_meta_factory,
- CodeLocation a_code_location)
- : test_base_name(a_test_base_name),
- test_meta_factory(a_test_meta_factory),
- code_location(std::move(a_code_location)) {}
- const std::string test_base_name;
- const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
- const CodeLocation code_location;
- };
- 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(std::string name_in, GeneratorCreationFunc* generator_in,
- ParamNameGeneratorFunc* name_func_in, const char* file_in,
- int line_in)
- : name(std::move(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_;
- ParameterizedTestSuiteInfo(const ParameterizedTestSuiteInfo&) = delete;
- ParameterizedTestSuiteInfo& operator=(const ParameterizedTestSuiteInfo&) =
- delete;
- }; // 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() = default;
- ~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(
- std::string test_suite_name, CodeLocation code_location) {
- ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
- auto item_it = suite_name_to_info_index_.find(test_suite_name);
- if (item_it != suite_name_to_info_index_.end()) {
- auto* test_suite_info = test_suite_infos_[item_it->second];
- if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<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.c_str(), code_location);
- posix::Abort();
- } else {
- // At this point we are sure that the object we found is of the same
- // type we are looking for, so we downcast it to that type
- // without further checks.
- typed_test_info =
- CheckedDowncastToActualType<ParameterizedTestSuiteInfo<TestSuite>>(
- test_suite_info);
- }
- }
- if (typed_test_info == nullptr) {
- typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
- test_suite_name, std::move(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);
- }
- 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(
- std::string test_case_name, CodeLocation code_location) {
- return GetTestSuitePatternHolder<TestCase>(std::move(test_case_name),
- std::move(code_location));
- }
- #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- private:
- using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
- TestSuiteInfoContainer test_suite_infos_;
- ::std::unordered_map<std::string, size_t> suite_name_to_info_index_;
- ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) =
- delete;
- ParameterizedTestSuiteRegistry& operator=(
- const ParameterizedTestSuiteRegistry&) = delete;
- };
- // 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(std::move(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.
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
- template <typename... Ts>
- class ValueArray {
- public:
- explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
- template <typename T>
- operator ParamGenerator<T>() const { // NOLINT
- return ValuesIn(MakeVector<T>(std::make_index_sequence<sizeof...(Ts)>()));
- }
- private:
- template <typename T, size_t... I>
- std::vector<T> MakeVector(std::index_sequence<I...>) const {
- return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
- }
- FlatTuple<Ts...> v_;
- };
- GTEST_DISABLE_MSC_WARNINGS_POP_() // 4100
- 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 = default;
- 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<std::index_sequence<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 = default;
- 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<std::make_index_sequence<sizeof...(T)>>;
- 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_;
- };
- template <typename From, typename To>
- class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
- public:
- ParamGeneratorConverter(ParamGenerator<From> gen) // NOLINT
- : generator_(std::move(gen)) {}
- ParamIteratorInterface<To>* Begin() const override {
- return new Iterator(this, generator_.begin(), generator_.end());
- }
- ParamIteratorInterface<To>* End() const override {
- return new Iterator(this, generator_.end(), generator_.end());
- }
- private:
- class Iterator : public ParamIteratorInterface<To> {
- public:
- Iterator(const ParamGeneratorInterface<To>* base, ParamIterator<From> it,
- ParamIterator<From> end)
- : base_(base), it_(it), end_(end) {
- if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
- }
- ~Iterator() override = default;
- const ParamGeneratorInterface<To>* BaseGenerator() const override {
- return base_;
- }
- void Advance() override {
- ++it_;
- if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
- }
- ParamIteratorInterface<To>* Clone() const override {
- return new Iterator(*this);
- }
- const To* Current() const override { return value_.get(); }
- bool Equals(const ParamIteratorInterface<To>& 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 ParamIterator<From> other_it =
- CheckedDowncastToActualType<const Iterator>(&other)->it_;
- return it_ == other_it;
- }
- private:
- Iterator(const Iterator& other) = default;
- const ParamGeneratorInterface<To>* const base_;
- ParamIterator<From> it_;
- ParamIterator<From> end_;
- std::shared_ptr<To> value_;
- }; // class ParamGeneratorConverter::Iterator
- ParamGenerator<From> generator_;
- }; // class ParamGeneratorConverter
- template <class Gen>
- class ParamConverterGenerator {
- public:
- ParamConverterGenerator(ParamGenerator<Gen> g) // NOLINT
- : generator_(std::move(g)) {}
- template <typename T>
- operator ParamGenerator<T>() const { // NOLINT
- return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator_));
- }
- private:
- ParamGenerator<Gen> generator_;
- };
- } // namespace internal
- } // namespace testing
- #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|