Home | History | Annotate | Download | only in Support
      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 
     24 template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &Exp) {
     25   return {TakeError(Exp.takeError()), Exp};
     26 }
     27 
     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:
     36   explicit ValueMatchesMono(const testing::Matcher<T> &Matcher)
     37       : Matcher(Matcher) {}
     38 
     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 
     54   void DescribeTo(std::ostream *OS) const override {
     55     *OS << "succeeded with value (";
     56     Matcher.DescribeTo(OS);
     57     *OS << ")";
     58   }
     59 
     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:
     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:
     88   explicit ErrorMatchesMono(Optional<testing::Matcher<InfoT &>> Matcher)
     89       : Matcher(std::move(Matcher)) {}
     90 
     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 
    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 
    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>
    148 testing::Matcher<const detail::ErrorHolder &> Failed() {
    149   return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None));
    150 }
    151 
    152 template <typename InfoT, typename M>
    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>
    159 detail::ValueMatchesPoly<M> HasValue(M Matcher) {
    160   return detail::ValueMatchesPoly<M>(Matcher);
    161 }
    162 
    163 } // namespace llvm
    164 
    165 #endif
    166