| 220 | }; |
| 221 | |
| 222 | class ErrorMatcher { |
| 223 | public: |
| 224 | explicit ErrorMatcher(StatusCode code, |
| 225 | std::optional<testing::Matcher<std::string>> message_matcher) |
| 226 | : code_(code), message_matcher_(std::move(message_matcher)) {} |
| 227 | |
| 228 | template <typename Res> |
| 229 | operator testing::Matcher<Res>() const { // NOLINT runtime/explicit |
| 230 | struct Impl : testing::MatcherInterface<const Res&> { |
| 231 | explicit Impl(StatusCode code, |
| 232 | std::optional<testing::Matcher<std::string>> message_matcher) |
| 233 | : code_(code), message_matcher_(std::move(message_matcher)) {} |
| 234 | |
| 235 | void DescribeTo(::std::ostream* os) const override { |
| 236 | *os << "raises StatusCode::" << Status::CodeAsString(code_); |
| 237 | if (message_matcher_) { |
| 238 | *os << " and message "; |
| 239 | message_matcher_->DescribeTo(os); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | void DescribeNegationTo(::std::ostream* os) const override { |
| 244 | *os << "does not raise StatusCode::" << Status::CodeAsString(code_); |
| 245 | if (message_matcher_) { |
| 246 | *os << " or message "; |
| 247 | message_matcher_->DescribeNegationTo(os); |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | bool MatchAndExplain(const Res& maybe_value, |
| 252 | testing::MatchResultListener* listener) const override { |
| 253 | const Status& status = ToStatus(maybe_value); |
| 254 | testing::StringMatchResultListener value_listener; |
| 255 | |
| 256 | bool match = status.code() == code_; |
| 257 | if (message_matcher_) { |
| 258 | match = match && |
| 259 | message_matcher_->MatchAndExplain(status.message(), &value_listener); |
| 260 | } |
| 261 | |
| 262 | if (match) { |
| 263 | *listener << "whose error matches"; |
| 264 | } else if (status.ok()) { |
| 265 | *listener << "whose non-error doesn't match"; |
| 266 | } else { |
| 267 | *listener << "whose error doesn't match"; |
| 268 | } |
| 269 | |
| 270 | testing::internal::PrintIfNotEmpty(value_listener.str(), listener->stream()); |
| 271 | return match; |
| 272 | } |
| 273 | |
| 274 | const StatusCode code_; |
| 275 | const std::optional<testing::Matcher<std::string>> message_matcher_; |
| 276 | }; |
| 277 | |
| 278 | return testing::Matcher<Res>(new Impl(code_, message_matcher_)); |
| 279 | } |