gtest-param-util.h 32.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Gennadiy Civil's avatar
 
Gennadiy Civil committed
29

30
31
32

// Type and function utilities for implementing parameterized tests.

Gennadiy Civil's avatar
 
Gennadiy Civil committed
33
34
// GOOGLETEST_CM0001 DO NOT DELETE

35
36
37
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_

38
39
#include <ctype.h>

Abseil Team's avatar
Abseil Team committed
40
#include <cassert>
41
#include <iterator>
misterg's avatar
misterg committed
42
#include <memory>
43
#include <set>
misterg's avatar
misterg committed
44
#include <tuple>
45
46
47
#include <utility>
#include <vector>

48
49
50
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-port.h"
#include "gtest/gtest-printers.h"
51
52

namespace testing {
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Input to a parameterized test name generator, describing a test parameter.
// Consists of the parameter value and the integer parameter index.
template <class ParamType>
struct TestParamInfo {
  TestParamInfo(const ParamType& a_param, size_t an_index) :
    param(a_param),
    index(an_index) {}
  ParamType param;
  size_t index;
};

// A builtin parameterized test name generator which returns the result of
// testing::PrintToString.
struct PrintToStringParamName {
  template <class ParamType>
  std::string operator()(const TestParamInfo<ParamType>& info) const {
    return PrintToString(info.param);
  }
};

73
74
75
namespace internal {

// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
misterg's avatar
misterg committed
76
77
// Utility Functions

78
// Outputs a message explaining invalid registration of different
misterg's avatar
misterg committed
79
// fixture class for the same test suite. This may happen when
80
81
// TEST_P macro is used to define two tests with the same name
// but in different namespaces.
misterg's avatar
misterg committed
82
83
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
                                           CodeLocation code_location);
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

template <typename> class ParamGeneratorInterface;
template <typename> class ParamGenerator;

// Interface for iterating over elements provided by an implementation
// of ParamGeneratorInterface<T>.
template <typename T>
class ParamIteratorInterface {
 public:
  virtual ~ParamIteratorInterface() {}
  // A pointer to the base generator instance.
  // Used only for the purposes of iterator comparison
  // to make sure that two iterators belong to the same generator.
  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
  // Advances iterator to point to the next element
  // provided by the generator. The caller is responsible
  // for not calling Advance() on an iterator equal to
  // BaseGenerator()->End().
  virtual void Advance() = 0;
  // Clones the iterator object. Used for implementing copy semantics
  // of ParamIterator<T>.
  virtual ParamIteratorInterface* Clone() const = 0;
  // Dereferences the current iterator and provides (read-only) access
  // to the pointed value. It is the caller's responsibility not to call
  // Current() on an iterator equal to BaseGenerator()->End().
  // Used for implementing ParamGenerator<T>::operator*().
  virtual const T* Current() const = 0;
  // Determines whether the given iterator and other point to the same
  // element in the sequence generated by the generator.
  // Used for implementing ParamGenerator<T>::operator==().
  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
};

// Class iterating over elements provided by an implementation of
// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
// and implements the const forward iterator concept.
template <typename T>
class ParamIterator {
 public:
  typedef T value_type;
  typedef const T& reference;
  typedef ptrdiff_t difference_type;

  // ParamIterator assumes ownership of the impl_ pointer.
  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
  ParamIterator& operator=(const ParamIterator& other) {
    if (this != &other)
      impl_.reset(other.impl_->Clone());
    return *this;
  }

  const T& operator*() const { return *impl_->Current(); }
  const T* operator->() const { return impl_->Current(); }
  // Prefix version of operator++.
  ParamIterator& operator++() {
    impl_->Advance();
    return *this;
  }
  // Postfix version of operator++.
  ParamIterator operator++(int /*unused*/) {
    ParamIteratorInterface<T>* clone = impl_->Clone();
    impl_->Advance();
    return ParamIterator(clone);
  }
  bool operator==(const ParamIterator& other) const {
    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
  }
  bool operator!=(const ParamIterator& other) const {
    return !(*this == other);
  }

