xref: /aosp_15_r20/external/federated-compute/fcp/testing/result_matchers.h (revision 14675a029014e728ec732f129a32e299b2da0601)
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