xref: /aosp_15_r20/external/abseil-cpp/absl/status/internal/status_matchers.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2024 The Abseil Authors
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker 
15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
16*9356374aSAndroid Build Coastguard Worker #define ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
17*9356374aSAndroid Build Coastguard Worker 
18*9356374aSAndroid Build Coastguard Worker #include <ostream>  // NOLINT
19*9356374aSAndroid Build Coastguard Worker #include <string>
20*9356374aSAndroid Build Coastguard Worker #include <type_traits>
21*9356374aSAndroid Build Coastguard Worker #include <utility>
22*9356374aSAndroid Build Coastguard Worker 
23*9356374aSAndroid Build Coastguard Worker #include "gmock/gmock.h"  // gmock_for_status_matchers.h
24*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
25*9356374aSAndroid Build Coastguard Worker #include "absl/status/status.h"
26*9356374aSAndroid Build Coastguard Worker #include "absl/status/statusor.h"
27*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
28*9356374aSAndroid Build Coastguard Worker 
29*9356374aSAndroid Build Coastguard Worker namespace absl_testing {
30*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
31*9356374aSAndroid Build Coastguard Worker namespace status_internal {
32*9356374aSAndroid Build Coastguard Worker 
GetStatus(const absl::Status & status)33*9356374aSAndroid Build Coastguard Worker inline const absl::Status& GetStatus(const absl::Status& status) {
34*9356374aSAndroid Build Coastguard Worker   return status;
35*9356374aSAndroid Build Coastguard Worker }
36*9356374aSAndroid Build Coastguard Worker 
37*9356374aSAndroid Build Coastguard Worker template <typename T>
GetStatus(const absl::StatusOr<T> & status)38*9356374aSAndroid Build Coastguard Worker inline const absl::Status& GetStatus(const absl::StatusOr<T>& status) {
39*9356374aSAndroid Build Coastguard Worker   return status.status();
40*9356374aSAndroid Build Coastguard Worker }
41*9356374aSAndroid Build Coastguard Worker 
42*9356374aSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////
43*9356374aSAndroid Build Coastguard Worker // Implementation of IsOkAndHolds().
44*9356374aSAndroid Build Coastguard Worker 
45*9356374aSAndroid Build Coastguard Worker // Monomorphic implementation of matcher IsOkAndHolds(m).  StatusOrType is a
46*9356374aSAndroid Build Coastguard Worker // reference to StatusOr<T>.
47*9356374aSAndroid Build Coastguard Worker template <typename StatusOrType>
48*9356374aSAndroid Build Coastguard Worker class IsOkAndHoldsMatcherImpl
49*9356374aSAndroid Build Coastguard Worker     : public ::testing::MatcherInterface<StatusOrType> {
50*9356374aSAndroid Build Coastguard Worker  public:
51*9356374aSAndroid Build Coastguard Worker   typedef
52*9356374aSAndroid Build Coastguard Worker       typename std::remove_reference<StatusOrType>::type::value_type value_type;
53*9356374aSAndroid Build Coastguard Worker 
54*9356374aSAndroid Build Coastguard Worker   template <typename InnerMatcher>
IsOkAndHoldsMatcherImpl(InnerMatcher && inner_matcher)55*9356374aSAndroid Build Coastguard Worker   explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
56*9356374aSAndroid Build Coastguard Worker       : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
57*9356374aSAndroid Build Coastguard Worker             std::forward<InnerMatcher>(inner_matcher))) {}
58*9356374aSAndroid Build Coastguard Worker 
DescribeTo(std::ostream * os)59*9356374aSAndroid Build Coastguard Worker   void DescribeTo(std::ostream* os) const override {
60*9356374aSAndroid Build Coastguard Worker     *os << "is OK and has a value that ";
61*9356374aSAndroid Build Coastguard Worker     inner_matcher_.DescribeTo(os);
62*9356374aSAndroid Build Coastguard Worker   }
63*9356374aSAndroid Build Coastguard Worker 
DescribeNegationTo(std::ostream * os)64*9356374aSAndroid Build Coastguard Worker   void DescribeNegationTo(std::ostream* os) const override {
65*9356374aSAndroid Build Coastguard Worker     *os << "isn't OK or has a value that ";
66*9356374aSAndroid Build Coastguard Worker     inner_matcher_.DescribeNegationTo(os);
67*9356374aSAndroid Build Coastguard Worker   }
68*9356374aSAndroid Build Coastguard Worker 
MatchAndExplain(StatusOrType actual_value,::testing::MatchResultListener * result_listener)69*9356374aSAndroid Build Coastguard Worker   bool MatchAndExplain(
70*9356374aSAndroid Build Coastguard Worker       StatusOrType actual_value,
71*9356374aSAndroid Build Coastguard Worker       ::testing::MatchResultListener* result_listener) const override {
72*9356374aSAndroid Build Coastguard Worker     if (!GetStatus(actual_value).ok()) {
73*9356374aSAndroid Build Coastguard Worker       *result_listener << "which has status " << GetStatus(actual_value);
74*9356374aSAndroid Build Coastguard Worker       return false;
75*9356374aSAndroid Build Coastguard Worker     }
76*9356374aSAndroid Build Coastguard Worker 
77*9356374aSAndroid Build Coastguard Worker     // Call through to the inner matcher.
78*9356374aSAndroid Build Coastguard Worker     return inner_matcher_.MatchAndExplain(*actual_value, result_listener);
79*9356374aSAndroid Build Coastguard Worker   }
80*9356374aSAndroid Build Coastguard Worker 
81*9356374aSAndroid Build Coastguard Worker  private:
82*9356374aSAndroid Build Coastguard Worker   const ::testing::Matcher<const value_type&> inner_matcher_;
83*9356374aSAndroid Build Coastguard Worker };
84*9356374aSAndroid Build Coastguard Worker 
85*9356374aSAndroid Build Coastguard Worker // Implements IsOkAndHolds(m) as a polymorphic matcher.
86*9356374aSAndroid Build Coastguard Worker template <typename InnerMatcher>
87*9356374aSAndroid Build Coastguard Worker class IsOkAndHoldsMatcher {
88*9356374aSAndroid Build Coastguard Worker  public:
IsOkAndHoldsMatcher(InnerMatcher inner_matcher)89*9356374aSAndroid Build Coastguard Worker   explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
90*9356374aSAndroid Build Coastguard Worker       : inner_matcher_(std::forward<InnerMatcher>(inner_matcher)) {}
91*9356374aSAndroid Build Coastguard Worker 
92*9356374aSAndroid Build Coastguard Worker   // Converts this polymorphic matcher to a monomorphic matcher of the
93*9356374aSAndroid Build Coastguard Worker   // given type.  StatusOrType can be either StatusOr<T> or a
94*9356374aSAndroid Build Coastguard Worker   // reference to StatusOr<T>.
95*9356374aSAndroid Build Coastguard Worker   template <typename StatusOrType>
96*9356374aSAndroid Build Coastguard Worker   operator ::testing::Matcher<StatusOrType>() const {  // NOLINT
97*9356374aSAndroid Build Coastguard Worker     return ::testing::Matcher<StatusOrType>(
98*9356374aSAndroid Build Coastguard Worker         new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
99*9356374aSAndroid Build Coastguard Worker   }
100*9356374aSAndroid Build Coastguard Worker 
101*9356374aSAndroid Build Coastguard Worker  private:
102*9356374aSAndroid Build Coastguard Worker   const InnerMatcher inner_matcher_;
103*9356374aSAndroid Build Coastguard Worker };
104*9356374aSAndroid Build Coastguard Worker 
105*9356374aSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////
106*9356374aSAndroid Build Coastguard Worker // Implementation of StatusIs().
107*9356374aSAndroid Build Coastguard Worker 
108*9356374aSAndroid Build Coastguard Worker // `StatusCode` is implicitly convertible from `int`, `absl::StatusCode`, and
109*9356374aSAndroid Build Coastguard Worker //  is explicitly convertible to these types as well.
110*9356374aSAndroid Build Coastguard Worker //
111*9356374aSAndroid Build Coastguard Worker // We need this class because `absl::StatusCode` (as a scoped enum) is not
112*9356374aSAndroid Build Coastguard Worker // implicitly convertible to `int`. In order to handle use cases like
113*9356374aSAndroid Build Coastguard Worker // ```
114*9356374aSAndroid Build Coastguard Worker // StatusIs(Anyof(absl::StatusCode::kUnknown, absl::StatusCode::kCancelled))
115*9356374aSAndroid Build Coastguard Worker // ```
116*9356374aSAndroid Build Coastguard Worker // which uses polymorphic matchers, we need to unify the interfaces into
117*9356374aSAndroid Build Coastguard Worker // `Matcher<StatusCode>`.
118*9356374aSAndroid Build Coastguard Worker class StatusCode {
119*9356374aSAndroid Build Coastguard Worker  public:
StatusCode(int code)120*9356374aSAndroid Build Coastguard Worker   /*implicit*/ StatusCode(int code)  // NOLINT
121*9356374aSAndroid Build Coastguard Worker       : code_(static_cast<::absl::StatusCode>(code)) {}
StatusCode(::absl::StatusCode code)122*9356374aSAndroid Build Coastguard Worker   /*implicit*/ StatusCode(::absl::StatusCode code) : code_(code) {}  // NOLINT
123*9356374aSAndroid Build Coastguard Worker 
124*9356374aSAndroid Build Coastguard Worker   explicit operator int() const { return static_cast<int>(code_); }
125*9356374aSAndroid Build Coastguard Worker 
PrintTo(const StatusCode & code,std::ostream * os)126*9356374aSAndroid Build Coastguard Worker   friend inline void PrintTo(const StatusCode& code, std::ostream* os) {
127*9356374aSAndroid Build Coastguard Worker     // TODO(b/321095377): Change this to print the status code as a string.
128*9356374aSAndroid Build Coastguard Worker     *os << static_cast<int>(code);
129*9356374aSAndroid Build Coastguard Worker   }
130*9356374aSAndroid Build Coastguard Worker 
131*9356374aSAndroid Build Coastguard Worker  private:
132*9356374aSAndroid Build Coastguard Worker   ::absl::StatusCode code_;
133*9356374aSAndroid Build Coastguard Worker };
134*9356374aSAndroid Build Coastguard Worker 
135*9356374aSAndroid Build Coastguard Worker // Relational operators to handle matchers like Eq, Lt, etc..
136*9356374aSAndroid Build Coastguard Worker inline bool operator==(const StatusCode& lhs, const StatusCode& rhs) {
137*9356374aSAndroid Build Coastguard Worker   return static_cast<int>(lhs) == static_cast<int>(rhs);
138*9356374aSAndroid Build Coastguard Worker }
139*9356374aSAndroid Build Coastguard Worker inline bool operator!=(const StatusCode& lhs, const StatusCode& rhs) {
140*9356374aSAndroid Build Coastguard Worker   return static_cast<int>(lhs) != static_cast<int>(rhs);
141*9356374aSAndroid Build Coastguard Worker }
142*9356374aSAndroid Build Coastguard Worker 
143*9356374aSAndroid Build Coastguard Worker // StatusIs() is a polymorphic matcher.  This class is the common
144*9356374aSAndroid Build Coastguard Worker // implementation of it shared by all types T where StatusIs() can be
145*9356374aSAndroid Build Coastguard Worker // used as a Matcher<T>.
146*9356374aSAndroid Build Coastguard Worker class StatusIsMatcherCommonImpl {
147*9356374aSAndroid Build Coastguard Worker  public:
StatusIsMatcherCommonImpl(::testing::Matcher<StatusCode> code_matcher,::testing::Matcher<absl::string_view> message_matcher)148*9356374aSAndroid Build Coastguard Worker   StatusIsMatcherCommonImpl(
149*9356374aSAndroid Build Coastguard Worker       ::testing::Matcher<StatusCode> code_matcher,
150*9356374aSAndroid Build Coastguard Worker       ::testing::Matcher<absl::string_view> message_matcher)
151*9356374aSAndroid Build Coastguard Worker       : code_matcher_(std::move(code_matcher)),
152*9356374aSAndroid Build Coastguard Worker         message_matcher_(std::move(message_matcher)) {}
153*9356374aSAndroid Build Coastguard Worker 
154*9356374aSAndroid Build Coastguard Worker   void DescribeTo(std::ostream* os) const;
155*9356374aSAndroid Build Coastguard Worker 
156*9356374aSAndroid Build Coastguard Worker   void DescribeNegationTo(std::ostream* os) const;
157*9356374aSAndroid Build Coastguard Worker 
158*9356374aSAndroid Build Coastguard Worker   bool MatchAndExplain(const absl::Status& status,
159*9356374aSAndroid Build Coastguard Worker                        ::testing::MatchResultListener* result_listener) const;
160*9356374aSAndroid Build Coastguard Worker 
161*9356374aSAndroid Build Coastguard Worker  private:
162*9356374aSAndroid Build Coastguard Worker   const ::testing::Matcher<StatusCode> code_matcher_;
163*9356374aSAndroid Build Coastguard Worker   const ::testing::Matcher<absl::string_view> message_matcher_;
164*9356374aSAndroid Build Coastguard Worker };
165*9356374aSAndroid Build Coastguard Worker 
166*9356374aSAndroid Build Coastguard Worker // Monomorphic implementation of matcher StatusIs() for a given type
167*9356374aSAndroid Build Coastguard Worker // T.  T can be Status, StatusOr<>, or a reference to either of them.
168*9356374aSAndroid Build Coastguard Worker template <typename T>
169*9356374aSAndroid Build Coastguard Worker class MonoStatusIsMatcherImpl : public ::testing::MatcherInterface<T> {
170*9356374aSAndroid Build Coastguard Worker  public:
MonoStatusIsMatcherImpl(StatusIsMatcherCommonImpl common_impl)171*9356374aSAndroid Build Coastguard Worker   explicit MonoStatusIsMatcherImpl(StatusIsMatcherCommonImpl common_impl)
172*9356374aSAndroid Build Coastguard Worker       : common_impl_(std::move(common_impl)) {}
173*9356374aSAndroid Build Coastguard Worker 
DescribeTo(std::ostream * os)174*9356374aSAndroid Build Coastguard Worker   void DescribeTo(std::ostream* os) const override {
175*9356374aSAndroid Build Coastguard Worker     common_impl_.DescribeTo(os);
176*9356374aSAndroid Build Coastguard Worker   }
177*9356374aSAndroid Build Coastguard Worker 
DescribeNegationTo(std::ostream * os)178*9356374aSAndroid Build Coastguard Worker   void DescribeNegationTo(std::ostream* os) const override {
179*9356374aSAndroid Build Coastguard Worker     common_impl_.DescribeNegationTo(os);
180*9356374aSAndroid Build Coastguard Worker   }
181*9356374aSAndroid Build Coastguard Worker 
MatchAndExplain(T actual_value,::testing::MatchResultListener * result_listener)182*9356374aSAndroid Build Coastguard Worker   bool MatchAndExplain(
183*9356374aSAndroid Build Coastguard Worker       T actual_value,
184*9356374aSAndroid Build Coastguard Worker       ::testing::MatchResultListener* result_listener) const override {
185*9356374aSAndroid Build Coastguard Worker     return common_impl_.MatchAndExplain(GetStatus(actual_value),
186*9356374aSAndroid Build Coastguard Worker                                         result_listener);
187*9356374aSAndroid Build Coastguard Worker   }
188*9356374aSAndroid Build Coastguard Worker 
189*9356374aSAndroid Build Coastguard Worker  private:
190*9356374aSAndroid Build Coastguard Worker   StatusIsMatcherCommonImpl common_impl_;
191*9356374aSAndroid Build Coastguard Worker };
192*9356374aSAndroid Build Coastguard Worker 
193*9356374aSAndroid Build Coastguard Worker // Implements StatusIs() as a polymorphic matcher.
194*9356374aSAndroid Build Coastguard Worker class StatusIsMatcher {
195*9356374aSAndroid Build Coastguard Worker  public:
196*9356374aSAndroid Build Coastguard Worker   template <typename StatusCodeMatcher, typename StatusMessageMatcher>
StatusIsMatcher(StatusCodeMatcher && code_matcher,StatusMessageMatcher && message_matcher)197*9356374aSAndroid Build Coastguard Worker   StatusIsMatcher(StatusCodeMatcher&& code_matcher,
198*9356374aSAndroid Build Coastguard Worker                   StatusMessageMatcher&& message_matcher)
199*9356374aSAndroid Build Coastguard Worker       : common_impl_(::testing::MatcherCast<StatusCode>(
200*9356374aSAndroid Build Coastguard Worker                          std::forward<StatusCodeMatcher>(code_matcher)),
201*9356374aSAndroid Build Coastguard Worker                      ::testing::MatcherCast<absl::string_view>(
202*9356374aSAndroid Build Coastguard Worker                          std::forward<StatusMessageMatcher>(message_matcher))) {
203*9356374aSAndroid Build Coastguard Worker   }
204*9356374aSAndroid Build Coastguard Worker 
205*9356374aSAndroid Build Coastguard Worker   // Converts this polymorphic matcher to a monomorphic matcher of the
206*9356374aSAndroid Build Coastguard Worker   // given type.  T can be StatusOr<>, Status, or a reference to
207*9356374aSAndroid Build Coastguard Worker   // either of them.
208*9356374aSAndroid Build Coastguard Worker   template <typename T>
209*9356374aSAndroid Build Coastguard Worker   /*implicit*/ operator ::testing::Matcher<T>() const {  // NOLINT
210*9356374aSAndroid Build Coastguard Worker     return ::testing::Matcher<T>(
211*9356374aSAndroid Build Coastguard Worker         new MonoStatusIsMatcherImpl<const T&>(common_impl_));
212*9356374aSAndroid Build Coastguard Worker   }
213*9356374aSAndroid Build Coastguard Worker 
214*9356374aSAndroid Build Coastguard Worker  private:
215*9356374aSAndroid Build Coastguard Worker   const StatusIsMatcherCommonImpl common_impl_;
216*9356374aSAndroid Build Coastguard Worker };
217*9356374aSAndroid Build Coastguard Worker 
218*9356374aSAndroid Build Coastguard Worker // Monomorphic implementation of matcher IsOk() for a given type T.
219*9356374aSAndroid Build Coastguard Worker // T can be Status, StatusOr<>, or a reference to either of them.
220*9356374aSAndroid Build Coastguard Worker template <typename T>
221*9356374aSAndroid Build Coastguard Worker class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
222*9356374aSAndroid Build Coastguard Worker  public:
DescribeTo(std::ostream * os)223*9356374aSAndroid Build Coastguard Worker   void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
DescribeNegationTo(std::ostream * os)224*9356374aSAndroid Build Coastguard Worker   void DescribeNegationTo(std::ostream* os) const override {
225*9356374aSAndroid Build Coastguard Worker     *os << "is not OK";
226*9356374aSAndroid Build Coastguard Worker   }
MatchAndExplain(T actual_value,::testing::MatchResultListener *)227*9356374aSAndroid Build Coastguard Worker   bool MatchAndExplain(T actual_value,
228*9356374aSAndroid Build Coastguard Worker                        ::testing::MatchResultListener*) const override {
229*9356374aSAndroid Build Coastguard Worker     return GetStatus(actual_value).ok();
230*9356374aSAndroid Build Coastguard Worker   }
231*9356374aSAndroid Build Coastguard Worker };
232*9356374aSAndroid Build Coastguard Worker 
233*9356374aSAndroid Build Coastguard Worker // Implements IsOk() as a polymorphic matcher.
234*9356374aSAndroid Build Coastguard Worker class IsOkMatcher {
235*9356374aSAndroid Build Coastguard Worker  public:
236*9356374aSAndroid Build Coastguard Worker   template <typename T>
237*9356374aSAndroid Build Coastguard Worker   /*implicit*/ operator ::testing::Matcher<T>() const {  // NOLINT
238*9356374aSAndroid Build Coastguard Worker     return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<const T&>());
239*9356374aSAndroid Build Coastguard Worker   }
240*9356374aSAndroid Build Coastguard Worker };
241*9356374aSAndroid Build Coastguard Worker 
242*9356374aSAndroid Build Coastguard Worker }  // namespace status_internal
243*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
244*9356374aSAndroid Build Coastguard Worker }  // namespace absl_testing
245*9356374aSAndroid Build Coastguard Worker 
246*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
247