[llvm] r320561 - [Testing/Support] Make the HasValue matcher composable

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 13 02:00:38 PST 2017


Author: labath
Date: Wed Dec 13 02:00:38 2017
New Revision: 320561

URL: http://llvm.org/viewvc/llvm-project?rev=320561&view=rev
Log:
[Testing/Support] Make the HasValue matcher composable

Summary:
This makes it possible to run an arbitrary matcher on the value
contained within the Expected<T> object.

To do this, I've needed to fully spell out the matcher, instead of using
the shorthand MATCHER_P macro.

The slight gotcha here is that standard template deduction will fail if
one tries to match HasValue(47) against an Expected<int &> -- the
workaround is to use HasValue(testing::Eq(47)).

The explanations produced by this matcher have changed a bit, since now
we delegate to the nested matcher to print the value. Since these don't
put quotes around the value, I've changed our PrintTo methods to match.

Reviewers: zturner

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D41065

Modified:
    llvm/trunk/include/llvm/Testing/Support/Error.h
    llvm/trunk/include/llvm/Testing/Support/SupportHelpers.h
    llvm/trunk/unittests/Support/ErrorTest.cpp

Modified: llvm/trunk/include/llvm/Testing/Support/Error.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Testing/Support/Error.h?rev=320561&r1=320560&r2=320561&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Testing/Support/Error.h (original)
+++ llvm/trunk/include/llvm/Testing/Support/Error.h Wed Dec 13 02:00:38 2017
@@ -28,6 +28,60 @@ template <typename T> ExpectedHolder<T>
 template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &&Exp) {
   return TakeExpected(Exp);
 }
+
+template <typename T>
+class ValueMatchesMono
+    : public testing::MatcherInterface<const ExpectedHolder<T> &> {
+public:
+  explicit ValueMatchesMono(const testing::Matcher<T> &Matcher)
+      : Matcher(Matcher) {}
+
+  bool MatchAndExplain(const ExpectedHolder<T> &Holder,
+                       testing::MatchResultListener *listener) const override {
+    if (!Holder.Success)
+      return false;
+
+    bool result = Matcher.MatchAndExplain(*Holder.Exp, listener);
+
+    if (result)
+      return result;
+    *listener << "(";
+    Matcher.DescribeNegationTo(listener->stream());
+    *listener << ")";
+    return result;
+  }
+
+  void DescribeTo(std::ostream *OS) const override {
+    *OS << "succeeded with value (";
+    Matcher.DescribeTo(OS);
+    *OS << ")";
+  }
+
+  void DescribeNegationTo(std::ostream *OS) const override {
+    *OS << "did not succeed or value (";
+    Matcher.DescribeNegationTo(OS);
+    *OS << ")";
+  }
+
+private:
+  testing::Matcher<T> Matcher;
+};
+
+template<typename M>
+class ValueMatchesPoly {
+public:
+  explicit ValueMatchesPoly(const M &Matcher) : Matcher(Matcher) {}
+
+  template <typename T>
+  operator testing::Matcher<const ExpectedHolder<T> &>() const {
+    return MakeMatcher(
+        new ValueMatchesMono<T>(testing::SafeMatcherCast<T>(Matcher)));
+  }
+
+private:
+  M Matcher;
+};
+
 } // namespace detail
 
 #define EXPECT_THAT_ERROR(Err, Matcher)                                        \
@@ -43,21 +97,11 @@ template <typename T> ExpectedHolder<T>
 MATCHER(Succeeded, "") { return arg.Success; }
 MATCHER(Failed, "") { return !arg.Success; }
 
-MATCHER_P(HasValue, value,
-          "succeeded with value \"" + testing::PrintToString(value) + '"') {
-  if (!arg.Success) {
-    *result_listener << "operation failed";
-    return false;
-  }
-
-  if (*arg.Exp != value) {
-    *result_listener << "but \"" + testing::PrintToString(*arg.Exp) +
-                            "\" != \"" + testing::PrintToString(value) + '"';
-    return false;
-  }
-
-  return true;
+template <typename M>
+detail::ValueMatchesPoly<M> HasValue(M Matcher) {
+  return detail::ValueMatchesPoly<M>(Matcher);
 }
+
 } // namespace llvm
 
 #endif

Modified: llvm/trunk/include/llvm/Testing/Support/SupportHelpers.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Testing/Support/SupportHelpers.h?rev=320561&r1=320560&r2=320561&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Testing/Support/SupportHelpers.h (original)
+++ llvm/trunk/include/llvm/Testing/Support/SupportHelpers.h Wed Dec 13 02:00:38 2017
@@ -38,8 +38,7 @@ inline void PrintTo(const ErrorHolder &E
 template <typename T>
 void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) {
   if (Item.Success) {
-    *Out << "succeeded with value \"" << ::testing::PrintToString(*Item.Exp)
-         << "\"";
+    *Out << "succeeded with value " << ::testing::PrintToString(*Item.Exp);
   } else {
     PrintTo(static_cast<const ErrorHolder &>(Item), Out);
   }

Modified: llvm/trunk/unittests/Support/ErrorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ErrorTest.cpp?rev=320561&r1=320560&r2=320561&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/ErrorTest.cpp (original)
+++ llvm/trunk/unittests/Support/ErrorTest.cpp Wed Dec 13 02:00:38 2017
@@ -735,23 +735,34 @@ TEST(Error, ErrorMatchers) {
   EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), Failed());
   EXPECT_NONFATAL_FAILURE(
       EXPECT_THAT_EXPECTED(Expected<int>(0), Failed()),
-      "Expected: failed\n  Actual: succeeded with value \"0\"");
+      "Expected: failed\n  Actual: succeeded with value 0");
 
   EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(0));
   EXPECT_NONFATAL_FAILURE(
       EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)),
                            HasValue(0)),
-      "Expected: succeeded with value \"0\"\n"
+      "Expected: succeeded with value (is equal to 0)\n"
       "  Actual: failed  (CustomError { 0})");
   EXPECT_NONFATAL_FAILURE(
       EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(0)),
-      "Expected: succeeded with value \"0\"\n"
-      "  Actual: succeeded with value \"1\", but \"1\" != \"0\"");
+      "Expected: succeeded with value (is equal to 0)\n"
+      "  Actual: succeeded with value 1, (isn't equal to 0)");
 
   EXPECT_THAT_EXPECTED(Expected<int &>(make_error<CustomError>(0)), Failed());
   int a = 1;
   EXPECT_THAT_EXPECTED(Expected<int &>(a), Succeeded());
-  EXPECT_THAT_EXPECTED(Expected<int &>(a), HasValue(1));
+  EXPECT_THAT_EXPECTED(Expected<int &>(a), HasValue(testing::Eq(1)));
+
+  EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(testing::Gt(0)));
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(testing::Gt(1))),
+      "Expected: succeeded with value (is > 1)\n"
+      "  Actual: succeeded with value 0, (isn't > 1)");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)),
+                           HasValue(testing::Gt(1))),
+      "Expected: succeeded with value (is > 1)\n"
+      "  Actual: failed  (CustomError { 0})");
 }
 
 } // end anon namespace




More information about the llvm-commits mailing list