This allows you to write EXPECT_OK(statusor), as well as EXPECT_THAT(status, IsStatusCode(StatusCode::kInvalidArgument). Change-Id: I53bed694d812c501eb305ed4ddb358e1f9a68277 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1704 Tested-by: BuildkiteCI Reviewed-by: glittershark <grfn@gws.fyi>
83 lines
2.5 KiB
C++
83 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include <absl/status/status.h>
|
|
#include <absl/status/statusor.h>
|
|
#include <absl/strings/str_cat.h>
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
namespace testing {
|
|
|
|
/*
|
|
* This file contains gtest matchers for absl::Status.
|
|
*
|
|
* Example usage:
|
|
*
|
|
* EXPECT_OK(status); -- fails the test if 'status' is an error
|
|
* ASSERT_OK(status); -- instantly fails the test if error
|
|
*
|
|
* using ::testing::IsStatusCode;
|
|
* EXPECT_THAT(status, IsStatusCode(absl::StatusCode::kInternal));
|
|
*/
|
|
|
|
namespace nix_internal {
|
|
|
|
using ::testing::MakeMatcher;
|
|
using ::testing::Matcher;
|
|
using ::testing::MatcherInterface;
|
|
using ::testing::MatchResultListener;
|
|
|
|
MATCHER_P(IsStatusCode, code, "") { return arg.code() == code; }
|
|
|
|
class StatusCodeMatcher {
|
|
public:
|
|
StatusCodeMatcher(absl::StatusCode code) : code_(code) {}
|
|
|
|
// Match on absl::Status.
|
|
template <class T,
|
|
typename std::enable_if<std::is_same<T, absl::Status>::value,
|
|
int>::type int_ = 0>
|
|
bool MatchAndExplain(const T& status,
|
|
MatchResultListener* /* listener */) const {
|
|
return status.code() == code_;
|
|
}
|
|
|
|
// Match on absl::StatusOr.
|
|
//
|
|
// note: I check for the return value of ConsumeValueOrDie because it's the
|
|
// only non-overloaded member I could figure out how to select. Checking for
|
|
// the presence of .status() didn't work because it's overloaded, so
|
|
// std::invoke_result can't pick which overload to use.
|
|
template <class T,
|
|
typename std::enable_if<
|
|
std::is_same<typename std::invoke_result<
|
|
decltype(&T::ConsumeValueOrDie), T>::type,
|
|
typename T::value_type>::value,
|
|
int>::type int_ = 0>
|
|
bool MatchAndExplain(const T& statusor,
|
|
MatchResultListener* /* listener */) const {
|
|
return statusor.status().code() == code_;
|
|
}
|
|
|
|
void DescribeTo(std::ostream* os) const { *os << "is " << code_; }
|
|
|
|
void DescribeNegationTo(std::ostream* os) const { *os << "isn't " << code_; }
|
|
|
|
private:
|
|
absl::StatusCode code_;
|
|
};
|
|
|
|
} // namespace nix_internal
|
|
|
|
PolymorphicMatcher<nix_internal::StatusCodeMatcher> IsStatusCode(
|
|
absl::StatusCode code) {
|
|
return MakePolymorphicMatcher(nix_internal::StatusCodeMatcher(code));
|
|
}
|
|
|
|
#define EXPECT_OK(status) \
|
|
EXPECT_THAT((status), testing::IsStatusCode(absl::StatusCode::kOk))
|
|
|
|
#define ASSERT_OK(status) \
|
|
ASSERT_THAT((status), testing::IsStatusCode(absl::StatusCode::kOk))
|
|
|
|
} // namespace testing
|