34 #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
35 #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
52 #if GTEST_HAS_PARAM_TEST
58 template <
class ParamType>
59 struct TestParamInfo {
60 TestParamInfo(
const ParamType& a_param,
size_t an_index) :
69 struct PrintToStringParamName {
70 template <
class ParamType>
71 std::string operator()(
const TestParamInfo<ParamType>& info)
const {
84 GTEST_API_ void ReportInvalidTestCaseType(
const char* test_case_name,
85 CodeLocation code_location);
87 template <
typename>
class ParamGeneratorInterface;
88 template <
typename>
class ParamGenerator;
93 class ParamIteratorInterface {
95 virtual ~ParamIteratorInterface() {}
99 virtual const ParamGeneratorInterface<T>* BaseGenerator()
const = 0;
104 virtual void Advance() = 0;
107 virtual ParamIteratorInterface* Clone()
const = 0;
112 virtual const T* Current()
const = 0;
116 virtual bool Equals(
const ParamIteratorInterface& other)
const = 0;
122 template <
typename T>
123 class ParamIterator {
126 typedef const T& reference;
127 typedef ptrdiff_t difference_type;
130 ParamIterator(
const ParamIterator& other) : impl_(other.impl_->Clone()) {}
131 ParamIterator&
operator=(
const ParamIterator& other) {
133 impl_.reset(other.impl_->Clone());
137 const T&
operator*()
const {
return *impl_->Current(); }
138 const T* operator->()
const {
return impl_->Current(); }
140 ParamIterator& operator++() {
145 ParamIterator operator++(
int ) {
146 ParamIteratorInterface<T>* clone = impl_->Clone();
148 return ParamIterator(clone);
150 bool operator==(
const ParamIterator& other)
const {
151 return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
153 bool operator!=(
const ParamIterator& other)
const {
154 return !(*
this == other);
158 friend class ParamGenerator<
T>;
159 explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
160 scoped_ptr<ParamIteratorInterface<T> > impl_;
165 template <
typename T>
166 class ParamGeneratorInterface {
170 virtual ~ParamGeneratorInterface() {}
173 virtual ParamIteratorInterface<T>* Begin()
const = 0;
174 virtual ParamIteratorInterface<T>* End()
const = 0;
183 class ParamGenerator {
185 typedef ParamIterator<T> iterator;
187 explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
188 ParamGenerator(
const ParamGenerator& other) : impl_(other.impl_) {}
190 ParamGenerator&
operator=(
const ParamGenerator& other) {
195 iterator
begin()
const {
return iterator(impl_->Begin()); }
196 iterator
end()
const {
return iterator(impl_->End()); }
199 linked_ptr<const ParamGeneratorInterface<T> > impl_;
206 template <
typename T,
typename IncrementT>
207 class RangeGenerator :
public ParamGeneratorInterface<T> {
210 : begin_(begin), end_(end),
211 step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
212 virtual ~RangeGenerator() {}
214 virtual ParamIteratorInterface<T>* Begin()
const {
215 return new Iterator(
this, begin_, 0, step_);
217 virtual ParamIteratorInterface<T>* End()
const {
218 return new Iterator(
this, end_, end_index_, step_);
222 class Iterator :
public ParamIteratorInterface<T> {
224 Iterator(
const ParamGeneratorInterface<T>* base,
T value,
int index,
226 : base_(base), value_(value), index_(index), step_(step) {}
227 virtual ~Iterator() {}
229 virtual const ParamGeneratorInterface<T>* BaseGenerator()
const {
232 virtual void Advance() {
233 value_ =
static_cast<T>(value_ + step_);
236 virtual ParamIteratorInterface<T>* Clone()
const {
237 return new Iterator(*
this);
239 virtual const T* Current()
const {
return &value_; }
240 virtual bool Equals(
const ParamIteratorInterface<T>& other)
const {
244 <<
"The program attempted to compare iterators "
245 <<
"from different generators." << std::endl;
246 const int other_index =
247 CheckedDowncastToActualType<const Iterator>(&other)->index_;
248 return index_ == other_index;
252 Iterator(
const Iterator& other)
253 : ParamIteratorInterface<
T>(),
254 base_(other.base_), value_(other.value_), index_(other.index_),
255 step_(other.step_) {}
260 const ParamGeneratorInterface<T>*
const base_;
263 const IncrementT step_;
266 static int CalculateEndIndex(
const T&
begin,
268 const IncrementT&
step) {
270 for (
T i = begin; i < end; i = static_cast<T>(
i +
step))
276 void operator=(
const RangeGenerator& other);
280 const IncrementT step_;
283 const int end_index_;
291 template <
typename T>
292 class ValuesInIteratorRangeGenerator :
public ParamGeneratorInterface<T> {
294 template <
typename ForwardIterator>
295 ValuesInIteratorRangeGenerator(ForwardIterator
begin, ForwardIterator
end)
296 : container_(begin, end) {}
297 virtual ~ValuesInIteratorRangeGenerator() {}
299 virtual ParamIteratorInterface<T>* Begin()
const {
300 return new Iterator(
this, container_.begin());
302 virtual ParamIteratorInterface<T>* End()
const {
303 return new Iterator(
this, container_.end());
307 typedef typename ::std::vector<T> ContainerType;
309 class Iterator :
public ParamIteratorInterface<T> {
311 Iterator(
const ParamGeneratorInterface<T>* base,
312 typename ContainerType::const_iterator iterator)
313 : base_(base), iterator_(iterator) {}
314 virtual ~Iterator() {}
316 virtual const ParamGeneratorInterface<T>* BaseGenerator()
const {
319 virtual void Advance() {
323 virtual ParamIteratorInterface<T>* Clone()
const {
324 return new Iterator(*
this);
333 virtual const T* Current()
const {
334 if (value_.get() == NULL)
335 value_.reset(
new T(*iterator_));
338 virtual bool Equals(
const ParamIteratorInterface<T>& other)
const {
342 <<
"The program attempted to compare iterators "
343 <<
"from different generators." << std::endl;
345 CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
349 Iterator(
const Iterator& other)
352 : ParamIteratorInterface<
T>(),
354 iterator_(other.iterator_) {}
356 const ParamGeneratorInterface<T>*
const base_;
357 typename ContainerType::const_iterator iterator_;
363 mutable scoped_ptr<const T> value_;
367 void operator=(
const ValuesInIteratorRangeGenerator& other);
369 const ContainerType container_;
376 template <
class ParamType>
377 std::string DefaultParamName(
const TestParamInfo<ParamType>& info) {
379 name_stream << info.index;
380 return name_stream.GetString();
388 template <
class ParamType,
class ParamNameGenFunctor>
389 ParamNameGenFunctor GetParamNameGen(ParamNameGenFunctor func) {
393 template <
class ParamType>
394 struct ParamNameGenFunc {
395 typedef std::string Type(
const TestParamInfo<ParamType>&);
398 template <
class ParamType>
399 typename ParamNameGenFunc<ParamType>::Type *GetParamNameGen() {
400 return DefaultParamName;
407 template <
class TestClass>
408 class ParameterizedTestFactory :
public TestFactoryBase {
410 typedef typename TestClass::ParamType ParamType;
411 explicit ParameterizedTestFactory(ParamType parameter) :
412 parameter_(parameter) {}
413 virtual Test* CreateTest() {
414 TestClass::SetParam(¶meter_);
415 return new TestClass();
419 const ParamType parameter_;
428 template <
class ParamType>
429 class TestMetaFactoryBase {
431 virtual ~TestMetaFactoryBase() {}
433 virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
444 template <
class TestCase>
445 class TestMetaFactory
446 :
public TestMetaFactoryBase<typename TestCase::ParamType> {
448 typedef typename TestCase::ParamType ParamType;
452 virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
453 return new ParameterizedTestFactory<TestCase>(parameter);
470 class ParameterizedTestCaseInfoBase {
472 virtual ~ParameterizedTestCaseInfoBase() {}
475 virtual const string& GetTestCaseName()
const = 0;
477 virtual TypeId GetTestCaseTypeId()
const = 0;
482 virtual void RegisterTests() = 0;
485 ParameterizedTestCaseInfoBase() {}
498 template <
class TestCase>
499 class ParameterizedTestCaseInfo :
public ParameterizedTestCaseInfoBase {
504 typedef typename TestCase::ParamType ParamType;
506 typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
507 typedef typename ParamNameGenFunc<ParamType>::Type ParamNameGeneratorFunc;
509 explicit ParameterizedTestCaseInfo(
510 const char*
name, CodeLocation code_location)
511 : test_case_name_(name), code_location_(code_location) {}
514 virtual const string& GetTestCaseName()
const {
return test_case_name_; }
516 virtual TypeId GetTestCaseTypeId()
const {
return GetTypeId<TestCase>(); }
523 void AddTestPattern(
const char* test_case_name,
524 const char* test_base_name,
525 TestMetaFactoryBase<ParamType>* meta_factory) {
526 tests_.push_back(linked_ptr<TestInfo>(
new TestInfo(test_case_name,
532 int AddTestCaseInstantiation(
const string& instantiation_name,
533 GeneratorCreationFunc* func,
534 ParamNameGeneratorFunc* name_func,
537 instantiations_.push_back(
538 InstantiationInfo(instantiation_name, func, name_func, file, line));
546 virtual void RegisterTests() {
547 for (
typename TestInfoContainer::iterator test_it = tests_.begin();
548 test_it != tests_.end(); ++test_it) {
549 linked_ptr<TestInfo> test_info = *test_it;
550 for (
typename InstantiationContainer::iterator gen_it =
551 instantiations_.begin(); gen_it != instantiations_.end();
553 const string& instantiation_name = gen_it->name;
554 ParamGenerator<ParamType>
generator((*gen_it->generator)());
555 ParamNameGeneratorFunc* name_func = gen_it->name_func;
556 const char* file = gen_it->file;
557 int line = gen_it->line;
559 string test_case_name;
560 if ( !instantiation_name.empty() )
561 test_case_name = instantiation_name +
"/";
562 test_case_name += test_info->test_case_base_name;
565 std::set<std::string> test_param_names;
566 for (
typename ParamGenerator<ParamType>::iterator param_it =
568 param_it !=
generator.end(); ++param_it, ++
i) {
569 Message test_name_stream;
572 TestParamInfo<ParamType>(*param_it, i));
575 <<
"Parameterized test name '" << param_name
576 <<
"' is invalid, in " << file
577 <<
" line " << line << std::endl;
580 <<
"Duplicate parameterized test name '" << param_name
581 <<
"', in " << file <<
" line " << line << std::endl;
583 test_param_names.insert(param_name);
585 test_name_stream << test_info->test_base_name <<
"/" << param_name;
587 test_case_name.c_str(),
588 test_name_stream.GetString().c_str(),
593 TestCase::SetUpTestCase,
594 TestCase::TearDownTestCase,
595 test_info->test_meta_factory->CreateTestFactory(*param_it));
605 TestInfo(
const char* a_test_case_base_name,
606 const char* a_test_base_name,
607 TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
608 test_case_base_name(a_test_case_base_name),
609 test_base_name(a_test_base_name),
610 test_meta_factory(a_test_meta_factory) {}
612 const string test_case_base_name;
613 const string test_base_name;
614 const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
616 typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
620 struct InstantiationInfo {
622 GeneratorCreationFunc* generator_in,
623 ParamNameGeneratorFunc* name_func_in,
628 name_func(name_func_in),
634 ParamNameGeneratorFunc* name_func;
638 typedef ::std::vector<InstantiationInfo> InstantiationContainer;
647 if (!isalnum(name[
index]) && name[
index] !=
'_')
654 const string test_case_name_;
655 CodeLocation code_location_;
656 TestInfoContainer tests_;
657 InstantiationContainer instantiations_;
668 class ParameterizedTestCaseRegistry {
670 ParameterizedTestCaseRegistry() {}
671 ~ParameterizedTestCaseRegistry() {
672 for (TestCaseInfoContainer::iterator
it = test_case_infos_.begin();
673 it != test_case_infos_.end(); ++
it) {
680 template <
class TestCase>
681 ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
682 const char* test_case_name,
683 CodeLocation code_location) {
684 ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
685 for (TestCaseInfoContainer::iterator
it = test_case_infos_.begin();
686 it != test_case_infos_.end(); ++
it) {
687 if ((*it)->GetTestCaseName() == test_case_name) {
688 if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
692 ReportInvalidTestCaseType(test_case_name, code_location);
699 ParameterizedTestCaseInfo<TestCase> >(*it);
704 if (typed_test_info == NULL) {
705 typed_test_info =
new ParameterizedTestCaseInfo<TestCase>(
706 test_case_name, code_location);
707 test_case_infos_.push_back(typed_test_info);
709 return typed_test_info;
711 void RegisterTests() {
712 for (TestCaseInfoContainer::iterator
it = test_case_infos_.begin();
713 it != test_case_infos_.end(); ++
it) {
714 (*it)->RegisterTests();
719 typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
721 TestCaseInfoContainer test_case_infos_;
729 #endif // GTEST_HAS_PARAM_TEST
731 #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_