gtest-param-util.h revision 4e8814adf2dc2d3853c03c503dcbe29404f90830
1// Copyright 2008 Google Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Author: vladl@google.com (Vlad Losev)
31
32// Type and function utilities for implementing parameterized tests.
33
34#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
35#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
36
37#include <cstddef>
38#include <iterator>
39#include <utility>
40#include <vector>
41
42#include <gtest/internal/gtest-port.h>
43
44#if GTEST_HAS_PARAM_TEST
45
46#if GTEST_HAS_RTTI
47#include <typeinfo>
48#endif  // GTEST_HAS_RTTI
49
50#include <gtest/internal/gtest-linked_ptr.h>
51#include <gtest/internal/gtest-internal.h>
52
53namespace testing {
54namespace internal {
55
56// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
57//
58// Outputs a message explaining invalid registration of different
59// fixture class for the same test case. This may happen when
60// TEST_P macro is used to define two tests with the same name
61// but in different namespaces.
62void ReportInvalidTestCaseType(const char* test_case_name,
63                               const char* file, int line);
64
65// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
66//
67// Downcasts the pointer of type Base to Derived.
68// Derived must be a subclass of Base. The parameter MUST
69// point to a class of type Derived, not any subclass of it.
70// When RTTI is available, the function performs a runtime
71// check to enforce this.
72template <class Derived, class Base>
73Derived* CheckedDowncastToActualType(Base* base) {
74#if GTEST_HAS_RTTI
75  GTEST_CHECK_(typeid(*base) == typeid(Derived));
76  Derived* derived = dynamic_cast<Derived*>(base);  // NOLINT
77#else
78  Derived* derived = static_cast<Derived*>(base);  // Poor man's downcast.
79#endif  // GTEST_HAS_RTTI
80  return derived;
81}
82
83template <typename> class ParamGeneratorInterface;
84template <typename> class ParamGenerator;
85
86// Interface for iterating over elements provided by an implementation
87// of ParamGeneratorInterface<T>.
88template <typename T>
89class ParamIteratorInterface {
90 public:
91  virtual ~ParamIteratorInterface() {}
92  // A pointer to the base generator instance.
93  // Used only for the purposes of iterator comparison
94  // to make sure that two iterators belong to the same generator.
95  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
96  // Advances iterator to point to the next element
97  // provided by the generator. The caller is responsible
98  // for not calling Advance() on an iterator equal to
99  // BaseGenerator()->End().
100  virtual void Advance() = 0;
101  // Clones the iterator object. Used for implementing copy semantics
102  // of ParamIterator<T>.
103  virtual ParamIteratorInterface* Clone() const = 0;
104  // Dereferences the current iterator and provides (read-only) access
105  // to the pointed value. It is the caller's responsibility not to call
106  // Current() on an iterator equal to BaseGenerator()->End().
107  // Used for implementing ParamGenerator<T>::operator*().
108  virtual const T* Current() const = 0;
109  // Determines whether the given iterator and other point to the same
110  // element in the sequence generated by the generator.
111  // Used for implementing ParamGenerator<T>::operator==().
112  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
113};
114
115// Class iterating over elements provided by an implementation of
116// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
117// and implements the const forward iterator concept.
118template <typename T>
119class ParamIterator {
120 public:
121  typedef T value_type;
122  typedef const T& reference;
123  typedef ptrdiff_t difference_type;
124
125  // ParamIterator assumes ownership of the impl_ pointer.
126  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
127  ParamIterator& operator=(const ParamIterator& other) {
128    if (this != &other)
129      impl_.reset(other.impl_->Clone());
130    return *this;
131  }
132
133  const T& operator*() const { return *impl_->Current(); }
134  const T* operator->() const { return impl_->Current(); }
135  // Prefix version of operator++.
136  ParamIterator& operator++() {
137    impl_->Advance();
138    return *this;
139  }
140  // Postfix version of operator++.
141  ParamIterator operator++(int /*unused*/) {
142    ParamIteratorInterface<T>* clone = impl_->Clone();
143    impl_->Advance();
144    return ParamIterator(clone);
145  }
146  bool operator==(const ParamIterator& other) const {
147    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
148  }
149  bool operator!=(const ParamIterator& other) const {
150    return !(*this == other);
151  }
152
153 private:
154  friend class ParamGenerator<T>;
155  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
156  scoped_ptr<ParamIteratorInterface<T> > impl_;
157};
158
159// ParamGeneratorInterface<T> is the binary interface to access generators
160// defined in other translation units.
161template <typename T>
162class ParamGeneratorInterface {
163 public:
164  typedef T ParamType;
165
166  virtual ~ParamGeneratorInterface() {}
167
168  // Generator interface definition
169  virtual ParamIteratorInterface<T>* Begin() const = 0;
170  virtual ParamIteratorInterface<T>* End() const = 0;
171};
172
173// Wraps ParamGeneratorInetrface<T> and provides general generator syntax
174// compatible with the STL Container concept.
175// This class implements copy initialization semantics and the contained
176// ParamGeneratorInterface<T> instance is shared among all copies
177// of the original object. This is possible because that instance is immutable.
178template<typename T>
179class ParamGenerator {
180 public:
181  typedef ParamIterator<T> iterator;
182
183  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
184  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
185
186  ParamGenerator& operator=(const ParamGenerator& other) {
187    impl_ = other.impl_;
188    return *this;
189  }
190
191  iterator begin() const { return iterator(impl_->Begin()); }
192  iterator end() const { return iterator(impl_->End()); }
193
194 private:
195  ::testing::internal::linked_ptr<const ParamGeneratorInterface<T> > impl_;
196};
197
198// Generates values from a range of two comparable values. Can be used to
199// generate sequences of user-defined types that implement operator+() and
200// operator<().
201// This class is used in the Range() function.
202template <typename T, typename IncrementT>
203class RangeGenerator : public ParamGeneratorInterface<T> {
204 public:
205  RangeGenerator(T begin, T end, IncrementT step)
206      : begin_(begin), end_(end),
207        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
208  virtual ~RangeGenerator() {}
209
210  virtual ParamIteratorInterface<T>* Begin() const {
211    return new Iterator(this, begin_, 0, step_);
212  }
213  virtual ParamIteratorInterface<T>* End() const {
214    return new Iterator(this, end_, end_index_, step_);
215  }
216
217 private:
218  class Iterator : public ParamIteratorInterface<T> {
219   public:
220    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
221             IncrementT step)
222        : base_(base), value_(value), index_(index), step_(step) {}
223    virtual ~Iterator() {}
224
225    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
226      return base_;
227    }
228    virtual void Advance() {
229      value_ = value_ + step_;
230      index_++;
231    }
232    virtual ParamIteratorInterface<T>* Clone() const {
233      return new Iterator(*this);
234    }
235    virtual const T* Current() const { return &value_; }
236    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
237      // Having the same base generator guarantees that the other
238      // iterator is of the same type and we can downcast.
239      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
240          << "The program attempted to compare iterators "
241          << "from different generators." << std::endl;
242      const int other_index =
243          CheckedDowncastToActualType<const Iterator>(&other)->index_;
244      return index_ == other_index;
245    }
246
247   private:
248    Iterator(const Iterator& other)
249        : base_(other.base_), value_(other.value_), index_(other.index_),
250          step_(other.step_) {}
251
252    const ParamGeneratorInterface<T>* const base_;
253    T value_;
254    int index_;
255    const IncrementT step_;
256  };  // class RangeGenerator::Iterator
257
258  static int CalculateEndIndex(const T& begin,
259                               const T& end,
260                               const IncrementT& step) {
261    int end_index = 0;
262    for (T i = begin; i < end; i = i + step)
263      end_index++;
264    return end_index;
265  }
266
267  const T begin_;
268  const T end_;
269  const IncrementT step_;
270  // The index for the end() iterator. All the elements in the generated
271  // sequence are indexed (0-based) to aid iterator comparison.
272  const int end_index_;
273};  // class RangeGenerator
274
275
276// Generates values from a pair of STL-style iterators. Used in the
277// ValuesIn() function. The elements are copied from the source range
278// since the source can be located on the stack, and the generator
279// is likely to persist beyond that stack frame.
280template <typename T>
281class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
282 public:
283  template <typename ForwardIterator>
284  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
285      : container_(begin, end) {}
286  virtual ~ValuesInIteratorRangeGenerator() {}
287
288  virtual ParamIteratorInterface<T>* Begin() const {
289    return new Iterator(this, container_.begin());
290  }
291  virtual ParamIteratorInterface<T>* End() const {
292    return new Iterator(this, container_.end());
293  }
294
295 private:
296  typedef typename ::std::vector<T> ContainerType;
297
298  class Iterator : public ParamIteratorInterface<T> {
299   public:
300    Iterator(const ParamGeneratorInterface<T>* base,
301             typename ContainerType::const_iterator iterator)
302        :  base_(base), iterator_(iterator) {}
303    virtual ~Iterator() {}
304
305    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
306      return base_;
307    }
308    virtual void Advance() {
309      ++iterator_;
310      value_.reset();
311    }
312    virtual ParamIteratorInterface<T>* Clone() const {
313      return new Iterator(*this);
314    }
315    // We need to use cached value referenced by iterator_ because *iterator_
316    // can return a temporary object (and of type other then T), so just
317    // having "return &*iterator_;" doesn't work.
318    // value_ is updated here and not in Advance() because Advance()
319    // can advance iterator_ beyond the end of the range, and we cannot
320    // detect that fact. The client code, on the other hand, is
321    // responsible for not calling Current() on an out-of-range iterator.
322    virtual const T* Current() const {
323      if (value_.get() == NULL)
324        value_.reset(new T(*iterator_));
325      return value_.get();
326    }
327    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
328      // Having the same base generator guarantees that the other
329      // iterator is of the same type and we can downcast.
330      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
331          << "The program attempted to compare iterators "
332          << "from different generators." << std::endl;
333      return iterator_ ==
334          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
335    }
336
337   private:
338    Iterator(const Iterator& other)
339          // The explicit constructor call suppresses a false warning
340          // emitted by gcc when supplied with the -Wextra option.
341        : ParamIteratorInterface<T>(),
342          base_(other.base_),
343          iterator_(other.iterator_) {}
344
345    const ParamGeneratorInterface<T>* const base_;
346    typename ContainerType::const_iterator iterator_;
347    // A cached value of *iterator_. We keep it here to allow access by
348    // pointer in the wrapping iterator's operator->().
349    // value_ needs to be mutable to be accessed in Current().
350    // Use of scoped_ptr helps manage cached value's lifetime,
351    // which is bound by the lifespan of the iterator itself.
352    mutable scoped_ptr<const T> value_;
353  };
354
355  const ContainerType container_;
356};  // class ValuesInIteratorRangeGenerator
357
358// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
359//
360// Stores a parameter value and later creates tests parameterized with that
361// value.
362template <class TestClass>
363class ParameterizedTestFactory : public TestFactoryBase {
364 public:
365  typedef typename TestClass::ParamType ParamType;
366  explicit ParameterizedTestFactory(ParamType parameter) :
367      parameter_(parameter) {}
368  virtual Test* CreateTest() {
369    TestClass::SetParam(&parameter_);
370    return new TestClass();
371  }
372
373 private:
374  const ParamType parameter_;
375
376  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
377};
378
379// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
380//
381// TestMetaFactoryBase is a base class for meta-factories that create
382// test factories for passing into MakeAndRegisterTestInfo function.
383template <class ParamType>
384class TestMetaFactoryBase {
385 public:
386  virtual ~TestMetaFactoryBase() {}
387
388  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
389};
390
391// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
392//
393// TestMetaFactory creates test factories for passing into
394// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
395// ownership of test factory pointer, same factory object cannot be passed
396// into that method twice. But ParameterizedTestCaseInfo is going to call
397// it for each Test/Parameter value combination. Thus it needs meta factory
398// creator class.
399template <class TestCase>
400class TestMetaFactory
401    : public TestMetaFactoryBase<typename TestCase::ParamType> {
402 public:
403  typedef typename TestCase::ParamType ParamType;
404
405  TestMetaFactory() {}
406
407  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
408    return new ParameterizedTestFactory<TestCase>(parameter);
409  }
410
411 private:
412  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
413};
414
415// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
416//
417// ParameterizedTestCaseInfoBase is a generic interface
418// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
419// accumulates test information provided by TEST_P macro invocations
420// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
421// and uses that information to register all resulting test instances
422// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
423// a collection of pointers to the ParameterizedTestCaseInfo objects
424// and calls RegisterTests() on each of them when asked.
425class ParameterizedTestCaseInfoBase {
426 public:
427  virtual ~ParameterizedTestCaseInfoBase() {}
428
429  // Base part of test case name for display purposes.
430  virtual const String& GetTestCaseName() const = 0;
431  // Test case id to verify identity.
432  virtual TypeId GetTestCaseTypeId() const = 0;
433  // UnitTest class invokes this method to register tests in this
434  // test case right before running them in RUN_ALL_TESTS macro.
435  // This method should not be called more then once on any single
436  // instance of a ParameterizedTestCaseInfoBase derived class.
437  virtual void RegisterTests() = 0;
438
439 protected:
440  ParameterizedTestCaseInfoBase() {}
441
442 private:
443  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
444};
445
446// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
447//
448// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
449// macro invocations for a particular test case and generators
450// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
451// test case. It registers tests with all values generated by all
452// generators when asked.
453template <class TestCase>
454class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
455 public:
456  // ParamType and GeneratorCreationFunc are private types but are required
457  // for declarations of public methods AddTestPattern() and
458  // AddTestCaseInstantiation().
459  typedef typename TestCase::ParamType ParamType;
460  // A function that returns an instance of appropriate generator type.
461  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
462
463  explicit ParameterizedTestCaseInfo(const char* name)
464      : test_case_name_(name) {}
465
466  // Test case base name for display purposes.
467  virtual const String& GetTestCaseName() const { return test_case_name_; }
468  // Test case id to verify identity.
469  virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
470  // TEST_P macro uses AddTestPattern() to record information
471  // about a single test in a LocalTestInfo structure.
472  // test_case_name is the base name of the test case (without invocation
473  // prefix). test_base_name is the name of an individual test without
474  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
475  // test case base name and DoBar is test base name.
476  void AddTestPattern(const char* test_case_name,
477                      const char* test_base_name,
478                      TestMetaFactoryBase<ParamType>* meta_factory) {
479    tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
480                                                       test_base_name,
481                                                       meta_factory)));
482  }
483  // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
484  // about a generator.
485  int AddTestCaseInstantiation(const char* instantiation_name,
486                               GeneratorCreationFunc* func,
487                               const char* file,
488                               int line) {
489    instantiations_.push_back(::std::make_pair(instantiation_name, func));
490    return 0;  // Return value used only to run this method in namespace scope.
491  }
492  // UnitTest class invokes this method to register tests in this test case
493  // test cases right before running tests in RUN_ALL_TESTS macro.
494  // This method should not be called more then once on any single
495  // instance of a ParameterizedTestCaseInfoBase derived class.
496  // UnitTest has a guard to prevent from calling this method more then once.
497  virtual void RegisterTests() {
498    for (typename TestInfoContainer::iterator test_it = tests_.begin();
499         test_it != tests_.end(); ++test_it) {
500      linked_ptr<TestInfo> test_info = *test_it;
501      for (typename InstantiationContainer::iterator gen_it =
502               instantiations_.begin(); gen_it != instantiations_.end();
503               ++gen_it) {
504        const String& instantiation_name = gen_it->first;
505        ParamGenerator<ParamType> generator((*gen_it->second)());
506
507        Message test_case_name_stream;
508        if ( !instantiation_name.empty() )
509          test_case_name_stream << instantiation_name.c_str() << "/";
510        test_case_name_stream << test_info->test_case_base_name.c_str();
511
512        int i = 0;
513        for (typename ParamGenerator<ParamType>::iterator param_it =
514                 generator.begin();
515             param_it != generator.end(); ++param_it, ++i) {
516          Message test_name_stream;
517          test_name_stream << test_info->test_base_name.c_str() << "/" << i;
518          ::testing::internal::MakeAndRegisterTestInfo(
519              test_case_name_stream.GetString().c_str(),
520              test_name_stream.GetString().c_str(),
521              "",  // test_case_comment
522              "",  // comment; TODO(vladl@google.com): provide parameter value
523                   //                                  representation.
524              GetTestCaseTypeId(),
525              TestCase::SetUpTestCase,
526              TestCase::TearDownTestCase,
527              test_info->test_meta_factory->CreateTestFactory(*param_it));
528        }  // for param_it
529      }  // for gen_it
530    }  // for test_it
531  }  // RegisterTests
532
533 private:
534  // LocalTestInfo structure keeps information about a single test registered
535  // with TEST_P macro.
536  struct TestInfo {
537    TestInfo(const char* test_case_base_name,
538             const char* test_base_name,
539             TestMetaFactoryBase<ParamType>* test_meta_factory) :
540        test_case_base_name(test_case_base_name),
541        test_base_name(test_base_name),
542        test_meta_factory(test_meta_factory) {}
543
544    const String test_case_base_name;
545    const String test_base_name;
546    const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
547  };
548  typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
549  // Keeps pairs of <Instantiation name, Sequence generator creation function>
550  // received from INSTANTIATE_TEST_CASE_P macros.
551  typedef ::std::vector<std::pair<String, GeneratorCreationFunc*> >
552      InstantiationContainer;
553
554  const String test_case_name_;
555  TestInfoContainer tests_;
556  InstantiationContainer instantiations_;
557
558  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
559};  // class ParameterizedTestCaseInfo
560
561// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
562//
563// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
564// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
565// macros use it to locate their corresponding ParameterizedTestCaseInfo
566// descriptors.
567class ParameterizedTestCaseRegistry {
568 public:
569  ParameterizedTestCaseRegistry() {}
570  ~ParameterizedTestCaseRegistry() {
571    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
572         it != test_case_infos_.end(); ++it) {
573      delete *it;
574    }
575  }
576
577  // Looks up or creates and returns a structure containing information about
578  // tests and instantiations of a particular test case.
579  template <class TestCase>
580  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
581      const char* test_case_name,
582      const char* file,
583      int line) {
584    ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
585    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
586         it != test_case_infos_.end(); ++it) {
587      if ((*it)->GetTestCaseName() == test_case_name) {
588        if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
589          // Complain about incorrect usage of Google Test facilities
590          // and terminate the program since we cannot guaranty correct
591          // test case setup and tear-down in this case.
592          ReportInvalidTestCaseType(test_case_name,  file, line);
593          abort();
594        } else {
595          // At this point we are sure that the object we found is of the same
596          // type we are looking for, so we downcast it to that type
597          // without further checks.
598          typed_test_info = CheckedDowncastToActualType<
599              ParameterizedTestCaseInfo<TestCase> >(*it);
600        }
601        break;
602      }
603    }
604    if (typed_test_info == NULL) {
605      typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
606      test_case_infos_.push_back(typed_test_info);
607    }
608    return typed_test_info;
609  }
610  void RegisterTests() {
611    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
612         it != test_case_infos_.end(); ++it) {
613      (*it)->RegisterTests();
614    }
615  }
616
617 private:
618  typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
619
620  TestCaseInfoContainer test_case_infos_;
621
622  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
623};
624
625}  // namespace internal
626}  // namespace testing
627
628#endif  //  GTEST_HAS_PARAM_TEST
629
630#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
631