xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/util/status_matchers.h (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li //     https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li 
15*ec63e07aSXin Li #ifndef SANDBOXED_API_UTIL_STATUS_MATCHERS_H_
16*ec63e07aSXin Li #define SANDBOXED_API_UTIL_STATUS_MATCHERS_H_
17*ec63e07aSXin Li 
18*ec63e07aSXin Li #include <ostream>
19*ec63e07aSXin Li #include <string>
20*ec63e07aSXin Li #include <type_traits>
21*ec63e07aSXin Li #include <utility>
22*ec63e07aSXin Li 
23*ec63e07aSXin Li #include "gmock/gmock.h"
24*ec63e07aSXin Li #include "gtest/gtest.h"
25*ec63e07aSXin Li #include "absl/status/status.h"
26*ec63e07aSXin Li #include "absl/status/statusor.h"
27*ec63e07aSXin Li #include "absl/strings/string_view.h"
28*ec63e07aSXin Li #include "absl/types/optional.h"
29*ec63e07aSXin Li #include "sandboxed_api/util/status_macros.h"
30*ec63e07aSXin Li 
31*ec63e07aSXin Li #define SAPI_ASSERT_OK(expr) ASSERT_THAT(expr, ::sapi::IsOk())
32*ec63e07aSXin Li 
33*ec63e07aSXin Li #define SAPI_ASSERT_OK_AND_ASSIGN(lhs, rexpr) \
34*ec63e07aSXin Li   SAPI_ASSERT_OK_AND_ASSIGN_IMPL(             \
35*ec63e07aSXin Li       SAPI_MACROS_IMPL_CONCAT(_sapi_statusor, __LINE__), lhs, rexpr)
36*ec63e07aSXin Li 
37*ec63e07aSXin Li #define SAPI_ASSERT_OK_AND_ASSIGN_IMPL(statusor, lhs, rexpr) \
38*ec63e07aSXin Li   auto statusor = (rexpr);                                   \
39*ec63e07aSXin Li   ASSERT_THAT(statusor.status(), ::sapi::IsOk());            \
40*ec63e07aSXin Li   lhs = std::move(statusor).value()
41*ec63e07aSXin Li 
42*ec63e07aSXin Li namespace sapi {
43*ec63e07aSXin Li namespace internal {
44*ec63e07aSXin Li 
45*ec63e07aSXin Li class IsOkMatcher {
46*ec63e07aSXin Li  public:
47*ec63e07aSXin Li   template <typename StatusT>
MatchAndExplain(const StatusT & status_container,::testing::MatchResultListener * listener)48*ec63e07aSXin Li   bool MatchAndExplain(const StatusT& status_container,
49*ec63e07aSXin Li                        ::testing::MatchResultListener* listener) const {
50*ec63e07aSXin Li     if (!status_container.ok()) {
51*ec63e07aSXin Li       *listener << "which is not OK";
52*ec63e07aSXin Li       return false;
53*ec63e07aSXin Li     }
54*ec63e07aSXin Li     return true;
55*ec63e07aSXin Li   }
56*ec63e07aSXin Li 
DescribeTo(std::ostream * os)57*ec63e07aSXin Li   void DescribeTo(std::ostream* os) const { *os << "is OK"; }
58*ec63e07aSXin Li 
DescribeNegationTo(std::ostream * os)59*ec63e07aSXin Li   void DescribeNegationTo(std::ostream* os) const { *os << "is not OK"; }
60*ec63e07aSXin Li };
61*ec63e07aSXin Li 
62*ec63e07aSXin Li class StatusIsMatcher {
63*ec63e07aSXin Li  public:
64*ec63e07aSXin Li   StatusIsMatcher(const StatusIsMatcher&) = default;
65*ec63e07aSXin Li 
StatusIsMatcher(absl::StatusCode code,absl::optional<absl::string_view> message)66*ec63e07aSXin Li   StatusIsMatcher(absl::StatusCode code,
67*ec63e07aSXin Li                   absl::optional<absl::string_view> message)
68*ec63e07aSXin Li       : code_(code), message_(message) {}
69*ec63e07aSXin Li 
70*ec63e07aSXin Li   template <typename T>
MatchAndExplain(const T & value,::testing::MatchResultListener * listener)71*ec63e07aSXin Li   bool MatchAndExplain(const T& value,
72*ec63e07aSXin Li                        ::testing::MatchResultListener* listener) const {
73*ec63e07aSXin Li     auto status = GetStatus(value);
74*ec63e07aSXin Li     if (code_ != status.code()) {
75*ec63e07aSXin Li       *listener << "whose error code is "
76*ec63e07aSXin Li                 << absl::StatusCodeToString(status.code());
77*ec63e07aSXin Li       return false;
78*ec63e07aSXin Li     }
79*ec63e07aSXin Li     if (message_.has_value() && status.message() != message_.value()) {
80*ec63e07aSXin Li       *listener << "whose error message is '" << message_.value() << "'";
81*ec63e07aSXin Li       return false;
82*ec63e07aSXin Li     }
83*ec63e07aSXin Li     return true;
84*ec63e07aSXin Li   }
85*ec63e07aSXin Li 
DescribeTo(std::ostream * os)86*ec63e07aSXin Li   void DescribeTo(std::ostream* os) const {
87*ec63e07aSXin Li     *os << "has a status code that is " << absl::StatusCodeToString(code_);
88*ec63e07aSXin Li     if (message_.has_value()) {
89*ec63e07aSXin Li       *os << ", and has an error message that is '" << message_.value() << "'";
90*ec63e07aSXin Li     }
91*ec63e07aSXin Li   }
92*ec63e07aSXin Li 
DescribeNegationTo(std::ostream * os)93*ec63e07aSXin Li   void DescribeNegationTo(std::ostream* os) const {
94*ec63e07aSXin Li     *os << "has a status code that is not " << absl::StatusCodeToString(code_);
95*ec63e07aSXin Li     if (message_.has_value()) {
96*ec63e07aSXin Li       *os << ", and has an error message that is not '" << message_.value()
97*ec63e07aSXin Li           << "'";
98*ec63e07aSXin Li     }
99*ec63e07aSXin Li   }
100*ec63e07aSXin Li 
101*ec63e07aSXin Li  private:
102*ec63e07aSXin Li   template <typename StatusT,
103*ec63e07aSXin Li             typename std::enable_if<
104*ec63e07aSXin Li                 !std::is_void<decltype(std::declval<StatusT>().code())>::value,
105*ec63e07aSXin Li                 int>::type = 0>
GetStatus(const StatusT & status)106*ec63e07aSXin Li   static const StatusT& GetStatus(const StatusT& status) {
107*ec63e07aSXin Li     return status;
108*ec63e07aSXin Li   }
109*ec63e07aSXin Li 
110*ec63e07aSXin Li   template <typename StatusOrT,
111*ec63e07aSXin Li             typename StatusT = decltype(std::declval<StatusOrT>().status())>
GetStatus(const StatusOrT & status_or)112*ec63e07aSXin Li   static StatusT GetStatus(const StatusOrT& status_or) {
113*ec63e07aSXin Li     return status_or.status();
114*ec63e07aSXin Li   }
115*ec63e07aSXin Li 
116*ec63e07aSXin Li   const absl::StatusCode code_;
117*ec63e07aSXin Li   const absl::optional<std::string> message_;
118*ec63e07aSXin Li };
119*ec63e07aSXin Li 
120*ec63e07aSXin Li }  // namespace internal
121*ec63e07aSXin Li 
IsOk()122*ec63e07aSXin Li inline ::testing::PolymorphicMatcher<internal::IsOkMatcher> IsOk() {
123*ec63e07aSXin Li   return ::testing::MakePolymorphicMatcher(internal::IsOkMatcher{});
124*ec63e07aSXin Li }
125*ec63e07aSXin Li 
126*ec63e07aSXin Li inline ::testing::PolymorphicMatcher<internal::StatusIsMatcher> StatusIs(
127*ec63e07aSXin Li     absl::StatusCode code,
128*ec63e07aSXin Li     absl::optional<absl::string_view> message = absl::nullopt) {
129*ec63e07aSXin Li   return ::testing::MakePolymorphicMatcher(
130*ec63e07aSXin Li       internal::StatusIsMatcher(code, message));
131*ec63e07aSXin Li }
132*ec63e07aSXin Li 
133*ec63e07aSXin Li }  // namespace sapi
134*ec63e07aSXin Li 
135*ec63e07aSXin Li #endif  // SANDBOXED_API_UTIL_STATUS_MATCHERS_H_
136