 private:
  friend class ParamGenerator<T>;
  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
misterg's avatar
misterg committed
158
  std::unique_ptr<ParamIteratorInterface<T> > impl_;
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
};

// ParamGeneratorInterface<T> is the binary interface to access generators
// defined in other translation units.
template <typename T>
class ParamGeneratorInterface {
 public:
  typedef T ParamType;

  virtual ~ParamGeneratorInterface() {}

  // Generator interface definition
  virtual ParamIteratorInterface<T>* Begin() const = 0;
  virtual ParamIteratorInterface<T>* End() const = 0;
};

175
// Wraps ParamGeneratorInterface<T> and provides general generator syntax
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// compatible with the STL Container concept.
// This class implements copy initialization semantics and the contained
// ParamGeneratorInterface<T> instance is shared among all copies
// of the original object. This is possible because that instance is immutable.
template<typename T>
class ParamGenerator {
 public:
  typedef ParamIterator<T> iterator;

  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}

  ParamGenerator& operator=(const ParamGenerator& other) {
    impl_ = other.impl_;
    return *this;
  }

  iterator begin() const { return iterator(impl_->Begin()); }
  iterator end() const { return iterator(impl_->End()); }

 private:
misterg's avatar
misterg committed
197
  std::shared_ptr<const ParamGeneratorInterface<T> > impl_;
198
199
200
201
202
203
204
205
206
207
208
209
};

// Generates values from a range of two comparable values. Can be used to
// generate sequences of user-defined types that implement operator+() and
// operator<().
// This class is used in the Range() function.
template <typename T, typename IncrementT>
class RangeGenerator : public ParamGeneratorInterface<T> {
 public:
  RangeGenerator(T begin, T end, IncrementT step)
      : begin_(begin), end_(end),
        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
Abseil Team's avatar
Abseil Team committed
210
  ~RangeGenerator() override {}
211

Abseil Team's avatar
Abseil Team committed
212
  ParamIteratorInterface<T>* Begin() const override {
213
214
    return new Iterator(this, begin_, 0, step_);
  }
Abseil Team's avatar
Abseil Team committed
215
  ParamIteratorInterface<T>* End() const override {
216
217
218
219
220
221
222
223
224
    return new Iterator(this, end_, end_index_, step_);
  }

 private:
  class Iterator : public ParamIteratorInterface<T> {
   public:
    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
             IncrementT step)
        : base_(base), value_(value), index_(index), step_(step) {}
Abseil Team's avatar
Abseil Team committed
225
    ~Iterator() override {}
226

Abseil Team's avatar
Abseil Team committed
227
    const ParamGeneratorInterface<T>* BaseGenerator() const override {
228
229
      return base_;
    }
Abseil Team's avatar
Abseil Team committed
230
    void Advance() override {
231
      value_ = static_cast<T>(value_ + step_);
232
233
      index_++;
    }
Abseil Team's avatar
Abseil Team committed
234
    ParamIteratorInterface<T>* Clone() const override {
235
236
      return new Iterator(*this);
    }
Abseil Team's avatar
Abseil Team committed
237
238
    const T* Current() const override { return &value_; }
    bool Equals(const ParamIteratorInterface<T>& other) const override {
239
240
241
242
243
244
245
246
247
248
249
250
      // Having the same base generator guarantees that the other
      // iterator is of the same type and we can downcast.
      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
          << "The program attempted to compare iterators "
          << "from different generators." << std::endl;
      const int other_index =
          CheckedDowncastToActualType<const Iterator>(&other)->index_;
      return index_ == other_index;
    }

