diff options
author | Baruch Burstein <bmburstein@gmail.com> | 2022-07-31 19:50:04 (GMT) |
---|---|---|
committer | Baruch Burstein <bmburstein@gmail.com> | 2022-07-31 19:50:04 (GMT) |
commit | 3280a930bf3f2fdb77da9a6cdf5866ef22708ff1 (patch) | |
tree | 592fb787261482da935fd0286d306510b67688a1 /googletest/include | |
parent | dd7a9d29a33de34836c345c3b753d4eba15c5f44 (diff) | |
download | googletest-3280a930bf3f2fdb77da9a6cdf5866ef22708ff1.zip googletest-3280a930bf3f2fdb77da9a6cdf5866ef22708ff1.tar.gz googletest-3280a930bf3f2fdb77da9a6cdf5866ef22708ff1.tar.bz2 |
Custom type with Combine(). Fix for #3781
Diffstat (limited to 'googletest/include')
-rw-r--r-- | googletest/include/gtest/gtest-param-test.h | 40 | ||||
-rw-r--r-- | googletest/include/gtest/gtest.h | 2 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-param-util.h | 71 |
3 files changed, 112 insertions, 1 deletions
diff --git a/googletest/include/gtest/gtest-param-test.h b/googletest/include/gtest/gtest-param-test.h index b55119a..d59e552 100644 --- a/googletest/include/gtest/gtest-param-test.h +++ b/googletest/include/gtest/gtest-param-test.h @@ -407,6 +407,46 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) { return internal::CartesianProductHolder<Generator...>(g...); } +// ConvertGenerator() wraps a parameter generator in order to cast each prduced +// value through a known type before supplying it to the test suite +// +// Synopsis: +// ConvertGenerator<T>(gen) +// - returns a generator producing the same elements as generated by gen, but +// each element is static_cast to type T before being returned +// +// It is useful when using the Combine() function to get the generated +// parameters in a custom type instead of std::tuple +// +// Example: +// +// This will instantiate tests in test suite AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// struct ParamType { +// using TupleT = std::tuple<const char*, Color>; +// std::string animal; +// Color color; +// ParamType(TupleT t) : animal(std::get<0>(t)), color(std::get<1>(t)) {} +// }; +// class AnimalTest +// : public testing::TestWithParam<ParamType> {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest, +// ConvertGenerator<ParamType::TupleT>( +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE)))); +// +template <typename T> +internal::ParamConverterGenerator<T> ConvertGenerator( + internal::ParamGenerator<T> gen) { + return internal::ParamConverterGenerator<T>(gen); +} + #define TEST_P(test_suite_name, test_name) \ class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ : public test_suite_name { \ diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index d19a587..0c97f6c 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -1625,7 +1625,7 @@ class GTEST_API_ AssertHelper { // the GetParam() method. // // Use it with one of the parameter generator defining functions, like Range(), -// Values(), ValuesIn(), Bool(), and Combine(). +// Values(), ValuesIn(), Bool(), Combine(), and ConvertGenerator<T>(). // // class FooTest : public ::testing::TestWithParam<int> { // protected: diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h index e7af2f9..c643a3b 100644 --- a/googletest/include/gtest/internal/gtest-param-util.h +++ b/googletest/include/gtest/internal/gtest-param-util.h @@ -950,6 +950,77 @@ class CartesianProductHolder { std::tuple<Gen...> generators_; }; +template <typename From, typename To> +class ParamGeneratorConverter : public ParamGeneratorInterface<To> { + public: + ParamGeneratorConverter(ParamGenerator<From> gen) + : generator_(std::move(gen)) {} + + ParamIteratorInterface<To>* Begin() const override { + return new Iterator(this, generator_.begin(), generator_.end()); + } + ParamIteratorInterface<To>* End() const override { + return new Iterator(this, generator_.end(), generator_.end()); + } + + private: + class Iterator : public ParamIteratorInterface<To> { + public: + Iterator(const ParamGeneratorInterface<To>* base, ParamIterator<From> it, + ParamIterator<From> end) + : base_(base), it_(it), end_(end) { + if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_)); + } + ~Iterator() override {} + + const ParamGeneratorInterface<To>* BaseGenerator() const override { + return base_; + } + void Advance() override { + ++it_; + if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_)); + } + ParamIteratorInterface<To>* Clone() const override { + return new Iterator(*this); + } + const To* Current() const override { return value_.get(); } + bool Equals(const ParamIteratorInterface<To>& 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 ParamIterator<From> other_it = + CheckedDowncastToActualType<const Iterator>(&other)->it_; + return it_ == other_it; + } + + private: + Iterator(const Iterator& other) = default; + + const ParamGeneratorInterface<To>* const base_; + ParamIterator<From> it_; + ParamIterator<From> end_; + std::shared_ptr<To> value_; + }; // class ParamGeneratorConverter::Iterator + + ParamGenerator<From> generator_; +}; // class ParamGeneratorConverter + +template <class Gen> +class ParamConverterGenerator { + public: + ParamConverterGenerator(ParamGenerator<Gen> g) : generator(g) {} + + template <typename T> + operator ParamGenerator<T>() const { + return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator)); + } + + private: + ParamGenerator<Gen> generator; +}; + } // namespace internal } // namespace testing |