diff options
Diffstat (limited to 'googlemock')
| -rw-r--r-- | googlemock/docs/CheatSheet.md | 2 | ||||
| -rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 71 | ||||
| -rw-r--r-- | googlemock/test/gmock-matchers_test.cc | 64 | 
3 files changed, 137 insertions, 0 deletions
| diff --git a/googlemock/docs/CheatSheet.md b/googlemock/docs/CheatSheet.md index c6367fdd..f8bbbfe6 100644 --- a/googlemock/docs/CheatSheet.md +++ b/googlemock/docs/CheatSheet.md @@ -178,6 +178,8 @@ divided into several categories:  |`Ne(value)`           |`argument != value`|  |`IsNull()`            |`argument` is a `NULL` pointer (raw or smart).|  |`NotNull()`           |`argument` is a non-null pointer (raw or smart).| +|`VariantWith<T>(m)`   |`argument` is `variant<>` that holds the alternative of +type T with a value matching `m`.|  |`Ref(variable)`       |`argument` is a reference to `variable`.|  |`TypedEq<type>(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.| diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 3d2d6177..9522c850 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -3636,6 +3636,66 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,                                                  const char* matcher_name,                                                  const Strings& param_values); +namespace variant_matcher { +// Overloads to allow VariantMatcher to do proper ADL lookup. +template <typename T> +void holds_alternative() {} +template <typename T> +void get() {} + +// Implements a matcher that checks the value of a variant<> type variable. +template <typename T> +class VariantMatcher { + public: +  explicit VariantMatcher(::testing::Matcher<const T&> matcher) +      : matcher_(internal::move(matcher)) {} + +  template <typename Variant> +  bool MatchAndExplain(const Variant& value, +                       ::testing::MatchResultListener* listener) const { +    if (!listener->IsInterested()) { +      return holds_alternative<T>(value) && matcher_.Matches(get<T>(value)); +    } + +    if (!holds_alternative<T>(value)) { +      *listener << "whose value is not of type '" << GetTypeName() << "'"; +      return false; +    } + +    const T& elem = get<T>(value); +    StringMatchResultListener elem_listener; +    const bool match = matcher_.MatchAndExplain(elem, &elem_listener); +    *listener << "whose value " << PrintToString(elem) +              << (match ? " matches" : " doesn't match"); +    PrintIfNotEmpty(elem_listener.str(), listener->stream()); +    return match; +  } + +  void DescribeTo(std::ostream* os) const { +    *os << "is a variant<> with value of type '" << GetTypeName() +        << "' and the value "; +    matcher_.DescribeTo(os); +  } + +  void DescribeNegationTo(std::ostream* os) const { +    *os << "is a variant<> with value of type other than '" << GetTypeName() +        << "' or the value "; +    matcher_.DescribeNegationTo(os); +  } + + private: +  static string GetTypeName() { +#if GTEST_HAS_RTTI +    return internal::GetTypeName<T>(); +#endif +    return "the element type"; +  } + +  const ::testing::Matcher<const T&> matcher_; +}; + +}  // namespace variant_matcher +  }  // namespace internal  // ElementsAreArray(iterator_first, iterator_last) @@ -4540,6 +4600,17 @@ inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) {  template <typename InnerMatcher>  inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; } +// Returns a matcher that matches the value of a variant<> type variable. +// The matcher implementation uses ADL to find the holds_alternative and get +// functions. +// It is compatible with std::variant. +template <typename T> +PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith( +    const Matcher<const T&>& matcher) { +  return MakePolymorphicMatcher( +      internal::variant_matcher::VariantMatcher<T>(matcher)); +} +  // These macros allow using matchers to check values in Google Test  // tests.  ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)  // succeed iff the value matches the matcher.  If the assertion fails, diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index 761c0c22..829935ef 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -5655,5 +5655,69 @@ TEST(UnorderedPointwiseTest, AllowsMonomorphicInnerMatcher) {    EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs));  } +class SampleVariantIntString { + public: +  SampleVariantIntString(int i) : i_(i), has_int_(true) {} +  SampleVariantIntString(const std::string& s) : s_(s), has_int_(false) {} + +  template <typename T> +  friend bool holds_alternative(const SampleVariantIntString& value) { +    return value.has_int_ == internal::IsSame<T, int>::value; +  } + +  template <typename T> +  friend const T& get(const SampleVariantIntString& value) { +    return value.get_impl(static_cast<T*>(NULL)); +  } + + private: +  const int& get_impl(int*) const { return i_; } +  const std::string& get_impl(std::string*) const { return s_; } + +  int i_; +  std::string s_; +  bool has_int_; +}; + +TEST(VariantTest, DescribesSelf) { +  const Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1)); +  EXPECT_THAT(Describe(m), ContainsRegex("is a variant<> with value of type " +                                         "'.*' and the value is equal to 1")); +} + +TEST(VariantTest, ExplainsSelf) { +  const Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1)); +  EXPECT_THAT(Explain(m, SampleVariantIntString(1)), +              ContainsRegex("whose value 1")); +  EXPECT_THAT(Explain(m, SampleVariantIntString("A")), +              HasSubstr("whose value is not of type '")); +  EXPECT_THAT(Explain(m, SampleVariantIntString(2)), +              "whose value 2 doesn't match"); +} + +TEST(VariantTest, FullMatch) { +  Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1)); +  EXPECT_TRUE(m.Matches(SampleVariantIntString(1))); + +  m = VariantWith<std::string>(Eq("1")); +  EXPECT_TRUE(m.Matches(SampleVariantIntString("1"))); +} + +TEST(VariantTest, TypeDoesNotMatch) { +  Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1)); +  EXPECT_FALSE(m.Matches(SampleVariantIntString("1"))); + +  m = VariantWith<std::string>(Eq("1")); +  EXPECT_FALSE(m.Matches(SampleVariantIntString(1))); +} + +TEST(VariantTest, InnerDoesNotMatch) { +  Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1)); +  EXPECT_FALSE(m.Matches(SampleVariantIntString(2))); + +  m = VariantWith<std::string>(Eq("1")); +  EXPECT_FALSE(m.Matches(SampleVariantIntString("2"))); +} +  }  // namespace gmock_matchers_test  }  // namespace testing | 
