1 | //===-- Matchers.h ----------------------------------------------*- C++ -*-===// |
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 | // GMock matchers that aren't specific to particular tests. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_MATCHERS_H |
14 | #define |
15 | #include "Protocol.h" |
16 | #include "gmock/gmock.h" |
17 | |
18 | namespace clang { |
19 | namespace clangd { |
20 | using ::testing::Matcher; |
21 | |
22 | // EXPECT_IFF expects matcher if condition is true, and Not(matcher) if false. |
23 | // This is hard to write as a function, because matchers may be polymorphic. |
24 | #define EXPECT_IFF(condition, value, matcher) \ |
25 | do { \ |
26 | if (condition) \ |
27 | EXPECT_THAT(value, matcher); \ |
28 | else \ |
29 | EXPECT_THAT(value, ::testing::Not(matcher)); \ |
30 | } while (0) |
31 | |
32 | // HasSubsequence(m1, m2, ...) matches a vector containing elements that match |
33 | // m1, m2 ... in that order. |
34 | // |
35 | // SubsequenceMatcher implements this once the type of vector is known. |
36 | template <typename T> |
37 | class SubsequenceMatcher |
38 | : public ::testing::MatcherInterface<const std::vector<T> &> { |
39 | std::vector<Matcher<T>> Matchers; |
40 | |
41 | public: |
42 | SubsequenceMatcher(std::vector<Matcher<T>> M) : Matchers(M) {} |
43 | |
44 | void DescribeTo(std::ostream *OS) const override { |
45 | *OS << "Contains the subsequence [" ; |
46 | const char *Sep = "" ; |
47 | for (const auto &M : Matchers) { |
48 | *OS << Sep; |
49 | M.DescribeTo(OS); |
50 | Sep = ", " ; |
51 | } |
52 | *OS << "]" ; |
53 | } |
54 | |
55 | bool MatchAndExplain(const std::vector<T> &V, |
56 | ::testing::MatchResultListener *L) const override { |
57 | std::vector<int> Matches(Matchers.size()); |
58 | size_t I = 0; |
59 | for (size_t J = 0; I < Matchers.size() && J < V.size(); ++J) |
60 | if (Matchers[I].Matches(V[J])) |
61 | Matches[I++] = J; |
62 | if (I == Matchers.size()) // We exhausted all matchers. |
63 | return true; |
64 | if (L->IsInterested()) { |
65 | *L << "\n Matched:" ; |
66 | for (size_t K = 0; K < I; ++K) { |
67 | *L << "\n\t" ; |
68 | Matchers[K].DescribeTo(L->stream()); |
69 | *L << " ==> " << ::testing::PrintToString(V[Matches[K]]); |
70 | } |
71 | *L << "\n\t" ; |
72 | Matchers[I].DescribeTo(L->stream()); |
73 | *L << " ==> no subsequent match" ; |
74 | } |
75 | return false; |
76 | } |
77 | }; |
78 | |
79 | // PolySubsequenceMatcher implements a "polymorphic" SubsequenceMatcher. |
80 | // It captures the types of the element matchers, and can be converted to |
81 | // Matcher<vector<T>> if each matcher can be converted to Matcher<T>. |
82 | // This allows HasSubsequence() to accept polymorphic matchers like Not(). |
83 | template <typename... M> class PolySubsequenceMatcher { |
84 | std::tuple<M...> Matchers; |
85 | |
86 | public: |
87 | PolySubsequenceMatcher(M &&... Args) |
88 | : Matchers(std::make_tuple(std::forward<M>(Args)...)) {} |
89 | |
90 | template <typename T> operator Matcher<const std::vector<T> &>() const { |
91 | return ::testing::MakeMatcher(new SubsequenceMatcher<T>( |
92 | TypedMatchers<T>(std::index_sequence_for<M...>{}))); |
93 | } |
94 | |
95 | private: |
96 | template <typename T, size_t... I> |
97 | std::vector<Matcher<T>> TypedMatchers(std::index_sequence<I...>) const { |
98 | return {std::get<I>(Matchers)...}; |
99 | } |
100 | }; |
101 | |
102 | // HasSubsequence(m1, m2, ...) matches a vector containing elements that match |
103 | // m1, m2 ... in that order. |
104 | // The real implementation is in SubsequenceMatcher. |
105 | template <typename... Args> |
106 | PolySubsequenceMatcher<Args...> HasSubsequence(Args &&... M) { |
107 | return PolySubsequenceMatcher<Args...>(std::forward<Args>(M)...); |
108 | } |
109 | |
110 | // EXPECT_ERROR seems like a pretty generic name, make sure it's not defined |
111 | // already. |
112 | #ifdef EXPECT_ERROR |
113 | #error "Refusing to redefine EXPECT_ERROR" |
114 | #endif |
115 | |
116 | // Consumes llvm::Expected<T>, checks it contains an error and marks it as |
117 | // handled. |
118 | #define EXPECT_ERROR(expectedValue) \ |
119 | do { \ |
120 | auto &&ComputedValue = (expectedValue); \ |
121 | if (ComputedValue) { \ |
122 | ADD_FAILURE() << "expected an error from " << #expectedValue \ |
123 | << " but got " \ |
124 | << ::testing::PrintToString(*ComputedValue); \ |
125 | break; \ |
126 | } \ |
127 | llvm::consumeError(ComputedValue.takeError()); \ |
128 | } while (false) |
129 | |
130 | // Implements the HasValue(m) matcher for matching an Optional whose |
131 | // value matches matcher m. |
132 | template <typename InnerMatcher> class OptionalMatcher { |
133 | public: |
134 | explicit OptionalMatcher(const InnerMatcher &matcher) : matcher_(matcher) {} |
135 | OptionalMatcher(const OptionalMatcher&) = default; |
136 | OptionalMatcher &operator=(const OptionalMatcher&) = delete; |
137 | |
138 | // This type conversion operator template allows Optional(m) to be |
139 | // used as a matcher for any Optional type whose value type is |
140 | // compatible with the inner matcher. |
141 | // |
142 | // The reason we do this instead of relying on |
143 | // MakePolymorphicMatcher() is that the latter is not flexible |
144 | // enough for implementing the DescribeTo() method of Optional(). |
145 | template <typename Optional> operator Matcher<Optional>() const { |
146 | return MakeMatcher(new Impl<Optional>(matcher_)); |
147 | } |
148 | |
149 | private: |
150 | // The monomorphic implementation that works for a particular optional type. |
151 | template <typename Optional> |
152 | class Impl : public ::testing::MatcherInterface<Optional> { |
153 | public: |
154 | using Value = typename std::remove_const< |
155 | typename std::remove_reference<Optional>::type>::type::value_type; |
156 | |
157 | explicit Impl(const InnerMatcher &matcher) |
158 | : matcher_(::testing::MatcherCast<const Value &>(matcher)) {} |
159 | |
160 | Impl(const Impl&) = default; |
161 | Impl &operator=(const Impl&) = delete; |
162 | |
163 | virtual void DescribeTo(::std::ostream *os) const { |
164 | *os << "has a value that " ; |
165 | matcher_.DescribeTo(os); |
166 | } |
167 | |
168 | virtual void DescribeNegationTo(::std::ostream *os) const { |
169 | *os << "does not have a value that " ; |
170 | matcher_.DescribeTo(os); |
171 | } |
172 | |
173 | virtual bool |
174 | MatchAndExplain(Optional optional, |
175 | ::testing::MatchResultListener *listener) const { |
176 | if (!optional) |
177 | return false; |
178 | |
179 | *listener << "which has a value " ; |
180 | return MatchPrintAndExplain(*optional, matcher_, listener); |
181 | } |
182 | |
183 | private: |
184 | const Matcher<const Value &> matcher_; |
185 | }; |
186 | |
187 | const InnerMatcher matcher_; |
188 | }; |
189 | |
190 | // Creates a matcher that matches an Optional that has a value |
191 | // that matches inner_matcher. |
192 | template <typename InnerMatcher> |
193 | inline OptionalMatcher<InnerMatcher> |
194 | HasValue(const InnerMatcher &inner_matcher) { |
195 | return OptionalMatcher<InnerMatcher>(inner_matcher); |
196 | } |
197 | |
198 | } // namespace clangd |
199 | } // namespace clang |
200 | #endif |
201 | |