mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 17:00:25 +01:00
Fix an incompatiblitiy between our YAML and ErrorOr test helpers (#6636)
The YAML test helpers didn't use the `Printable` abstraction in one place and instead directly used `<<` with a `std::ostream`. This matches the `require`s expression in the `error_test_helpers.h` printing logic for `ErrorOr`, but fails to provide the necessary implementation for `llvm::formatv` to succeed with the `Yaml::Value` type. The main fix is to use `Printable` and to define the `Print` method in terms of `llvm::raw_ostream`. We already have all the mapping hooks in place to also support `std::ostream` when needed based on that definition. This also adds some constraints to the printing in `error_test_helpers.h` so it is a bit less under-constrained and more understandable when it is correctly being used. These are just tidying though, they aren't what makes these headers work together. I've added a test to try and make sure these test helpers compose as well.
This commit is contained in:
@@ -199,6 +199,7 @@ cc_library(
|
||||
hdrs = ["error_test_helpers.h"],
|
||||
deps = [
|
||||
":error",
|
||||
":ostream",
|
||||
"@googletest//:gtest",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <concepts>
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/ostream.h"
|
||||
|
||||
namespace Carbon::Testing {
|
||||
|
||||
@@ -122,6 +125,8 @@ namespace Carbon {
|
||||
|
||||
// Supports printing `ErrorOr<T>` to `std::ostream` in tests.
|
||||
template <typename T, typename ErrorT>
|
||||
requires(std::same_as<ErrorT, Error> ||
|
||||
std::derived_from<ErrorT, ErrorBase<ErrorT>>)
|
||||
auto operator<<(std::ostream& out, const ErrorOr<T, ErrorT>& error_or)
|
||||
-> std::ostream& {
|
||||
if (error_or.ok()) {
|
||||
|
||||
@@ -98,6 +98,7 @@ cc_test(
|
||||
srcs = ["yaml_test_helpers_test.cpp"],
|
||||
deps = [
|
||||
":yaml_test_helpers",
|
||||
"//common:error_test_helpers",
|
||||
"//testing/base:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
],
|
||||
|
||||
@@ -88,13 +88,17 @@ auto Value::FromText(llvm::StringRef text) -> ErrorOr<SequenceValue> {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto operator<<(std::ostream& os, const Value& v) -> std::ostream& {
|
||||
auto Value::Print(llvm::raw_ostream& os) const -> void {
|
||||
// Variant visitor that prints the value in the form of code to recreate the
|
||||
// value.
|
||||
struct Printer {
|
||||
auto operator()(NullValue /*v*/) -> void { out << "Yaml::NullValue()"; }
|
||||
auto operator()(AliasValue /*v*/) -> void { out << "Yaml::AliasValue()"; }
|
||||
auto operator()(const ScalarValue& v) -> void { out << std::quoted(v); }
|
||||
auto operator()(const ScalarValue& v) -> void {
|
||||
out << "\"";
|
||||
out.write_escaped(v);
|
||||
out << "\"";
|
||||
}
|
||||
auto operator()(const MappingValue& v) -> void {
|
||||
out << "Yaml::MappingValue{";
|
||||
bool first = true;
|
||||
@@ -122,10 +126,10 @@ auto operator<<(std::ostream& os, const Value& v) -> std::ostream& {
|
||||
out << "}";
|
||||
}
|
||||
|
||||
std::ostream& out;
|
||||
llvm::raw_ostream& out;
|
||||
};
|
||||
std::visit(Printer{.out = os}, v);
|
||||
return os;
|
||||
|
||||
std::visit(Printer{.out = os}, *this);
|
||||
}
|
||||
|
||||
} // namespace Carbon::Testing::Yaml
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
|
||||
#include "absl/strings/str_replace.h"
|
||||
#include "common/error.h"
|
||||
#include "common/ostream.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace Carbon::Testing::Yaml {
|
||||
@@ -81,12 +82,13 @@ struct AliasValue : EmptyComparable {};
|
||||
// A thin wrapper around a variant of possible YAML value types. This type
|
||||
// intentionally provides no additional encapsulation or invariants beyond
|
||||
// those of the variant.
|
||||
struct Value : std::variant<NullValue, ScalarValue, MappingValue, SequenceValue,
|
||||
struct Value : Carbon::Printable<Value>,
|
||||
std::variant<NullValue, ScalarValue, MappingValue, SequenceValue,
|
||||
AliasValue> {
|
||||
using variant::variant;
|
||||
|
||||
// Prints the Value in the form of code to recreate the value.
|
||||
friend auto operator<<(std::ostream& os, const Value& v) -> std::ostream&;
|
||||
auto Print(llvm::raw_ostream& os) const -> void;
|
||||
|
||||
// Parses a sequence of YAML documents from the given YAML text.
|
||||
static auto FromText(llvm::StringRef text) -> ErrorOr<SequenceValue>;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/error_test_helpers.h"
|
||||
|
||||
namespace Carbon::Testing {
|
||||
namespace {
|
||||
|
||||
@@ -28,5 +30,21 @@ TEST(YamlTestHelpersTest, InvalidYaml) {
|
||||
EXPECT_THAT(result, Not(Yaml::IsYaml(_)));
|
||||
}
|
||||
|
||||
TEST(YamlTestHelpersTest, ComposeWithErrorOr) {
|
||||
auto helper = []() -> ErrorOr<Yaml::Value> {
|
||||
auto result = Yaml::Value::FromText("[foo, bar]");
|
||||
if (!result.ok()) {
|
||||
return std::move(result).error();
|
||||
}
|
||||
return {*std::move(result)};
|
||||
};
|
||||
|
||||
// Make sure this works correctly with the generic `ErrorOr` test helper as
|
||||
// well. Note that `FromText` always produces a sequence of its own, so there
|
||||
// are two layers of nested sequence here.
|
||||
EXPECT_THAT(helper(), IsSuccess(Yaml::Sequence(ElementsAre(
|
||||
Yaml::Sequence(ElementsAre("foo", "bar"))))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Carbon::Testing
|
||||
|
||||
Reference in New Issue
Block a user