1 //===-- Matchers.h ----------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // GMock matchers that aren't specific to particular tests.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_MATCHERS_H
14 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_MATCHERS_H
16 #include "gmock/gmock.h"
20 using ::testing::Matcher
;
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) \
27 EXPECT_THAT(value, matcher); \
29 EXPECT_THAT(value, ::testing::Not(matcher)); \
32 // HasSubsequence(m1, m2, ...) matches a vector containing elements that match
33 // m1, m2 ... in that order.
35 // SubsequenceMatcher implements this once the type of vector is known.
37 class SubsequenceMatcher
38 : public ::testing::MatcherInterface
<const std::vector
<T
> &> {
39 std::vector
<Matcher
<T
>> Matchers
;
42 SubsequenceMatcher(std::vector
<Matcher
<T
>> M
) : Matchers(M
) {}
44 void DescribeTo(std::ostream
*OS
) const override
{
45 *OS
<< "Contains the subsequence [";
47 for (const auto &M
: Matchers
) {
55 bool MatchAndExplain(const std::vector
<T
> &V
,
56 ::testing::MatchResultListener
*L
) const override
{
57 std::vector
<int> Matches(Matchers
.size());
59 for (size_t J
= 0; I
< Matchers
.size() && J
< V
.size(); ++J
)
60 if (Matchers
[I
].Matches(V
[J
]))
62 if (I
== Matchers
.size()) // We exhausted all matchers.
64 if (L
->IsInterested()) {
66 for (size_t K
= 0; K
< I
; ++K
) {
68 Matchers
[K
].DescribeTo(L
->stream());
69 *L
<< " ==> " << ::testing::PrintToString(V
[Matches
[K
]]);
72 Matchers
[I
].DescribeTo(L
->stream());
73 *L
<< " ==> no subsequent match";
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
;
87 PolySubsequenceMatcher(M
&&... Args
)
88 : Matchers(std::make_tuple(std::forward
<M
>(Args
)...)) {}
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
...>{})));
96 template <typename T
, size_t... I
>
97 std::vector
<Matcher
<T
>> TypedMatchers(std::index_sequence
<I
...>) const {
98 return {std::get
<I
>(Matchers
)...};
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
)...);
110 // EXPECT_ERROR seems like a pretty generic name, make sure it's not defined
113 #error "Refusing to redefine EXPECT_ERROR"
116 // Consumes llvm::Expected<T>, checks it contains an error and marks it as
118 #define EXPECT_ERROR(expectedValue) \
120 auto &&ComputedValue = (expectedValue); \
121 if (ComputedValue) { \
122 ADD_FAILURE() << "expected an error from " << #expectedValue \
124 << ::testing::PrintToString(*ComputedValue); \
127 llvm::consumeError(ComputedValue.takeError()); \
130 // Implements the HasValue(m) matcher for matching an Optional whose
131 // value matches matcher m.
132 template <typename InnerMatcher
> class OptionalMatcher
{
134 explicit OptionalMatcher(const InnerMatcher
&matcher
) : matcher_(matcher
) {}
135 OptionalMatcher(const OptionalMatcher
&) = default;
136 OptionalMatcher
&operator=(const OptionalMatcher
&) = delete;
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.
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_
));
150 // The monomorphic implementation that works for a particular optional type.
151 template <typename Optional
>
152 class Impl
: public ::testing::MatcherInterface
<Optional
> {
154 using Value
= typename
std::remove_const
<
155 typename
std::remove_reference
<Optional
>::type
>::type::value_type
;
157 explicit Impl(const InnerMatcher
&matcher
)
158 : matcher_(::testing::MatcherCast
<const Value
&>(matcher
)) {}
160 Impl(const Impl
&) = default;
161 Impl
&operator=(const Impl
&) = delete;
163 virtual void DescribeTo(::std::ostream
*os
) const {
164 *os
<< "has a value that ";
165 matcher_
.DescribeTo(os
);
168 virtual void DescribeNegationTo(::std::ostream
*os
) const {
169 *os
<< "does not have a value that ";
170 matcher_
.DescribeTo(os
);
174 MatchAndExplain(Optional optional
,
175 ::testing::MatchResultListener
*listener
) const {
179 *listener
<< "which has a value ";
180 return MatchPrintAndExplain(*optional
, matcher_
, listener
);
184 const Matcher
<const Value
&> matcher_
;
187 const InnerMatcher matcher_
;
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
);
198 } // namespace clangd