diff options
Diffstat (limited to 'googlemock/test')
| -rw-r--r-- | googlemock/test/gmock-actions_test.cc | 78 | ||||
| -rw-r--r-- | googlemock/test/gmock-function-mocker_test.cc | 4 | ||||
| -rw-r--r-- | googlemock/test/gmock-matchers-arithmetic_test.cc | 237 | ||||
| -rw-r--r-- | googlemock/test/gmock-matchers-comparisons_test.cc | 136 | ||||
| -rw-r--r-- | googlemock/test/gmock-matchers-containers_test.cc | 336 | ||||
| -rw-r--r-- | googlemock/test/gmock-matchers-misc_test.cc | 105 | ||||
| -rw-r--r-- | googlemock/test/gmock-more-actions_test.cc | 49 | ||||
| -rw-r--r-- | googlemock/test/gmock-pp_test.cc | 2 | ||||
| -rw-r--r-- | googlemock/test/gmock-spec-builders_test.cc | 7 | ||||
| -rw-r--r-- | googlemock/test/gmock_link_test.h | 2 |
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; |