   private:
    Iterator(const Iterator& other)
251
252
        : ParamIteratorInterface<T>(),
          base_(other.base_), value_(other.value_), index_(other.index_),
253
254
          step_(other.step_) {}

255
256
257
    // No implementation - assignment is unsupported.
    void operator=(const Iterator& other);

258
259
260
261
262
263
264
265
266
267
    const ParamGeneratorInterface<T>* const base_;
    T value_;
    int index_;
    const IncrementT step_;
  };  // class RangeGenerator::Iterator

  static int CalculateEndIndex(const T& begin,
                               const T& end,
                               const IncrementT& step) {
    int end_index = 0;
268
    for (T i = begin; i < end; i = static_cast<T>(i + step))
269
270
271
272
      end_index++;
    return end_index;
  }

273
274
275
  // No implementation - assignment is unsupported.
  void operator=(const RangeGenerator& other);

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  const T begin_;
  const T end_;
  const IncrementT step_;
  // The index for the end() iterator. All the elements in the generated
  // sequence are indexed (0-based) to aid iterator comparison.
  const int end_index_;
};  // class RangeGenerator


// Generates values from a pair of STL-style iterators. Used in the
// ValuesIn() function. The elements are copied from the source range
// since the source can be located on the stack, and the generator
// is likely to persist beyond that stack frame.
template <typename T>
class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
 public:
  template <typename ForwardIterator>
  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
      : container_(begin, end) {}
Abseil Team's avatar
Abseil Team committed
295
  ~ValuesInIteratorRangeGenerator() override {}
296

Abseil Team's avatar
Abseil Team committed
297
  ParamIteratorInterface<T>* Begin() const override {
298
299
    return new Iterator(this, container_.begin());
  }
Abseil Team's avatar
Abseil Team committed
300
  ParamIteratorInterface<T>* End() const override {
301
302
303
304
305
306
307
308
309
310
    return new Iterator(this, container_.end());
  }

 private:
  typedef typename ::std::vector<T> ContainerType;

  class Iterator : public ParamIteratorInterface<T> {
   public:
    Iterator(const ParamGeneratorInterface<T>* base,
             typename ContainerType::const_iterator iterator)
311
        : base_(base), iterator_(iterator) {}
Abseil Team's avatar
Abseil Team committed
312
    ~Iterator() override {}
313

Abseil Team's avatar
Abseil Team committed
314
    const ParamGeneratorInterface<T>* BaseGenerator() const override {
315
316
      return base_;
    }
Abseil Team's avatar
Abseil Team committed
317
    void Advance() override {
318
319
320
      ++iterator_;
      value_.reset();
    }
Abseil Team's avatar
Abseil Team committed
321
    ParamIteratorInterface<T>* Clone() const override {
322
323
324
325
326
327
328
329
330
      return new Iterator(*this);
    }
    // We need to use cached value referenced by iterator_ because *iterator_
    // can return a temporary object (and of type other then T), so just
    // having "return &*iterator_;" doesn't work.
    // value_ is updated here and not in Advance() because Advance()
    // can advance iterator_ beyond the end of the range, and we cannot
    // detect that fact. The client code, on the other hand, is
    // responsible for not calling Current() on an out-of-range iterator.
Abseil Team's avatar
Abseil Team committed
331
    const T* Current() const override {
332
      if (value_.get() == nullptr) value_.reset(new T(*iterator_));
333
334
      return value_.get();
    }
Abseil Team's avatar
Abseil Team committed
335
    bool Equals(const ParamIteratorInterface<T>& other) const override {
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
      // Having the same base generator guarantees that the other
      // iterator is of the same type and we can downcast.
      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
          << "The program attempted to compare iterators "
          << "from different generators." << std::endl;
      return iterator_ ==
          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
    }

   private:
    Iterator(const Iterator& other)
          // The explicit constructor call suppresses a false warning
          // emitted by gcc when supplied with the -Wextra option.
        : ParamIteratorInterface<T>(),
          base_(other.base_),
          iterator_(other.iterator_) {}

    const ParamGeneratorInterface<T>* const base_;
    typename ContainerType::const_iterator iterator_;
    // A cached value of *iterator_. We keep it here to allow access by
    // pointer in the wrapping iterator's operator->().
    // value_ needs to be mutable to be accessed in Current().
misterg's avatar
misterg committed
358
    // Use of std::unique_ptr helps manage cached value's lifetime,
359
    // which is bound by the lifespan of the iterator itself.
misterg's avatar
misterg committed
360
    mutable std::unique_ptr<const T> value_;
361
362
363
364
  };  // class ValuesInIteratorRangeGenerator::Iterator

  // No implementation - assignment is unsupported.
  void operator=(const ValuesInIteratorRangeGenerator& other);
