1 //===- llvm/Testing/Support/Error.h ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_TESTING_SUPPORT_ERROR_H
10 #define LLVM_TESTING_SUPPORT_ERROR_H
11 
12 #include "llvm/ADT/Optional.h"
13 #include "llvm/Support/Error.h"
14 #include "llvm/Testing/Support/SupportHelpers.h"
15 
16 #include "gmock/gmock.h"
17 #include <ostream>
18 
19 namespace llvm {
20 namespace detail {
21 ErrorHolder TakeError(Error Err);
22 
23 template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &Exp) {
24   return {TakeError(Exp.takeError()), Exp};
25 }
26 
27 template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &&Exp) {
28   return TakeExpected(Exp);
29 }
30 
31 template <typename T>
32 class ValueMatchesMono
33     : public testing::MatcherInterface<const ExpectedHolder<T> &> {
34 public:
35   explicit ValueMatchesMono(const testing::Matcher<T> &Matcher)
36       : Matcher(Matcher) {}
37 
38   bool MatchAndExplain(const ExpectedHolder<T> &Holder,
39                        testing::MatchResultListener *listener) const override {
40     if (!Holder.Success())
41       return false;
42 
43     bool result = Matcher.MatchAndExplain(*Holder.Exp, listener);
44 
45     if (result || !listener->IsInterested())
46       return result;
47     *listener << "(";
48     Matcher.DescribeNegationTo(listener->stream());
49     *listener << ")";
50     return result;
51   }
52 
53   void DescribeTo(std::ostream *OS) const override {
54     *OS << "succeeded with value (";
55     Matcher.DescribeTo(OS);
56     *OS << ")";
57   }
58 
59   void DescribeNegationTo(std::ostream *OS) const override {
60     *OS << "did not succeed or value (";
61     Matcher.DescribeNegationTo(OS);
62     *OS << ")";
63   }
64 
65 private:
66   testing::Matcher<T> Matcher;
67 };
68 
69 template<typename M>
70 class ValueMatchesPoly {
71 public:
72   explicit ValueMatchesPoly(const M &Matcher) : Matcher(Matcher) {}
73 
74   template <typename T>
75   operator testing::Matcher<const ExpectedHolder<T> &>() const {
76     return MakeMatcher(
77         new ValueMatchesMono<T>(testing::SafeMatcherCast<T>(Matcher)));
78   }
79 
80 private:
81   M Matcher;
82 };
83 
84 template <typename InfoT>
85 class ErrorMatchesMono : public testing::MatcherInterface<const ErrorHolder &> {
86 public:
87   explicit ErrorMatchesMono(Optional<testing::Matcher<InfoT &>> Matcher)
88       : Matcher(std::move(Matcher)) {}
89 
90   bool MatchAndExplain(const ErrorHolder &Holder,
91                        testing::MatchResultListener *listener) const override {
92     if (Holder.Success())
93       return false;
94 
95     if (Holder.Infos.size() > 1) {
96       *listener << "multiple errors";
97       return false;
98     }
99 
100     auto &Info = *Holder.Infos[0];
101     if (!Info.isA<InfoT>()) {
102       *listener << "Error was not of given type";
103       return false;
104     }
105 
106     if (!Matcher)
107       return true;
108 
109     return Matcher->MatchAndExplain(static_cast<InfoT &>(Info), listener);
110   }
111 
112   void DescribeTo(std::ostream *OS) const override {
113     *OS << "failed with Error of given type";
114     if (Matcher) {
115       *OS << " and the error ";
116       Matcher->DescribeTo(OS);
117     }
118   }
119 
120   void DescribeNegationTo(std::ostream *OS) const override {
121     *OS << "succeeded or did not fail with the error of given type";
122     if (Matcher) {
123       *OS << " or the error ";
124       Matcher->DescribeNegationTo(OS);
125     }
126   }
127 
128 private:
129   Optional<testing::Matcher<InfoT &>> Matcher;
130 };
131 
132 class ErrorMessageMatches
133     : public testing::MatcherInterface<const ErrorHolder &> {
134 public:
135   explicit ErrorMessageMatches(
136       testing::Matcher<std::vector<std::string>> Matcher)
137       : Matcher(std::move(Matcher)) {}
138 
139   bool MatchAndExplain(const ErrorHolder &Holder,
140                        testing::MatchResultListener *listener) const override {
141     std::vector<std::string> Messages;
142     for (const std::shared_ptr<ErrorInfoBase> &Info: Holder.Infos)
143       Messages.push_back(Info->message());
144 
145     return Matcher.MatchAndExplain(Messages, listener);
146   }
147 
148   void DescribeTo(std::ostream *OS) const override {
149     *OS << "failed with Error whose message ";
150     Matcher.DescribeTo(OS);
151   }
152 
153   void DescribeNegationTo(std::ostream *OS) const override {
154     *OS << "failed with an Error whose message ";
155     Matcher.DescribeNegationTo(OS);
156   }
157 
158 private:
159   testing::Matcher<std::vector<std::string>> Matcher;
160 };
161 } // namespace detail
162 
163 #define EXPECT_THAT_ERROR(Err, Matcher)                                        \
164   EXPECT_THAT(llvm::detail::TakeError(Err), Matcher)
165 #define ASSERT_THAT_ERROR(Err, Matcher)                                        \
166   ASSERT_THAT(llvm::detail::TakeError(Err), Matcher)
167 
168 /// Helper macro for checking the result of an 'Expected<T>'
169 ///
170 ///   @code{.cpp}
171 ///     // function to be tested
172 ///     Expected<int> myDivide(int A, int B);
173 ///
174 ///     TEST(myDivideTests, GoodAndBad) {
175 ///       // test good case
176 ///       // if you only care about success or failure:
177 ///       EXPECT_THAT_EXPECTED(myDivide(10, 5), Succeeded());
178 ///       // if you also care about the value:
179 ///       EXPECT_THAT_EXPECTED(myDivide(10, 5), HasValue(2));
180 ///
181 ///       // test the error case
182 ///       EXPECT_THAT_EXPECTED(myDivide(10, 0), Failed());
183 ///       // also check the error message
184 ///       EXPECT_THAT_EXPECTED(myDivide(10, 0),
185 ///           FailedWithMessage("B must not be zero!"));
186 ///     }
187 ///   @endcode
188 
189 #define EXPECT_THAT_EXPECTED(Err, Matcher)                                     \
190   EXPECT_THAT(llvm::detail::TakeExpected(Err), Matcher)
191 #define ASSERT_THAT_EXPECTED(Err, Matcher)                                     \
192   ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher)
193 
194 MATCHER(Succeeded, "") { return arg.Success(); }
195 MATCHER(Failed, "") { return !arg.Success(); }
196 
197 template <typename InfoT>
198 testing::Matcher<const detail::ErrorHolder &> Failed() {
199   return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None));
200 }
201 
202 template <typename InfoT, typename M>
203 testing::Matcher<const detail::ErrorHolder &> Failed(M Matcher) {
204   return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(
205       testing::SafeMatcherCast<InfoT &>(Matcher)));
206 }
207 
208 template <typename... M>
209 testing::Matcher<const detail::ErrorHolder &> FailedWithMessage(M... Matcher) {
210   static_assert(sizeof...(M) > 0, "");
211   return MakeMatcher(
212       new detail::ErrorMessageMatches(testing::ElementsAre(Matcher...)));
213 }
214 
215 template <typename M>
216 testing::Matcher<const detail::ErrorHolder &> FailedWithMessageArray(M Matcher) {
217   return MakeMatcher(new detail::ErrorMessageMatches(Matcher));
218 }
219 
220 template <typename M>
221 detail::ValueMatchesPoly<M> HasValue(M Matcher) {
222   return detail::ValueMatchesPoly<M>(Matcher);
223 }
224 
225 } // namespace llvm
226 
227 #endif
228