summaryrefslogtreecommitdiffstats
path: root/googletest
diff options
context:
space:
mode:
authorCopybara-Service <copybara-worker@google.com>2022-10-04 14:06:58 (GMT)
committerCopybara-Service <copybara-worker@google.com>2022-10-04 14:06:58 (GMT)
commit8c4dc11539e814ad7e16f3063dd0e36c4fd5a9b4 (patch)
tree02f80ef4b0f00b51b2acfcfbaae99247d25191a4 /googletest
parent93f08be653c36ddc6943e9513fc14c7292b4d007 (diff)
parent79d0399dba364a335e3ca621a8cce091ef5706da (diff)
downloadgoogletest-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.h40
-rw-r--r--googletest/include/gtest/gtest.h2
-rw-r--r--googletest/include/gtest/internal/gtest-param-util.h72
-rw-r--r--googletest/test/googletest-param-test-test.cc78
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) {