Repository: carbon-language/carbon-lang
File: common/error_test.cpp (C++)

Code before:

auto IndirectError() -> Error { return Error("test"); }

TEST(ErrorTest, IndirectError) { EXPECT_EQ(IndirectError().message(), "test"); }

TEST(ErrorTest, ErrorBuilderOperatorImplicitCast) {
  ErrorOr<int> result = ErrorBuilder() << "msg";
  EXPECT_THAT(result, IsError("msg"));
}

TEST(ErrorTest, StreamError) {
  Error result = ErrorBuilder("TestFunc") << "msg";
  RawStringOstream result_stream;
  result_stream << result;
  EXPECT_EQ(result_stream.TakeStr(), "TestFunc: msg");
}

class CustomError : public ErrorBase<CustomError> {
 public:
  auto Print(llvm::raw_ostream& os) const -> void {
    os << "Custom test error!";
  }
};

template <typename ErrorT>
struct ErrorOrTest : ::testing::Test {
  template <typename T>
  using TestErrorOr = ErrorOr<T, ErrorT>;

  auto ErrorStr() -> std::string {
    if constexpr (std::same_as<ErrorT, Error>) {
      return "test error";
    } else if constexpr (std::same_as<ErrorT, CustomError>) {
      return CustomError().ToString();
    } else {
      static_assert(false, "Unsupported custom error type!");
    }
  }

  auto MakeError() -> ErrorT {
    if constexpr (std::same_as<ErrorT, Error>) {
      return Error("test error");
    } else if constexpr (std::same_as<ErrorT, CustomError>) {
      return CustomError();
    } else {
      static_assert(false, "Unsupported custom error type!");
    }
  }
};

using ErrorOrTestParams = ::testing::Types<Error, CustomError>;

Review comment (suggestion):
```suggestion
class ErrorOrTest : public ::testing::Test {
 public:
```

I thought we usually wrote tests as classes, because they have complex functionality?

I'll note too, for inheritance, we'd had a discussion about implicit public inheritance due to something zygoloid did and I think both Josh and I lacked the right instincts for `struct` -- we're too used to doing that on classes only.

Code after:

auto IndirectError() -> Error { return Error("test"); }

TEST(ErrorTest, IndirectError) { EXPECT_EQ(IndirectError().message(), "test"); }

TEST(ErrorTest, ErrorBuilderOperatorImplicitCast) {
  ErrorOr<int> result = ErrorBuilder() << "msg";
  EXPECT_THAT(result, IsError("msg"));
}

TEST(ErrorTest, StreamError) {
  Error result = ErrorBuilder("TestFunc") << "msg";
  RawStringOstream result_stream;
  result_stream << result;
  EXPECT_EQ(result_stream.TakeStr(), "TestFunc: msg");
}

class CustomError : public ErrorBase<CustomError> {
 public:
  auto Print(llvm::raw_ostream& os) const -> void {
    os << "Custom test error!";
  }
};

template <typename ErrorT>
class ErrorOrTest : public ::testing::Test {
 public:
  auto ErrorStr() -> std::string {
    if constexpr (std::same_as<ErrorT, Error>) {
      return "test error";
    } else if constexpr (std::same_as<ErrorT, CustomError>) {
      return CustomError().ToString();
    } else {
      static_assert(false, "Unsupported custom error type!");
    }
  }

  auto MakeError() -> ErrorT {
    if constexpr (std::same_as<ErrorT, Error>) {
      return Error("test error");
    } else if constexpr (std::same_as<ErrorT, CustomError>) {
      return CustomError();
    } else {
      static_assert(false, "Unsupported custom error type!");
    }
  }
};

using ErrorOrTestParams = ::testing::Types<Error, CustomError>;
TYPED_TEST_SUITE(ErrorOrTest, ErrorOrTestParams);