365
366
367
368

  const ContainerType container_;
};  // class ValuesInIteratorRangeGenerator

369
370
371
372
373
374
375
376
377
378
379
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Default parameterized test name generator, returns a string containing the
// integer test parameter index.
template <class ParamType>
std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
  Message name_stream;
  name_stream << info.index;
  return name_stream.GetString();
}

misterg's avatar
misterg committed
380
381
382
template <typename T = int>
void TestNotEmpty() {
  static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
383
}
misterg's avatar
misterg committed
384
385
template <typename T = int>
void TestNotEmpty(const T&) {}
386

387
388
389
390
391
392
393
394
395
396
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Stores a parameter value and later creates tests parameterized with that
// value.
template <class TestClass>
class ParameterizedTestFactory : public TestFactoryBase {
 public:
  typedef typename TestClass::ParamType ParamType;
  explicit ParameterizedTestFactory(ParamType parameter) :
      parameter_(parameter) {}
Abseil Team's avatar
Abseil Team committed
397
  Test* CreateTest() override {
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
    TestClass::SetParam(&parameter_);
    return new TestClass();
  }

 private:
  const ParamType parameter_;

  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
};

// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// TestMetaFactoryBase is a base class for meta-factories that create
// test factories for passing into MakeAndRegisterTestInfo function.
template <class ParamType>
class TestMetaFactoryBase {
 public:
  virtual ~TestMetaFactoryBase() {}

  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
};

// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// TestMetaFactory creates test factories for passing into
// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
// ownership of test factory pointer, same factory object cannot be passed
misterg's avatar
misterg committed
425
// into that method twice. But ParameterizedTestSuiteInfo is going to call
426
427
// it for each Test/Parameter value combination. Thus it needs meta factory
// creator class.
misterg's avatar
misterg committed
428
template <class TestSuite>
429
class TestMetaFactory
misterg's avatar
misterg committed
430
    : public TestMetaFactoryBase<typename TestSuite::ParamType> {
431
 public:
misterg's avatar
misterg committed
432
  using ParamType = typename TestSuite::ParamType;
433
434
435

  TestMetaFactory() {}

Abseil Team's avatar
Abseil Team committed
436
  TestFactoryBase* CreateTestFactory(ParamType parameter) override {
misterg's avatar
misterg committed
437
    return new ParameterizedTestFactory<TestSuite>(parameter);
438
439
440
441
442
443
444
445
  }

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
};

// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
misterg's avatar
misterg committed
446
447
// ParameterizedTestSuiteInfoBase is a generic interface
// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
448
// accumulates test information provided by TEST_P macro invocations
misterg's avatar
misterg committed
449
// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations
450
// and uses that information to register all resulting test instances
misterg's avatar
misterg committed
451
452
// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
// a collection of pointers to the ParameterizedTestSuiteInfo objects
453
// and calls RegisterTests() on each of them when asked.
misterg's avatar
misterg committed
454
class ParameterizedTestSuiteInfoBase {
455
 public:
misterg's avatar
misterg committed
456
  virtual ~ParameterizedTestSuiteInfoBase() {}
457

misterg's avatar
misterg committed
458
459
  // Base part of test suite name for display purposes.
  virtual const std::string& GetTestSuiteName() const = 0;
460
  // Test case id to verify identity.
misterg's avatar
misterg committed
461
  virtual TypeId GetTestSuiteTypeId() const = 0;
462
  // UnitTest class invokes this method to register tests in this
misterg's avatar
misterg committed
463
  // test suite right before running them in RUN_ALL_TESTS macro.
Abseil Team's avatar
Abseil Team committed
464
  // This method should not be called more than once on any single
misterg's avatar
misterg committed
465
  // instance of a ParameterizedTestSuiteInfoBase derived class.
466
467
468
  virtual void RegisterTests() = 0;

