| #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 |