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 <iterator>
00038 #include <utility>
00039 #include <vector>
00040
00041
00042
00043
00044 #include "gtest/internal/gtest-internal.h"
00045 #include "gtest/internal/gtest-linked_ptr.h"
00046 #include "gtest/internal/gtest-port.h"
00047 #include "gtest/gtest-printers.h"
00048
00049 #if GTEST_HAS_PARAM_TEST
00050
00051 namespace testing {
00052 namespace internal {
00053
00054
00055
00056
00057
00058
00059
00060 GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
00061 const char* file, int line);
00062
00063 template <typename> class ParamGeneratorInterface;
00064 template <typename> class ParamGenerator;
00065
00066
00067
00068 template <typename T>
00069 class ParamIteratorInterface {
00070 public:
00071 virtual ~ParamIteratorInterface() {}
00072
00073
00074
00075 virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
00076
00077
00078
00079
00080 virtual void Advance() = 0;
00081
00082
00083 virtual ParamIteratorInterface* Clone() const = 0;
00084
00085
00086
00087
00088 virtual const T* Current() const = 0;
00089
00090
00091
00092 virtual bool Equals(const ParamIteratorInterface& other) const = 0;
00093 };
00094
00095
00096
00097
00098 template <typename T>
00099 class ParamIterator {
00100 public:
00101 typedef T value_type;
00102 typedef const T& reference;
00103 typedef ptrdiff_t difference_type;
00104
00105
00106 ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
00107 ParamIterator& operator=(const ParamIterator& other) {
00108 if (this != &other)
00109 impl_.reset(other.impl_->Clone());
00110 return *this;
00111 }
00112
00113 const T& operator*() const { return *impl_->Current(); }
00114 const T* operator->() const { return impl_->Current(); }
00115
00116 ParamIterator& operator++() {
00117 impl_->Advance();
00118 return *this;
00119 }
00120
00121 ParamIterator operator++(int ) {
00122 ParamIteratorInterface<T>* clone = impl_->Clone();
00123 impl_->Advance();
00124 return ParamIterator(clone);
00125 }
00126 bool operator==(const ParamIterator& other) const {
00127 return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
00128 }
00129 bool operator!=(const ParamIterator& other) const {
00130 return !(*this == other);
00131 }
00132
00133 private:
00134 friend class ParamGenerator<T>;
00135 explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
00136 scoped_ptr<ParamIteratorInterface<T> > impl_;
00137 };
00138
00139
00140
00141 template <typename T>
00142 class ParamGeneratorInterface {
00143 public:
00144 typedef T ParamType;
00145
00146 virtual ~ParamGeneratorInterface() {}
00147
00148
00149 virtual ParamIteratorInterface<T>* Begin() const = 0;
00150 virtual ParamIteratorInterface<T>* End() const = 0;
00151 };
00152
00153
00154
00155
00156
00157
00158 template<typename T>
00159 class ParamGenerator {
00160 public:
00161 typedef ParamIterator<T> iterator;
00162
00163 explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
00164 ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
00165
00166 ParamGenerator& operator=(const ParamGenerator& other) {
00167 impl_ = other.impl_;
00168 return *this;
00169 }
00170
00171 iterator begin() const { return iterator(impl_->Begin()); }
00172 iterator end() const { return iterator(impl_->End()); }
00173
00174 private:
00175 linked_ptr<const ParamGeneratorInterface<T> > impl_;
00176 };
00177
00178
00179
00180
00181
00182 template <typename T, typename IncrementT>
00183 class RangeGenerator : public ParamGeneratorInterface<T> {
00184 public:
00185 RangeGenerator(T begin, T end, IncrementT step)
00186 : begin_(begin), end_(end),
00187 step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
00188 virtual ~RangeGenerator() {}
00189
00190 virtual ParamIteratorInterface<T>* Begin() const {
00191 return new Iterator(this, begin_, 0, step_);
00192 }
00193 virtual ParamIteratorInterface<T>* End() const {
00194 return new Iterator(this, end_, end_index_, step_);
00195 }
00196
00197 private:
00198 class Iterator : public ParamIteratorInterface<T> {
00199 public:
00200 Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
00201 IncrementT step)
00202 : base_(base), value_(value), index_(index), step_(step) {}
00203 virtual ~Iterator() {}
00204
00205 virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
00206 return base_;
00207 }
00208 virtual void Advance() {
00209 value_ = value_ + step_;
00210 index_++;
00211 }
00212 virtual ParamIteratorInterface<T>* Clone() const {
00213 return new Iterator(*this);
00214 }
00215 virtual const T* Current() const { return &value_; }
00216 virtual bool Equals(const ParamIteratorInterface<T>& other) const {
00217
00218
00219 GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
00220 << "The program attempted to compare iterators "
00221 << "from different generators." << std::endl;
00222 const int other_index =
00223 CheckedDowncastToActualType<const Iterator>(&other)->index_;
00224 return index_ == other_index;
00225 }
00226
00227 private:
00228 Iterator(const Iterator& other)
00229 : ParamIteratorInterface<T>(),
00230 base_(other.base_), value_(other.value_), index_(other.index_),
00231 step_(other.step_) {}
00232
00233
00234 void operator=(const Iterator& other);
00235
00236 const ParamGeneratorInterface<T>* const base_;
00237 T value_;
00238 int index_;
00239 const IncrementT step_;
00240 };
00241
00242 static int CalculateEndIndex(const T& begin,
00243 const T& end,
00244 const IncrementT& step) {
00245 int end_index = 0;
00246 for (T i = begin; i < end; i = i + step)
00247 end_index++;
00248 return end_index;
00249 }
00250
00251
00252 void operator=(const RangeGenerator& other);
00253
00254 const T begin_;
00255 const T end_;
00256 const IncrementT step_;
00257
00258
00259 const int end_index_;
00260 };
00261
00262
00263
00264
00265
00266
00267 template <typename T>
00268 class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
00269 public:
00270 template <typename ForwardIterator>
00271 ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
00272 : container_(begin, end) {}
00273 virtual ~ValuesInIteratorRangeGenerator() {}
00274
00275 virtual ParamIteratorInterface<T>* Begin() const {
00276 return new Iterator(this, container_.begin());
00277 }
00278 virtual ParamIteratorInterface<T>* End() const {
00279 return new Iterator(this, container_.end());
00280 }
00281
00282 private:
00283 typedef typename ::std::vector<T> ContainerType;
00284
00285 class Iterator : public ParamIteratorInterface<T> {
00286 public:
00287 Iterator(const ParamGeneratorInterface<T>* base,
00288 typename ContainerType::const_iterator iterator)
00289 : base_(base), iterator_(iterator) {}
00290 virtual ~Iterator() {}
00291
00292 virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
00293 return base_;
00294 }
00295 virtual void Advance() {
00296 ++iterator_;
00297 value_.reset();
00298 }
00299 virtual ParamIteratorInterface<T>* Clone() const {
00300 return new Iterator(*this);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 virtual const T* Current() const {
00310 if (value_.get() == NULL)
00311 value_.reset(new T(*iterator_));
00312 return value_.get();
00313 }
00314 virtual bool Equals(const ParamIteratorInterface<T>& other) const {
00315
00316
00317 GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
00318 << "The program attempted to compare iterators "
00319 << "from different generators." << std::endl;
00320 return iterator_ ==
00321 CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
00322 }
00323
00324 private:
00325 Iterator(const Iterator& other)
00326
00327
00328 : ParamIteratorInterface<T>(),
00329 base_(other.base_),
00330 iterator_(other.iterator_) {}
00331
00332 const ParamGeneratorInterface<T>* const base_;
00333 typename ContainerType::const_iterator iterator_;
00334
00335
00336
00337
00338
00339 mutable scoped_ptr<const T> value_;
00340 };
00341
00342
00343 void operator=(const ValuesInIteratorRangeGenerator& other);
00344
00345 const ContainerType container_;
00346 };
00347
00348
00349
00350
00351
00352 template <class TestClass>
00353 class ParameterizedTestFactory : public TestFactoryBase {
00354 public:
00355 typedef typename TestClass::ParamType ParamType;
00356 explicit ParameterizedTestFactory(ParamType parameter) :
00357 parameter_(parameter) {}
00358 virtual Test* CreateTest() {
00359 TestClass::SetParam(¶meter_);
00360 return new TestClass();
00361 }
00362
00363 private:
00364 const ParamType parameter_;
00365
00366 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
00367 };
00368
00369
00370
00371
00372
00373 template <class ParamType>
00374 class TestMetaFactoryBase {
00375 public:
00376 virtual ~TestMetaFactoryBase() {}
00377
00378 virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
00379 };
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 template <class TestCase>
00390 class TestMetaFactory
00391 : public TestMetaFactoryBase<typename TestCase::ParamType> {
00392 public:
00393 typedef typename TestCase::ParamType ParamType;
00394
00395 TestMetaFactory() {}
00396
00397 virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
00398 return new ParameterizedTestFactory<TestCase>(parameter);
00399 }
00400
00401 private:
00402 GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
00403 };
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 class ParameterizedTestCaseInfoBase {
00416 public:
00417 virtual ~ParameterizedTestCaseInfoBase() {}
00418
00419
00420 virtual const string& GetTestCaseName() const = 0;
00421
00422 virtual TypeId GetTestCaseTypeId() const = 0;
00423
00424
00425
00426
00427 virtual void RegisterTests() = 0;
00428
00429 protected:
00430 ParameterizedTestCaseInfoBase() {}
00431
00432 private:
00433 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
00434 };
00435
00436
00437
00438
00439
00440
00441
00442
00443 template <class TestCase>
00444 class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
00445 public:
00446
00447
00448
00449 typedef typename TestCase::ParamType ParamType;
00450
00451 typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
00452
00453 explicit ParameterizedTestCaseInfo(const char* name)
00454 : test_case_name_(name) {}
00455
00456
00457 virtual const string& GetTestCaseName() const { return test_case_name_; }
00458
00459 virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
00460
00461
00462
00463
00464
00465
00466 void AddTestPattern(const char* test_case_name,
00467 const char* test_base_name,
00468 TestMetaFactoryBase<ParamType>* meta_factory) {
00469 tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
00470 test_base_name,
00471 meta_factory)));
00472 }
00473
00474
00475 int AddTestCaseInstantiation(const string& instantiation_name,
00476 GeneratorCreationFunc* func,
00477 const char* ,
00478 int ) {
00479 instantiations_.push_back(::std::make_pair(instantiation_name, func));
00480 return 0;
00481 }
00482
00483
00484
00485
00486
00487 virtual void RegisterTests() {
00488 for (typename TestInfoContainer::iterator test_it = tests_.begin();
00489 test_it != tests_.end(); ++test_it) {
00490 linked_ptr<TestInfo> test_info = *test_it;
00491 for (typename InstantiationContainer::iterator gen_it =
00492 instantiations_.begin(); gen_it != instantiations_.end();
00493 ++gen_it) {
00494 const string& instantiation_name = gen_it->first;
00495 ParamGenerator<ParamType> generator((*gen_it->second)());
00496
00497 Message test_case_name_stream;
00498 if ( !instantiation_name.empty() )
00499 test_case_name_stream << instantiation_name << "/";
00500 test_case_name_stream << test_info->test_case_base_name;
00501
00502 int i = 0;
00503 for (typename ParamGenerator<ParamType>::iterator param_it =
00504 generator.begin();
00505 param_it != generator.end(); ++param_it, ++i) {
00506 Message test_name_stream;
00507 test_name_stream << test_info->test_base_name << "/" << i;
00508 MakeAndRegisterTestInfo(
00509 test_case_name_stream.GetString().c_str(),
00510 test_name_stream.GetString().c_str(),
00511 NULL,
00512 PrintToString(*param_it).c_str(),
00513 GetTestCaseTypeId(),
00514 TestCase::SetUpTestCase,
00515 TestCase::TearDownTestCase,
00516 test_info->test_meta_factory->CreateTestFactory(*param_it));
00517 }
00518 }
00519 }
00520 }
00521
00522 private:
00523
00524
00525 struct TestInfo {
00526 TestInfo(const char* a_test_case_base_name,
00527 const char* a_test_base_name,
00528 TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
00529 test_case_base_name(a_test_case_base_name),
00530 test_base_name(a_test_base_name),
00531 test_meta_factory(a_test_meta_factory) {}
00532
00533 const string test_case_base_name;
00534 const string test_base_name;
00535 const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
00536 };
00537 typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
00538
00539
00540 typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
00541 InstantiationContainer;
00542
00543 const string test_case_name_;
00544 TestInfoContainer tests_;
00545 InstantiationContainer instantiations_;
00546
00547 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
00548 };
00549
00550
00551
00552
00553
00554
00555
00556 class ParameterizedTestCaseRegistry {
00557 public:
00558 ParameterizedTestCaseRegistry() {}
00559 ~ParameterizedTestCaseRegistry() {
00560 for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
00561 it != test_case_infos_.end(); ++it) {
00562 delete *it;
00563 }
00564 }
00565
00566
00567
00568 template <class TestCase>
00569 ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
00570 const char* test_case_name,
00571 const char* file,
00572 int line) {
00573 ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
00574 for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
00575 it != test_case_infos_.end(); ++it) {
00576 if ((*it)->GetTestCaseName() == test_case_name) {
00577 if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
00578
00579
00580
00581 ReportInvalidTestCaseType(test_case_name, file, line);
00582 posix::Abort();
00583 } else {
00584
00585
00586
00587 typed_test_info = CheckedDowncastToActualType<
00588 ParameterizedTestCaseInfo<TestCase> >(*it);
00589 }
00590 break;
00591 }
00592 }
00593 if (typed_test_info == NULL) {
00594 typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
00595 test_case_infos_.push_back(typed_test_info);
00596 }
00597 return typed_test_info;
00598 }
00599 void RegisterTests() {
00600 for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
00601 it != test_case_infos_.end(); ++it) {
00602 (*it)->RegisterTests();
00603 }
00604 }
00605
00606 private:
00607 typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
00608
00609 TestCaseInfoContainer test_case_infos_;
00610
00611 GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
00612 };
00613
00614 }
00615 }
00616
00617 #endif // GTEST_HAS_PARAM_TEST
00618
00619 #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_