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