Restructure syntax branches in text format conformance tests.

This doesn't change the tests at all, but refactors them to be more reusable in different contexts.  Specifically, this will make it easier to add corresponding editions-based tests.  This also splits the concept of "uses a proto3 message" and "runs proto3 tests", in preparation for that change.

PiperOrigin-RevId: 574310612
pull/14452/head
Mike Kruskal 2 years ago committed by Copybara-Service
parent 39752aaea3
commit 28e573e77f
  1. 3
      conformance/BUILD.bazel
  2. 14
      conformance/binary_json_conformance_suite.cc
  3. 18
      conformance/conformance_test.cc
  4. 3
      conformance/conformance_test.h
  5. 242
      conformance/text_format_conformance_suite.cc
  6. 56
      conformance/text_format_conformance_suite.h

@ -171,6 +171,9 @@ cc_library(
":conformance_test", ":conformance_test",
":test_messages_proto2_proto_cc", ":test_messages_proto2_proto_cc",
":test_messages_proto3_proto_cc", ":test_messages_proto3_proto_cc",
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/log:die_if_null",
"@com_google_absl//absl/strings",
], ],
) )

@ -349,7 +349,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::
ConformanceResponse response; ConformanceResponse response;
std::string effective_test_name = std::string effective_test_name =
absl::StrCat(setting.ConformanceLevelToString(level), ".", absl::StrCat(setting.ConformanceLevelToString(level), ".",
SyntaxIdentifier(), ".ProtobufInput.", test_name); setting.GetSyntaxIdentifier(), ".ProtobufInput.", test_name);
suite_.RunTest(effective_test_name, request, &response); suite_.RunTest(effective_test_name, request, &response);
if (response.result_case() == ConformanceResponse::kParseError) { if (response.result_case() == ConformanceResponse::kParseError) {
@ -522,9 +522,9 @@ void BinaryAndJsonConformanceSuiteImpl<
test_name, input_json); test_name, input_json);
const ConformanceRequest& request = setting.GetRequest(); const ConformanceRequest& request = setting.GetRequest();
ConformanceResponse response; ConformanceResponse response;
std::string effective_test_name = std::string effective_test_name = absl::StrCat(
absl::StrCat(setting.ConformanceLevelToString(level), ".", setting.ConformanceLevelToString(level), ".",
SyntaxIdentifier(), ".JsonInput.", test_name, ".Validator"); setting.GetSyntaxIdentifier(), ".JsonInput.", test_name, ".Validator");
suite_.RunTest(effective_test_name, request, &response); suite_.RunTest(effective_test_name, request, &response);
@ -3202,7 +3202,7 @@ BinaryAndJsonConformanceSuiteImpl<MessageType>::GetFieldForType(
} }
ABSL_LOG(FATAL) << "Couldn't find field with type: " << repeated_string ABSL_LOG(FATAL) << "Couldn't find field with type: " << repeated_string
<< packed_string << FieldDescriptor::TypeName(type) << " for " << packed_string << FieldDescriptor::TypeName(type) << " for "
<< SyntaxIdentifier(); << d->full_name();
return nullptr; return nullptr;
} }
@ -3226,7 +3226,7 @@ BinaryAndJsonConformanceSuiteImpl<MessageType>::GetFieldForMapType(
ABSL_LOG(FATAL) << "Couldn't find map field with type: " ABSL_LOG(FATAL) << "Couldn't find map field with type: "
<< FieldDescriptor::TypeName(key_type) << " and " << FieldDescriptor::TypeName(key_type) << " and "
<< FieldDescriptor::TypeName(key_type) << " for " << FieldDescriptor::TypeName(key_type) << " for "
<< SyntaxIdentifier(); << d->full_name();
return nullptr; return nullptr;
} }
@ -3244,7 +3244,7 @@ BinaryAndJsonConformanceSuiteImpl<MessageType>::GetFieldForOneofType(
ABSL_LOG(FATAL) << "Couldn't find oneof field with type: " ABSL_LOG(FATAL) << "Couldn't find oneof field with type: "
<< FieldDescriptor::TypeName(type) << " for " << FieldDescriptor::TypeName(type) << " for "
<< SyntaxIdentifier(); << d->full_name();
return nullptr; return nullptr;
} }

