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) 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 #define EXPECT_THAT_EXPECTED(Err, Matcher) \ 169 EXPECT_THAT(llvm::detail::TakeExpected(Err), Matcher) 170 #define ASSERT_THAT_EXPECTED(Err, Matcher) \ 171 ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher) 172 173 MATCHER(Succeeded, "") { return arg.Success(); } 174 MATCHER(Failed, "") { return !arg.Success(); } 175 176 template <typename InfoT> 177 testing::Matcher<const detail::ErrorHolder &> Failed() { 178 return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None)); 179 } 180 181 template <typename InfoT, typename M> 182 testing::Matcher<const detail::ErrorHolder &> Failed(M Matcher) { 183 return MakeMatcher(new detail::ErrorMatchesMono<InfoT>( 184 testing::SafeMatcherCast<InfoT &>(Matcher))); 185 } 186 187 template <typename... M> 188 testing::Matcher<const detail::ErrorHolder &> FailedWithMessage(M... Matcher) { 189 static_assert(sizeof...(M) > 0, ""); 190 return MakeMatcher( 191 new detail::ErrorMessageMatches(testing::ElementsAre(Matcher...))); 192 } 193 194 template <typename M> 195 testing::Matcher<const detail::ErrorHolder &> FailedWithMessageArray(M Matcher) { 196 return MakeMatcher(new detail::ErrorMessageMatches(Matcher)); 197 } 198 199 template <typename M> 200 detail::ValueMatchesPoly<M> HasValue(M Matcher) { 201 return detail::ValueMatchesPoly<M>(Matcher); 202 } 203 204 } // namespace llvm 205 206 #endif 207