xref: /aosp_15_r20/external/tink/cc/util/test_matchers.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang // Copyright 2018 Google Inc.
2*e7b1675dSTing-Kang Chang //
3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang //
7*e7b1675dSTing-Kang Chang //      http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang //
9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang // limitations under the License.
14*e7b1675dSTing-Kang Chang //
15*e7b1675dSTing-Kang Chang ////////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang 
17*e7b1675dSTing-Kang Chang #ifndef TINK_UTIL_TEST_MATCHERS_H_
18*e7b1675dSTing-Kang Chang #define TINK_UTIL_TEST_MATCHERS_H_
19*e7b1675dSTing-Kang Chang 
20*e7b1675dSTing-Kang Chang #include <ostream>
21*e7b1675dSTing-Kang Chang #include <string>
22*e7b1675dSTing-Kang Chang 
23*e7b1675dSTing-Kang Chang #include "gmock/gmock.h"
24*e7b1675dSTing-Kang Chang #include "gtest/gtest.h"
25*e7b1675dSTing-Kang Chang #include "absl/status/status.h"
26*e7b1675dSTing-Kang Chang #include "tink/util/status.h"
27*e7b1675dSTing-Kang Chang #include "tink/util/statusor.h"
28*e7b1675dSTing-Kang Chang 
29*e7b1675dSTing-Kang Chang namespace crypto {
30*e7b1675dSTing-Kang Chang namespace tink {
31*e7b1675dSTing-Kang Chang namespace test {
32*e7b1675dSTing-Kang Chang namespace internal {
33*e7b1675dSTing-Kang Chang 
34*e7b1675dSTing-Kang Chang ////////////////////////////////////////////////////////////
35*e7b1675dSTing-Kang Chang // Implementation of IsOkAndHolds().
36*e7b1675dSTing-Kang Chang 
37*e7b1675dSTing-Kang Chang // Monomorphic implementation of matcher IsOkAndHolds(m).  StatusOrType is a
38*e7b1675dSTing-Kang Chang // reference to StatusOr<T>.
39*e7b1675dSTing-Kang Chang template <typename StatusOrType>
40*e7b1675dSTing-Kang Chang class IsOkAndHoldsMatcherImpl
41*e7b1675dSTing-Kang Chang     : public ::testing::MatcherInterface<StatusOrType> {
42*e7b1675dSTing-Kang Chang  public:
43*e7b1675dSTing-Kang Chang   using value_type =
44*e7b1675dSTing-Kang Chang       typename std::remove_reference<StatusOrType>::type::value_type;
45*e7b1675dSTing-Kang Chang 
46*e7b1675dSTing-Kang Chang   template <typename InnerMatcher>
IsOkAndHoldsMatcherImpl(InnerMatcher && inner_matcher)47*e7b1675dSTing-Kang Chang   explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
48*e7b1675dSTing-Kang Chang       : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
49*e7b1675dSTing-Kang Chang             std::forward<InnerMatcher>(inner_matcher))) {}
50*e7b1675dSTing-Kang Chang 
DescribeTo(std::ostream * os)51*e7b1675dSTing-Kang Chang   void DescribeTo(std::ostream* os) const override {
52*e7b1675dSTing-Kang Chang     *os << "is OK and has a value that ";
53*e7b1675dSTing-Kang Chang     inner_matcher_.DescribeTo(os);
54*e7b1675dSTing-Kang Chang   }
55*e7b1675dSTing-Kang Chang 
DescribeNegationTo(std::ostream * os)56*e7b1675dSTing-Kang Chang   void DescribeNegationTo(std::ostream* os) const override {
57*e7b1675dSTing-Kang Chang     *os << "isn't OK or has a value that ";
58*e7b1675dSTing-Kang Chang     inner_matcher_.DescribeNegationTo(os);
59*e7b1675dSTing-Kang Chang   }
60*e7b1675dSTing-Kang Chang 
MatchAndExplain(StatusOrType actual_value,::testing::MatchResultListener * result_listener)61*e7b1675dSTing-Kang Chang   bool MatchAndExplain(
62*e7b1675dSTing-Kang Chang       StatusOrType actual_value,
63*e7b1675dSTing-Kang Chang       ::testing::MatchResultListener* result_listener) const override {
64*e7b1675dSTing-Kang Chang     if (!actual_value.ok()) {
65*e7b1675dSTing-Kang Chang       *result_listener << "which has status " << actual_value.status();
66*e7b1675dSTing-Kang Chang       return false;
67*e7b1675dSTing-Kang Chang     }
68*e7b1675dSTing-Kang Chang 
69*e7b1675dSTing-Kang Chang     ::testing::StringMatchResultListener inner_listener;
70*e7b1675dSTing-Kang Chang     const bool matches =
71*e7b1675dSTing-Kang Chang         inner_matcher_.MatchAndExplain(*actual_value, &inner_listener);
72*e7b1675dSTing-Kang Chang     const std::string inner_explanation = inner_listener.str();
73*e7b1675dSTing-Kang Chang     if (!inner_explanation.empty()) {
74*e7b1675dSTing-Kang Chang       *result_listener << "which contains value "
75*e7b1675dSTing-Kang Chang                        << ::testing::PrintToString(*actual_value) << ", "
76*e7b1675dSTing-Kang Chang                        << inner_explanation;
77*e7b1675dSTing-Kang Chang     }
78*e7b1675dSTing-Kang Chang     return matches;
79*e7b1675dSTing-Kang Chang   }
80*e7b1675dSTing-Kang Chang 
81*e7b1675dSTing-Kang Chang  private:
82*e7b1675dSTing-Kang Chang   const ::testing::Matcher<const value_type&> inner_matcher_;
83*e7b1675dSTing-Kang Chang };
84*e7b1675dSTing-Kang Chang 
85*e7b1675dSTing-Kang Chang // Implements IsOkAndHolds(m) as a polymorphic matcher.
86*e7b1675dSTing-Kang Chang template <typename InnerMatcher>
87*e7b1675dSTing-Kang Chang class IsOkAndHoldsMatcher {
88*e7b1675dSTing-Kang Chang  public:
IsOkAndHoldsMatcher(InnerMatcher inner_matcher)89*e7b1675dSTing-Kang Chang   explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
90*e7b1675dSTing-Kang Chang       : inner_matcher_(std::move(inner_matcher)) {}
91*e7b1675dSTing-Kang Chang 
92*e7b1675dSTing-Kang Chang   // Converts this polymorphic matcher to a monomorphic matcher of the
93*e7b1675dSTing-Kang Chang   // given type.  StatusOrType can be either StatusOr<T> or a
94*e7b1675dSTing-Kang Chang   // reference to StatusOr<T>.
95*e7b1675dSTing-Kang Chang   template <typename StatusOrType>
96*e7b1675dSTing-Kang Chang   operator ::testing::Matcher<StatusOrType>() const {  // NOLINT
97*e7b1675dSTing-Kang Chang     return ::testing::Matcher<StatusOrType>(
98*e7b1675dSTing-Kang Chang         new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
99*e7b1675dSTing-Kang Chang   }
100*e7b1675dSTing-Kang Chang 
101*e7b1675dSTing-Kang Chang  private:
102*e7b1675dSTing-Kang Chang   const InnerMatcher inner_matcher_;
103*e7b1675dSTing-Kang Chang };
104*e7b1675dSTing-Kang Chang }  // namespace internal
105*e7b1675dSTing-Kang Chang 
StatusToString(const util::Status & s)106*e7b1675dSTing-Kang Chang inline std::string StatusToString(const util::Status& s) {
107*e7b1675dSTing-Kang Chang   return s.ToString();
108*e7b1675dSTing-Kang Chang }
109*e7b1675dSTing-Kang Chang 
110*e7b1675dSTing-Kang Chang template <typename T>
StatusToString(const util::StatusOr<T> & s)111*e7b1675dSTing-Kang Chang std::string StatusToString(const util::StatusOr<T>& s) {
112*e7b1675dSTing-Kang Chang   return s.status().ToString();
113*e7b1675dSTing-Kang Chang }
114*e7b1675dSTing-Kang Chang 
115*e7b1675dSTing-Kang Chang // Matches a util::StatusOk() value.
116*e7b1675dSTing-Kang Chang // This is better than EXPECT_TRUE(status.ok())
117*e7b1675dSTing-Kang Chang // because the error message is a part of the failure messsage.
118*e7b1675dSTing-Kang Chang MATCHER(IsOk,
119*e7b1675dSTing-Kang Chang         absl::StrCat(negation ? "isn't" : "is", " a Status with an OK value")) {
120*e7b1675dSTing-Kang Chang   if (arg.ok()) {
121*e7b1675dSTing-Kang Chang     return true;
122*e7b1675dSTing-Kang Chang   }
123*e7b1675dSTing-Kang Chang   *result_listener << StatusToString(arg);
124*e7b1675dSTing-Kang Chang   return false;
125*e7b1675dSTing-Kang Chang }
126*e7b1675dSTing-Kang Chang 
127*e7b1675dSTing-Kang Chang // Returns a gMock matcher that matches a StatusOr<> whose status is
128*e7b1675dSTing-Kang Chang // OK and whose value matches the inner matcher.
129*e7b1675dSTing-Kang Chang template <typename InnerMatcher>
130*e7b1675dSTing-Kang Chang internal::IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>
IsOkAndHolds(InnerMatcher && inner_matcher)131*e7b1675dSTing-Kang Chang IsOkAndHolds(InnerMatcher&& inner_matcher) {
132*e7b1675dSTing-Kang Chang   return internal::IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>(
133*e7b1675dSTing-Kang Chang       std::forward<InnerMatcher>(inner_matcher));
134*e7b1675dSTing-Kang Chang }
135*e7b1675dSTing-Kang Chang 
136*e7b1675dSTing-Kang Chang // Matches a Status with the specified 'code' as code().
137*e7b1675dSTing-Kang Chang MATCHER_P(StatusIs, code,
138*e7b1675dSTing-Kang Chang           "is a Status with a " + absl::StatusCodeToString(code) + " code") {
139*e7b1675dSTing-Kang Chang   if (arg.code() == code) {
140*e7b1675dSTing-Kang Chang     return true;
141*e7b1675dSTing-Kang Chang   }
142*e7b1675dSTing-Kang Chang   *result_listener << ::testing::PrintToString(arg);
143*e7b1675dSTing-Kang Chang   return false;
144*e7b1675dSTing-Kang Chang }
145*e7b1675dSTing-Kang Chang 
146*e7b1675dSTing-Kang Chang // Matches a Status whose code() equals 'code', and whose message() matches
147*e7b1675dSTing-Kang Chang // 'message_macher'.
148*e7b1675dSTing-Kang Chang MATCHER_P2(StatusIs, code, message_matcher, "") {
149*e7b1675dSTing-Kang Chang   return (arg.code() == code) &&
150*e7b1675dSTing-Kang Chang          testing::Matches(message_matcher)(std::string(arg.message()));
151*e7b1675dSTing-Kang Chang }
152*e7b1675dSTing-Kang Chang 
153*e7b1675dSTing-Kang Chang // Matches a Keyset::Key with `key`.
154*e7b1675dSTing-Kang Chang MATCHER_P(EqualsKey, key, "is equals to the expected key") {
155*e7b1675dSTing-Kang Chang   if (arg.key_id() == key.key_id() && arg.status() == key.status() &&
156*e7b1675dSTing-Kang Chang          arg.output_prefix_type() == key.output_prefix_type() &&
157*e7b1675dSTing-Kang Chang          arg.key_data().type_url() == key.key_data().type_url() &&
158*e7b1675dSTing-Kang Chang          arg.key_data().key_material_type() ==
159*e7b1675dSTing-Kang Chang              key.key_data().key_material_type() &&
160*e7b1675dSTing-Kang Chang          arg.key_data().value() == key.key_data().value()) {
161*e7b1675dSTing-Kang Chang     return true;
162*e7b1675dSTing-Kang Chang   }
163*e7b1675dSTing-Kang Chang   *result_listener << arg.DebugString();
164*e7b1675dSTing-Kang Chang   return false;
165*e7b1675dSTing-Kang Chang }
166*e7b1675dSTing-Kang Chang 
167*e7b1675dSTing-Kang Chang }  // namespace test
168*e7b1675dSTing-Kang Chang }  // namespace tink
169*e7b1675dSTing-Kang Chang }  // namespace crypto
170*e7b1675dSTing-Kang Chang 
171*e7b1675dSTing-Kang Chang #endif  // TINK_UTIL_TEST_MATCHERS_H_
172