 protected:
misterg's avatar
misterg committed
469
  ParameterizedTestSuiteInfoBase() {}
470
471

 private:
misterg's avatar
misterg committed
472
  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
473
474
475
476
};

// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
misterg's avatar
misterg committed
477
478
479
480
// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
// macro invocations for a particular test suite and generators
// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
// test suite. It registers tests with all values generated by all
481
// generators when asked.
misterg's avatar
misterg committed
482
483
template <class TestSuite>
class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
484
485
486
 public:
  // ParamType and GeneratorCreationFunc are private types but are required
  // for declarations of public methods AddTestPattern() and
misterg's avatar
misterg committed
487
488
  // AddTestSuiteInstantiation().
  using ParamType = typename TestSuite::ParamType;
489
490
  // A function that returns an instance of appropriate generator type.
  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
misterg's avatar
misterg committed
491
  using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
492

misterg's avatar
misterg committed
493
494
495
  explicit ParameterizedTestSuiteInfo(const char* name,
                                      CodeLocation code_location)
      : test_suite_name_(name), code_location_(code_location) {}
496
497

  // Test case base name for display purposes.
misterg's avatar
misterg committed
498
499
  const std::string& GetTestSuiteName() const override {
    return test_suite_name_;
Abseil Team's avatar
Abseil Team committed
500
  }
501
  // Test case id to verify identity.
misterg's avatar
misterg committed
502
  TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
503
504
  // TEST_P macro uses AddTestPattern() to record information
  // about a single test in a LocalTestInfo structure.
misterg's avatar
misterg committed
505
  // test_suite_name is the base name of the test suite (without invocation
506
507
  // prefix). test_base_name is the name of an individual test without
  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
misterg's avatar
misterg committed
508
509
  // test suite base name and DoBar is test base name.
  void AddTestPattern(const char* test_suite_name, const char* test_base_name,
510
                      TestMetaFactoryBase<ParamType>* meta_factory) {
misterg's avatar
misterg committed
511
    tests_.push_back(std::shared_ptr<TestInfo>(
misterg's avatar
misterg committed
512
        new TestInfo(test_suite_name, test_base_name, meta_factory)));
513
  }
misterg's avatar
misterg committed
514
  // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
515
  // about a generator.
misterg's avatar
misterg committed
516
517
518
519
  int AddTestSuiteInstantiation(const std::string& instantiation_name,
                                GeneratorCreationFunc* func,
                                ParamNameGeneratorFunc* name_func,
                                const char* file, int line) {
520
521
    instantiations_.push_back(
        InstantiationInfo(instantiation_name, func, name_func, file, line));
522
523
    return 0;  // Return value used only to run this method in namespace scope.
  }
misterg's avatar
misterg committed
524
525
  // UnitTest class invokes this method to register tests in this test suite
  // test suites right before running tests in RUN_ALL_TESTS macro.
Abseil Team's avatar
Abseil Team committed
526
  // This method should not be called more than once on any single
misterg's avatar
misterg committed
527
  // instance of a ParameterizedTestSuiteInfoBase derived class.
Abseil Team's avatar
Abseil Team committed
528
  // UnitTest has a guard to prevent from calling this method more than once.
