aboutsummaryrefslogtreecommitdiff
path: root/googlemock/test
diff options
context:
space:
mode:
Diffstat (limited to 'googlemock/test')
-rw-r--r--googlemock/test/gmock-actions_test.cc78
-rw-r--r--googlemock/test/gmock-function-mocker_test.cc4
-rw-r--r--googlemock/test/gmock-matchers-arithmetic_test.cc237
-rw-r--r--googlemock/test/gmock-matchers-comparisons_test.cc136
-rw-r--r--googlemock/test/gmock-matchers-containers_test.cc336
-rw-r--r--googlemock/test/gmock-matchers-misc_test.cc105
-rw-r--r--googlemock/test/gmock-more-actions_test.cc49
-rw-r--r--googlemock/test/gmock-pp_test.cc2
-rw-r--r--googlemock/test/gmock-spec-builders_test.cc7
-rw-r--r--googlemock/test/gmock_link_test.h2
10 files changed, 857 insertions, 99 deletions
diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc
index da1675c525d1..46b0e91871c5 100644
--- a/googlemock/test/gmock-actions_test.cc
+++ b/googlemock/test/gmock-actions_test.cc
@@ -222,8 +222,8 @@ TEST(TypeTraits, IsInvocableRV) {
// In C++17 and above, where it's guaranteed that functions can return
// non-moveable objects, everything should work fine for non-moveable rsult
// types too.
-#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
- GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
+ // TODO(b/396121064) - Fix this test under MSVC
+#ifndef _MSC_VER
{
struct NonMoveable {
NonMoveable() = default;
@@ -244,7 +244,7 @@ TEST(TypeTraits, IsInvocableRV) {
static_assert(!internal::is_callable_r<int, Callable>::value);
static_assert(!internal::is_callable_r<NonMoveable, Callable, int>::value);
}
-#endif // C++17 and above
+#endif // _MSC_VER
// Nothing should choke when we try to call other arguments besides directly
// callable objects, but they should not show up as callable.
@@ -441,8 +441,8 @@ TEST(DefaultValueDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
EXPECT_EQ(0, DefaultValue<int>::Get());
- EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
- "");
+ EXPECT_DEATH_IF_SUPPORTED(
+ { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
}
TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
@@ -505,8 +505,8 @@ TEST(DefaultValueOfReferenceDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<int&>::Get(); }, "");
- EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
- "");
+ EXPECT_DEATH_IF_SUPPORTED(
+ { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
}
// Tests that ActionInterface can be implemented by defining the
@@ -1477,6 +1477,54 @@ TEST(DoAll, SupportsTypeErasedActions) {
}
}
+// A DoAll action should be convertible to a OnceAction, even when its component
+// sub-actions are user-provided types that define only an Action conversion
+// operator. If they supposed being called more than once then they also support
+// being called at most once.
+TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
+ // Simplest case: only one sub-action.
+ struct CustomFinal final {
+ operator Action<int()>() { // NOLINT
+ return Return(17);
+ }
+
+ operator Action<int(int, char)>() { // NOLINT
+ return Return(19);
+ }
+ };
+
+ {
+ OnceAction<int()> action = DoAll(CustomFinal{});
+ EXPECT_EQ(17, std::move(action).Call());
+ }
+
+ {
+ OnceAction<int(int, char)> action = DoAll(CustomFinal{});
+ EXPECT_EQ(19, std::move(action).Call(0, 0));
+ }
+
+ // It should also work with multiple sub-actions.
+ struct CustomInitial final {
+ operator Action<void()>() { // NOLINT
+ return [] {};
+ }
+
+ operator Action<void(int, char)>() { // NOLINT
+ return [] {};
+ }
+ };
+
+ {
+ OnceAction<int()> action = DoAll(CustomInitial{}, CustomFinal{});
+ EXPECT_EQ(17, std::move(action).Call());
+ }
+
+ {
+ OnceAction<int(int, char)> action = DoAll(CustomInitial{}, CustomFinal{});
+ EXPECT_EQ(19, std::move(action).Call(0, 0));
+ }
+}
+
// Tests using WithArgs and with an action that takes 1 argument.
TEST(WithArgsTest, OneArg) {
Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT
@@ -1597,6 +1645,22 @@ TEST(WithArgsTest, RefQualifiedInnerAction) {
EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
}
+// It should be fine to provide an lvalue WithArgsAction to WillOnce, even when
+// the inner action only wants to convert to OnceAction.
+TEST(WithArgsTest, ProvideAsLvalueToWillOnce) {
+ struct SomeAction {
+ operator OnceAction<int(int)>() const { // NOLINT
+ return [](const int arg) { return arg + 2; };
+ }
+ };
+
+ const auto wa = WithArg<1>(SomeAction{});
+
+ MockFunction<int(int, int)> mock;
+ EXPECT_CALL(mock, Call).WillOnce(wa);
+ EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
+}
+
#ifndef GTEST_OS_WINDOWS_MOBILE
class SetErrnoAndReturnTest : public testing::Test {
diff --git a/googlemock/test/gmock-function-mocker_test.cc b/googlemock/test/gmock-function-mocker_test.cc
index f7b31ae33852..cdac79b7e7cc 100644
--- a/googlemock/test/gmock-function-mocker_test.cc
+++ b/googlemock/test/gmock-function-mocker_test.cc
@@ -325,8 +325,8 @@ TYPED_TEST(FunctionMockerTest, MocksBinaryFunction) {
// Tests mocking a decimal function.
TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
- EXPECT_CALL(this->mock_foo_,
- Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi"))
+ EXPECT_CALL(this->mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100),
+ 5U, nullptr, "hi"))
.WillOnce(Return(5));
EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
diff --git a/googlemock/test/gmock-matchers-arithmetic_test.cc b/googlemock/test/gmock-matchers-arithmetic_test.cc
index f176962855ea..b6c35119e29b 100644
--- a/googlemock/test/gmock-matchers-arithmetic_test.cc
+++ b/googlemock/test/gmock-matchers-arithmetic_test.cc
@@ -34,9 +34,12 @@
#include <cmath>
#include <limits>
#include <memory>
+#include <ostream>
#include <string>
+#include "gmock/gmock.h"
#include "test/gmock-matchers_test.h"
+#include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter
@@ -396,6 +399,188 @@ TEST(NanSensitiveDoubleNearTest, CanDescribeSelfWithNaNs) {
EXPECT_EQ("are an almost-equal pair", Describe(m));
}
+// Tests that DistanceFrom() can describe itself properly.
+TEST(DistanceFrom, CanDescribeSelf) {
+ Matcher<double> m = DistanceFrom(1.5, Lt(0.1));
+ EXPECT_EQ(Describe(m), "is < 0.1 away from 1.5");
+
+ m = DistanceFrom(2.5, Gt(0.2));
+ EXPECT_EQ(Describe(m), "is > 0.2 away from 2.5");
+}
+
+// Tests that DistanceFrom() can explain match failure.
+TEST(DistanceFrom, CanExplainMatchFailure) {
+ Matcher<double> m = DistanceFrom(1.5, Lt(0.1));
+ EXPECT_EQ(Explain(m, 2.0), "which is 0.5 away from 1.5");
+}
+
+// Tests that DistanceFrom() matches a double that is within the given range of
+// the given value.
+TEST(DistanceFrom, MatchesDoubleWithinRange) {
+ const Matcher<double> m = DistanceFrom(0.5, Le(0.1));
+ EXPECT_TRUE(m.Matches(0.45));
+ EXPECT_TRUE(m.Matches(0.5));
+ EXPECT_TRUE(m.Matches(0.55));
+ EXPECT_FALSE(m.Matches(0.39));
+ EXPECT_FALSE(m.Matches(0.61));
+}
+
+// Tests that DistanceFrom() matches a double reference that is within the given
+// range of the given value.
+TEST(DistanceFrom, MatchesDoubleRefWithinRange) {
+ const Matcher<const double&> m = DistanceFrom(0.5, Le(0.1));
+ EXPECT_TRUE(m.Matches(0.45));
+ EXPECT_TRUE(m.Matches(0.5));
+ EXPECT_TRUE(m.Matches(0.55));
+ EXPECT_FALSE(m.Matches(0.39));
+ EXPECT_FALSE(m.Matches(0.61));
+}
+
+// Tests that DistanceFrom() can be implicitly converted to a matcher depending
+// on the type of the argument.
+TEST(DistanceFrom, CanBeImplicitlyConvertedToMatcher) {
+ EXPECT_THAT(0.58, DistanceFrom(0.5, Le(0.1)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5, Le(0.1))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5f, Le(0.1f)));
+ EXPECT_THAT(0.7f, Not(DistanceFrom(0.5f, Le(0.1f))));
+}
+
+// Tests that DistanceFrom() can be used on compatible types (i.e. not
+// everything has to be of the same type).
+TEST(DistanceFrom, CanBeUsedOnCompatibleTypes) {
+ EXPECT_THAT(0.58, DistanceFrom(0.5, Le(0.1f)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5, Le(0.1f))));
+
+ EXPECT_THAT(0.58, DistanceFrom(0.5f, Le(0.1)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5f, Le(0.1))));
+
+ EXPECT_THAT(0.58, DistanceFrom(0.5f, Le(0.1f)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5f, Le(0.1f))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5, Le(0.1)));
+ EXPECT_THAT(0.2f, Not(DistanceFrom(0.5, Le(0.1))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5, Le(0.1f)));
+ EXPECT_THAT(0.2f, Not(DistanceFrom(0.5, Le(0.1f))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5f, Le(0.1)));
+ EXPECT_THAT(0.2f, Not(DistanceFrom(0.5f, Le(0.1))));
+}
+
+// A 2-dimensional point. For testing using DistanceFrom() with a custom type
+// that doesn't have a built-in distance function.
+class Point {
+ public:
+ Point(double x, double y) : x_(x), y_(y) {}
+ double x() const { return x_; }
+ double y() const { return y_; }
+
+ private:
+ double x_;
+ double y_;
+};
+
+// Returns the distance between two points.
+double PointDistance(const Point& lhs, const Point& rhs) {
+ return std::sqrt(std::pow(lhs.x() - rhs.x(), 2) +
+ std::pow(lhs.y() - rhs.y(), 2));
+}
+
+// Tests that DistanceFrom() can be used on a type with a custom distance
+// function.
+TEST(DistanceFrom, CanBeUsedOnTypeWithCustomDistanceFunction) {
+ const Matcher<Point> m =
+ DistanceFrom(Point(0.5, 0.5), PointDistance, Le(0.1));
+ EXPECT_THAT(Point(0.45, 0.45), m);
+ EXPECT_THAT(Point(0.2, 0.45), Not(m));
+}
+
+// A wrapper around a double value. For testing using DistanceFrom() with a
+// custom type that has neither a built-in distance function nor a built-in
+// distance comparator.
+class Double {
+ public:
+ explicit Double(double value) : value_(value) {}
+ Double(const Double& other) = default;
+ double value() const { return value_; }
+
+ // Defines how to print a Double value. We don't use the AbslStringify API
+ // because googletest doesn't require absl yet.
+ friend void PrintTo(const Double& value, std::ostream* os) {
+ *os << "Double(" << value.value() << ")";
+ }
+
+ private:
+ double value_;
+};
+
+// Returns the distance between two Double values.
+Double DoubleDistance(Double lhs, Double rhs) {
+ return Double(std::abs(lhs.value() - rhs.value()));
+}
+
+MATCHER_P(DoubleLe, rhs, (negation ? "is > " : "is <= ") + PrintToString(rhs)) {
+ return arg.value() <= rhs.value();
+}
+
+// Tests that DistanceFrom() can describe itself properly for a type with a
+// custom printer.
+TEST(DistanceFrom, CanDescribeWithCustomPrinter) {
+ const Matcher<Double> m =
+ DistanceFrom(Double(0.5), DoubleDistance, DoubleLe(Double(0.1)));
+ EXPECT_EQ(Describe(m), "is <= Double(0.1) away from Double(0.5)");
+ EXPECT_EQ(DescribeNegation(m), "is > Double(0.1) away from Double(0.5)");
+}
+
+// Tests that DistanceFrom() can be used with a custom distance function and
+// comparator.
+TEST(DistanceFrom, CanCustomizeDistanceAndComparator) {
+ const Matcher<Double> m =
+ DistanceFrom(Double(0.5), DoubleDistance, DoubleLe(Double(0.1)));
+ EXPECT_TRUE(m.Matches(Double(0.45)));
+ EXPECT_TRUE(m.Matches(Double(0.5)));
+ EXPECT_FALSE(m.Matches(Double(0.39)));
+ EXPECT_FALSE(m.Matches(Double(0.61)));
+}
+
+// For testing using DistanceFrom() with a type that supports both - and abs.
+class Float {
+ public:
+ explicit Float(float value) : value_(value) {}
+ Float(const Float& other) = default;
+ float value() const { return value_; }
+
+ private:
+ float value_ = 0.0f;
+};
+
+// Returns the difference between two Float values. This must be defined in the
+// same namespace as Float.
+Float operator-(const Float& lhs, const Float& rhs) {
+ return Float(lhs.value() - rhs.value());
+}
+
+// Returns the absolute value of a Float value. This must be defined in the
+// same namespace as Float.
+Float abs(Float value) { return Float(std::abs(value.value())); }
+
+// Returns true if and only if the first Float value is less than the second
+// Float value. This must be defined in the same namespace as Float.
+bool operator<(const Float& lhs, const Float& rhs) {
+ return lhs.value() < rhs.value();
+}
+
+// Tests that DistanceFrom() can be used with a type that supports both - and
+// abs.
+TEST(DistanceFrom, CanBeUsedWithTypeThatSupportsBothMinusAndAbs) {
+ const Matcher<Float> m = DistanceFrom(Float(0.5f), Lt(Float(0.1f)));
+ EXPECT_TRUE(m.Matches(Float(0.45f)));
+ EXPECT_TRUE(m.Matches(Float(0.55f)));
+ EXPECT_FALSE(m.Matches(Float(0.39f)));
+ EXPECT_FALSE(m.Matches(Float(0.61f)));
+}
+
// Tests that Not(m) matches any value that doesn't match m.
TEST(NotTest, NegatesMatcher) {
Matcher<int> m;
@@ -559,10 +744,9 @@ TEST_P(AllOfTestP, ExplainsResult) {
Matcher<int> m;
// Successful match. Both matchers need to explain. The second
- // matcher doesn't give an explanation, so only the first matcher's
- // explanation is printed.
+ // matcher doesn't give an explanation, so the matcher description is used.
m = AllOf(GreaterThan(10), Lt(30));
- EXPECT_EQ("which is 15 more than 10", Explain(m, 25));
+ EXPECT_EQ("which is 15 more than 10, and is < 30", Explain(m, 25));
// Successful match. Both matchers need to explain.
m = AllOf(GreaterThan(10), GreaterThan(20));
@@ -572,8 +756,9 @@ TEST_P(AllOfTestP, ExplainsResult) {
// Successful match. All matchers need to explain. The second
// matcher doesn't given an explanation.
m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20));
- EXPECT_EQ("which is 15 more than 10, and which is 5 more than 20",
- Explain(m, 25));
+ EXPECT_EQ(
+ "which is 15 more than 10, and is < 30, and which is 5 more than 20",
+ Explain(m, 25));
// Successful match. All matchers need to explain.
m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
@@ -588,10 +773,10 @@ TEST_P(AllOfTestP, ExplainsResult) {
EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
// Failed match. The second matcher, which failed, needs to
- // explain. Since it doesn't given an explanation, nothing is
+ // explain. Since it doesn't given an explanation, the matcher text is
// printed.
m = AllOf(GreaterThan(10), Lt(30));
- EXPECT_EQ("", Explain(m, 40));
+ EXPECT_EQ("which doesn't match (is < 30)", Explain(m, 40));
// Failed match. The second matcher, which failed, needs to
// explain.
@@ -774,45 +959,43 @@ TEST(AnyOfTest, AnyOfMatcherSafelyCastsMonomorphicMatchers) {
TEST_P(AnyOfTestP, ExplainsResult) {
Matcher<int> m;
- // Failed match. Both matchers need to explain. The second
- // matcher doesn't give an explanation, so only the first matcher's
- // explanation is printed.
+ // Failed match. The second matcher have no explanation (description is used).
m = AnyOf(GreaterThan(10), Lt(0));
- EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
+ EXPECT_EQ("which is 5 less than 10, and isn't < 0", Explain(m, 5));
- // Failed match. Both matchers need to explain.
+ // Failed match. Both matchers have explanations.
m = AnyOf(GreaterThan(10), GreaterThan(20));
EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
Explain(m, 5));
- // Failed match. All matchers need to explain. The second
- // matcher doesn't given an explanation.
+ // Failed match. The middle matcher have no explanation.
m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
- EXPECT_EQ("which is 5 less than 10, and which is 25 less than 30",
- Explain(m, 5));
+ EXPECT_EQ(
+ "which is 5 less than 10, and isn't > 20, and which is 25 less than 30",
+ Explain(m, 5));
- // Failed match. All matchers need to explain.
+ // Failed match. All three matchers have explanations.
m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
EXPECT_EQ(
"which is 5 less than 10, and which is 15 less than 20, "
"and which is 25 less than 30",
Explain(m, 5));
- // Successful match. The first matcher, which succeeded, needs to
- // explain.
+ // Successful match. The first macher succeeded and has explanation.
m = AnyOf(GreaterThan(10), GreaterThan(20));
EXPECT_EQ("which is 5 more than 10", Explain(m, 15));
- // Successful match. The second matcher, which succeeded, needs to
- // explain. Since it doesn't given an explanation, nothing is
- // printed.
- m = AnyOf(GreaterThan(10), Lt(30));
- EXPECT_EQ("", Explain(m, 0));
-
- // Successful match. The second matcher, which succeeded, needs to
- // explain.
+ // Successful match. The second matcher succeeded and has explanation.
m = AnyOf(GreaterThan(30), GreaterThan(20));
EXPECT_EQ("which is 5 more than 20", Explain(m, 25));
+
+ // Successful match. The first matcher succeeded and has no explanation.
+ m = AnyOf(Gt(10), Lt(20));
+ EXPECT_EQ("which matches (is > 10)", Explain(m, 15));
+
+ // Successful match. The second matcher succeeded and has no explanation.
+ m = AnyOf(Gt(30), Gt(20));
+ EXPECT_EQ("which matches (is > 20)", Explain(m, 25));
}
// The following predicate function and predicate functor are for
diff --git a/googlemock/test/gmock-matchers-comparisons_test.cc b/googlemock/test/gmock-matchers-comparisons_test.cc
index 5b75b457be04..87eca08f5ad2 100644
--- a/googlemock/test/gmock-matchers-comparisons_test.cc
+++ b/googlemock/test/gmock-matchers-comparisons_test.cc
@@ -33,17 +33,19 @@
#include <functional>
#include <memory>
+#include <optional>
#include <string>
#include <tuple>
#include <vector>
+#include "gmock/gmock.h"
#include "test/gmock-matchers_test.h"
+#include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
-
namespace testing {
namespace gmock_matchers_test {
namespace {
@@ -410,9 +412,27 @@ class IntValue {
int value_;
};
+// For testing casting matchers between compatible types. This is similar to
+// IntValue, but takes a non-const reference to the value, showing MatcherCast
+// works with such types (and doesn't, for example, use a const ref internally).
+class MutableIntView {
+ public:
+ // An int& can be statically (although not implicitly) cast to a
+ // MutableIntView.
+ explicit MutableIntView(int& a_value) : value_(a_value) {}
+
+ int& value() const { return value_; }
+
+ private:
+ int& value_;
+};
+
// For testing casting matchers between compatible types.
bool IsPositiveIntValue(const IntValue& foo) { return foo.value() > 0; }
+// For testing casting matchers between compatible types.
+bool IsPositiveMutableIntView(MutableIntView foo) { return foo.value() > 0; }
+
// Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T
// can be statically converted to U.
TEST(MatcherCastTest, FromCompatibleType) {
@@ -428,14 +448,34 @@ TEST(MatcherCastTest, FromCompatibleType) {
// predicate.
EXPECT_TRUE(m4.Matches(1));
EXPECT_FALSE(m4.Matches(0));
+
+ Matcher<MutableIntView> m5 = Truly(IsPositiveMutableIntView);
+ Matcher<int> m6 = MatcherCast<int>(m5);
+ // In the following, the arguments 1 and 0 are statically converted to
+ // MutableIntView objects, and then tested by the IsPositiveMutableIntView()
+ // predicate.
+ EXPECT_TRUE(m6.Matches(1));
+ EXPECT_FALSE(m6.Matches(0));
}
// Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>.
TEST(MatcherCastTest, FromConstReferenceToNonReference) {
- Matcher<const int&> m1 = Eq(0);
+ int n = 0;
+ Matcher<const int&> m1 = Ref(n);
Matcher<int> m2 = MatcherCast<int>(m1);
- EXPECT_TRUE(m2.Matches(0));
- EXPECT_FALSE(m2.Matches(1));
+ int n1 = 0;
+ EXPECT_TRUE(m2.Matches(n));
+ EXPECT_FALSE(m2.Matches(n1));
+}
+
+// Tests that MatcherCast<T&>(m) works when m is a Matcher<const T&>.
+TEST(MatcherCastTest, FromConstReferenceToReference) {
+ int n = 0;
+ Matcher<const int&> m1 = Ref(n);
+ Matcher<int&> m2 = MatcherCast<int&>(m1);
+ int n1 = 0;
+ EXPECT_TRUE(m2.Matches(n));
+ EXPECT_FALSE(m2.Matches(n1));
}
// Tests that MatcherCast<T>(m) works when m is a Matcher<T&>.
@@ -444,6 +484,12 @@ TEST(MatcherCastTest, FromReferenceToNonReference) {
Matcher<int> m2 = MatcherCast<int>(m1);
EXPECT_TRUE(m2.Matches(0));
EXPECT_FALSE(m2.Matches(1));
+
+ // Of course, reference identity isn't preserved since a copy is required.
+ int n = 0;
+ Matcher<int&> m3 = Ref(n);
+ Matcher<int> m4 = MatcherCast<int>(m3);
+ EXPECT_FALSE(m4.Matches(n));
}
// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
@@ -648,6 +694,16 @@ TEST(SafeMatcherCastTest, FromBaseClass) {
EXPECT_FALSE(m4.Matches(d2));
}
+// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<const T&>.
+TEST(SafeMatcherCastTest, FromConstReferenceToNonReference) {
+ int n = 0;
+ Matcher<const int&> m1 = Ref(n);
+ Matcher<int> m2 = SafeMatcherCast<int>(m1);
+ int n1 = 0;
+ EXPECT_TRUE(m2.Matches(n));
+ EXPECT_FALSE(m2.Matches(n1));
+}
+
// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>.
TEST(SafeMatcherCastTest, FromConstReferenceToReference) {
int n = 0;
@@ -2334,9 +2390,79 @@ TEST(ExplainMatchResultTest, AllOf_True_True) {
EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6));
}
+// Tests that when AllOf() succeeds, but matchers have no explanation,
+// the matcher description is used.
TEST(ExplainMatchResultTest, AllOf_True_True_2) {
const Matcher<int> m = AllOf(Ge(2), Le(3));
- EXPECT_EQ("", Explain(m, 2));
+ EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
+}
+
+// A matcher that records whether the listener was interested.
+template <typename T>
+class CountingMatcher : public MatcherInterface<T> {
+ public:
+ explicit CountingMatcher(const Matcher<T>& base_matcher,
+ std::vector<bool>* listener_interested)
+ : base_matcher_(base_matcher),
+ listener_interested_(listener_interested) {}
+
+ bool MatchAndExplain(T x, MatchResultListener* listener) const override {
+ listener_interested_->push_back(listener->IsInterested());
+ return base_matcher_.MatchAndExplain(x, listener);
+ }
+
+ void DescribeTo(ostream* os) const override { base_matcher_.DescribeTo(os); }
+
+ private:
+ Matcher<T> base_matcher_;
+ std::vector<bool>* listener_interested_;
+};
+
+TEST(AllOfTest, DoesNotFormatChildMatchersWhenNotInterested) {
+ std::vector<bool> listener_interested;
+ Matcher<int> matcher =
+ MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
+ EXPECT_TRUE(matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ Matcher<int> all_of_matcher = AllOf(matcher, matcher);
+ EXPECT_TRUE(all_of_matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false, false));
+ listener_interested.clear();
+ EXPECT_FALSE(all_of_matcher.Matches(0));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+}
+
+TEST(AnyOfTest, DoesNotFormatChildMatchersWhenNotInterested) {
+ std::vector<bool> listener_interested;
+ Matcher<int> matcher =
+ MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
+ EXPECT_TRUE(matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ Matcher<int> any_of_matcher = AnyOf(matcher, matcher);
+ EXPECT_TRUE(any_of_matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ EXPECT_FALSE(any_of_matcher.Matches(0));
+ EXPECT_THAT(listener_interested, ElementsAre(false, false));
+}
+
+TEST(OptionalTest, DoesNotFormatChildMatcherWhenNotInterested) {
+ std::vector<bool> listener_interested;
+ Matcher<int> matcher =
+ MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
+ EXPECT_TRUE(matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ Matcher<std::optional<int>> optional_matcher = Optional(matcher);
+ EXPECT_FALSE(optional_matcher.Matches(std::nullopt));
+ EXPECT_THAT(listener_interested, ElementsAre());
+ EXPECT_TRUE(optional_matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ EXPECT_FALSE(matcher.Matches(0));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
}
INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
diff --git a/googlemock/test/gmock-matchers-containers_test.cc b/googlemock/test/gmock-matchers-containers_test.cc
index acea4ec357e0..e9f1a02d85d1 100644
--- a/googlemock/test/gmock-matchers-containers_test.cc
+++ b/googlemock/test/gmock-matchers-containers_test.cc
@@ -33,6 +33,7 @@
#include <algorithm>
#include <array>
+#include <cstddef>
#include <deque>
#include <forward_list>
#include <iterator>
@@ -43,14 +44,14 @@
#include <tuple>
#include <vector>
+#include "gmock/gmock.h"
+#include "test/gmock-matchers_test.h"
#include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
-#include "test/gmock-matchers_test.h"
-
namespace testing {
namespace gmock_matchers_test {
namespace {
@@ -1204,13 +1205,16 @@ TEST(SizeIsTest, ExplainsResult) {
vector<int> container;
EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container));
EXPECT_EQ("whose size 0 matches", Explain(m2, container));
- EXPECT_EQ("whose size 0 matches", Explain(m3, container));
+ EXPECT_EQ("whose size 0 matches, which matches (is equal to 0)",
+ Explain(m3, container));
EXPECT_EQ("whose size 0 doesn't match", Explain(m4, container));
container.push_back(0);
container.push_back(0);
EXPECT_EQ("whose size 2 matches", Explain(m1, container));
EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container));
- EXPECT_EQ("whose size 2 doesn't match", Explain(m3, container));
+ EXPECT_EQ(
+ "whose size 2 doesn't match, isn't equal to 0, and isn't equal to 3",
+ Explain(m3, container));
EXPECT_EQ("whose size 2 matches", Explain(m4, container));
}
@@ -1268,10 +1272,11 @@ TEST(WhenSortedByTest, CanDescribeSelf) {
TEST(WhenSortedByTest, ExplainsMatchResult) {
const int a[] = {2, 1};
- EXPECT_EQ("which is { 1, 2 } when sorted, whose element #0 doesn't match",
- Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a));
- EXPECT_EQ("which is { 1, 2 } when sorted",
- Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a));
+ EXPECT_EQ(
+ Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a),
+ "which is { 1, 2 } when sorted, whose element #0 (1) isn't equal to 2");
+ EXPECT_EQ(Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a),
+ "which is { 1, 2 } when sorted");
}
// WhenSorted() is a simple wrapper on WhenSortedBy(). Hence we don't
@@ -1475,8 +1480,10 @@ TEST_P(BeginEndDistanceIsTestP, ExplainsResult) {
Explain(m1, container));
EXPECT_EQ("whose distance between begin() and end() 0 matches",
Explain(m2, container));
- EXPECT_EQ("whose distance between begin() and end() 0 matches",
- Explain(m3, container));
+ EXPECT_EQ(
+ "whose distance between begin() and end() 0 matches, which matches (is "
+ "equal to 0)",
+ Explain(m3, container));
EXPECT_EQ(
"whose distance between begin() and end() 0 doesn't match, which is 1 "
"less than 1",
@@ -1487,8 +1494,10 @@ TEST_P(BeginEndDistanceIsTestP, ExplainsResult) {
Explain(m1, container));
EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
Explain(m2, container));
- EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
- Explain(m3, container));
+ EXPECT_EQ(
+ "whose distance between begin() and end() 2 doesn't match, isn't equal "
+ "to 0, and isn't equal to 3",
+ Explain(m3, container));
EXPECT_EQ(
"whose distance between begin() and end() 2 matches, which is 1 more "
"than 1",
@@ -1768,6 +1777,295 @@ TEST(IsSubsetOfTest, WorksWithMoveOnly) {
helper.Call(MakeUniquePtrs({2}));
}
+// A container whose iterator returns a temporary. This can iterate over the
+// characters in a string.
+class CharString {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary.
+TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInIterator) {
+ CharString s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary.
+TEST(ElementsAreArrayTest, WorksWithContainerThatReturnsTempInIterator) {
+ CharString s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
+// A container whose iterator returns a temporary and is not copy-assignable.
+// This simulates the behavior of the proxy object returned by absl::StrSplit().
+class CharString2 {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ // Make const_iterator copy-constructible but not copy-assignable,
+ // simulating the behavior of the proxy object returned by absl::StrSplit().
+ const_iterator(const const_iterator&) = default;
+ const_iterator& operator=(const const_iterator&) = delete;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString2(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary and is not copy-assignable.
+TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInUnassignableIterator) {
+ CharString2 s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary and is not copy-assignable.
+TEST(ElementsAreArrayTest,
+ WorksWithContainerThatReturnsTempInUnassignableIterator) {
+ CharString2 s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
+// A container whose iterator returns a temporary and is neither
+// copy-constructible nor copy-assignable.
+class CharString3 {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ // Make const_iterator neither copy-constructible nor copy-assignable.
+ const_iterator(const const_iterator&) = delete;
+ const_iterator& operator=(const const_iterator&) = delete;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString3(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary and is neither copy-constructible nor copy-assignable.
+TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInUncopyableIterator) {
+ CharString3 s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary and is neither copy-constructible nor copy-assignable.
+TEST(ElementsAreArrayTest,
+ WorksWithContainerThatReturnsTempInUncopyableIterator) {
+ CharString3 s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
+// A container whose iterator returns a temporary, is neither
+// copy-constructible nor copy-assignable, and has no member types.
+class CharString4 {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ // Do not define difference_type, etc.
+
+ // Make const_iterator neither copy-constructible nor copy-assignable.
+ const_iterator(const const_iterator&) = delete;
+ const_iterator& operator=(const const_iterator&) = delete;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString4(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary, is neither copy-constructible nor copy-assignable, and has no
+// member types.
+TEST(ElementsAreTest, WorksWithContainerWithIteratorWithNoMemberTypes) {
+ CharString4 s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary, is neither copy-constructible nor copy-assignable, and has no
+// member types.
+TEST(ElementsAreArrayTest, WorksWithContainerWithIteratorWithNoMemberTypes) {
+ CharString4 s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
// Tests using ElementsAre() and ElementsAreArray() with stream-like
// "containers".
@@ -2148,7 +2446,7 @@ TEST_P(EachTestP, ExplainsMatchResultCorrectly) {
Matcher<set<int>> m = Each(2);
EXPECT_EQ("", Explain(m, a));
- Matcher<const int(&)[1]> n = Each(1); // NOLINT
+ Matcher<const int (&)[1]> n = Each(1); // NOLINT
const int b[1] = {1};
EXPECT_EQ("", Explain(n, b));
@@ -2283,7 +2581,7 @@ TEST(PointwiseTest, MakesCopyOfRhs) {
rhs.push_back(4);
int lhs[] = {1, 2};
- const Matcher<const int(&)[2]> m = Pointwise(IsHalfOf(), rhs);
+ const Matcher<const int (&)[2]> m = Pointwise(IsHalfOf(), rhs);
EXPECT_THAT(lhs, m);
// Changing rhs now shouldn't affect m, which made a copy of rhs.
@@ -2411,7 +2709,7 @@ TEST(UnorderedPointwiseTest, MakesCopyOfRhs) {
rhs.push_back(4);
int lhs[] = {2, 1};
- const Matcher<const int(&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
+ const Matcher<const int (&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
EXPECT_THAT(lhs, m);
// Changing rhs now shouldn't affect m, which made a copy of rhs.
@@ -2662,11 +2960,11 @@ TEST_P(ElementsAreTestP, CanExplainMismatchRightSize) {
vector<int> v;
v.push_back(2);
v.push_back(1);
- EXPECT_EQ("whose element #0 doesn't match", Explain(m, v));
+ EXPECT_EQ(Explain(m, v), "whose element #0 (2) isn't equal to 1");
v[0] = 1;
- EXPECT_EQ("whose element #1 doesn't match, which is 4 less than 5",
- Explain(m, v));
+ EXPECT_EQ(Explain(m, v),
+ "whose element #1 (1) is <= 5, which is 4 less than 5");
}
TEST(ElementsAreTest, MatchesOneElementVector) {
@@ -3066,7 +3364,7 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
TEST_P(ContainsTestP, ExplainsMatchResultCorrectly) {
const int a[2] = {1, 2};
- Matcher<const int(&)[2]> m = Contains(2);
+ Matcher<const int (&)[2]> m = Contains(2);
EXPECT_EQ("whose element #1 matches", Explain(m, a));
m = Contains(3);
diff --git a/googlemock/test/gmock-matchers-misc_test.cc b/googlemock/test/gmock-matchers-misc_test.cc
index b8f64587db14..de8b76c69af4 100644
--- a/googlemock/test/gmock-matchers-misc_test.cc
+++ b/googlemock/test/gmock-matchers-misc_test.cc
@@ -32,6 +32,7 @@
// This file tests some commonly used argument matchers.
#include <array>
+#include <cstdint>
#include <memory>
#include <ostream>
#include <string>
@@ -39,14 +40,14 @@
#include <utility>
#include <vector>
+#include "gmock/gmock.h"
+#include "test/gmock-matchers_test.h"
#include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
-#include "test/gmock-matchers_test.h"
-
namespace testing {
namespace gmock_matchers_test {
namespace {
@@ -674,6 +675,8 @@ TEST_P(MatcherTupleTestP, ExplainsMatchFailure) {
// explanation.
}
+#if GTEST_HAS_TYPED_TEST
+
// Sample optional type implementation with minimal requirements for use with
// Optional matcher.
template <typename T>
@@ -691,38 +694,94 @@ class SampleOptional {
bool has_value_;
};
-TEST(OptionalTest, DescribesSelf) {
- const Matcher<SampleOptional<int>> m = Optional(Eq(1));
+// Sample optional type implementation with alternative minimal requirements for
+// use with Optional matcher. In particular, while it doesn't have a bool
+// conversion operator, it does have a has_value() method.
+template <typename T>
+class SampleOptionalWithoutBoolConversion {
+ public:
+ using value_type = T;
+ explicit SampleOptionalWithoutBoolConversion(T value)
+ : value_(std::move(value)), has_value_(true) {}
+ SampleOptionalWithoutBoolConversion() : value_(), has_value_(false) {}
+ bool has_value() const { return has_value_; }
+ const T& operator*() const { return value_; }
+
+ private:
+ T value_;
+ bool has_value_;
+};
+
+template <typename T>
+class OptionalTest : public testing::Test {};
+
+using OptionalTestTypes =
+ testing::Types<SampleOptional<int>,
+ SampleOptionalWithoutBoolConversion<int>>;
+
+TYPED_TEST_SUITE(OptionalTest, OptionalTestTypes);
+
+TYPED_TEST(OptionalTest, DescribesSelf) {
+ const Matcher<TypeParam> m = Optional(Eq(1));
EXPECT_EQ("value is equal to 1", Describe(m));
}
-TEST(OptionalTest, ExplainsSelf) {
- const Matcher<SampleOptional<int>> m = Optional(Eq(1));
- EXPECT_EQ("whose value 1 matches", Explain(m, SampleOptional<int>(1)));
- EXPECT_EQ("whose value 2 doesn't match", Explain(m, SampleOptional<int>(2)));
+TYPED_TEST(OptionalTest, ExplainsSelf) {
+ const Matcher<TypeParam> m = Optional(Eq(1));
+ EXPECT_EQ("whose value 1 matches", Explain(m, TypeParam(1)));
+ EXPECT_EQ("whose value 2 doesn't match", Explain(m, TypeParam(2)));
}
-TEST(OptionalTest, MatchesNonEmptyOptional) {
- const Matcher<SampleOptional<int>> m1 = Optional(1);
- const Matcher<SampleOptional<int>> m2 = Optional(Eq(2));
- const Matcher<SampleOptional<int>> m3 = Optional(Lt(3));
- SampleOptional<int> opt(1);
+TYPED_TEST(OptionalTest, MatchesNonEmptyOptional) {
+ const Matcher<TypeParam> m1 = Optional(1);
+ const Matcher<TypeParam> m2 = Optional(Eq(2));
+ const Matcher<TypeParam> m3 = Optional(Lt(3));
+ TypeParam opt(1);
EXPECT_TRUE(m1.Matches(opt));
EXPECT_FALSE(m2.Matches(opt));
EXPECT_TRUE(m3.Matches(opt));
}
-TEST(OptionalTest, DoesNotMatchNullopt) {
- const Matcher<SampleOptional<int>> m = Optional(1);
- SampleOptional<int> empty;
+TYPED_TEST(OptionalTest, DoesNotMatchNullopt) {
+ const Matcher<TypeParam> m = Optional(1);
+ TypeParam empty;
EXPECT_FALSE(m.Matches(empty));
}
-TEST(OptionalTest, WorksWithMoveOnly) {
- Matcher<SampleOptional<std::unique_ptr<int>>> m = Optional(Eq(nullptr));
- EXPECT_TRUE(m.Matches(SampleOptional<std::unique_ptr<int>>(nullptr)));
+TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersTakingReferences) {
+ const Matcher<const int&> eq1 = Eq(1);
+ const Matcher<const int&> eq2 = Eq(2);
+ TypeParam opt(1);
+ EXPECT_THAT(opt, Optional(eq1));
+ EXPECT_THAT(opt, Optional(Not(eq2)));
+ EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
+}
+
+TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersRequiringConversion) {
+ const Matcher<int64_t> eq1 = Eq(1);
+ const Matcher<int64_t> eq2 = Eq(2);
+ TypeParam opt(1);
+ EXPECT_THAT(opt, Optional(eq1));
+ EXPECT_THAT(opt, Optional(Not(eq2)));
+ EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
+}
+
+template <typename T>
+class MoveOnlyOptionalTest : public testing::Test {};
+
+using MoveOnlyOptionalTestTypes =
+ testing::Types<SampleOptional<std::unique_ptr<int>>,
+ SampleOptionalWithoutBoolConversion<std::unique_ptr<int>>>;
+
+TYPED_TEST_SUITE(MoveOnlyOptionalTest, MoveOnlyOptionalTestTypes);
+
+TYPED_TEST(MoveOnlyOptionalTest, WorksWithMoveOnly) {
+ Matcher<TypeParam> m = Optional(Eq(nullptr));
+ EXPECT_TRUE(m.Matches(TypeParam(nullptr)));
}
+#endif // GTEST_HAS_TYPED_TEST
+
class SampleVariantIntString {
public:
SampleVariantIntString(int i) : i_(i), has_int_(true) {}
@@ -1576,10 +1635,10 @@ TEST_P(AnyOfArrayTestP, ExplainsMatchResultCorrectly) {
const Matcher<int> m1 = AnyOfArray(v1);
const Matcher<int> m2 = AnyOfArray(v2);
EXPECT_EQ("", Explain(m0, 0));
- EXPECT_EQ("", Explain(m1, 1));
- EXPECT_EQ("", Explain(m1, 2));
- EXPECT_EQ("", Explain(m2, 3));
- EXPECT_EQ("", Explain(m2, 4));
+ EXPECT_EQ("which matches (is equal to 1)", Explain(m1, 1));
+ EXPECT_EQ("isn't equal to 1", Explain(m1, 2));
+ EXPECT_EQ("which matches (is equal to 3)", Explain(m2, 3));
+ EXPECT_EQ("isn't equal to 2, and isn't equal to 3", Explain(m2, 4));
EXPECT_EQ("()", Describe(m0));
EXPECT_EQ("(is equal to 1)", Describe(m1));
EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2));
diff --git a/googlemock/test/gmock-more-actions_test.cc b/googlemock/test/gmock-more-actions_test.cc
index 354a79b192c8..5b8b566f4c9f 100644
--- a/googlemock/test/gmock-more-actions_test.cc
+++ b/googlemock/test/gmock-more-actions_test.cc
@@ -59,6 +59,7 @@ using testing::Invoke;
using testing::ReturnArg;
using testing::ReturnPointee;
using testing::SaveArg;
+using testing::SaveArgByMove;
using testing::SaveArgPointee;
using testing::SetArgReferee;
using testing::Unused;
@@ -492,6 +493,34 @@ TEST(SaveArgActionTest, WorksForCompatibleType) {
EXPECT_EQ('a', result);
}
+struct MoveOnly {
+ explicit MoveOnly(int v) : i(v) {}
+ MoveOnly(MoveOnly&& o) {
+ i = o.i;
+ o.i = -1;
+ }
+ MoveOnly& operator=(MoveOnly&& o) {
+ i = o.i;
+ o.i = -1;
+ return *this;
+ }
+ int i;
+};
+
+TEST(SaveArgByMoveActionTest, WorksForSameType) {
+ MoveOnly result{0};
+ const Action<void(MoveOnly v)> a1 = SaveArgByMove<0>(&result);
+ a1.Perform(std::make_tuple(MoveOnly{5}));
+ EXPECT_EQ(5, result.i);
+}
+
+TEST(SaveArgByMoveActionTest, WorksForCompatibleType) {
+ MoveOnly result{0};
+ const Action<void(bool, MoveOnly)> a1 = SaveArgByMove<1>(&result);
+ a1.Perform(std::make_tuple(true, MoveOnly{7}));
+ EXPECT_EQ(7, result.i);
+}
+
TEST(SaveArgPointeeActionTest, WorksForSameType) {
int result = 0;
const int value = 5;
@@ -756,34 +785,34 @@ TEST(InvokeArgumentTest, Functor6) {
// Tests using InvokeArgument with a 7-ary function.
TEST(InvokeArgumentTest, Function7) {
- Action<std::string(std::string(*)(const char*, const char*, const char*,
- const char*, const char*, const char*,
- const char*))>
+ Action<std::string(std::string (*)(const char*, const char*, const char*,
+ const char*, const char*, const char*,
+ const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7)));
}
// Tests using InvokeArgument with a 8-ary function.
TEST(InvokeArgumentTest, Function8) {
- Action<std::string(std::string(*)(const char*, const char*, const char*,
- const char*, const char*, const char*,
- const char*, const char*))>
+ Action<std::string(std::string (*)(const char*, const char*, const char*,
+ const char*, const char*, const char*,
+ const char*, const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8)));
}
// Tests using InvokeArgument with a 9-ary function.
TEST(InvokeArgumentTest, Function9) {
- Action<std::string(std::string(*)(const char*, const char*, const char*,
- const char*, const char*, const char*,
- const char*, const char*, const char*))>
+ Action<std::string(std::string (*)(const char*, const char*, const char*,
+ const char*, const char*, const char*,
+ const char*, const char*, const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9)));
}
// Tests using InvokeArgument with a 10-ary function.
TEST(InvokeArgumentTest, Function10) {
- Action<std::string(std::string(*)(
+ Action<std::string(std::string (*)(
const char*, const char*, const char*, const char*, const char*,
const char*, const char*, const char*, const char*, const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
diff --git a/googlemock/test/gmock-pp_test.cc b/googlemock/test/gmock-pp_test.cc
index 5d1566e38853..e447f7651d3c 100644
--- a/googlemock/test/gmock-pp_test.cc
+++ b/googlemock/test/gmock-pp_test.cc
@@ -70,7 +70,7 @@ static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y) == 2, "");
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(silly) == 1, "");
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y, z) == 3, "");
-// TODO(iserna): The following asserts fail in --config=lexan.
+// TODO(iserna): The following asserts fail in --config=windows.
#define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1
static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1), "");
static_assert(GMOCK_PP_IS_EMPTY(), "");
diff --git a/googlemock/test/gmock-spec-builders_test.cc b/googlemock/test/gmock-spec-builders_test.cc
index aaf88d74ee79..9e68aa0cbeca 100644
--- a/googlemock/test/gmock-spec-builders_test.cc
+++ b/googlemock/test/gmock-spec-builders_test.cc
@@ -804,9 +804,8 @@ TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
"to be called at least once");
}
-#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
- GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
+// TODO(b/396121064) - Fix this test under MSVC
+#ifndef _MSC_VER
// It should be possible to return a non-moveable type from a mock action in
// C++17 and above, where it's guaranteed that such a type can be initialized
// from a prvalue returned from a function.
@@ -847,7 +846,7 @@ TEST(ExpectCallTest, NonMoveableType) {
EXPECT_EQ(17, mock.AsStdFunction()().x);
}
-#endif // C++17 and above
+#endif // _MSC_VER
// Tests that the n-th action is taken for the n-th matching
// invocation.
diff --git a/googlemock/test/gmock_link_test.h b/googlemock/test/gmock_link_test.h
index cf0a985b6320..cb5179b2f83b 100644
--- a/googlemock/test/gmock_link_test.h
+++ b/googlemock/test/gmock_link_test.h
@@ -186,8 +186,8 @@ using testing::SetErrnoAndReturn;
#endif
#if GTEST_HAS_EXCEPTIONS
-using testing::Throw;
using testing::Rethrow;
+using testing::Throw;
#endif
using testing::ContainsRegex;