Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:33:36

0001 // Copyright 2024 The Abseil Authors
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //     https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
0016 #define ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
0017 
0018 #include <ostream>  // NOLINT
0019 #include <string>
0020 #include <type_traits>
0021 #include <utility>
0022 
0023 #include "gmock/gmock.h"  // gmock_for_status_matchers.h
0024 #include "absl/base/config.h"
0025 #include "absl/status/status.h"
0026 #include "absl/status/statusor.h"
0027 #include "absl/strings/string_view.h"
0028 
0029 namespace absl_testing {
0030 ABSL_NAMESPACE_BEGIN
0031 namespace status_internal {
0032 
0033 inline const absl::Status& GetStatus(const absl::Status& status) {
0034   return status;
0035 }
0036 
0037 template <typename T>
0038 inline const absl::Status& GetStatus(const absl::StatusOr<T>& status) {
0039   return status.status();
0040 }
0041 
0042 ////////////////////////////////////////////////////////////
0043 // Implementation of IsOkAndHolds().
0044 
0045 // Monomorphic implementation of matcher IsOkAndHolds(m).  StatusOrType is a
0046 // reference to StatusOr<T>.
0047 template <typename StatusOrType>
0048 class IsOkAndHoldsMatcherImpl
0049     : public ::testing::MatcherInterface<StatusOrType> {
0050  public:
0051   typedef
0052       typename std::remove_reference<StatusOrType>::type::value_type value_type;
0053 
0054   template <typename InnerMatcher>
0055   explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
0056       : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
0057             std::forward<InnerMatcher>(inner_matcher))) {}
0058 
0059   void DescribeTo(std::ostream* os) const override {
0060     *os << "is OK and has a value that ";
0061     inner_matcher_.DescribeTo(os);
0062   }
0063 
0064   void DescribeNegationTo(std::ostream* os) const override {
0065     *os << "isn't OK or has a value that ";
0066     inner_matcher_.DescribeNegationTo(os);
0067   }
0068 
0069   bool MatchAndExplain(
0070       StatusOrType actual_value,
0071       ::testing::MatchResultListener* result_listener) const override {
0072     if (!GetStatus(actual_value).ok()) {
0073       *result_listener << "which has status " << GetStatus(actual_value);
0074       return false;
0075     }
0076 
0077     // Call through to the inner matcher.
0078     return inner_matcher_.MatchAndExplain(*actual_value, result_listener);
0079   }
0080 
0081  private:
0082   const ::testing::Matcher<const value_type&> inner_matcher_;
0083 };
0084 
0085 // Implements IsOkAndHolds(m) as a polymorphic matcher.
0086 template <typename InnerMatcher>
0087 class IsOkAndHoldsMatcher {
0088  public:
0089   explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
0090       : inner_matcher_(std::forward<InnerMatcher>(inner_matcher)) {}
0091 
0092   // Converts this polymorphic matcher to a monomorphic matcher of the
0093   // given type.  StatusOrType can be either StatusOr<T> or a
0094   // reference to StatusOr<T>.
0095   template <typename StatusOrType>
0096   operator ::testing::Matcher<StatusOrType>() const {  // NOLINT
0097     return ::testing::Matcher<StatusOrType>(
0098         new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
0099   }
0100 
0101  private:
0102   const InnerMatcher inner_matcher_;
0103 };
0104 
0105 ////////////////////////////////////////////////////////////
0106 // Implementation of StatusIs().
0107 
0108 // `StatusCode` is implicitly convertible from `int`, `absl::StatusCode`, and
0109 //  is explicitly convertible to these types as well.
0110 //
0111 // We need this class because `absl::StatusCode` (as a scoped enum) is not
0112 // implicitly convertible to `int`. In order to handle use cases like
0113 // ```
0114 // StatusIs(Anyof(absl::StatusCode::kUnknown, absl::StatusCode::kCancelled))
0115 // ```
0116 // which uses polymorphic matchers, we need to unify the interfaces into
0117 // `Matcher<StatusCode>`.
0118 class StatusCode {
0119  public:
0120   /*implicit*/ StatusCode(int code)  // NOLINT
0121       : code_(static_cast<::absl::StatusCode>(code)) {}
0122   /*implicit*/ StatusCode(::absl::StatusCode code) : code_(code) {}  // NOLINT
0123 
0124   explicit operator int() const { return static_cast<int>(code_); }
0125 
0126   friend inline void PrintTo(const StatusCode& code, std::ostream* os) {
0127     // TODO(b/321095377): Change this to print the status code as a string.
0128     *os << static_cast<int>(code);
0129   }
0130 
0131  private:
0132   ::absl::StatusCode code_;
0133 };
0134 
0135 // Relational operators to handle matchers like Eq, Lt, etc..
0136 inline bool operator==(const StatusCode& lhs, const StatusCode& rhs) {
0137   return static_cast<int>(lhs) == static_cast<int>(rhs);
0138 }
0139 inline bool operator!=(const StatusCode& lhs, const StatusCode& rhs) {
0140   return static_cast<int>(lhs) != static_cast<int>(rhs);
0141 }
0142 
0143 // StatusIs() is a polymorphic matcher.  This class is the common
0144 // implementation of it shared by all types T where StatusIs() can be
0145 // used as a Matcher<T>.
0146 class StatusIsMatcherCommonImpl {
0147  public:
0148   StatusIsMatcherCommonImpl(
0149       ::testing::Matcher<StatusCode> code_matcher,
0150       ::testing::Matcher<absl::string_view> message_matcher)
0151       : code_matcher_(std::move(code_matcher)),
0152         message_matcher_(std::move(message_matcher)) {}
0153 
0154   void DescribeTo(std::ostream* os) const;
0155 
0156   void DescribeNegationTo(std::ostream* os) const;
0157 
0158   bool MatchAndExplain(const absl::Status& status,
0159                        ::testing::MatchResultListener* result_listener) const;
0160 
0161  private:
0162   const ::testing::Matcher<StatusCode> code_matcher_;
0163   const ::testing::Matcher<absl::string_view> message_matcher_;
0164 };
0165 
0166 // Monomorphic implementation of matcher StatusIs() for a given type
0167 // T.  T can be Status, StatusOr<>, or a reference to either of them.
0168 template <typename T>
0169 class MonoStatusIsMatcherImpl : public ::testing::MatcherInterface<T> {
0170  public:
0171   explicit MonoStatusIsMatcherImpl(StatusIsMatcherCommonImpl common_impl)
0172       : common_impl_(std::move(common_impl)) {}
0173 
0174   void DescribeTo(std::ostream* os) const override {
0175     common_impl_.DescribeTo(os);
0176   }
0177 
0178   void DescribeNegationTo(std::ostream* os) const override {
0179     common_impl_.DescribeNegationTo(os);
0180   }
0181 
0182   bool MatchAndExplain(
0183       T actual_value,
0184       ::testing::MatchResultListener* result_listener) const override {
0185     return common_impl_.MatchAndExplain(GetStatus(actual_value),
0186                                         result_listener);
0187   }
0188 
0189  private:
0190   StatusIsMatcherCommonImpl common_impl_;
0191 };
0192 
0193 // Implements StatusIs() as a polymorphic matcher.
0194 class StatusIsMatcher {
0195  public:
0196   template <typename StatusCodeMatcher, typename StatusMessageMatcher>
0197   StatusIsMatcher(StatusCodeMatcher&& code_matcher,
0198                   StatusMessageMatcher&& message_matcher)
0199       : common_impl_(::testing::MatcherCast<StatusCode>(
0200                          std::forward<StatusCodeMatcher>(code_matcher)),
0201                      ::testing::MatcherCast<absl::string_view>(
0202                          std::forward<StatusMessageMatcher>(message_matcher))) {
0203   }
0204 
0205   // Converts this polymorphic matcher to a monomorphic matcher of the
0206   // given type.  T can be StatusOr<>, Status, or a reference to
0207   // either of them.
0208   template <typename T>
0209   /*implicit*/ operator ::testing::Matcher<T>() const {  // NOLINT
0210     return ::testing::Matcher<T>(
0211         new MonoStatusIsMatcherImpl<const T&>(common_impl_));
0212   }
0213 
0214  private:
0215   const StatusIsMatcherCommonImpl common_impl_;
0216 };
0217 
0218 // Monomorphic implementation of matcher IsOk() for a given type T.
0219 // T can be Status, StatusOr<>, or a reference to either of them.
0220 template <typename T>
0221 class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
0222  public:
0223   void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
0224   void DescribeNegationTo(std::ostream* os) const override {
0225     *os << "is not OK";
0226   }
0227   bool MatchAndExplain(T actual_value,
0228                        ::testing::MatchResultListener*) const override {
0229     return GetStatus(actual_value).ok();
0230   }
0231 };
0232 
0233 // Implements IsOk() as a polymorphic matcher.
0234 class IsOkMatcher {
0235  public:
0236   template <typename T>
0237   /*implicit*/ operator ::testing::Matcher<T>() const {  // NOLINT
0238     return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<const T&>());
0239   }
0240 };
0241 
0242 }  // namespace status_internal
0243 ABSL_NAMESPACE_END
0244 }  // namespace absl_testing
0245 
0246 #endif  // ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_