File indexing completed on 2025-03-13 09:14:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
0037 #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
0038
0039 #include <ctype.h>
0040
0041 #include <cassert>
0042 #include <iterator>
0043 #include <memory>
0044 #include <set>
0045 #include <tuple>
0046 #include <type_traits>
0047 #include <utility>
0048 #include <vector>
0049
0050 #include "gtest/gtest-printers.h"
0051 #include "gtest/gtest-test-part.h"
0052 #include "gtest/internal/gtest-internal.h"
0053 #include "gtest/internal/gtest-port.h"
0054
0055 namespace testing {
0056
0057
0058 template <class ParamType>
0059 struct TestParamInfo {
0060 TestParamInfo(const ParamType& a_param, size_t an_index)
0061 : param(a_param), index(an_index) {}
0062 ParamType param;
0063 size_t index;
0064 };
0065
0066
0067
0068 struct PrintToStringParamName {
0069 template <class ParamType>
0070 std::string operator()(const TestParamInfo<ParamType>& info) const {
0071 return PrintToString(info.param);
0072 }
0073 };
0074
0075 namespace internal {
0076
0077
0078
0079
0080
0081
0082
0083
0084 GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
0085 CodeLocation code_location);
0086
0087 template <typename>
0088 class ParamGeneratorInterface;
0089 template <typename>
0090 class ParamGenerator;
0091
0092
0093
0094 template <typename T>
0095 class ParamIteratorInterface {
0096 public:
0097 virtual ~ParamIteratorInterface() {}
0098
0099
0100
0101 virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
0102
0103
0104
0105
0106 virtual void Advance() = 0;
0107
0108
0109 virtual ParamIteratorInterface* Clone() const = 0;
0110
0111
0112
0113
0114 virtual const T* Current() const = 0;
0115
0116
0117
0118 virtual bool Equals(const ParamIteratorInterface& other) const = 0;
0119 };
0120
0121
0122
0123
0124 template <typename T>
0125 class ParamIterator {
0126 public:
0127 typedef T value_type;
0128 typedef const T& reference;
0129 typedef ptrdiff_t difference_type;
0130
0131
0132 ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
0133 ParamIterator& operator=(const ParamIterator& other) {
0134 if (this != &other) impl_.reset(other.impl_->Clone());
0135 return *this;
0136 }
0137
0138 const T& operator*() const { return *impl_->Current(); }
0139 const T* operator->() const { return impl_->Current(); }
0140
0141 ParamIterator& operator++() {
0142 impl_->Advance();
0143 return *this;
0144 }
0145
0146 ParamIterator operator++(int ) {
0147 ParamIteratorInterface<T>* clone = impl_->Clone();
0148 impl_->Advance();
0149 return ParamIterator(clone);
0150 }
0151 bool operator==(const ParamIterator& other) const {
0152 return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
0153 }
0154 bool operator!=(const ParamIterator& other) const {
0155 return !(*this == other);
0156 }
0157
0158 private:
0159 friend class ParamGenerator<T>;
0160 explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
0161 std::unique_ptr<ParamIteratorInterface<T>> impl_;
0162 };
0163
0164
0165
0166 template <typename T>
0167 class ParamGeneratorInterface {
0168 public:
0169 typedef T ParamType;
0170
0171 virtual ~ParamGeneratorInterface() {}
0172
0173
0174 virtual ParamIteratorInterface<T>* Begin() const = 0;
0175 virtual ParamIteratorInterface<T>* End() const = 0;
0176 };
0177
0178
0179
0180
0181
0182
0183 template <typename T>
0184 class ParamGenerator {
0185 public:
0186 typedef ParamIterator<T> iterator;
0187
0188 explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
0189 ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
0190
0191 ParamGenerator& operator=(const ParamGenerator& other) {
0192 impl_ = other.impl_;
0193 return *this;
0194 }
0195
0196 iterator begin() const { return iterator(impl_->Begin()); }
0197 iterator end() const { return iterator(impl_->End()); }
0198
0199 private:
0200 std::shared_ptr<const ParamGeneratorInterface<T>> impl_;
0201 };
0202
0203
0204
0205
0206
0207 template <typename T, typename IncrementT>
0208 class RangeGenerator : public ParamGeneratorInterface<T> {
0209 public:
0210 RangeGenerator(T begin, T end, IncrementT step)
0211 : begin_(begin),
0212 end_(end),
0213 step_(step),
0214 end_index_(CalculateEndIndex(begin, end, step)) {}
0215 ~RangeGenerator() override {}
0216
0217 ParamIteratorInterface<T>* Begin() const override {
0218 return new Iterator(this, begin_, 0, step_);
0219 }
0220 ParamIteratorInterface<T>* End() const override {
0221 return new Iterator(this, end_, end_index_, step_);
0222 }
0223
0224 private:
0225 class Iterator : public ParamIteratorInterface<T> {
0226 public:
0227 Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
0228 IncrementT step)
0229 : base_(base), value_(value), index_(index), step_(step) {}
0230 ~Iterator() override {}
0231
0232 const ParamGeneratorInterface<T>* BaseGenerator() const override {
0233 return base_;
0234 }
0235 void Advance() override {
0236 value_ = static_cast<T>(value_ + step_);
0237 index_++;
0238 }
0239 ParamIteratorInterface<T>* Clone() const override {
0240 return new Iterator(*this);
0241 }
0242 const T* Current() const override { return &value_; }
0243 bool Equals(const ParamIteratorInterface<T>& other) const override {
0244
0245
0246 GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
0247 << "The program attempted to compare iterators "
0248 << "from different generators." << std::endl;
0249 const int other_index =
0250 CheckedDowncastToActualType<const Iterator>(&other)->index_;
0251 return index_ == other_index;
0252 }
0253
0254 private:
0255 Iterator(const Iterator& other)
0256 : ParamIteratorInterface<T>(),
0257 base_(other.base_),
0258 value_(other.value_),
0259 index_(other.index_),
0260 step_(other.step_) {}
0261
0262
0263 void operator=(const Iterator& other);
0264
0265 const ParamGeneratorInterface<T>* const base_;
0266 T value_;
0267 int index_;
0268 const IncrementT step_;
0269 };
0270
0271 static int CalculateEndIndex(const T& begin, const T& end,
0272 const IncrementT& step) {
0273 int end_index = 0;
0274 for (T i = begin; i < end; i = static_cast<T>(i + step)) end_index++;
0275 return end_index;
0276 }
0277
0278
0279 void operator=(const RangeGenerator& other);
0280
0281 const T begin_;
0282 const T end_;
0283 const IncrementT step_;
0284
0285
0286 const int end_index_;
0287 };
0288
0289
0290
0291
0292
0293 template <typename T>
0294 class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
0295 public:
0296 template <typename ForwardIterator>
0297 ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
0298 : container_(begin, end) {}
0299 ~ValuesInIteratorRangeGenerator() override {}
0300
0301 ParamIteratorInterface<T>* Begin() const override {
0302 return new Iterator(this, container_.begin());
0303 }
0304 ParamIteratorInterface<T>* End() const override {
0305 return new Iterator(this, container_.end());
0306 }
0307
0308 private:
0309 typedef typename ::std::vector<T> ContainerType;
0310
0311 class Iterator : public ParamIteratorInterface<T> {
0312 public:
0313 Iterator(const ParamGeneratorInterface<T>* base,
0314 typename ContainerType::const_iterator iterator)
0315 : base_(base), iterator_(iterator) {}
0316 ~Iterator() override {}
0317
0318 const ParamGeneratorInterface<T>* BaseGenerator() const override {
0319 return base_;
0320 }
0321 void Advance() override {
0322 ++iterator_;
0323 value_.reset();
0324 }
0325 ParamIteratorInterface<T>* Clone() const override {
0326 return new Iterator(*this);
0327 }
0328
0329
0330
0331
0332
0333
0334
0335 const T* Current() const override {
0336 if (value_.get() == nullptr) value_.reset(new T(*iterator_));
0337 return value_.get();
0338 }
0339 bool Equals(const ParamIteratorInterface<T>& other) const override {
0340
0341
0342 GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
0343 << "The program attempted to compare iterators "
0344 << "from different generators." << std::endl;
0345 return iterator_ ==
0346 CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
0347 }
0348
0349 private:
0350 Iterator(const Iterator& other)
0351
0352
0353 : ParamIteratorInterface<T>(),
0354 base_(other.base_),
0355 iterator_(other.iterator_) {}
0356
0357 const ParamGeneratorInterface<T>* const base_;
0358 typename ContainerType::const_iterator iterator_;
0359
0360
0361
0362
0363
0364 mutable std::unique_ptr<const T> value_;
0365 };
0366
0367
0368 void operator=(const ValuesInIteratorRangeGenerator& other);
0369
0370 const ContainerType container_;
0371 };
0372
0373
0374
0375
0376
0377 template <class ParamType>
0378 std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
0379 Message name_stream;
0380 name_stream << info.index;
0381 return name_stream.GetString();
0382 }
0383
0384 template <typename T = int>
0385 void TestNotEmpty() {
0386 static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
0387 }
0388 template <typename T = int>
0389 void TestNotEmpty(const T&) {}
0390
0391
0392
0393
0394
0395 template <class TestClass>
0396 class ParameterizedTestFactory : public TestFactoryBase {
0397 public:
0398 typedef typename TestClass::ParamType ParamType;
0399 explicit ParameterizedTestFactory(ParamType parameter)
0400 : parameter_(parameter) {}
0401 Test* CreateTest() override {
0402 TestClass::SetParam(¶meter_);
0403 return new TestClass();
0404 }
0405
0406 private:
0407 const ParamType parameter_;
0408
0409 ParameterizedTestFactory(const ParameterizedTestFactory&) = delete;
0410 ParameterizedTestFactory& operator=(const ParameterizedTestFactory&) = delete;
0411 };
0412
0413
0414
0415
0416
0417 template <class ParamType>
0418 class TestMetaFactoryBase {
0419 public:
0420 virtual ~TestMetaFactoryBase() {}
0421
0422 virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
0423 };
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433 template <class TestSuite>
0434 class TestMetaFactory
0435 : public TestMetaFactoryBase<typename TestSuite::ParamType> {
0436 public:
0437 using ParamType = typename TestSuite::ParamType;
0438
0439 TestMetaFactory() {}
0440
0441 TestFactoryBase* CreateTestFactory(ParamType parameter) override {
0442 return new ParameterizedTestFactory<TestSuite>(parameter);
0443 }
0444
0445 private:
0446 TestMetaFactory(const TestMetaFactory&) = delete;
0447 TestMetaFactory& operator=(const TestMetaFactory&) = delete;
0448 };
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460 class ParameterizedTestSuiteInfoBase {
0461 public:
0462 virtual ~ParameterizedTestSuiteInfoBase() {}
0463
0464
0465 virtual const std::string& GetTestSuiteName() const = 0;
0466
0467 virtual TypeId GetTestSuiteTypeId() const = 0;
0468
0469
0470
0471
0472 virtual void RegisterTests() = 0;
0473
0474 protected:
0475 ParameterizedTestSuiteInfoBase() {}
0476
0477 private:
0478 ParameterizedTestSuiteInfoBase(const ParameterizedTestSuiteInfoBase&) =
0479 delete;
0480 ParameterizedTestSuiteInfoBase& operator=(
0481 const ParameterizedTestSuiteInfoBase&) = delete;
0482 };
0483
0484
0485
0486
0487
0488 struct GTEST_API_ MarkAsIgnored {
0489 explicit MarkAsIgnored(const char* test_suite);
0490 };
0491
0492 GTEST_API_ void InsertSyntheticTestCase(const std::string& name,
0493 CodeLocation location, bool has_test_p);
0494
0495
0496
0497
0498
0499
0500
0501
0502 template <class TestSuite>
0503 class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
0504 public:
0505
0506
0507
0508 using ParamType = typename TestSuite::ParamType;
0509
0510 typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
0511 using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
0512
0513 explicit ParameterizedTestSuiteInfo(const char* name,
0514 CodeLocation code_location)
0515 : test_suite_name_(name), code_location_(code_location) {}
0516
0517
0518 const std::string& GetTestSuiteName() const override {
0519 return test_suite_name_;
0520 }
0521
0522 TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
0523
0524
0525
0526
0527
0528
0529 void AddTestPattern(const char* test_suite_name, const char* test_base_name,
0530 TestMetaFactoryBase<ParamType>* meta_factory,
0531 CodeLocation code_location) {
0532 tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo(
0533 test_suite_name, test_base_name, meta_factory, code_location)));
0534 }
0535
0536
0537 int AddTestSuiteInstantiation(const std::string& instantiation_name,
0538 GeneratorCreationFunc* func,
0539 ParamNameGeneratorFunc* name_func,
0540 const char* file, int line) {
0541 instantiations_.push_back(
0542 InstantiationInfo(instantiation_name, func, name_func, file, line));
0543 return 0;
0544 }
0545
0546
0547
0548
0549
0550 void RegisterTests() override {
0551 bool generated_instantiations = false;
0552
0553 for (typename TestInfoContainer::iterator test_it = tests_.begin();
0554 test_it != tests_.end(); ++test_it) {
0555 std::shared_ptr<TestInfo> test_info = *test_it;
0556 for (typename InstantiationContainer::iterator gen_it =
0557 instantiations_.begin();
0558 gen_it != instantiations_.end(); ++gen_it) {
0559 const std::string& instantiation_name = gen_it->name;
0560 ParamGenerator<ParamType> generator((*gen_it->generator)());
0561 ParamNameGeneratorFunc* name_func = gen_it->name_func;
0562 const char* file = gen_it->file;
0563 int line = gen_it->line;
0564
0565 std::string test_suite_name;
0566 if (!instantiation_name.empty())
0567 test_suite_name = instantiation_name + "/";
0568 test_suite_name += test_info->test_suite_base_name;
0569
0570 size_t i = 0;
0571 std::set<std::string> test_param_names;
0572 for (typename ParamGenerator<ParamType>::iterator param_it =
0573 generator.begin();
0574 param_it != generator.end(); ++param_it, ++i) {
0575 generated_instantiations = true;
0576
0577 Message test_name_stream;
0578
0579 std::string param_name =
0580 name_func(TestParamInfo<ParamType>(*param_it, i));
0581
0582 GTEST_CHECK_(IsValidParamName(param_name))
0583 << "Parameterized test name '" << param_name
0584 << "' is invalid, in " << file << " line " << line << std::endl;
0585
0586 GTEST_CHECK_(test_param_names.count(param_name) == 0)
0587 << "Duplicate parameterized test name '" << param_name << "', in "
0588 << file << " line " << line << std::endl;
0589
0590 test_param_names.insert(param_name);
0591
0592 if (!test_info->test_base_name.empty()) {
0593 test_name_stream << test_info->test_base_name << "/";
0594 }
0595 test_name_stream << param_name;
0596 MakeAndRegisterTestInfo(
0597 test_suite_name.c_str(), test_name_stream.GetString().c_str(),
0598 nullptr,
0599 PrintToString(*param_it).c_str(), test_info->code_location,
0600 GetTestSuiteTypeId(),
0601 SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
0602 SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
0603 test_info->test_meta_factory->CreateTestFactory(*param_it));
0604 }
0605 }
0606 }
0607
0608 if (!generated_instantiations) {
0609
0610 InsertSyntheticTestCase(GetTestSuiteName(), code_location_,
0611 !tests_.empty());
0612 }
0613 }
0614
0615 private:
0616
0617
0618 struct TestInfo {
0619 TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
0620 TestMetaFactoryBase<ParamType>* a_test_meta_factory,
0621 CodeLocation a_code_location)
0622 : test_suite_base_name(a_test_suite_base_name),
0623 test_base_name(a_test_base_name),
0624 test_meta_factory(a_test_meta_factory),
0625 code_location(a_code_location) {}
0626
0627 const std::string test_suite_base_name;
0628 const std::string test_base_name;
0629 const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
0630 const CodeLocation code_location;
0631 };
0632 using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo>>;
0633
0634
0635
0636 struct InstantiationInfo {
0637 InstantiationInfo(const std::string& name_in,
0638 GeneratorCreationFunc* generator_in,
0639 ParamNameGeneratorFunc* name_func_in, const char* file_in,
0640 int line_in)
0641 : name(name_in),
0642 generator(generator_in),
0643 name_func(name_func_in),
0644 file(file_in),
0645 line(line_in) {}
0646
0647 std::string name;
0648 GeneratorCreationFunc* generator;
0649 ParamNameGeneratorFunc* name_func;
0650 const char* file;
0651 int line;
0652 };
0653 typedef ::std::vector<InstantiationInfo> InstantiationContainer;
0654
0655 static bool IsValidParamName(const std::string& name) {
0656
0657 if (name.empty()) return false;
0658
0659
0660 for (std::string::size_type index = 0; index < name.size(); ++index) {
0661 if (!IsAlNum(name[index]) && name[index] != '_') return false;
0662 }
0663
0664 return true;
0665 }
0666
0667 const std::string test_suite_name_;
0668 CodeLocation code_location_;
0669 TestInfoContainer tests_;
0670 InstantiationContainer instantiations_;
0671
0672 ParameterizedTestSuiteInfo(const ParameterizedTestSuiteInfo&) = delete;
0673 ParameterizedTestSuiteInfo& operator=(const ParameterizedTestSuiteInfo&) =
0674 delete;
0675 };
0676
0677
0678 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
0679 template <class TestCase>
0680 using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
0681 #endif
0682
0683
0684
0685
0686
0687
0688
0689 class ParameterizedTestSuiteRegistry {
0690 public:
0691 ParameterizedTestSuiteRegistry() {}
0692 ~ParameterizedTestSuiteRegistry() {
0693 for (auto& test_suite_info : test_suite_infos_) {
0694 delete test_suite_info;
0695 }
0696 }
0697
0698
0699
0700 template <class TestSuite>
0701 ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
0702 const char* test_suite_name, CodeLocation code_location) {
0703 ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
0704 for (auto& test_suite_info : test_suite_infos_) {
0705 if (test_suite_info->GetTestSuiteName() == test_suite_name) {
0706 if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
0707
0708
0709
0710 ReportInvalidTestSuiteType(test_suite_name, code_location);
0711 posix::Abort();
0712 } else {
0713
0714
0715
0716 typed_test_info = CheckedDowncastToActualType<
0717 ParameterizedTestSuiteInfo<TestSuite>>(test_suite_info);
0718 }
0719 break;
0720 }
0721 }
0722 if (typed_test_info == nullptr) {
0723 typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
0724 test_suite_name, code_location);
0725 test_suite_infos_.push_back(typed_test_info);
0726 }
0727 return typed_test_info;
0728 }
0729 void RegisterTests() {
0730 for (auto& test_suite_info : test_suite_infos_) {
0731 test_suite_info->RegisterTests();
0732 }
0733 }
0734
0735 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
0736 template <class TestCase>
0737 ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
0738 const char* test_case_name, CodeLocation code_location) {
0739 return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
0740 }
0741
0742 #endif
0743
0744 private:
0745 using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
0746
0747 TestSuiteInfoContainer test_suite_infos_;
0748
0749 ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) =
0750 delete;
0751 ParameterizedTestSuiteRegistry& operator=(
0752 const ParameterizedTestSuiteRegistry&) = delete;
0753 };
0754
0755
0756
0757
0758 class TypeParameterizedTestSuiteRegistry {
0759 public:
0760
0761 void RegisterTestSuite(const char* test_suite_name,
0762 CodeLocation code_location);
0763
0764
0765 void RegisterInstantiation(const char* test_suite_name);
0766
0767
0768
0769 void CheckForInstantiations();
0770
0771 private:
0772 struct TypeParameterizedTestSuiteInfo {
0773 explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
0774 : code_location(c), instantiated(false) {}
0775
0776 CodeLocation code_location;
0777 bool instantiated;
0778 };
0779
0780 std::map<std::string, TypeParameterizedTestSuiteInfo> suites_;
0781 };
0782
0783 }
0784
0785
0786
0787 template <class Container>
0788 internal::ParamGenerator<typename Container::value_type> ValuesIn(
0789 const Container& container);
0790
0791 namespace internal {
0792
0793
0794 #ifdef _MSC_VER
0795 #pragma warning(push)
0796 #pragma warning(disable : 4100)
0797 #endif
0798
0799 template <typename... Ts>
0800 class ValueArray {
0801 public:
0802 explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
0803
0804 template <typename T>
0805 operator ParamGenerator<T>() const {
0806 return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
0807 }
0808
0809 private:
0810 template <typename T, size_t... I>
0811 std::vector<T> MakeVector(IndexSequence<I...>) const {
0812 return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
0813 }
0814
0815 FlatTuple<Ts...> v_;
0816 };
0817
0818 #ifdef _MSC_VER
0819 #pragma warning(pop)
0820 #endif
0821
0822 template <typename... T>
0823 class CartesianProductGenerator
0824 : public ParamGeneratorInterface<::std::tuple<T...>> {
0825 public:
0826 typedef ::std::tuple<T...> ParamType;
0827
0828 CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
0829 : generators_(g) {}
0830 ~CartesianProductGenerator() override {}
0831
0832 ParamIteratorInterface<ParamType>* Begin() const override {
0833 return new Iterator(this, generators_, false);
0834 }
0835 ParamIteratorInterface<ParamType>* End() const override {
0836 return new Iterator(this, generators_, true);
0837 }
0838
0839 private:
0840 template <class I>
0841 class IteratorImpl;
0842 template <size_t... I>
0843 class IteratorImpl<IndexSequence<I...>>
0844 : public ParamIteratorInterface<ParamType> {
0845 public:
0846 IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
0847 const std::tuple<ParamGenerator<T>...>& generators,
0848 bool is_end)
0849 : base_(base),
0850 begin_(std::get<I>(generators).begin()...),
0851 end_(std::get<I>(generators).end()...),
0852 current_(is_end ? end_ : begin_) {
0853 ComputeCurrentValue();
0854 }
0855 ~IteratorImpl() override {}
0856
0857 const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
0858 return base_;
0859 }
0860
0861
0862 void Advance() override {
0863 assert(!AtEnd());
0864
0865 ++std::get<sizeof...(T) - 1>(current_);
0866
0867 AdvanceIfEnd<sizeof...(T) - 1>();
0868 ComputeCurrentValue();
0869 }
0870 ParamIteratorInterface<ParamType>* Clone() const override {
0871 return new IteratorImpl(*this);
0872 }
0873
0874 const ParamType* Current() const override { return current_value_.get(); }
0875
0876 bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
0877
0878
0879 GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
0880 << "The program attempted to compare iterators "
0881 << "from different generators." << std::endl;
0882 const IteratorImpl* typed_other =
0883 CheckedDowncastToActualType<const IteratorImpl>(&other);
0884
0885
0886
0887
0888 if (AtEnd() && typed_other->AtEnd()) return true;
0889
0890 bool same = true;
0891 bool dummy[] = {
0892 (same = same && std::get<I>(current_) ==
0893 std::get<I>(typed_other->current_))...};
0894 (void)dummy;
0895 return same;
0896 }
0897
0898 private:
0899 template <size_t ThisI>
0900 void AdvanceIfEnd() {
0901 if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;
0902
0903 bool last = ThisI == 0;
0904 if (last) {
0905
0906 return;
0907 }
0908
0909 constexpr size_t NextI = ThisI - (ThisI != 0);
0910 std::get<ThisI>(current_) = std::get<ThisI>(begin_);
0911 ++std::get<NextI>(current_);
0912 AdvanceIfEnd<NextI>();
0913 }
0914
0915 void ComputeCurrentValue() {
0916 if (!AtEnd())
0917 current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
0918 }
0919 bool AtEnd() const {
0920 bool at_end = false;
0921 bool dummy[] = {
0922 (at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
0923 (void)dummy;
0924 return at_end;
0925 }
0926
0927 const ParamGeneratorInterface<ParamType>* const base_;
0928 std::tuple<typename ParamGenerator<T>::iterator...> begin_;
0929 std::tuple<typename ParamGenerator<T>::iterator...> end_;
0930 std::tuple<typename ParamGenerator<T>::iterator...> current_;
0931 std::shared_ptr<ParamType> current_value_;
0932 };
0933
0934 using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
0935
0936 std::tuple<ParamGenerator<T>...> generators_;
0937 };
0938
0939 template <class... Gen>
0940 class CartesianProductHolder {
0941 public:
0942 CartesianProductHolder(const Gen&... g) : generators_(g...) {}
0943 template <typename... T>
0944 operator ParamGenerator<::std::tuple<T...>>() const {
0945 return ParamGenerator<::std::tuple<T...>>(
0946 new CartesianProductGenerator<T...>(generators_));
0947 }
0948
0949 private:
0950 std::tuple<Gen...> generators_;
0951 };
0952
0953 }
0954 }
0955
0956 #endif