Abseil Team's avatar
Abseil Team committed
529
  void RegisterTests() override {
530
531
    for (typename TestInfoContainer::iterator test_it = tests_.begin();
         test_it != tests_.end(); ++test_it) {
misterg's avatar
misterg committed
532
      std::shared_ptr<TestInfo> test_info = *test_it;
533
534
535
      for (typename InstantiationContainer::iterator gen_it =
               instantiations_.begin(); gen_it != instantiations_.end();
               ++gen_it) {
536
        const std::string& instantiation_name = gen_it->name;
537
538
539
540
        ParamGenerator<ParamType> generator((*gen_it->generator)());
        ParamNameGeneratorFunc* name_func = gen_it->name_func;
        const char* file = gen_it->file;
        int line = gen_it->line;
541

misterg's avatar
misterg committed
542
        std::string test_suite_name;
543
        if ( !instantiation_name.empty() )
misterg's avatar
misterg committed
544
545
          test_suite_name = instantiation_name + "/";
        test_suite_name += test_info->test_suite_base_name;
546

547
548
        size_t i = 0;
        std::set<std::string> test_param_names;
549
550
551
552
        for (typename ParamGenerator<ParamType>::iterator param_it =
                 generator.begin();
             param_it != generator.end(); ++param_it, ++i) {
          Message test_name_stream;
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

          std::string param_name = name_func(
              TestParamInfo<ParamType>(*param_it, i));

          GTEST_CHECK_(IsValidParamName(param_name))
              << "Parameterized test name '" << param_name
              << "' is invalid, in " << file
              << " line " << line << std::endl;

          GTEST_CHECK_(test_param_names.count(param_name) == 0)
              << "Duplicate parameterized test name '" << param_name
              << "', in " << file << " line " << line << std::endl;

          test_param_names.insert(param_name);

          test_name_stream << test_info->test_base_name << "/" << param_name;
569
          MakeAndRegisterTestInfo(
misterg's avatar
misterg committed
570
              test_suite_name.c_str(), test_name_stream.GetString().c_str(),
571
572
              nullptr,  // No type parameter.
              PrintToString(*param_it).c_str(), code_location_,
misterg's avatar
misterg committed
573
              GetTestSuiteTypeId(),
misterg's avatar
misterg committed
574
575
              SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
              SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
576
577
578
579
              test_info->test_meta_factory->CreateTestFactory(*param_it));
        }  // for param_it
      }  // for gen_it
    }  // for test_it
Abseil Team's avatar
Abseil Team committed
580
  }    // RegisterTests
581
582
583
584
585

 private:
  // LocalTestInfo structure keeps information about a single test registered
  // with TEST_P macro.
  struct TestInfo {
misterg's avatar
misterg committed
586
587
588
589
590
591
592
    TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
             TestMetaFactoryBase<ParamType>* a_test_meta_factory)
        : test_suite_base_name(a_test_suite_base_name),
          test_base_name(a_test_base_name),
          test_meta_factory(a_test_meta_factory) {}

    const std::string test_suite_base_name;
593
    const std::string test_base_name;
misterg's avatar
misterg committed
594
    const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
595
  };
misterg's avatar
misterg committed
596
  using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
misterg's avatar
misterg committed
597
  // Records data received from INSTANTIATE_TEST_SUITE_P macros:
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
  //  <Instantiation name, Sequence generator creation function,
  //     Name generator function, Source file, Source line>
  struct InstantiationInfo {
      InstantiationInfo(const std::string &name_in,
                        GeneratorCreationFunc* generator_in,
                        ParamNameGeneratorFunc* name_func_in,
                        const char* file_in,
                        int line_in)
          : name(name_in),
            generator(generator_in),
            name_func(name_func_in),
            file(file_in),
            line(line_in) {}

      std::string name;
      GeneratorCreationFunc* generator;
      ParamNameGeneratorFunc* name_func;
      const char* file;
      int line;
  };
  typedef ::std::vector<InstantiationInfo> InstantiationContainer;

  static bool IsValidParamName(const std::string& name) {
    // Check for empty string
    if (name.empty())
      return false;

    // Check for invalid characters
    for (std::string::size_type index = 0; index < name.size(); ++index) {
      if (!isalnum(name[index]) && name[index] != '_')
        return false;
    }

    return true;
  }
