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 } // namespace detail 132 133 #define EXPECT_THAT_ERROR(Err, Matcher) \ 134 EXPECT_THAT(llvm::detail::TakeError(Err), Matcher) 135 #define ASSERT_THAT_ERROR(Err, Matcher) \ 136 ASSERT_THAT(llvm::detail::TakeError(Err), Matcher) 137 138 #define EXPECT_THAT_EXPECTED(Err, Matcher) \ 139 EXPECT_THAT(llvm::detail::TakeExpected(Err), Matcher) 140 #define ASSERT_THAT_EXPECTED(Err, Matcher) \ 141 ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher) 142 143 MATCHER(Succeeded, "") { return arg.Success(); } 144 MATCHER(Failed, "") { return !arg.Success(); } 145 146 template <typename InfoT> 147 testing::Matcher<const detail::ErrorHolder &> Failed() { 148 return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None)); 149 } 150 151 template <typename InfoT, typename M> 152 testing::Matcher<const detail::ErrorHolder &> Failed(M Matcher) { 153 return MakeMatcher(new detail::ErrorMatchesMono<InfoT>( 154 testing::SafeMatcherCast<InfoT &>(Matcher))); 155 } 156 157 template <typename M> 158 detail::ValueMatchesPoly<M> HasValue(M Matcher) { 159 return detail::ValueMatchesPoly<M>(Matcher); 160 } 161 162 } // namespace llvm 163 164 #endif 165