00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
00035 #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
00036
00037 #include <ctype.h>
00038
00039 #include <iterator>
00040 #include <set>
00041 #include <utility>
00042 #include <vector>
00043
00044
00045
00046
00047 #include "gtest/internal/gtest-internal.h"
00048 #include "gtest/internal/gtest-linked_ptr.h"
00049 #include "gtest/internal/gtest-port.h"
00050 #include "gtest/gtest-printers.h"
00051
00052 #if GTEST_HAS_PARAM_TEST
00053
00054 namespace testing {
00055
00056
00057
00058 template <class ParamType>
00059 struct TestParamInfo {
00060 TestParamInfo(const ParamType& a_param, size_t an_index) :
00061 param(a_param),
00062 index(an_index) {}
00063 ParamType param;
00064 size_t index;
00065 };
00066
00067
00068
00069 struct PrintToStringParamName {
00070 template <class ParamType>
00071 std::string operator()(const TestParamInfo<ParamType>& info) const {
00072 return PrintToString(info.param);
00073 }
00074 };
00075
00076 namespace internal {
00077
00078
00079
00080
00081
00082
00083
00084 GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
00085 CodeLocation code_location);
00086
00087 template <typename> class ParamGeneratorInterface;
00088 template <typename> class ParamGenerator;
00089
00090
00091
00092 template <typename T>
00093 class ParamIteratorInterface {
00094 public:
00095 virtual ~ParamIteratorInterface() {}
00096
00097
00098
00099 virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
00100
00101
00102
00103
00104 virtual void Advance() = 0;
00105
00106
00107 virtual ParamIteratorInterface* Clone() const = 0;
00108
00109
00110
00111
00112 virtual const T* Current() const = 0;
00113
00114
00115
00116 virtual bool Equals(const ParamIteratorInterface& other) const = 0;
00117 };
00118
00119
00120
00121
00122 template <typename T>
00123 class ParamIterator {
00124 public:
00125 typedef T value_type;
00126 typedef const T& reference;
00127 typedef ptrdiff_t difference_type;
00128
00129
00130 ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
00131 ParamIterator& operator=(const ParamIterator& other) {
00132 if (this != &other)
00133 impl_.reset(other.impl_->Clone());
00134 return *this;
00135 }
00136
00137 const T& operator*() const { return *impl_->Current(); }
00138 const T* operator->() const { return impl_->Current(); }
00139
00140 ParamIterator& operator++() {
00141 impl_->Advance();
00142 return *this;
00143 }
00144
00145 ParamIterator operator++(int ) {
00146 ParamIteratorInterface<T>* clone = impl_->Clone();
00147 impl_->Advance();
00148 return ParamIterator(clone);
00149 }
00150 bool operator==(const ParamIterator& other) const {
00151 return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
00152 }
00153 bool operator!=(const ParamIterator& other) const {
00154 return !(*this == other);
00155 }
00156
00157 private:
00158 friend class ParamGenerator<T>;
00159 explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
00160 scoped_ptr<ParamIteratorInterface<T> > impl_;
00161 };
00162
00163
00164
00165 template <typename T>
00166 class ParamGeneratorInterface {
00167 public:
00168 typedef T ParamType;
00169
00170 virtual ~ParamGeneratorInterface() {}
00171
00172
00173 virtual ParamIteratorInterface<T>* Begin() const = 0;
00174 virtual ParamIteratorInterface<T>* End() const = 0;
00175 };
00176
00177
00178
00179
00180
00181
00182 template<typename T>
00183 class ParamGenerator {
00184 public:
00185 typedef ParamIterator<T> iterator;
00186
00187 explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
00188 ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
00189
00190 ParamGenerator& operator=(const ParamGenerator& other) {
00191 impl_ = other.impl_;
00192 return *this;
00193 }
00194
00195 iterator begin() const { return iterator(impl_->Begin()); }
00196 iterator end() const { return iterator(impl_->End()); }
00197
00198 private:
00199 linked_ptr<const ParamGeneratorInterface<T> > impl_;
00200 };
00201
00202
00203
00204
00205
00206 template <typename T, typename IncrementT>
00207 class RangeGenerator : public ParamGeneratorInterface<T> {
00208 public:
00209 RangeGenerator(T begin, T end, IncrementT step)
00210 : begin_(begin), end_(end),
00211 step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
00212 virtual ~RangeGenerator() {}
00213
00214 virtual ParamIteratorInterface<T>* Begin() const {
00215 return new Iterator(this, begin_, 0, step_);
00216 }
00217 virtual ParamIteratorInterface<T>* End() const {
00218 return new Iterator(this, end_, end_index_, step_);
00219 }
00220
00221 private:
00222 class Iterator : public ParamIteratorInterface<T> {
00223 public:
00224 Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
00225 IncrementT step)
00226 : base_(base), value_(value), index_(index), step_(step) {}
00227 virtual ~Iterator() {}
00228
00229 virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
00230 return base_;
00231 }
00232 virtual void Advance() {
00233 value_ = static_cast<T>(value_ + step_);
00234 index_++;
00235 }
00236 virtual ParamIteratorInterface<T>* Clone() const {
00237 return new Iterator(*this);
00238 }
00239 virtual const T* Current() const { return &value_; }
00240 virtual bool Equals(const ParamIteratorInterface<T>& other) const {
00241
00242
00243 GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
00244 << "The program attempted to compare iterators "
00245 << "from different generators." << std::endl;
00246 const int other_index =
00247 CheckedDowncastToActualType<const Iterator>(&other)->index_;
00248 return index_ == other_index;
00249 }
00250
00251 private:
00252 Iterator(const Iterator& other)
00253 : ParamIteratorInterface<T>(),
00254 base_(other.base_), value_(other.value_), index_(other.index_),
00255 step_(other.step_) {}
00256
00257
00258 void operator=(const Iterator& other);
00259
00260 const ParamGeneratorInterface<T>* const base_;
00261 T value_;
00262 int index_;
00263 const IncrementT step_;
00264 };
00265
00266 static int CalculateEndIndex(const T& begin,
00267 const T& end,
00268 const IncrementT& step) {
00269 int end_index = 0;
00270 for (T i = begin; i < end; i = static_cast<T>(i + step))
00271 end_index++;
00272 return end_index;
00273 }
00274
00275
00276 void operator=(const RangeGenerator& other);
00277
00278 const T begin_;
00279 const T end_;
00280 const IncrementT step_;
00281
00282
00283 const int end_index_;
00284 };
00285
00286
00287
00288
00289
00290
00291 template <typename T>
00292 class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
00293 public:
00294 template <typename ForwardIterator>
00295 ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
00296 : container_(begin, end) {}
00297 virtual ~ValuesInIteratorRangeGenerator() {}
00298
00299 virtual ParamIteratorInterface<T>* Begin() const {
00300 return new Iterator(this, container_.begin());
00301 }
00302 virtual ParamIteratorInterface<T>* End() const {
00303 return new Iterator(this, container_.end());
00304 }
00305
00306 private:
00307 typedef typename ::std::vector<T> ContainerType;
00308
00309 class Iterator : public ParamIteratorInterface<T> {
00310 public:
00311 Iterator(const ParamGeneratorInterface<T>* base,
00312 typename ContainerType::const_iterator iterator)
00313 : base_(base), iterator_(iterator) {}
00314 virtual ~Iterator() {}
00315
00316 virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
00317 return base_;
00318 }
00319 virtual void Advance() {
00320 ++iterator_;
00321 value_.reset();
00322 }
00323 virtual ParamIteratorInterface<T>* Clone() const {
00324 return new Iterator(*this);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 virtual const T* Current() const {
00334 if (value_.get() == NULL)
00335 value_.reset(new T(*iterator_));
00336 return value_.get();
00337 }
00338 virtual bool Equals(const ParamIteratorInterface<T>& other) const {
00339
00340
00341 GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
00342 << "The program attempted to compare iterators "
00343 << "from different generators." << std::endl;
00344 return iterator_ ==
00345 CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
00346 }
00347
00348 private:
00349 Iterator(const Iterator& other)
00350
00351
00352 : ParamIteratorInterface<T>(),
00353 base_(other.base_),
00354 iterator_(other.iterator_) {}
00355
00356 const ParamGeneratorInterface<T>* const base_;
00357 typename ContainerType::const_iterator iterator_;
00358
00359
00360
00361
00362
00363 mutable scoped_ptr<const T> value_;
00364 };
00365
00366
00367 void operator=(const ValuesInIteratorRangeGenerator& other);
00368
00369 const ContainerType container_;
00370 };
00371
00372
00373
00374
00375
00376 template <class ParamType>
00377 std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
00378 Message name_stream;
00379 name_stream << info.index;
00380 return name_stream.GetString();
00381 }
00382
00383
00384
00385
00386
00387
00388 template <class ParamType, class ParamNameGenFunctor>
00389 ParamNameGenFunctor GetParamNameGen(ParamNameGenFunctor func) {
00390 return func;
00391 }
00392
00393 template <class ParamType>
00394 struct ParamNameGenFunc {
00395 typedef std::string Type(const TestParamInfo<ParamType>&);
00396 };
00397
00398 template <class ParamType>
00399 typename ParamNameGenFunc<ParamType>::Type *GetParamNameGen() {
00400 return DefaultParamName;
00401 }
00402
00403
00404
00405
00406
00407 template <class TestClass>
00408 class ParameterizedTestFactory : public TestFactoryBase {
00409 public:
00410 typedef typename TestClass::ParamType ParamType;
00411 explicit ParameterizedTestFactory(ParamType parameter) :
00412 parameter_(parameter) {}
00413 virtual Test* CreateTest() {
00414 TestClass::SetParam(¶meter_);
00415 return new TestClass();
00416 }
00417
00418 private:
00419 const ParamType parameter_;
00420
00421 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
00422 };
00423
00424
00425
00426
00427
00428 template <class ParamType>
00429 class TestMetaFactoryBase {
00430 public:
00431 virtual ~TestMetaFactoryBase() {}
00432
00433 virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
00434 };
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 template <class TestCase>
00445 class TestMetaFactory
00446 : public TestMetaFactoryBase<typename TestCase::ParamType> {
00447 public:
00448 typedef typename TestCase::ParamType ParamType;
00449
00450 TestMetaFactory() {}
00451
00452 virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
00453 return new ParameterizedTestFactory<TestCase>(parameter);
00454 }
00455
00456 private:
00457 GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
00458 };
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 class ParameterizedTestCaseInfoBase {
00471 public:
00472 virtual ~ParameterizedTestCaseInfoBase() {}
00473
00474
00475 virtual const string& GetTestCaseName() const = 0;
00476
00477 virtual TypeId GetTestCaseTypeId() const = 0;
00478
00479
00480
00481
00482 virtual void RegisterTests() = 0;
00483
00484 protected:
00485 ParameterizedTestCaseInfoBase() {}
00486
00487 private:
00488 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
00489 };
00490
00491
00492
00493
00494
00495
00496
00497
00498 template <class TestCase>
00499 class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
00500 public:
00501
00502
00503
00504 typedef typename TestCase::ParamType ParamType;
00505
00506 typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
00507 typedef typename ParamNameGenFunc<ParamType>::Type ParamNameGeneratorFunc;
00508
00509 explicit ParameterizedTestCaseInfo(
00510 const char* name, CodeLocation code_location)
00511 : test_case_name_(name), code_location_(code_location) {}
00512
00513
00514 virtual const string& GetTestCaseName() const { return test_case_name_; }
00515
00516 virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
00517
00518
00519
00520
00521
00522
00523 void AddTestPattern(const char* test_case_name,
00524 const char* test_base_name,
00525 TestMetaFactoryBase<ParamType>* meta_factory) {
00526 tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
00527 test_base_name,
00528 meta_factory)));
00529 }
00530
00531
00532 int AddTestCaseInstantiation(const string& instantiation_name,
00533 GeneratorCreationFunc* func,
00534 ParamNameGeneratorFunc* name_func,
00535 const char* file,
00536 int line) {
00537 instantiations_.push_back(
00538 InstantiationInfo(instantiation_name, func, name_func, file, line));
00539 return 0;
00540 }
00541
00542
00543
00544
00545
00546 virtual void RegisterTests() {
00547 for (typename TestInfoContainer::iterator test_it = tests_.begin();
00548 test_it != tests_.end(); ++test_it) {
00549 linked_ptr<TestInfo> test_info = *test_it;
00550 for (typename InstantiationContainer::iterator gen_it =
00551 instantiations_.begin(); gen_it != instantiations_.end();
00552 ++gen_it) {
00553 const string& instantiation_name = gen_it->name;
00554 ParamGenerator<ParamType> generator((*gen_it->generator)());
00555 ParamNameGeneratorFunc* name_func = gen_it->name_func;
00556 const char* file = gen_it->file;
00557 int line = gen_it->line;
00558
00559 string test_case_name;
00560 if ( !instantiation_name.empty() )
00561 test_case_name = instantiation_name + "/";
00562 test_case_name += test_info->test_case_base_name;
00563
00564 size_t i = 0;
00565 std::set<std::string> test_param_names;
00566 for (typename ParamGenerator<ParamType>::iterator param_it =
00567 generator.begin();
00568 param_it != generator.end(); ++param_it, ++i) {
00569 Message test_name_stream;
00570
00571 std::string param_name = name_func(
00572 TestParamInfo<ParamType>(*param_it, i));
00573
00574 GTEST_CHECK_(IsValidParamName(param_name))
00575 << "Parameterized test name '" << param_name
00576 << "' is invalid, in " << file
00577 << " line " << line << std::endl;
00578
00579 GTEST_CHECK_(test_param_names.count(param_name) == 0)
00580 << "Duplicate parameterized test name '" << param_name
00581 << "', in " << file << " line " << line << std::endl;
00582
00583 test_param_names.insert(param_name);
00584
00585 test_name_stream << test_info->test_base_name << "/" << param_name;
00586 MakeAndRegisterTestInfo(
00587 test_case_name.c_str(),
00588 test_name_stream.GetString().c_str(),
00589 NULL,
00590 PrintToString(*param_it).c_str(),
00591 code_location_,
00592 GetTestCaseTypeId(),
00593 TestCase::SetUpTestCase,
00594 TestCase::TearDownTestCase,
00595 test_info->test_meta_factory->CreateTestFactory(*param_it));
00596 }
00597 }
00598 }
00599 }
00600
00601 private:
00602
00603
00604 struct TestInfo {
00605 TestInfo(const char* a_test_case_base_name,
00606 const char* a_test_base_name,
00607 TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
00608 test_case_base_name(a_test_case_base_name),
00609 test_base_name(a_test_base_name),
00610 test_meta_factory(a_test_meta_factory) {}
00611
00612 const string test_case_base_name;
00613 const string test_base_name;
00614 const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
00615 };
00616 typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
00617
00618
00619
00620 struct InstantiationInfo {
00621 InstantiationInfo(const std::string &name_in,
00622 GeneratorCreationFunc* generator_in,
00623 ParamNameGeneratorFunc* name_func_in,
00624 const char* file_in,
00625 int line_in)
00626 : name(name_in),
00627 generator(generator_in),
00628 name_func(name_func_in),
00629 file(file_in),
00630 line(line_in) {}
00631
00632 std::string name;
00633 GeneratorCreationFunc* generator;
00634 ParamNameGeneratorFunc* name_func;
00635 const char* file;
00636 int line;
00637 };
00638 typedef ::std::vector<InstantiationInfo> InstantiationContainer;
00639
00640 static bool IsValidParamName(const std::string& name) {
00641
00642 if (name.empty())
00643 return false;
00644
00645
00646 for (std::string::size_type index = 0; index < name.size(); ++index) {
00647 if (!isalnum(name[index]) && name[index] != '_')
00648 return false;
00649 }
00650
00651 return true;
00652 }
00653
00654 const string test_case_name_;
00655 CodeLocation code_location_;
00656 TestInfoContainer tests_;
00657 InstantiationContainer instantiations_;
00658
00659 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
00660 };
00661
00662
00663
00664
00665
00666
00667
00668 class ParameterizedTestCaseRegistry {
00669 public:
00670 ParameterizedTestCaseRegistry() {}
00671 ~ParameterizedTestCaseRegistry() {
00672 for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
00673 it != test_case_infos_.end(); ++it) {
00674 delete *it;
00675 }
00676 }
00677
00678
00679
00680 template <class TestCase>
00681 ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
00682 const char* test_case_name,
00683 CodeLocation code_location) {
00684 ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
00685 for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
00686 it != test_case_infos_.end(); ++it) {
00687 if ((*it)->GetTestCaseName() == test_case_name) {
00688 if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
00689
00690
00691
00692 ReportInvalidTestCaseType(test_case_name, code_location);
00693 posix::Abort();
00694 } else {
00695
00696
00697
00698 typed_test_info = CheckedDowncastToActualType<
00699 ParameterizedTestCaseInfo<TestCase> >(*it);
00700 }
00701 break;
00702 }
00703 }
00704 if (typed_test_info == NULL) {
00705 typed_test_info = new ParameterizedTestCaseInfo<TestCase>(
00706 test_case_name, code_location);
00707 test_case_infos_.push_back(typed_test_info);
00708 }
00709 return typed_test_info;
00710 }
00711 void RegisterTests() {
00712 for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
00713 it != test_case_infos_.end(); ++it) {
00714 (*it)->RegisterTests();
00715 }
00716 }
00717
00718 private:
00719 typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
00720
00721 TestCaseInfoContainer test_case_infos_;
00722
00723 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
00724 };
00725
00726 }
00727 }
00728
00729 #endif // GTEST_HAS_PARAM_TEST
00730
00731 #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_