blob: ac77e413f5dcc6d027c7ed4e21c006992dafae59 [file]
#include "conformance/testee.h"
#include <string>
#include <utility>
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "conformance/binary_wireformat.h"
#include "conformance/conformance.pb.h"
#include "conformance/naming.h"
#include "google/protobuf/descriptor.h"
namespace google {
namespace protobuf {
namespace conformance {
namespace internal {
namespace {
using ::conformance::ConformanceRequest;
using ::conformance::ConformanceResponse;
::conformance::WireFormat GetInputFormat(
const ::conformance::ConformanceRequest& request) {
switch (request.payload_case()) {
case ::conformance::ConformanceRequest::kProtobufPayload:
return ::conformance::PROTOBUF;
case ::conformance::ConformanceRequest::kJsonPayload:
return ::conformance::JSON;
case ::conformance::ConformanceRequest::kTextPayload:
return ::conformance::TEXT_FORMAT;
default:
ABSL_LOG(FATAL) << "Unsupported input format";
}
return ::conformance::UNSPECIFIED;
}
std::string GetTestName(absl::string_view test_name, TestPriority priority,
const ::conformance::ConformanceRequest& request,
const Descriptor& message) {
absl::string_view level = PriorityLevelName(priority);
std::string syntax_identifier = GetEditionIdentifier(message);
return absl::StrCat(
level, ".", syntax_identifier, ".",
GetFormatIdentifier(GetInputFormat(request)), "Input.", test_name, ".",
GetFormatIdentifier(request.requested_output_format()), "Output");
}
} // namespace
::conformance::ConformanceResponse Testee::Run(
absl::string_view test_name, const ConformanceRequest& request) {
ABSL_CHECK(test_names_ran_.emplace(test_name).second)
<< "Duplicated test name: " << test_name;
std::string serialized_request;
// TODO: Remove this suppression.
(void)request.SerializeToString(&serialized_request);
std::string serialized_response =
runner_->RunTest(test_name, serialized_request);
ConformanceResponse response;
if (!response.ParseFromString(serialized_response)) {
response.set_runtime_error("response proto could not be parsed.");
}
return response;
}
InMemoryMessage Test::ParseBinary(const Descriptor* type, Wire input) && {
::conformance::ConformanceRequest request;
request.set_protobuf_payload(std::move(input).data());
request.set_test_category(::conformance::BINARY_TEST);
request.set_message_type(type->full_name());
return InMemoryMessage(testee_, name_, priority_, type, std::move(request));
}
InMemoryMessage Test::ParseText(const Descriptor* type,
absl::string_view input) && {
::conformance::ConformanceRequest request;
request.set_text_payload(input);
request.set_test_category(::conformance::TEXT_FORMAT_TEST);
request.set_message_type(type->full_name());
return InMemoryMessage(testee_, name_, priority_, type, std::move(request));
}
InMemoryMessage Test::ParseJson(const Descriptor* type, absl::string_view input,
JsonParseOptions options) && {
::conformance::ConformanceRequest request;
request.set_json_payload(input);
if (options.ignore_unknown_fields) {
request.set_test_category(::conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST);
} else {
request.set_test_category(::conformance::JSON_TEST);
}
request.set_message_type(type->full_name());
return InMemoryMessage(testee_, name_, priority_, type, std::move(request));
}
TestResult InMemoryMessage::SerializeBinary() && {
return SerializeImpl(::conformance::PROTOBUF);
}
TestResult InMemoryMessage::SerializeText(TextSerializationOptions options) && {
if (options.print_unknown_fields) {
request_.set_print_unknown_fields(true);
}
return SerializeImpl(::conformance::TEXT_FORMAT);
}
TestResult InMemoryMessage::SerializeJson() && {
return SerializeImpl(::conformance::JSON);
}
TestResult InMemoryMessage::SerializeImpl(
const ::conformance::WireFormat format) {
request_.set_requested_output_format(format);
std::string full_name = GetTestName(name_, priority_, request_, *type_);
::conformance::ConformanceResponse response =
testee_->Run(full_name, request_);
return TestResult(full_name, priority_, type_, format, std::move(response));
}
} // namespace internal
absl::string_view PriorityName(TestPriority priority) {
switch (priority) {
case TestPriority::kP0:
return "P0";
case TestPriority::kP1:
return "P1";
}
return "Unknown";
}
bool AbslParseFlag(absl::string_view text, TestPriority* priority,
std::string* error) {
int number;
if (!absl::SimpleAtoi(text, &number) || number < 0 ||
number > static_cast<int>(kLowestPriority)) {
*error = absl::StrCat("expected a priority number from 0 to ",
static_cast<int>(kLowestPriority));
return false;
}
*priority = static_cast<TestPriority>(number);
return true;
}
std::string AbslUnparseFlag(TestPriority priority) {
return absl::StrCat(static_cast<int>(priority));
}
absl::string_view PriorityLevelName(TestPriority priority) {
// TODO: b/564550230 - return PriorityName() once the tests are renamed.
return priority == TestPriority::kP1 ? "Recommended" : "Required";
}
} // namespace conformance
} // namespace protobuf
} // namespace google