Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
|
|
@ -0,0 +1,246 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
|
||||
#define ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
|
||||
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock.h" // gmock_for_status_matchers.h
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace absl_testing {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace status_internal {
|
||||
|
||||
inline const absl::Status& GetStatus(const absl::Status& status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const absl::Status& GetStatus(const absl::StatusOr<T>& status) {
|
||||
return status.status();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Implementation of IsOkAndHolds().
|
||||
|
||||
// Monomorphic implementation of matcher IsOkAndHolds(m). StatusOrType is a
|
||||
// reference to StatusOr<T>.
|
||||
template <typename StatusOrType>
|
||||
class IsOkAndHoldsMatcherImpl
|
||||
: public ::testing::MatcherInterface<StatusOrType> {
|
||||
public:
|
||||
typedef
|
||||
typename std::remove_reference<StatusOrType>::type::value_type value_type;
|
||||
|
||||
template <typename InnerMatcher>
|
||||
explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
|
||||
: inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
|
||||
std::forward<InnerMatcher>(inner_matcher))) {}
|
||||
|
||||
void DescribeTo(std::ostream* os) const override {
|
||||
*os << "is OK and has a value that ";
|
||||
inner_matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
void DescribeNegationTo(std::ostream* os) const override {
|
||||
*os << "isn't OK or has a value that ";
|
||||
inner_matcher_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
bool MatchAndExplain(
|
||||
StatusOrType actual_value,
|
||||
::testing::MatchResultListener* result_listener) const override {
|
||||
if (!GetStatus(actual_value).ok()) {
|
||||
*result_listener << "which has status " << GetStatus(actual_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call through to the inner matcher.
|
||||
return inner_matcher_.MatchAndExplain(*actual_value, result_listener);
|
||||
}
|
||||
|
||||
private:
|
||||
const ::testing::Matcher<const value_type&> inner_matcher_;
|
||||
};
|
||||
|
||||
// Implements IsOkAndHolds(m) as a polymorphic matcher.
|
||||
template <typename InnerMatcher>
|
||||
class IsOkAndHoldsMatcher {
|
||||
public:
|
||||
explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
|
||||
: inner_matcher_(std::forward<InnerMatcher>(inner_matcher)) {}
|
||||
|
||||
// Converts this polymorphic matcher to a monomorphic matcher of the
|
||||
// given type. StatusOrType can be either StatusOr<T> or a
|
||||
// reference to StatusOr<T>.
|
||||
template <typename StatusOrType>
|
||||
operator ::testing::Matcher<StatusOrType>() const { // NOLINT
|
||||
return ::testing::Matcher<StatusOrType>(
|
||||
new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
|
||||
}
|
||||
|
||||
private:
|
||||
const InnerMatcher inner_matcher_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Implementation of StatusIs().
|
||||
|
||||
// `StatusCode` is implicitly convertible from `int`, `absl::StatusCode`, and
|
||||
// is explicitly convertible to these types as well.
|
||||
//
|
||||
// We need this class because `absl::StatusCode` (as a scoped enum) is not
|
||||
// implicitly convertible to `int`. In order to handle use cases like
|
||||
// ```
|
||||
// StatusIs(Anyof(absl::StatusCode::kUnknown, absl::StatusCode::kCancelled))
|
||||
// ```
|
||||
// which uses polymorphic matchers, we need to unify the interfaces into
|
||||
// `Matcher<StatusCode>`.
|
||||
class StatusCode {
|
||||
public:
|
||||
/*implicit*/ StatusCode(int code) // NOLINT
|
||||
: code_(static_cast<::absl::StatusCode>(code)) {}
|
||||
/*implicit*/ StatusCode(::absl::StatusCode code) : code_(code) {} // NOLINT
|
||||
|
||||
explicit operator int() const { return static_cast<int>(code_); }
|
||||
|
||||
friend inline void PrintTo(const StatusCode& code, std::ostream* os) {
|
||||
// TODO(b/321095377): Change this to print the status code as a string.
|
||||
*os << static_cast<int>(code);
|
||||
}
|
||||
|
||||
private:
|
||||
::absl::StatusCode code_;
|
||||
};
|
||||
|
||||
// Relational operators to handle matchers like Eq, Lt, etc..
|
||||
inline bool operator==(const StatusCode& lhs, const StatusCode& rhs) {
|
||||
return static_cast<int>(lhs) == static_cast<int>(rhs);
|
||||
}
|
||||
inline bool operator!=(const StatusCode& lhs, const StatusCode& rhs) {
|
||||
return static_cast<int>(lhs) != static_cast<int>(rhs);
|
||||
}
|
||||
|
||||
// StatusIs() is a polymorphic matcher. This class is the common
|
||||
// implementation of it shared by all types T where StatusIs() can be
|
||||
// used as a Matcher<T>.
|
||||
class StatusIsMatcherCommonImpl {
|
||||
public:
|
||||
StatusIsMatcherCommonImpl(
|
||||
::testing::Matcher<StatusCode> code_matcher,
|
||||
::testing::Matcher<absl::string_view> message_matcher)
|
||||
: code_matcher_(std::move(code_matcher)),
|
||||
message_matcher_(std::move(message_matcher)) {}
|
||||
|
||||
void DescribeTo(std::ostream* os) const;
|
||||
|
||||
void DescribeNegationTo(std::ostream* os) const;
|
||||
|
||||
bool MatchAndExplain(const absl::Status& status,
|
||||
::testing::MatchResultListener* result_listener) const;
|
||||
|
||||
private:
|
||||
const ::testing::Matcher<StatusCode> code_matcher_;
|
||||
const ::testing::Matcher<absl::string_view> message_matcher_;
|
||||
};
|
||||
|
||||
// Monomorphic implementation of matcher StatusIs() for a given type
|
||||
// T. T can be Status, StatusOr<>, or a reference to either of them.
|
||||
template <typename T>
|
||||
class MonoStatusIsMatcherImpl : public ::testing::MatcherInterface<T> {
|
||||
public:
|
||||
explicit MonoStatusIsMatcherImpl(StatusIsMatcherCommonImpl common_impl)
|
||||
: common_impl_(std::move(common_impl)) {}
|
||||
|
||||
void DescribeTo(std::ostream* os) const override {
|
||||
common_impl_.DescribeTo(os);
|
||||
}
|
||||
|
||||
void DescribeNegationTo(std::ostream* os) const override {
|
||||
common_impl_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
bool MatchAndExplain(
|
||||
T actual_value,
|
||||
::testing::MatchResultListener* result_listener) const override {
|
||||
return common_impl_.MatchAndExplain(GetStatus(actual_value),
|
||||
result_listener);
|
||||
}
|
||||
|
||||
private:
|
||||
StatusIsMatcherCommonImpl common_impl_;
|
||||
};
|
||||
|
||||
// Implements StatusIs() as a polymorphic matcher.
|
||||
class StatusIsMatcher {
|
||||
public:
|
||||
template <typename StatusCodeMatcher, typename StatusMessageMatcher>
|
||||
StatusIsMatcher(StatusCodeMatcher&& code_matcher,
|
||||
StatusMessageMatcher&& message_matcher)
|
||||
: common_impl_(::testing::MatcherCast<StatusCode>(
|
||||
std::forward<StatusCodeMatcher>(code_matcher)),
|
||||
::testing::MatcherCast<absl::string_view>(
|
||||
std::forward<StatusMessageMatcher>(message_matcher))) {
|
||||
}
|
||||
|
||||
// Converts this polymorphic matcher to a monomorphic matcher of the
|
||||
// given type. T can be StatusOr<>, Status, or a reference to
|
||||
// either of them.
|
||||
template <typename T>
|
||||
/*implicit*/ operator ::testing::Matcher<T>() const { // NOLINT
|
||||
return ::testing::Matcher<T>(
|
||||
new MonoStatusIsMatcherImpl<const T&>(common_impl_));
|
||||
}
|
||||
|
||||
private:
|
||||
const StatusIsMatcherCommonImpl common_impl_;
|
||||
};
|
||||
|
||||
// Monomorphic implementation of matcher IsOk() for a given type T.
|
||||
// T can be Status, StatusOr<>, or a reference to either of them.
|
||||
template <typename T>
|
||||
class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
|
||||
public:
|
||||
void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
|
||||
void DescribeNegationTo(std::ostream* os) const override {
|
||||
*os << "is not OK";
|
||||
}
|
||||
bool MatchAndExplain(T actual_value,
|
||||
::testing::MatchResultListener*) const override {
|
||||
return GetStatus(actual_value).ok();
|
||||
}
|
||||
};
|
||||
|
||||
// Implements IsOk() as a polymorphic matcher.
|
||||
class IsOkMatcher {
|
||||
public:
|
||||
template <typename T>
|
||||
/*implicit*/ operator ::testing::Matcher<T>() const { // NOLINT
|
||||
return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<const T&>());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace status_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl_testing
|
||||
|
||||
#endif // ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue