clang-tools  9.0.0
clangd/unittests/Matchers.h
Go to the documentation of this file.
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_UNITTESTS_CLANGD_MATCHERS_H
14 #define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_MATCHERS_H
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>
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>(llvm::index_sequence_for<M...>{})));
93  }
94 
95 private:
96  template <typename T, size_t... I>
97  std::vector<Matcher<T>> TypedMatchers(llvm::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 
136  // This type conversion operator template allows Optional(m) to be
137  // used as a matcher for any Optional type whose value type is
138  // compatible with the inner matcher.
139  //
140  // The reason we do this instead of relying on
141  // MakePolymorphicMatcher() is that the latter is not flexible
142  // enough for implementing the DescribeTo() method of Optional().
143  template <typename Optional> operator Matcher<Optional>() const {
144  return MakeMatcher(new Impl<Optional>(matcher_));
145  }
146 
147 private:
148  // The monomorphic implementation that works for a particular optional type.
149  template <typename Optional>
150  class Impl : public ::testing::MatcherInterface<Optional> {
151  public:
152  using Value = typename std::remove_const<
153  typename std::remove_reference<Optional>::type>::type::value_type;
154 
155  explicit Impl(const InnerMatcher &matcher)
156  : matcher_(::testing::MatcherCast<const Value &>(matcher)) {}
157 
158  virtual void DescribeTo(::std::ostream *os) const {
159  *os << "has a value that ";
160  matcher_.DescribeTo(os);
161  }
162 
163  virtual void DescribeNegationTo(::std::ostream *os) const {
164  *os << "does not have a value that ";
165  matcher_.DescribeTo(os);
166  }
167 
168  virtual bool
169  MatchAndExplain(Optional optional,
170  ::testing::MatchResultListener *listener) const {
171  if (!optional.hasValue())
172  return false;
173 
174  *listener << "which has a value ";
175  return MatchPrintAndExplain(*optional, matcher_, listener);
176  }
177 
178  private:
179  const Matcher<const Value &> matcher_;
180 
181  GTEST_DISALLOW_ASSIGN_(Impl);
182  };
183 
184  const InnerMatcher matcher_;
185 
186  GTEST_DISALLOW_ASSIGN_(OptionalMatcher);
187 };
188 
189 // Creates a matcher that matches an Optional that has a value
190 // that matches inner_matcher.
191 template <typename InnerMatcher>
193 HasValue(const InnerMatcher &inner_matcher) {
194  return OptionalMatcher<InnerMatcher>(inner_matcher);
195 }
196 
197 } // namespace clangd
198 } // namespace clang
199 #endif
void DescribeTo(std::ostream *OS) const override
OptionalMatcher< InnerMatcher > HasValue(const InnerMatcher &inner_matcher)
bool MatchAndExplain(const std::vector< T > &V, ::testing::MatchResultListener *L) const override
PolySubsequenceMatcher< Args... > HasSubsequence(Args &&... M)
SubsequenceMatcher(std::vector< Matcher< T >> M)
OptionalMatcher(const InnerMatcher &matcher)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//