633

misterg's avatar
misterg committed
634
  const std::string test_suite_name_;
kosak's avatar
kosak committed
635
  CodeLocation code_location_;
636
637
638
  TestInfoContainer tests_;
  InstantiationContainer instantiations_;

misterg's avatar
misterg committed
639
640
641
642
643
644
645
646
  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
};  // class ParameterizedTestSuiteInfo

//  Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
template <class TestCase>
using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
647
648
649

// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
misterg's avatar
misterg committed
650
651
652
653
654
// ParameterizedTestSuiteRegistry contains a map of
// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
// ParameterizedTestSuiteInfo descriptors.
class ParameterizedTestSuiteRegistry {
655
 public:
misterg's avatar
misterg committed
656
657
658
659
  ParameterizedTestSuiteRegistry() {}
  ~ParameterizedTestSuiteRegistry() {
    for (auto& test_suite_info : test_suite_infos_) {
      delete test_suite_info;
660
661
662
663
    }
  }

  // Looks up or creates and returns a structure containing information about
misterg's avatar
misterg committed
664
665
666
667
668
669
670
671
  // tests and instantiations of a particular test suite.
  template <class TestSuite>
  ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
      const char* test_suite_name, CodeLocation code_location) {
    ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
    for (auto& test_suite_info : test_suite_infos_) {
      if (test_suite_info->GetTestSuiteName() == test_suite_name) {
        if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
672
673
          // Complain about incorrect usage of Google Test facilities
          // and terminate the program since we cannot guaranty correct
misterg's avatar
misterg committed
674
675
          // test suite setup and tear-down in this case.
          ReportInvalidTestSuiteType(test_suite_name, code_location);
676
          posix::Abort();
677
678
679
680
681
        } else {
          // At this point we are sure that the object we found is of the same
          // type we are looking for, so we downcast it to that type
          // without further checks.
          typed_test_info = CheckedDowncastToActualType<
misterg's avatar
misterg committed
682
              ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
683
684
685
686
        }
        break;
      }
    }
687
    if (typed_test_info == nullptr) {
misterg's avatar
misterg committed
688
689
690
      typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
          test_suite_name, code_location);
      test_suite_infos_.push_back(typed_test_info);
691
692
693
694
    }
    return typed_test_info;
  }
  void RegisterTests() {
misterg's avatar
misterg committed
695
696
    for (auto& test_suite_info : test_suite_infos_) {
      test_suite_info->RegisterTests();
697
698
    }
  }
misterg's avatar
misterg committed
699
700
701
702
703
704
705
706
707
//  Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
  template <class TestCase>
  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
      const char* test_case_name, CodeLocation code_location) {
    return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
  }

#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
708
709

 private:
misterg's avatar
misterg committed
710
  using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
711

misterg's avatar
misterg committed
712
  TestSuiteInfoContainer test_suite_infos_;
713

misterg's avatar
misterg committed
714
  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
715
716
};

misterg's avatar
misterg committed
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
}  // namespace internal

// Forward declarations of ValuesIn(), which is implemented in
// include/gtest/gtest-param-test.h.
template <class Container>
internal::ParamGenerator<typename Container::value_type> ValuesIn(
    const Container& container);

namespace internal {
// Used in the Values() function to provide polymorphic capabilities.

template <typename... Ts>
class ValueArray {
 public:
  ValueArray(Ts... v) : v_{std::move(v)...} {}

Abseil Team's avatar
Abseil Team committed
733
734
735
  template <typename T>
  operator ParamGenerator<T>() const {  // NOLINT
    return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
misterg's avatar
misterg committed
736
737
738
  }

 private:
Abseil Team's avatar
Abseil Team committed
739
740
741
742
743
744
  template <typename T, size_t... I>
  std::vector<T> MakeVector(IndexSequence<I...>) const {
    return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
  }

