• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- llvm/Testing/Support/Error.h ---------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_TESTING_SUPPORT_ERROR_H
11 #define LLVM_TESTING_SUPPORT_ERROR_H
12 
13 #include "llvm/ADT/Optional.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Testing/Support/SupportHelpers.h"
16 
17 #include "gmock/gmock.h"
18 #include <ostream>
19 
20 namespace llvm {
21 namespace detail {
22 ErrorHolder TakeError(Error Err);
23 
TakeExpected(Expected<T> & Exp)24 template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &Exp) {
25   return {TakeError(Exp.takeError()), Exp};
26 }
27 
TakeExpected(Expected<T> && Exp)28 template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &&Exp) {
29   return TakeExpected(Exp);
30 }
31 
32 template <typename T>
33 class ValueMatchesMono
34     : public testing::MatcherInterface<const ExpectedHolder<T> &> {
35 public:
ValueMatchesMono(const testing::Matcher<T> & Matcher)36   explicit ValueMatchesMono(const testing::Matcher<T> &Matcher)
37       : Matcher(Matcher) {}
38 
MatchAndExplain(const ExpectedHolder<T> & Holder,testing::MatchResultListener * listener)39   bool MatchAndExplain(const ExpectedHolder<T> &Holder,
40                        testing::MatchResultListener *listener) const override {
41     if (!Holder.Success())
42       return false;
43 
44     bool result = Matcher.MatchAndExplain(*Holder.Exp, listener);
45 
46     if (result)
47       return result;
48     *listener << "(";
49     Matcher.DescribeNegationTo(listener->stream());
50     *listener << ")";
51     return result;
52   }
53 
DescribeTo(std::ostream * OS)54   void DescribeTo(std::ostream *OS) const override {
55     *OS << "succeeded with value (";
56     Matcher.DescribeTo(OS);
57     *OS << ")";
58   }
59 
DescribeNegationTo(std::ostream * OS)60   void DescribeNegationTo(std::ostream *OS) const override {
61     *OS << "did not succeed or value (";
62     Matcher.DescribeNegationTo(OS);
63     *OS << ")";
64   }
65 
66 private:
67   testing::Matcher<T> Matcher;
68 };
69 
70 template<typename M>
71 class ValueMatchesPoly {
72 public:
ValueMatchesPoly(const M & Matcher)73   explicit ValueMatchesPoly(const M &Matcher) : Matcher(Matcher) {}
74 
75   template <typename T>
76   operator testing::Matcher<const ExpectedHolder<T> &>() const {
77     return MakeMatcher(
78         new ValueMatchesMono<T>(testing::SafeMatcherCast<T>(Matcher)));
79   }
80 
81 private:
82   M Matcher;
83 };
84 
85 template <typename InfoT>
86 class ErrorMatchesMono : public testing::MatcherInterface<const ErrorHolder &> {
87 public:
ErrorMatchesMono(Optional<testing::Matcher<InfoT &>> Matcher)88   explicit ErrorMatchesMono(Optional<testing::Matcher<InfoT &>> Matcher)
89       : Matcher(std::move(Matcher)) {}
90 
MatchAndExplain(const ErrorHolder & Holder,testing::MatchResultListener * listener)91   bool MatchAndExplain(const ErrorHolder &Holder,
92                        testing::MatchResultListener *listener) const override {
93     if (Holder.Success())
94       return false;
95 
96     if (Holder.Infos.size() > 1) {
97       *listener << "multiple errors";
98       return false;
99     }
100 
101     auto &Info = *Holder.Infos[0];
102     if (!Info.isA<InfoT>()) {
103       *listener << "Error was not of given type";
104       return false;
105     }
106 
107     if (!Matcher)
108       return true;
109 
110     return Matcher->MatchAndExplain(static_cast<InfoT &>(Info), listener);
111   }
112 
DescribeTo(std::ostream * OS)113   void DescribeTo(std::ostream *OS) const override {
114     *OS << "failed with Error of given type";
115     if (Matcher) {
116       *OS << " and the error ";
117       Matcher->DescribeTo(OS);
118     }
119   }
120 
DescribeNegationTo(std::ostream * OS)121   void DescribeNegationTo(std::ostream *OS) const override {
122     *OS << "succeeded or did not fail with the error of given type";
123     if (Matcher) {
124       *OS << " or the error ";
125       Matcher->DescribeNegationTo(OS);
126     }
127   }
128 
129 private:
130   Optional<testing::Matcher<InfoT &>> Matcher;
131 };
132 } // namespace detail
133 
134 #define EXPECT_THAT_ERROR(Err, Matcher)                                        \
135   EXPECT_THAT(llvm::detail::TakeError(Err), Matcher)
136 #define ASSERT_THAT_ERROR(Err, Matcher)                                        \
137   ASSERT_THAT(llvm::detail::TakeError(Err), Matcher)
138 
139 #define EXPECT_THAT_EXPECTED(Err, Matcher)                                     \
140   EXPECT_THAT(llvm::detail::TakeExpected(Err), Matcher)
141 #define ASSERT_THAT_EXPECTED(Err, Matcher)                                     \
142   ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher)
143 
144 MATCHER(Succeeded, "") { return arg.Success(); }
145 MATCHER(Failed, "") { return !arg.Success(); }
146 
147 template <typename InfoT>
Failed()148 testing::Matcher<const detail::ErrorHolder &> Failed() {
149   return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None));
150 }
151 
152 template <typename InfoT, typename M>
Failed(M Matcher)153 testing::Matcher<const detail::ErrorHolder &> Failed(M Matcher) {
154   return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(
155       testing::SafeMatcherCast<InfoT &>(Matcher)));
156 }
157 
158 template <typename M>
HasValue(M Matcher)159 detail::ValueMatchesPoly<M> HasValue(M Matcher) {
160   return detail::ValueMatchesPoly<M>(Matcher);
161 }
162 
163 } // namespace llvm
164 
165 #endif
166