@ -141,22 +141,22 @@ ConformanceTestSuite::ConformanceRequestSetting::NewTestMessage() const {
return std::unique_ptr<Message>(prototype_message_for_compare_->New()); return std::unique_ptr<Message>(prototype_message_for_compare_->New());
} }
std::string ConformanceTestSuite::ConformanceRequestSetting::GetTestName() std::string
const { ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const {
std::string rname;
switch (FileDescriptorLegacy(prototype_message_.GetDescriptor()->file()) switch (FileDescriptorLegacy(prototype_message_.GetDescriptor()->file())
.syntax()) { .syntax()) {
case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3: case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3:
rname = ".Proto3."; return "Proto3";
break;
case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2: case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2:
rname = ".Proto2."; return "Proto2";
break;
default: default:
break; return "Unknown";
}
} }
return absl::StrCat(ConformanceLevelToString(level_), rname, string ConformanceTestSuite::ConformanceRequestSetting::GetTestName() const {
return absl::StrCat(ConformanceLevelToString(level_), ".",
GetSyntaxIdentifier(), ".",
InputFormatString(input_format_), ".", test_name_, ".", InputFormatString(input_format_), ".", test_name_, ".",
OutputFormatString(output_format_)); OutputFormatString(output_format_));
} }

@ -19,6 +19,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/util/type_resolver.h" #include "google/protobuf/util/type_resolver.h"
#include "absl/container/btree_set.h" #include "absl/container/btree_set.h"
#include "absl/container/flat_hash_set.h" #include "absl/container/flat_hash_set.h"
@ -200,6 +201,8 @@ class ConformanceTestSuite {
std::unique_ptr<Message> NewTestMessage() const; std::unique_ptr<Message> NewTestMessage() const;
std::string GetSyntaxIdentifier() const;
std::string GetTestName() const; std::string GetTestName() const;
const conformance::ConformanceRequest& GetRequest() const { const conformance::ConformanceRequest& GetRequest() const {

@ -12,19 +12,18 @@
#include <vector> #include <vector>
#include "absl/log/absl_log.h" #include "absl/log/absl_log.h"
#include "absl/log/die_if_null.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "conformance_test.h" #include "conformance_test.h"
#include "google/protobuf/test_messages_proto2.pb.h" #include "google/protobuf/test_messages_proto2.pb.h"
#include "google/protobuf/test_messages_proto3.pb.h" #include "google/protobuf/test_messages_proto3.pb.h"
#include "google/protobuf/text_format.h" #include "google/protobuf/text_format.h"
namespace proto2_messages = protobuf_test_messages::proto2;
using conformance::ConformanceRequest; using conformance::ConformanceRequest;
using conformance::ConformanceResponse; using conformance::ConformanceResponse;
using conformance::WireFormat; using conformance::WireFormat;
using proto2_messages::TestAllTypesProto2; using protobuf_test_messages::proto2::TestAllTypesProto2;
using proto2_messages::UnknownToTestAllTypes; using protobuf_test_messages::proto2::UnknownToTestAllTypes;
using protobuf_test_messages::proto3::TestAllTypesProto3; using protobuf_test_messages::proto3::TestAllTypesProto3;
namespace google { namespace google {
@ -111,10 +110,35 @@ bool TextFormatConformanceTestSuite::ParseResponse(
return true; return true;
} }
void TextFormatConformanceTestSuite::ExpectParseFailure( void TextFormatConformanceTestSuite::RunSuiteImpl() {
TextFormatConformanceTestSuiteImpl<TestAllTypesProto2>(this);
TextFormatConformanceTestSuiteImpl<TestAllTypesProto3>(this);
}
template <typename MessageType>
TextFormatConformanceTestSuiteImpl<MessageType>::
TextFormatConformanceTestSuiteImpl(TextFormatConformanceTestSuite* suite)
: suite_(*ABSL_DIE_IF_NULL(suite)) {
// Flag control performance tests to keep them internal and opt-in only
if (suite_.performance_) {
RunTextFormatPerformanceTests();
} else {
if (MessageType::GetDescriptor()->name() == "TestAllTypesProto2") {
RunGroupTests();
}
if (MessageType::GetDescriptor()->name() == "TestAllTypesProto3") {
RunAnyTests();
// TODO Run these over proto2 also.
RunAllTests();
}
}
}
template <typename MessageType>
void TextFormatConformanceTestSuiteImpl<MessageType>::ExpectParseFailure(
const std::string& test_name, ConformanceLevel level, const std::string& test_name, ConformanceLevel level,
const std::string& input) { const std::string& input) {
TestAllTypesProto3 prototype; MessageType prototype;
// We don't expect output, but if the program erroneously accepts the protobuf // We don't expect output, but if the program erroneously accepts the protobuf
// we let it send its response as this. We must not leave it unspecified. // we let it send its response as this. We must not leave it unspecified.
ConformanceRequestSetting setting( ConformanceRequestSetting setting(
@ -122,89 +146,75 @@ void TextFormatConformanceTestSuite::ExpectParseFailure(
conformance::TEXT_FORMAT_TEST, prototype, test_name, input); conformance::TEXT_FORMAT_TEST, prototype, test_name, input);
const ConformanceRequest& request = setting.GetRequest(); const ConformanceRequest& request = setting.GetRequest();
ConformanceResponse response; ConformanceResponse response;
std::string effective_test_name = std::string effective_test_name = absl::StrCat(
absl::StrCat(setting.ConformanceLevelToString(level), setting.ConformanceLevelToString(level), ".",
".Proto3.TextFormatInput.", test_name); setting.GetSyntaxIdentifier(), ".TextFormatInput.", test_name);
RunTest(effective_test_name, request, &response); suite_.RunTest(effective_test_name, request, &response);
if (response.result_case() == ConformanceResponse::kParseError) { if (response.result_case() == ConformanceResponse::kParseError) {
ReportSuccess(effective_test_name); suite_.ReportSuccess(effective_test_name);
} else if (response.result_case() == ConformanceResponse::kSkipped) { } else if (response.result_case() == ConformanceResponse::kSkipped) {
ReportSkip(effective_test_name, request, response); suite_.ReportSkip(effective_test_name, request, response);
} else { } else {
ReportFailure(effective_test_name, level, request, response, suite_.ReportFailure(effective_test_name, level, request, response,
"Should have failed to parse, but didn't."); "Should have failed to parse, but didn't.");
} }
} }
void TextFormatConformanceTestSuite::RunValidTextFormatTest( template <typename MessageType>
void TextFormatConformanceTestSuiteImpl<MessageType>::RunValidTextFormatTest(
const std::string& test_name, ConformanceLevel level, const std::string& test_name, ConformanceLevel level,
const std::string& input_text) { const std::string& input_text) {
TestAllTypesProto3 prototype; MessageType prototype;
RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype);
} }
void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2( template <typename MessageType>
const std::string& test_name, ConformanceLevel level, void TextFormatConformanceTestSuiteImpl<MessageType>::
const std::string& input_text) { RunValidTextFormatTestWithMessage(const std::string& test_name,
TestAllTypesProto2 prototype; ConformanceLevel level,
RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); const std::string& input_text,
} const Message& message) {
void TextFormatConformanceTestSuite::RunValidTextFormatTestWithExpected(
const std::string& test_name, ConformanceLevel level,
const std::string& input_text, const std::string& expected_text) {
TestAllTypesProto3 prototype;
RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text,
prototype);
}
void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2WithExpected(
const std::string& test_name, ConformanceLevel level,
const std::string& input_text, const std::string& expected_text) {
TestAllTypesProto2 prototype;
RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text,
prototype);
}
void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage(
const std::string& test_name, ConformanceLevel level,
const std::string& input_text, const Message& prototype) {
ConformanceRequestSetting setting1( ConformanceRequestSetting setting1(
level, conformance::TEXT_FORMAT, conformance::PROTOBUF, level, conformance::TEXT_FORMAT, conformance::PROTOBUF,
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); conformance::TEXT_FORMAT_TEST, message, test_name, input_text);
RunValidInputTest(setting1, input_text); suite_.RunValidInputTest(setting1, input_text);
ConformanceRequestSetting setting2( ConformanceRequestSetting setting2(
level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); conformance::TEXT_FORMAT_TEST, message, test_name, input_text);
RunValidInputTest(setting2, input_text); suite_.RunValidInputTest(setting2, input_text);
} }
void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage( template <typename MessageType>
const std::string& test_name, ConformanceLevel level, void TextFormatConformanceTestSuiteImpl<MessageType>::
const std::string& input_text, const std::string& expected_text, RunValidTextFormatTestWithExpected(const std::string& test_name,
const Message& prototype) { ConformanceLevel level,
const std::string& input_text,
const std::string& expected_text) {
MessageType prototype;
ConformanceRequestSetting setting1( ConformanceRequestSetting setting1(
level, conformance::TEXT_FORMAT, conformance::PROTOBUF, level, conformance::TEXT_FORMAT, conformance::PROTOBUF,
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
RunValidInputTest(setting1, expected_text); suite_.RunValidInputTest(setting1, expected_text);
ConformanceRequestSetting setting2( ConformanceRequestSetting setting2(
level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
RunValidInputTest(setting2, expected_text); suite_.RunValidInputTest(setting2, expected_text);
} }
void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest( template <typename MessageType>
const std::string& test_name, const Message& message) { void TextFormatConformanceTestSuiteImpl<
MessageType>::RunValidUnknownTextFormatTest(const std::string& test_name,
const Message& message) {
std::string serialized_input; std::string serialized_input;
message.SerializeToString(&serialized_input); message.SerializeToString(&serialized_input);
TestAllTypesProto3 prototype; MessageType prototype;
ConformanceRequestSetting setting1( ConformanceRequestSetting setting1(
RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
conformance::TEXT_FORMAT_TEST, prototype, conformance::TEXT_FORMAT_TEST, prototype,
absl::StrCat(test_name, "_Drop"), serialized_input); absl::StrCat(test_name, "_Drop"), serialized_input);
setting1.SetPrototypeMessageForCompare(message); setting1.SetPrototypeMessageForCompare(message);
RunValidBinaryInputTest(setting1, ""); suite_.RunValidBinaryInputTest(setting1, "");
ConformanceRequestSetting setting2( ConformanceRequestSetting setting2(
RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
@ -212,11 +222,20 @@ void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest(
absl::StrCat(test_name, "_Print"), serialized_input); absl::StrCat(test_name, "_Print"), serialized_input);
setting2.SetPrototypeMessageForCompare(message); setting2.SetPrototypeMessageForCompare(message);
setting2.SetPrintUnknownFields(true); setting2.SetPrintUnknownFields(true);
RunValidBinaryInputTest(setting2, serialized_input); suite_.RunValidBinaryInputTest(setting2, serialized_input);
} }
void TextFormatConformanceTestSuite::RunSuiteImpl() { template <typename MessageType>
if (!performance_) { void TextFormatConformanceTestSuiteImpl<MessageType>::RunGroupTests() {
RunValidTextFormatTest("GroupFieldNoColon", REQUIRED,
"Data { group_int32: 1 }");
RunValidTextFormatTest("GroupFieldWithColon", REQUIRED,
"Data: { group_int32: 1 }");
RunValidTextFormatTest("GroupFieldEmpty", REQUIRED, "Data {}");
}
template <typename MessageType>
void TextFormatConformanceTestSuiteImpl<MessageType>::RunAllTests() {
RunValidTextFormatTest("HelloWorld", REQUIRED, RunValidTextFormatTest("HelloWorld", REQUIRED,
"optional_string: 'Hello, World!'"); "optional_string: 'Hello, World!'");
// Integer fields. // Integer fields.
@ -255,8 +274,7 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
"optional_float: 3.4028235e+38"); "optional_float: 3.4028235e+38");
RunValidTextFormatTest("FloatFieldMinValue", REQUIRED, RunValidTextFormatTest("FloatFieldMinValue", REQUIRED,
"optional_float: 1.17549e-38"); "optional_float: 1.17549e-38");
RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED, RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED, "optional_float: NaN");
"optional_float: NaN");
RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED, RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED,
"optional_float: inf"); "optional_float: inf");
RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED, RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED,
@ -285,8 +303,8 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
RunValidTextFormatTest( RunValidTextFormatTest(
absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED, absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED,
absl::StrCat(field_name, ": '\\341\\210\\264'")); absl::StrCat(field_name, ": '\\341\\210\\264'"));
RunValidTextFormatTest( RunValidTextFormatTest(absl::StrCat("StringLiteralHexEscapes", field_type),
absl::StrCat("StringLiteralHexEscapes", field_type), REQUIRED, REQUIRED,
absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'")); absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'"));
RunValidTextFormatTest( RunValidTextFormatTest(
absl::StrCat("StringLiteralShortUnicodeEscape", field_type), absl::StrCat("StringLiteralShortUnicodeEscape", field_type),
@ -295,8 +313,8 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
absl::StrCat("StringLiteralLongUnicodeEscapes", field_type), absl::StrCat("StringLiteralLongUnicodeEscapes", field_type),
RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'")); RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'"));
// String literals don't include line feeds. // String literals don't include line feeds.
ExpectParseFailure( ExpectParseFailure(absl::StrCat("StringLiteralIncludesLF", field_type),
absl::StrCat("StringLiteralIncludesLF", field_type), REQUIRED, REQUIRED,
absl::StrCat(field_name, ": 'first line\nsecond line'")); absl::StrCat(field_name, ": 'first line\nsecond line'"));
// Unicode escapes don't include code points that lie beyond the planes // Unicode escapes don't include code points that lie beyond the planes
// (> 0x10ffff). // (> 0x10ffff).
@ -325,8 +343,7 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
field_type), field_type),
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'")); RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'"));
ExpectParseFailure( ExpectParseFailure(
absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type),
field_type),
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'")); RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'"));
ExpectParseFailure( ExpectParseFailure(
absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort", absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort",
@ -341,23 +358,16 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
// validation. // validation.
const auto test_method = const auto test_method =
field_type == "String" field_type == "String"
? &TextFormatConformanceTestSuite::ExpectParseFailure ? &TextFormatConformanceTestSuiteImpl::ExpectParseFailure
: &TextFormatConformanceTestSuite::RunValidTextFormatTest; : &TextFormatConformanceTestSuiteImpl::RunValidTextFormatTest;
// String fields reject invalid UTF-8 byte sequences; bytes fields don't. // String fields reject invalid UTF-8 byte sequences; bytes fields don't.
(this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"), (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"),
REQUIRED, absl::StrCat(field_name, ": '\\300'")); REQUIRED, absl::StrCat(field_name, ": '\\300'"));
(this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"), (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"), REQUIRED,
REQUIRED, absl::StrCat(field_name, ": '\\xc0'")); absl::StrCat(field_name, ": '\\xc0'"));
} }
// Group fields
RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED,
"Data { group_int32: 1 }");
RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED,
"Data: { group_int32: 1 }");
RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED, "Data {}");
// Unknown Fields // Unknown Fields
UnknownToTestAllTypes message; UnknownToTestAllTypes message;
// Unable to print unknown Fixed32/Fixed64 fields as if they are known. // Unable to print unknown Fixed32/Fixed64 fields as if they are known.
@ -380,33 +390,8 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
message.add_repeated_int32(3); message.add_repeated_int32(3);
RunValidUnknownTextFormatTest("RepeatedUnknownFields", message); RunValidUnknownTextFormatTest("RepeatedUnknownFields", message);
// Any fields
RunValidTextFormatTest("AnyField", REQUIRED,
R"(
optional_any: {
[type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
optional_int32: 12345
}
}
)");
RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED,
R"(
optional_any: {
type_url: "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
value: "\b\271`"
}
)");
ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED,
R"(
optional_any: {
[type.googleapis.com/unknown] {
optional_int32: 12345
}
}
)");
// Map fields // Map fields
TestAllTypesProto3 prototype; MessageType prototype;
(*prototype.mutable_map_string_string())["c"] = "value"; (*prototype.mutable_map_string_string())["c"] = "value";
(*prototype.mutable_map_string_string())["b"] = "value"; (*prototype.mutable_map_string_string())["b"] = "value";
(*prototype.mutable_map_string_string())["a"] = "value"; (*prototype.mutable_map_string_string())["a"] = "value";
@ -432,8 +417,7 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
(*prototype.mutable_map_int32_int32())[3] = 0; (*prototype.mutable_map_int32_int32())[3] = 0;
(*prototype.mutable_map_int32_int32())[2] = 0; (*prototype.mutable_map_int32_int32())[2] = 0;
(*prototype.mutable_map_int32_int32())[1] = 0; (*prototype.mutable_map_int32_int32())[1] = 0;
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", REQUIRED,
REQUIRED,
R"( R"(
map_int32_int32 { map_int32_int32 {
key: 1 key: 1
@ -453,8 +437,7 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
prototype.Clear(); prototype.Clear();
(*prototype.mutable_map_bool_bool())[true] = false; (*prototype.mutable_map_bool_bool())[true] = false;
(*prototype.mutable_map_bool_bool())[false] = false; (*prototype.mutable_map_bool_bool())[false] = false;
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", REQUIRED,
REQUIRED,
R"( R"(
map_bool_bool { map_bool_bool {
key: false key: false
@ -481,20 +464,46 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() {
} }
)"); )");
// The last-specified value will be retained in a parsed map // The last-specified value will be retained in a parsed map
RunValidInputTest(setting_map, R"( suite_.RunValidInputTest(setting_map, R"(
map_string_nested_message { map_string_nested_message {
key: "duplicate" key: "duplicate"
value: { corecursive: {} } value: { corecursive: {} }
} }
)"); )");
} }
// Flag control performance tests to keep them internal and opt-in only
if (performance_) { template <typename MessageType>
RunTextFormatPerformanceTests(); void TextFormatConformanceTestSuiteImpl<MessageType>::RunAnyTests() {
// Any fields
RunValidTextFormatTest("AnyField", REQUIRED,
R"(
optional_any: {
[type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3]
{ optional_int32: 12345
}
}
)");
RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED,
R"(
optional_any: {
type_url:
"type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" value:
"\b\271`"
} }
)");
ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED,
R"(
optional_any: {
[type.googleapis.com/unknown] {
optional_int32: 12345
}
}
)");
} }
void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() { template <typename MessageType>
void TextFormatConformanceTestSuiteImpl<
MessageType>::RunTextFormatPerformanceTests() {
TestTextFormatPerformanceMergeMessageWithRepeatedField("Bool", TestTextFormatPerformanceMergeMessageWithRepeatedField("Bool",
"repeated_bool: true"); "repeated_bool: true");
TestTextFormatPerformanceMergeMessageWithRepeatedField( TestTextFormatPerformanceMergeMessageWithRepeatedField(
@ -510,7 +519,8 @@ void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() {
} }
// This is currently considered valid input by some languages but not others // This is currently considered valid input by some languages but not others
void TextFormatConformanceTestSuite:: template <typename MessageType>
void TextFormatConformanceTestSuiteImpl<MessageType>::
TestTextFormatPerformanceMergeMessageWithRepeatedField( TestTextFormatPerformanceMergeMessageWithRepeatedField(
const std::string& test_type_name, const std::string& message_field) { const std::string& test_type_name, const std::string& message_field) {
std::string recursive_message = std::string recursive_message =
@ -527,13 +537,9 @@ void TextFormatConformanceTestSuite::
} }
absl::StrAppend(&expected, "}"); absl::StrAppend(&expected, "}");
RunValidTextFormatTestProto2WithExpected(
absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField",
test_type_name, "Proto2"),
RECOMMENDED, input, expected);
RunValidTextFormatTestWithExpected( RunValidTextFormatTestWithExpected(
absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField", absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField",
test_type_name, "Proto3"), test_type_name),
RECOMMENDED, input, expected); RECOMMENDED, input, expected);
} }

