error_test_helpers.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_COMMON_ERROR_TEST_HELPERS_H_
  5. #define CARBON_COMMON_ERROR_TEST_HELPERS_H_
  6. #include <gmock/gmock.h>
  7. #include "common/error.h"
  8. namespace Carbon::Testing {
  9. // Matches the message for an error state of `ErrorOr<T>`. For example:
  10. // EXPECT_THAT(my_result, IsError(StrEq("error message")));
  11. class IsError {
  12. public:
  13. // NOLINTNEXTLINE(readability-identifier-naming)
  14. using is_gtest_matcher = void;
  15. explicit IsError(::testing::Matcher<std::string> matcher)
  16. : matcher_(std::move(matcher)) {}
  17. template <typename T>
  18. auto MatchAndExplain(const ErrorOr<T>& result,
  19. ::testing::MatchResultListener* listener) const -> bool {
  20. if (result.ok()) {
  21. *listener->stream() << "is a success";
  22. return false;
  23. } else {
  24. return matcher_.MatchAndExplain(result.error().message(), listener);
  25. }
  26. }
  27. auto DescribeTo(std::ostream* os) const -> void {
  28. *os << "is an error and matches ";
  29. matcher_.DescribeTo(os);
  30. }
  31. auto DescribeNegationTo(std::ostream* os) const -> void {
  32. *os << "is a success or does not match ";
  33. matcher_.DescribeTo(os);
  34. }
  35. private:
  36. ::testing::Matcher<std::string> matcher_;
  37. };
  38. // Matches the value for a non-error state of `ErrorOr<T>`. For example:
  39. // EXPECT_THAT(my_result, IsSuccess(Eq(3)));
  40. template <typename InnerMatcher>
  41. class IsSuccessMatcher {
  42. public:
  43. // NOLINTNEXTLINE(readability-identifier-naming)
  44. using is_gtest_matcher = void;
  45. explicit IsSuccessMatcher(InnerMatcher matcher)
  46. : matcher_(std::move(matcher)) {}
  47. template <typename T>
  48. auto MatchAndExplain(const ErrorOr<T>& result,
  49. ::testing::MatchResultListener* listener) const -> bool {
  50. if (result.ok()) {
  51. return ::testing::Matcher<T>(matcher_).MatchAndExplain(*result, listener);
  52. } else {
  53. *listener->stream() << "is an error with `" << result.error().message()
  54. << "`";
  55. return false;
  56. }
  57. }
  58. auto DescribeTo(std::ostream* os) const -> void {
  59. *os << "is a success and matches ";
  60. matcher_.DescribeTo(os);
  61. }
  62. auto DescribeNegationTo(std::ostream* os) const -> void {
  63. *os << "is an error or does not match ";
  64. matcher_.DescribeTo(os);
  65. }
  66. private:
  67. InnerMatcher matcher_;
  68. };
  69. // Wraps `IsSuccessMatcher` for the inner matcher deduction.
  70. template <typename InnerMatcher>
  71. auto IsSuccess(InnerMatcher matcher) -> IsSuccessMatcher<InnerMatcher> {
  72. return IsSuccessMatcher<InnerMatcher>(matcher);
  73. }
  74. } // namespace Carbon::Testing
  75. namespace Carbon {
  76. // Supports printing `ErrorOr<T>` to `std::ostream` in tests.
  77. template <typename T>
  78. auto operator<<(std::ostream& out, const ErrorOr<T>& error_or)
  79. -> std::ostream& {
  80. if (error_or.ok()) {
  81. out << llvm::formatv("ErrorOr{{.value = `{0}`}}", *error_or);
  82. } else {
  83. out << llvm::formatv("ErrorOr{{.error = \"{0}\"}}",
  84. error_or.error().message());
  85. }
  86. return out;
  87. }
  88. } // namespace Carbon
  89. #endif // CARBON_COMMON_ERROR_TEST_HELPERS_H_