diff options
author | Abseil Team <absl-team@google.com> | 2021-07-07 14:28:06 (GMT) |
---|---|---|
committer | Derek Mauro <dmauro@google.com> | 2021-07-07 18:34:28 (GMT) |
commit | 8306020a3e9eceafec65508868d7ab5c63bb41f7 (patch) | |
tree | 5e8b09aa5a8e2be5184d9aa0838acdc4438a3497 | |
parent | 977cffc4423a2d6c0df3fc9a7b5253b8f79c3f18 (diff) | |
download | googletest-8306020a3e9eceafec65508868d7ab5c63bb41f7.zip googletest-8306020a3e9eceafec65508868d7ab5c63bb41f7.tar.gz googletest-8306020a3e9eceafec65508868d7ab5c63bb41f7.tar.bz2 |
Googletest export
Add `Conditional` wrapper to gtest
This follows an initial proposal for an 'EqIff` matcher. `Conditional` was considered more precise as an EqIff() matcher may suffer from `Iff` not being universally understood.
PiperOrigin-RevId: 383407665
-rw-r--r-- | CONTRIBUTORS | 1 | ||||
-rw-r--r-- | docs/reference/matchers.md | 1 | ||||
-rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 36 | ||||
-rw-r--r-- | googlemock/test/gmock-matchers_test.cc | 28 |
4 files changed, 66 insertions, 0 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 76db0b4..d9bc587 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -34,6 +34,7 @@ Manuel Klimek <klimek@google.com> Mario Tanev <radix@google.com> Mark Paskin Markus Heule <markus.heule@gmail.com> +Martijn Vels <mvels@google.com> Matthew Simmons <simmonmt@acm.org> Mika Raento <mikie@iki.fi> Mike Bland <mbland@google.com> diff --git a/docs/reference/matchers.md b/docs/reference/matchers.md index 0d8f81b..1a60b4c 100644 --- a/docs/reference/matchers.md +++ b/docs/reference/matchers.md @@ -238,6 +238,7 @@ You can make a matcher from one or more other matchers: | `AnyOf(m1, m2, ..., mn)` | `argument` matches at least one of the matchers `m1` to `mn`. | | `AnyOfArray({m0, m1, ..., mn})`, `AnyOfArray(a_container)`, `AnyOfArray(begin, end)`, `AnyOfArray(array)`, or `AnyOfArray(array, count)` | The same as `AnyOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. | | `Not(m)` | `argument` doesn't match matcher `m`. | +| `Conditional(cond, m1, m2)` | Matches matcher `m1` if `cond` evalutes to true, else matches `m2`.| ## Adapters for Matchers diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index e1a7606..f1bb22c 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -1405,6 +1405,30 @@ class AnyOfMatcherImpl : public MatcherInterface<const T&> { template <typename... Args> using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>; +// ConditionalMatcher is the implementation of Conditional(cond, m1, m2) +template <typename MatcherTrue, typename MatcherFalse> +class ConditionalMatcher { + public: + ConditionalMatcher(bool condition, MatcherTrue matcher_true, + MatcherFalse matcher_false) + : condition_(condition), + matcher_true_(std::move(matcher_true)), + matcher_false_(std::move(matcher_false)) {} + + template <typename T> + operator Matcher<T>() const { // NOLINT(runtime/explicit) + return condition_ ? SafeMatcherCast<T>(matcher_true_) + : SafeMatcherCast<T>(matcher_false_); + } + + private: + bool condition_; + MatcherTrue matcher_true_; + MatcherFalse matcher_false_; + + GTEST_DISALLOW_ASSIGN_(ConditionalMatcher); +}; + // Wrapper for implementation of Any/AllOfArray(). template <template <class> class MatcherImpl, typename T> class SomeOfArrayMatcher { @@ -4926,6 +4950,18 @@ Pair(FirstMatcher first_matcher, SecondMatcher second_matcher) { } namespace no_adl { +// Conditional() creates a matcher that conditionally uses either the first or +// second matcher provided. For example, we could create an `equal if, and only +// if' matcher using the Conditonal wrapper as follows: +// +// EXPECT_THAT(result, Conditional(condition, Eq(expected), Ne(expected))); +template <typename MatcherTrue, typename MatcherFalse> +internal::ConditionalMatcher<MatcherTrue, MatcherFalse> Conditional( + bool condition, MatcherTrue matcher_true, MatcherFalse matcher_false) { + return internal::ConditionalMatcher<MatcherTrue, MatcherFalse>( + condition, std::move(matcher_true), std::move(matcher_false)); +} + // FieldsAre(matchers...) matches piecewise the fields of compatible structs. // These include those that support `get<I>(obj)`, and when structured bindings // are enabled any class that supports them. diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index 6c22990..e6f280d 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -2772,6 +2772,34 @@ TEST(AnyOfTest, VariadicMatchesWhenAnyMatches) { "43", "44", "45", "46", "47", "48", "49", "50")); } +TEST(ConditionalTest, MatchesFirstIfCondition) { + Matcher<std::string> eq_red = Eq("red"); + Matcher<std::string> ne_red = Ne("red"); + Matcher<std::string> m = Conditional(true, eq_red, ne_red); + EXPECT_TRUE(m.Matches("red")); + EXPECT_FALSE(m.Matches("green")); + + StringMatchResultListener listener; + StringMatchResultListener expected; + EXPECT_FALSE(m.MatchAndExplain("green", &listener)); + EXPECT_FALSE(eq_red.MatchAndExplain("green", &expected)); + EXPECT_THAT(listener.str(), Eq(expected.str())); +} + +TEST(ConditionalTest, MatchesSecondIfCondition) { + Matcher<std::string> eq_red = Eq("red"); + Matcher<std::string> ne_red = Ne("red"); + Matcher<std::string> m = Conditional(false, eq_red, ne_red); + EXPECT_FALSE(m.Matches("red")); + EXPECT_TRUE(m.Matches("green")); + + StringMatchResultListener listener; + StringMatchResultListener expected; + EXPECT_FALSE(m.MatchAndExplain("red", &listener)); + EXPECT_FALSE(ne_red.MatchAndExplain("red", &expected)); + EXPECT_THAT(listener.str(), Eq(expected.str())); +} + // Tests the variadic version of the ElementsAreMatcher TEST(ElementsAreTest, HugeMatcher) { vector<int> test_vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; |