  FlatTuple<Ts...> v_;
misterg's avatar
misterg committed
745
746
};

Abseil Team's avatar
Abseil Team committed
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
template <typename... T>
class CartesianProductGenerator
    : public ParamGeneratorInterface<::std::tuple<T...>> {
 public:
  typedef ::std::tuple<T...> ParamType;

  CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
      : generators_(g) {}
  ~CartesianProductGenerator() override {}

  ParamIteratorInterface<ParamType>* Begin() const override {
    return new Iterator(this, generators_, false);
  }
  ParamIteratorInterface<ParamType>* End() const override {
    return new Iterator(this, generators_, true);
  }

 private:
  template <class I>
  class IteratorImpl;
  template <size_t... I>
  class IteratorImpl<IndexSequence<I...>>
      : public ParamIteratorInterface<ParamType> {
   public:
    IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
             const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
        : base_(base),
          begin_(std::get<I>(generators).begin()...),
          end_(std::get<I>(generators).end()...),
          current_(is_end ? end_ : begin_) {
      ComputeCurrentValue();
    }
    ~IteratorImpl() override {}

    const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
      return base_;
    }
    // Advance should not be called on beyond-of-range iterators
    // so no component iterators must be beyond end of range, either.
    void Advance() override {
      assert(!AtEnd());
      // Advance the last iterator.
      ++std::get<sizeof...(T) - 1>(current_);
      // if that reaches end, propagate that up.
      AdvanceIfEnd<sizeof...(T) - 1>();
      ComputeCurrentValue();
    }
    ParamIteratorInterface<ParamType>* Clone() const override {
      return new IteratorImpl(*this);
    }

    const ParamType* Current() const override { return current_value_.get(); }

    bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
      // Having the same base generator guarantees that the other
      // iterator is of the same type and we can downcast.
      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
          << "The program attempted to compare iterators "
          << "from different generators." << std::endl;
      const IteratorImpl* typed_other =
          CheckedDowncastToActualType<const IteratorImpl>(&other);

      // We must report iterators equal if they both point beyond their
      // respective ranges. That can happen in a variety of fashions,
      // so we have to consult AtEnd().
      if (AtEnd() && typed_other->AtEnd()) return true;

      bool same = true;
      bool dummy[] = {
          (same = same && std::get<I>(current_) ==
                              std::get<I>(typed_other->current_))...};
      (void)dummy;
      return same;
    }

   private:
    template <size_t ThisI>
    void AdvanceIfEnd() {
      if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;

      bool last = ThisI == 0;
      if (last) {
        // We are done. Nothing else to propagate.
        return;
      }

      constexpr size_t NextI = ThisI - (ThisI != 0);
      std::get<ThisI>(current_) = std::get<ThisI>(begin_);
      ++std::get<NextI>(current_);
      AdvanceIfEnd<NextI>();
    }

    void ComputeCurrentValue() {
      if (!AtEnd())
        current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
    }
    bool AtEnd() const {
      bool at_end = false;
      bool dummy[] = {
          (at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
      (void)dummy;
      return at_end;
    }

    const ParamGeneratorInterface<ParamType>* const base_;
    std::tuple<typename ParamGenerator<T>::iterator...> begin_;
    std::tuple<typename ParamGenerator<T>::iterator...> end_;
    std::tuple<typename ParamGenerator<T>::iterator...> current_;
    std::shared_ptr<ParamType> current_value_;
  };

  using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;

  std::tuple<ParamGenerator<T>...> generators_;
};

template <class... Gen>
class CartesianProductHolder {
 public:
  CartesianProductHolder(const Gen&... g) : generators_(g...) {}
  template <typename... T>
  operator ParamGenerator<::std::tuple<T...>>() const {
    return ParamGenerator<::std::tuple<T...>>(
        new CartesianProductGenerator<T...>(generators_));
  }

 private:
  std::tuple<Gen...> generators_;
};

877
878
879
880
}  // namespace internal
}  // namespace testing

#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_