@ -22,41 +22,55 @@ class TextFormatConformanceTestSuite : public ConformanceTestSuite {
private: private:
void RunSuiteImpl() override; void RunSuiteImpl() override;
bool ParseTextFormatResponse(const conformance::ConformanceResponse& response,
const ConformanceRequestSetting& setting,
Message* test_message);
bool ParseResponse(const conformance::ConformanceResponse& response,
const ConformanceRequestSetting& setting,
Message* test_message) override;
template <typename MessageType>
friend class TextFormatConformanceTestSuiteImpl;
};
template <typename MessageType>
class TextFormatConformanceTestSuiteImpl {
public:
explicit TextFormatConformanceTestSuiteImpl(
TextFormatConformanceTestSuite* suite);
private:
using ConformanceRequestSetting =
TextFormatConformanceTestSuite::ConformanceRequestSetting;
using ConformanceLevel = TextFormatConformanceTestSuite::ConformanceLevel;
constexpr static ConformanceLevel RECOMMENDED = ConformanceLevel::RECOMMENDED;
constexpr static ConformanceLevel REQUIRED = ConformanceLevel::REQUIRED;
void RunAllTests();
void RunGroupTests();
void RunAnyTests();
void RunTextFormatPerformanceTests(); void RunTextFormatPerformanceTests();
void RunValidTextFormatTest(const std::string& test_name, void RunValidTextFormatTest(const std::string& test_name,
ConformanceLevel level, const std::string& input); ConformanceLevel level, const std::string& input);
void RunValidTextFormatTestProto2(const std::string& test_name,
ConformanceLevel level,
const std::string& input);
void RunValidTextFormatTestWithExpected(const std::string& test_name, void RunValidTextFormatTestWithExpected(const std::string& test_name,
ConformanceLevel level,
const std::string& input,
const std::string& expected);
void RunValidTextFormatTestProto2WithExpected(const std::string& test_name,
ConformanceLevel level,
const std::string& input,
const std::string& expected);
void RunValidTextFormatTestWithMessage(const std::string& test_name,
ConformanceLevel level, ConformanceLevel level,
const std::string& input_text, const std::string& input_text,
const Message& prototype); const std::string& expected_text);
void RunValidUnknownTextFormatTest(const std::string& test_name,
const Message& message);
void RunValidTextFormatTestWithMessage(const std::string& test_name, void RunValidTextFormatTestWithMessage(const std::string& test_name,
ConformanceLevel level, ConformanceLevel level,
const std::string& input_text, const std::string& input_text,
const std::string& expected_text,
const Message& prototype);
void RunValidUnknownTextFormatTest(const std::string& test_name,
const Message& message); const Message& message);
void ExpectParseFailure(const std::string& test_name, ConformanceLevel level, void ExpectParseFailure(const std::string& test_name, ConformanceLevel level,
const std::string& input); const std::string& input);
bool ParseTextFormatResponse(const conformance::ConformanceResponse& response,
const ConformanceRequestSetting& setting,
Message* test_message);
bool ParseResponse(const conformance::ConformanceResponse& response,
const ConformanceRequestSetting& setting,
Message* test_message) override;
void TestTextFormatPerformanceMergeMessageWithRepeatedField( void TestTextFormatPerformanceMergeMessageWithRepeatedField(
const std::string& test_type_name, const std::string& message_field); const std::string& test_type_name, const std::string& message_field);
TextFormatConformanceTestSuite& suite_;
}; };
} // namespace protobuf } // namespace protobuf

Loading…
Cancel
Save