Merge pull request #1482 from zhangxy988/variant_matcher
Add matcher for std::variant.
This commit is contained in:
commit
fe1144246e
|
@ -178,6 +178,8 @@ divided into several categories:
|
||||||
|`Ne(value)` |`argument != value`|
|
|`Ne(value)` |`argument != value`|
|
||||||
|`IsNull()` |`argument` is a `NULL` pointer (raw or smart).|
|
|`IsNull()` |`argument` is a `NULL` pointer (raw or smart).|
|
||||||
|`NotNull()` |`argument` is a non-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`.|
|
|`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.|
|
|`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.|
|
||||||
|
|
||||||
|
|
|
@ -3636,6 +3636,66 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
|
||||||
const char* matcher_name,
|
const char* matcher_name,
|
||||||
const Strings& param_values);
|
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
|
} // namespace internal
|
||||||
|
|
||||||
// ElementsAreArray(iterator_first, iterator_last)
|
// ElementsAreArray(iterator_first, iterator_last)
|
||||||
|
@ -4540,6 +4600,17 @@ inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) {
|
||||||
template <typename InnerMatcher>
|
template <typename InnerMatcher>
|
||||||
inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
|
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
|
// These macros allow using matchers to check values in Google Test
|
||||||
// tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
|
// tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
|
||||||
// succeed iff the value matches the matcher. If the assertion fails,
|
// succeed iff the value matches the matcher. If the assertion fails,
|
||||||
|
|
|
@ -5655,5 +5655,69 @@ TEST(UnorderedPointwiseTest, AllowsMonomorphicInnerMatcher) {
|
||||||
EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs));
|
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 gmock_matchers_test
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
Loading…
Reference in New Issue
Block a user