tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

status_matchers.h (8331B)


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