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`|
|
||||
|`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.|
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user