summaryrefslogtreecommitdiffstats
path: root/googletest/include
diff options
context:
space:
mode:
authorBaruch Burstein <bmburstein@gmail.com>2022-07-31 19:50:04 (GMT)
committerBaruch Burstein <bmburstein@gmail.com>2022-07-31 19:50:04 (GMT)
commit3280a930bf3f2fdb77da9a6cdf5866ef22708ff1 (patch)
tree592fb787261482da935fd0286d306510b67688a1 /googletest/include
parentdd7a9d29a33de34836c345c3b753d4eba15c5f44 (diff)
downloadgoogletest-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.h40
-rw-r--r--googletest/include/gtest/gtest.h2
-rw-r--r--googletest/include/gtest/internal/gtest-param-util.h71
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