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