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
19namespace llvm {
20namespace detail {
21ErrorHolder TakeError(Error Err);
22
23template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &Exp) {
24  return {TakeError(Exp.takeError()), Exp};
25}
26
27template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &&Exp) {
28  return TakeExpected(Exp);
29}
30
31template <typename T>
32class ValueMatchesMono
33    : public testing::MatcherInterface<const ExpectedHolder<T> &> {
34public:
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
65private:
66  testing::Matcher<T> Matcher;
67};
68
69template<typename M>
70class ValueMatchesPoly {
71public:
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
80private:
81  M Matcher;
82};
83
84template <typename InfoT>
85class ErrorMatchesMono : public testing::MatcherInterface<const ErrorHolder &> {
86public:
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
128private:
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
143MATCHER(Succeeded, "") { return arg.Success(); }
144MATCHER(Failed, "") { return !arg.Success(); }
145
146template <typename InfoT>
147testing::Matcher<const detail::ErrorHolder &> Failed() {
148  return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None));
149}
150
151template <typename InfoT, typename M>
152testing::Matcher<const detail::ErrorHolder &> Failed(M Matcher) {
153  return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(
154      testing::SafeMatcherCast<InfoT &>(Matcher)));
155}
156
157template <typename M>
158detail::ValueMatchesPoly<M> HasValue(M Matcher) {
159  return detail::ValueMatchesPoly<M>(Matcher);
160}
161
162} // namespace llvm
163
164#endif
165