1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker #ifndef FCP_TESTING_RESULT_MATCHERS_H_
18*14675a02SAndroid Build Coastguard Worker #define FCP_TESTING_RESULT_MATCHERS_H_
19*14675a02SAndroid Build Coastguard Worker
20*14675a02SAndroid Build Coastguard Worker #include <string>
21*14675a02SAndroid Build Coastguard Worker
22*14675a02SAndroid Build Coastguard Worker #include "gmock/gmock.h"
23*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
24*14675a02SAndroid Build Coastguard Worker #include "fcp/base/error.h"
25*14675a02SAndroid Build Coastguard Worker #include "fcp/base/result.h"
26*14675a02SAndroid Build Coastguard Worker
27*14675a02SAndroid Build Coastguard Worker namespace fcp {
28*14675a02SAndroid Build Coastguard Worker
29*14675a02SAndroid Build Coastguard Worker // Allows to formulate test expectation on a result containing error as:
30*14675a02SAndroid Build Coastguard Worker // EXPECT_THAT(result, IsError());
31*14675a02SAndroid Build Coastguard Worker MATCHER(IsError, "") { return arg.is_error(); }
32*14675a02SAndroid Build Coastguard Worker
33*14675a02SAndroid Build Coastguard Worker // Allows to formulate test expectation on a non-error result with existing
34*14675a02SAndroid Build Coastguard Worker // gtest matchers (such as Eq) as:
35*14675a02SAndroid Build Coastguard Worker // EXPECT_THAT(result, HasValue(Eq(value)));
36*14675a02SAndroid Build Coastguard Worker template <typename MatcherType>
37*14675a02SAndroid Build Coastguard Worker class HasValueMatcher {
38*14675a02SAndroid Build Coastguard Worker public:
HasValueMatcher(MatcherType matcher)39*14675a02SAndroid Build Coastguard Worker explicit HasValueMatcher(MatcherType matcher)
40*14675a02SAndroid Build Coastguard Worker : matcher_(std::move(matcher)) {}
41*14675a02SAndroid Build Coastguard Worker
42*14675a02SAndroid Build Coastguard Worker template <typename TargetType>
43*14675a02SAndroid Build Coastguard Worker operator testing::Matcher<TargetType>() const { // NOLINT
44*14675a02SAndroid Build Coastguard Worker using D = std::remove_cv_t<std::remove_reference_t<TargetType>>;
45*14675a02SAndroid Build Coastguard Worker static_assert(result_internal::ResultTraits<D>::is_result());
46*14675a02SAndroid Build Coastguard Worker using V = typename result_internal::ResultTraits<D>::ValueType;
47*14675a02SAndroid Build Coastguard Worker return testing::Matcher<TargetType>(
48*14675a02SAndroid Build Coastguard Worker new Impl<V>(testing::SafeMatcherCast<V const&>(matcher_)));
49*14675a02SAndroid Build Coastguard Worker }
50*14675a02SAndroid Build Coastguard Worker
51*14675a02SAndroid Build Coastguard Worker private:
52*14675a02SAndroid Build Coastguard Worker template <typename ValueType>
53*14675a02SAndroid Build Coastguard Worker class Impl : public testing::MatcherInterface<Result<ValueType> const&> {
54*14675a02SAndroid Build Coastguard Worker public:
Impl(testing::Matcher<ValueType const &> matcher)55*14675a02SAndroid Build Coastguard Worker explicit Impl(testing::Matcher<ValueType const&> matcher)
56*14675a02SAndroid Build Coastguard Worker : concrete_matcher_(std::move(matcher)) {}
57*14675a02SAndroid Build Coastguard Worker
58*14675a02SAndroid Build Coastguard Worker bool MatchAndExplain(
59*14675a02SAndroid Build Coastguard Worker Result<ValueType> const& arg,
60*14675a02SAndroid Build Coastguard Worker testing::MatchResultListener* result_listener) const override;
61*14675a02SAndroid Build Coastguard Worker
DescribeTo(std::ostream * os)62*14675a02SAndroid Build Coastguard Worker void DescribeTo(std::ostream* os) const override {
63*14675a02SAndroid Build Coastguard Worker *os << FormatDescription(false);
64*14675a02SAndroid Build Coastguard Worker }
65*14675a02SAndroid Build Coastguard Worker
DescribeNegationTo(std::ostream * os)66*14675a02SAndroid Build Coastguard Worker void DescribeNegationTo(std::ostream* os) const override {
67*14675a02SAndroid Build Coastguard Worker *os << FormatDescription(true);
68*14675a02SAndroid Build Coastguard Worker }
69*14675a02SAndroid Build Coastguard Worker
70*14675a02SAndroid Build Coastguard Worker private:
71*14675a02SAndroid Build Coastguard Worker std::string FormatDescription(bool negation) const;
72*14675a02SAndroid Build Coastguard Worker testing::Matcher<ValueType const&> concrete_matcher_;
73*14675a02SAndroid Build Coastguard Worker };
74*14675a02SAndroid Build Coastguard Worker
75*14675a02SAndroid Build Coastguard Worker MatcherType matcher_;
76*14675a02SAndroid Build Coastguard Worker };
77*14675a02SAndroid Build Coastguard Worker
78*14675a02SAndroid Build Coastguard Worker template <typename MatcherType>
HasValue(MatcherType matcher)79*14675a02SAndroid Build Coastguard Worker HasValueMatcher<MatcherType> HasValue(MatcherType matcher) {
80*14675a02SAndroid Build Coastguard Worker return HasValueMatcher<MatcherType>(std::move(matcher));
81*14675a02SAndroid Build Coastguard Worker }
82*14675a02SAndroid Build Coastguard Worker
83*14675a02SAndroid Build Coastguard Worker template <typename MatcherType>
84*14675a02SAndroid Build Coastguard Worker template <typename ValueType>
MatchAndExplain(Result<ValueType> const & arg,testing::MatchResultListener * result_listener)85*14675a02SAndroid Build Coastguard Worker bool HasValueMatcher<MatcherType>::Impl<ValueType>::MatchAndExplain(
86*14675a02SAndroid Build Coastguard Worker Result<ValueType> const& arg,
87*14675a02SAndroid Build Coastguard Worker testing::MatchResultListener* result_listener) const {
88*14675a02SAndroid Build Coastguard Worker if (arg.is_error()) {
89*14675a02SAndroid Build Coastguard Worker *result_listener << "is error";
90*14675a02SAndroid Build Coastguard Worker return false;
91*14675a02SAndroid Build Coastguard Worker } else {
92*14675a02SAndroid Build Coastguard Worker ValueType const& value = arg.GetValueOrDie();
93*14675a02SAndroid Build Coastguard Worker *result_listener << "value = " << testing::PrintToString(value);
94*14675a02SAndroid Build Coastguard Worker return testing::ExplainMatchResult(concrete_matcher_, value,
95*14675a02SAndroid Build Coastguard Worker result_listener);
96*14675a02SAndroid Build Coastguard Worker }
97*14675a02SAndroid Build Coastguard Worker }
98*14675a02SAndroid Build Coastguard Worker
99*14675a02SAndroid Build Coastguard Worker template <typename MatcherType>
100*14675a02SAndroid Build Coastguard Worker template <typename ValueType>
FormatDescription(bool negation)101*14675a02SAndroid Build Coastguard Worker std::string HasValueMatcher<MatcherType>::Impl<ValueType>::FormatDescription(
102*14675a02SAndroid Build Coastguard Worker bool negation) const {
103*14675a02SAndroid Build Coastguard Worker std::stringstream desc;
104*14675a02SAndroid Build Coastguard Worker if (negation) {
105*14675a02SAndroid Build Coastguard Worker concrete_matcher_.DescribeNegationTo(&desc);
106*14675a02SAndroid Build Coastguard Worker } else {
107*14675a02SAndroid Build Coastguard Worker concrete_matcher_.DescribeTo(&desc);
108*14675a02SAndroid Build Coastguard Worker }
109*14675a02SAndroid Build Coastguard Worker return desc.str();
110*14675a02SAndroid Build Coastguard Worker }
111*14675a02SAndroid Build Coastguard Worker
112*14675a02SAndroid Build Coastguard Worker // Expect a particular status for testing failure modes of protocols.
113*14675a02SAndroid Build Coastguard Worker // Prefer ExpectOk (defined in result.h) for OK status.
114*14675a02SAndroid Build Coastguard Worker template <fcp::StatusCode Code>
115*14675a02SAndroid Build Coastguard Worker struct ExpectStatus : public ExpectBase {
116*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase;
117*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectStatus(
118*14675a02SAndroid Build Coastguard Worker SourceLocation loc = SourceLocation::current())
ExpectBaseExpectStatus119*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {}
120*14675a02SAndroid Build Coastguard Worker
operatorExpectStatus121*14675a02SAndroid Build Coastguard Worker Result<Unit> operator()(const Status& s) const {
122*14675a02SAndroid Build Coastguard Worker if (s.code() == Code) {
123*14675a02SAndroid Build Coastguard Worker return Unit{};
124*14675a02SAndroid Build Coastguard Worker } else {
125*14675a02SAndroid Build Coastguard Worker return TraceUnexpectedStatus(Code, s);
126*14675a02SAndroid Build Coastguard Worker }
127*14675a02SAndroid Build Coastguard Worker }
128*14675a02SAndroid Build Coastguard Worker };
129*14675a02SAndroid Build Coastguard Worker
130*14675a02SAndroid Build Coastguard Worker } // namespace fcp
131*14675a02SAndroid Build Coastguard Worker
132*14675a02SAndroid Build Coastguard Worker #endif // FCP_TESTING_RESULT_MATCHERS_H_
133