diff options
author | Copybara-Service <copybara-worker@google.com> | 2022-10-04 14:06:58 (GMT) |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-10-04 14:06:58 (GMT) |
commit | 8c4dc11539e814ad7e16f3063dd0e36c4fd5a9b4 (patch) | |
tree | 02f80ef4b0f00b51b2acfcfbaae99247d25191a4 /googletest | |
parent | 93f08be653c36ddc6943e9513fc14c7292b4d007 (diff) | |
parent | 79d0399dba364a335e3ca621a8cce091ef5706da (diff) | |
download | googletest-8c4dc11539e814ad7e16f3063dd0e36c4fd5a9b4.zip googletest-8c4dc11539e814ad7e16f3063dd0e36c4fd5a9b4.tar.gz googletest-8c4dc11539e814ad7e16f3063dd0e36c4fd5a9b4.tar.bz2 |
Merge pull request #3967 from BMBurstein:custom_type_combine
PiperOrigin-RevId: 478775323
Change-Id: I92231bb8edd8e01b9b7cbe445c43dcf84f458521
Diffstat (limited to 'googletest')
-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 | 72 | ||||
-rw-r--r-- | googletest/test/googletest-param-test-test.cc | 78 |
4 files changed, 182 insertions, 10 deletions
diff --git a/googletest/include/gtest/gtest-param-test.h b/googletest/include/gtest/gtest-param-test.h index 2d38b96..10d6a07 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, private ::testing::internal::GTestNonCopyable {\ diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index 81e124f..7963e8c 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -1636,7 +1636,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..fb989e0 100644 --- a/googletest/include/gtest/internal/gtest-param-util.h +++ b/googletest/include/gtest/internal/gtest-param-util.h @@ -950,6 +950,78 @@ class CartesianProductHolder { std::tuple<Gen...> generators_; }; +template <typename From, typename To> +class ParamGeneratorConverter : public ParamGeneratorInterface<To> { + public: + ParamGeneratorConverter(ParamGenerator<From> gen) // NOLINT + : 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) // NOLINT + : generator_(std::move(g)) {} + + template <typename T> + operator ParamGenerator<T>() const { // NOLINT + return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator_)); + } + + private: + ParamGenerator<Gen> generator_; +}; + } // namespace internal } // namespace testing diff --git a/googletest/test/googletest-param-test-test.cc b/googletest/test/googletest-param-test-test.cc index e3090ae..63db286 100644 --- a/googletest/test/googletest-param-test-test.cc +++ b/googletest/test/googletest-param-test-test.cc @@ -40,6 +40,7 @@ #include <set> #include <sstream> #include <string> +#include <tuple> #include <vector> #include "gtest/gtest.h" @@ -51,6 +52,7 @@ using ::std::vector; using ::testing::AddGlobalTestEnvironment; using ::testing::Bool; using ::testing::Combine; +using ::testing::ConvertGenerator; using ::testing::Message; using ::testing::Range; using ::testing::TestWithParam; @@ -402,7 +404,7 @@ TEST(BoolTest, BoolWorks) { TEST(CombineTest, CombineWithTwoParameters) { const char* foo = "foo"; const char* bar = "bar"; - const ParamGenerator<std::tuple<const char*, int> > gen = + const ParamGenerator<std::tuple<const char*, int>> gen = Combine(Values(foo, bar), Values(3, 4)); std::tuple<const char*, int> expected_values[] = { @@ -413,7 +415,7 @@ TEST(CombineTest, CombineWithTwoParameters) { // Tests that Combine() with three parameters generates the expected sequence. TEST(CombineTest, CombineWithThreeParameters) { - const ParamGenerator<std::tuple<int, int, int> > gen = + const ParamGenerator<std::tuple<int, int, int>> gen = Combine(Values(0, 1), Values(3, 4), Values(5, 6)); std::tuple<int, int, int> expected_values[] = { std::make_tuple(0, 3, 5), std::make_tuple(0, 3, 6), @@ -427,7 +429,7 @@ TEST(CombineTest, CombineWithThreeParameters) { // sequence generates a sequence with the number of elements equal to the // number of elements in the sequence generated by the second parameter. TEST(CombineTest, CombineWithFirstParameterSingleValue) { - const ParamGenerator<std::tuple<int, int> > gen = + const ParamGenerator<std::tuple<int, int>> gen = Combine(Values(42), Values(0, 1)); std::tuple<int, int> expected_values[] = {std::make_tuple(42, 0), @@ -439,7 +441,7 @@ TEST(CombineTest, CombineWithFirstParameterSingleValue) { // sequence generates a sequence with the number of elements equal to the // number of elements in the sequence generated by the first parameter. TEST(CombineTest, CombineWithSecondParameterSingleValue) { - const ParamGenerator<std::tuple<int, int> > gen = + const ParamGenerator<std::tuple<int, int>> gen = Combine(Values(0, 1), Values(42)); std::tuple<int, int> expected_values[] = {std::make_tuple(0, 42), @@ -450,7 +452,7 @@ TEST(CombineTest, CombineWithSecondParameterSingleValue) { // Tests that when the first parameter produces an empty sequence, // Combine() produces an empty sequence, too. TEST(CombineTest, CombineWithFirstParameterEmptyRange) { - const ParamGenerator<std::tuple<int, int> > gen = + const ParamGenerator<std::tuple<int, int>> gen = Combine(Range(0, 0), Values(0, 1)); VerifyGeneratorIsEmpty(gen); } @@ -458,7 +460,7 @@ TEST(CombineTest, CombineWithFirstParameterEmptyRange) { // Tests that when the second parameter produces an empty sequence, // Combine() produces an empty sequence, too. TEST(CombineTest, CombineWithSecondParameterEmptyRange) { - const ParamGenerator<std::tuple<int, int> > gen = + const ParamGenerator<std::tuple<int, int>> gen = Combine(Values(0, 1), Range(1, 1)); VerifyGeneratorIsEmpty(gen); } @@ -469,7 +471,7 @@ TEST(CombineTest, CombineWithMaxNumberOfParameters) { const char* foo = "foo"; const char* bar = "bar"; const ParamGenerator< - std::tuple<const char*, int, int, int, int, int, int, int, int, int> > + std::tuple<const char*, int, int, int, int, int, int, int, int, int>> gen = Combine(Values(foo, bar), Values(1), Values(2), Values(3), Values(4), Values(5), Values(6), Values(7), Values(8), Values(9)); @@ -497,11 +499,11 @@ class NonDefaultConstructAssignString { }; TEST(CombineTest, NonDefaultConstructAssign) { - const ParamGenerator<std::tuple<int, NonDefaultConstructAssignString> > gen = + const ParamGenerator<std::tuple<int, NonDefaultConstructAssignString>> gen = Combine(Values(0, 1), Values(NonDefaultConstructAssignString("A"), NonDefaultConstructAssignString("B"))); - ParamGenerator<std::tuple<int, NonDefaultConstructAssignString> >::iterator + ParamGenerator<std::tuple<int, NonDefaultConstructAssignString>>::iterator it = gen.begin(); EXPECT_EQ(0, std::get<0>(*it)); @@ -523,6 +525,64 @@ TEST(CombineTest, NonDefaultConstructAssign) { EXPECT_TRUE(it == gen.end()); } +template <typename T> +class ConstructFromT { + public: + explicit ConstructFromT(const T& t) : t_(t) {} + template <typename... Args, + typename std::enable_if<sizeof...(Args) != 1, int>::type = 0> + ConstructFromT(Args&&... args) : t_(std::forward<Args>(args)...) {} + + bool operator==(const ConstructFromT& other) const { return other.t_ == t_; } + + const T& get() const { return t_; } + + private: + T t_; +}; + +TEST(ConvertTest, CombineWithTwoParameters) { + const char* foo = "foo"; + const char* bar = "bar"; + const ParamGenerator<ConstructFromT<std::tuple<const char*, int>>> gen = + ConvertGenerator<std::tuple<const char*, int>>( + Combine(Values(foo, bar), Values(3, 4))); + + ConstructFromT<std::tuple<const char*, int>> expected_values[] = { + {foo, 3}, {foo, 4}, {bar, 3}, {bar, 4}}; + VerifyGenerator(gen, expected_values); +} + +TEST(ConvertTest, NonDefaultConstructAssign) { + const ParamGenerator< + ConstructFromT<std::tuple<int, NonDefaultConstructAssignString>>> + gen = ConvertGenerator<std::tuple<int, NonDefaultConstructAssignString>>( + Combine(Values(0, 1), Values(NonDefaultConstructAssignString("A"), + NonDefaultConstructAssignString("B")))); + + ParamGenerator<ConstructFromT< + std::tuple<int, NonDefaultConstructAssignString>>>::iterator it = + gen.begin(); + + EXPECT_EQ(0, std::get<0>(it->get())); + EXPECT_EQ("A", std::get<1>(it->get()).str()); + ++it; + + EXPECT_EQ(0, std::get<0>(it->get())); + EXPECT_EQ("B", std::get<1>(it->get()).str()); + ++it; + + EXPECT_EQ(1, std::get<0>(it->get())); + EXPECT_EQ("A", std::get<1>(it->get()).str()); + ++it; + + EXPECT_EQ(1, std::get<0>(it->get())); + EXPECT_EQ("B", std::get<1>(it->get()).str()); + ++it; + + EXPECT_TRUE(it == gen.end()); +} + // Tests that an generator produces correct sequence after being // assigned from another generator. TEST(ParamGeneratorTest, AssignmentWorks) { |