|
|
|
@ -7,25 +7,30 @@ |
|
|
|
|
|
|
|
|
|
#include "text_format_conformance_suite.h" |
|
|
|
|
|
|
|
|
|
#include "google/protobuf/any.pb.h" |
|
|
|
|
#include <cstddef> |
|
|
|
|
#include <string> |
|
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
#include "absl/log/absl_log.h" |
|
|
|
|
#include "absl/log/die_if_null.h" |
|
|
|
|
#include "absl/strings/str_cat.h" |
|
|
|
|
#include "conformance_test.h" |
|
|
|
|
#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h" |
|
|
|
|
#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h" |
|
|
|
|
#include "google/protobuf/test_messages_proto2.pb.h" |
|
|
|
|
#include "google/protobuf/test_messages_proto3.pb.h" |
|
|
|
|
#include "google/protobuf/text_format.h" |
|
|
|
|
|
|
|
|
|
namespace proto2_messages = protobuf_test_messages::proto2; |
|
|
|
|
|
|
|
|
|
using conformance::ConformanceRequest; |
|
|
|
|
using conformance::ConformanceResponse; |
|
|
|
|
using conformance::WireFormat; |
|
|
|
|
using google::protobuf::Message; |
|
|
|
|
using google::protobuf::TextFormat; |
|
|
|
|
using proto2_messages::TestAllTypesProto2; |
|
|
|
|
using proto2_messages::UnknownToTestAllTypes; |
|
|
|
|
using protobuf_test_messages::proto2::TestAllTypesProto2; |
|
|
|
|
using protobuf_test_messages::proto2::UnknownToTestAllTypes; |
|
|
|
|
using protobuf_test_messages::proto3::TestAllTypesProto3; |
|
|
|
|
using std::string; |
|
|
|
|
using TestAllTypesProto2Editions = |
|
|
|
|
protobuf_test_messages::editions::proto2::TestAllTypesProto2; |
|
|
|
|
using TestAllTypesProto3Editions = |
|
|
|
|
protobuf_test_messages::editions::proto3::TestAllTypesProto3; |
|
|
|
|
|
|
|
|
|
namespace google { |
|
|
|
|
namespace protobuf { |
|
|
|
@ -61,7 +66,7 @@ bool TextFormatConformanceTestSuite::ParseResponse( |
|
|
|
|
const ConformanceRequestSetting& setting, Message* test_message) { |
|
|
|
|
const ConformanceRequest& request = setting.GetRequest(); |
|
|
|
|
WireFormat requested_output = request.requested_output_format(); |
|
|
|
|
const string& test_name = setting.GetTestName(); |
|
|
|
|
const std::string& test_name = setting.GetTestName(); |
|
|
|
|
ConformanceLevel level = setting.GetLevel(); |
|
|
|
|
|
|
|
|
|
switch (response.result_case()) { |
|
|
|
@ -111,10 +116,39 @@ bool TextFormatConformanceTestSuite::ParseResponse( |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::ExpectParseFailure(const string& test_name, |
|
|
|
|
ConformanceLevel level, |
|
|
|
|
const string& input) { |
|
|
|
|
TestAllTypesProto3 prototype; |
|
|
|
|
void TextFormatConformanceTestSuite::RunSuiteImpl() { |
|
|
|
|
TextFormatConformanceTestSuiteImpl<TestAllTypesProto2>(this); |
|
|
|
|
TextFormatConformanceTestSuiteImpl<TestAllTypesProto3>(this); |
|
|
|
|
if (maximum_edition_ >= Edition::EDITION_2023) { |
|
|
|
|
TextFormatConformanceTestSuiteImpl<TestAllTypesProto2Editions>(this); |
|
|
|
|
TextFormatConformanceTestSuiteImpl<TestAllTypesProto3Editions>(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& input) { |
|
|
|
|
MessageType prototype; |
|
|
|
|
// 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.
|
|
|
|
|
ConformanceRequestSetting setting( |
|
|
|
@ -122,86 +156,75 @@ void TextFormatConformanceTestSuite::ExpectParseFailure(const string& test_name, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, test_name, input); |
|
|
|
|
const ConformanceRequest& request = setting.GetRequest(); |
|
|
|
|
ConformanceResponse response; |
|
|
|
|
string effective_test_name = |
|
|
|
|
absl::StrCat(setting.ConformanceLevelToString(level), |
|
|
|
|
".Proto3.TextFormatInput.", test_name); |
|
|
|
|
std::string effective_test_name = absl::StrCat( |
|
|
|
|
setting.ConformanceLevelToString(level), ".", |
|
|
|
|
setting.GetSyntaxIdentifier(), ".TextFormatInput.", test_name); |
|
|
|
|
|
|
|
|
|
RunTest(effective_test_name, request, &response); |
|
|
|
|
suite_.RunTest(effective_test_name, request, &response); |
|
|
|
|
if (response.result_case() == ConformanceResponse::kParseError) { |
|
|
|
|
ReportSuccess(effective_test_name); |
|
|
|
|
suite_.ReportSuccess(effective_test_name); |
|
|
|
|
} else if (response.result_case() == ConformanceResponse::kSkipped) { |
|
|
|
|
ReportSkip(effective_test_name, request, response); |
|
|
|
|
suite_.ReportSkip(effective_test_name, request, response); |
|
|
|
|
} else { |
|
|
|
|
ReportFailure(effective_test_name, level, request, response, |
|
|
|
|
"Should have failed to parse, but didn't."); |
|
|
|
|
suite_.ReportFailure(effective_test_name, level, request, response, |
|
|
|
|
"Should have failed to parse, but didn't."); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunValidTextFormatTest( |
|
|
|
|
const string& test_name, ConformanceLevel level, const string& input_text) { |
|
|
|
|
TestAllTypesProto3 prototype; |
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl<MessageType>::RunValidTextFormatTest( |
|
|
|
|
const std::string& test_name, ConformanceLevel level, |
|
|
|
|
const std::string& input_text) { |
|
|
|
|
MessageType prototype; |
|
|
|
|
RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2( |
|
|
|
|
const string& test_name, ConformanceLevel level, const string& input_text) { |
|
|
|
|
TestAllTypesProto2 prototype; |
|
|
|
|
RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunValidTextFormatTestWithExpected( |
|
|
|
|
const string& test_name, ConformanceLevel level, const string& input_text, |
|
|
|
|
const string& expected_text) { |
|
|
|
|
TestAllTypesProto3 prototype; |
|
|
|
|
RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text, |
|
|
|
|
prototype); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2WithExpected( |
|
|
|
|
const string& test_name, ConformanceLevel level, const string& input_text, |
|
|
|
|
const string& expected_text) { |
|
|
|
|
TestAllTypesProto2 prototype; |
|
|
|
|
RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text, |
|
|
|
|
prototype); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage( |
|
|
|
|
const string& test_name, ConformanceLevel level, const string& input_text, |
|
|
|
|
const Message& prototype) { |
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl<MessageType>:: |
|
|
|
|
RunValidTextFormatTestWithMessage(const std::string& test_name, |
|
|
|
|
ConformanceLevel level, |
|
|
|
|
const std::string& input_text, |
|
|
|
|
const Message& message) { |
|
|
|
|
ConformanceRequestSetting setting1( |
|
|
|
|
level, conformance::TEXT_FORMAT, conformance::PROTOBUF, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); |
|
|
|
|
RunValidInputTest(setting1, input_text); |
|
|
|
|
conformance::TEXT_FORMAT_TEST, message, test_name, input_text); |
|
|
|
|
suite_.RunValidInputTest(setting1, input_text); |
|
|
|
|
ConformanceRequestSetting setting2( |
|
|
|
|
level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); |
|
|
|
|
RunValidInputTest(setting2, input_text); |
|
|
|
|
conformance::TEXT_FORMAT_TEST, message, test_name, input_text); |
|
|
|
|
suite_.RunValidInputTest(setting2, input_text); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage( |
|
|
|
|
const string& test_name, ConformanceLevel level, const string& input_text, |
|
|
|
|
const string& expected_text, const Message& prototype) { |
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl<MessageType>:: |
|
|
|
|
RunValidTextFormatTestWithExpected(const std::string& test_name, |
|
|
|
|
ConformanceLevel level, |
|
|
|
|
const std::string& input_text, |
|
|
|
|
const std::string& expected_text) { |
|
|
|
|
MessageType prototype; |
|
|
|
|
ConformanceRequestSetting setting1( |
|
|
|
|
level, conformance::TEXT_FORMAT, conformance::PROTOBUF, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); |
|
|
|
|
RunValidInputTest(setting1, expected_text); |
|
|
|
|
suite_.RunValidInputTest(setting1, expected_text); |
|
|
|
|
ConformanceRequestSetting setting2( |
|
|
|
|
level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); |
|
|
|
|
RunValidInputTest(setting2, expected_text); |
|
|
|
|
suite_.RunValidInputTest(setting2, expected_text); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest( |
|
|
|
|
const string& test_name, const Message& message) { |
|
|
|
|
string serialized_input; |
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl< |
|
|
|
|
MessageType>::RunValidUnknownTextFormatTest(const std::string& test_name, |
|
|
|
|
const Message& message) { |
|
|
|
|
std::string serialized_input; |
|
|
|
|
message.SerializeToString(&serialized_input); |
|
|
|
|
TestAllTypesProto3 prototype; |
|
|
|
|
MessageType prototype; |
|
|
|
|
ConformanceRequestSetting setting1( |
|
|
|
|
RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, |
|
|
|
|
absl::StrCat(test_name, "_Drop"), serialized_input); |
|
|
|
|
setting1.SetPrototypeMessageForCompare(message); |
|
|
|
|
RunValidBinaryInputTest(setting1, ""); |
|
|
|
|
suite_.RunValidBinaryInputTest(setting1, ""); |
|
|
|
|
|
|
|
|
|
ConformanceRequestSetting setting2( |
|
|
|
|
RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, |
|
|
|
@ -209,207 +232,182 @@ void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest( |
|
|
|
|
absl::StrCat(test_name, "_Print"), serialized_input); |
|
|
|
|
setting2.SetPrototypeMessageForCompare(message); |
|
|
|
|
setting2.SetPrintUnknownFields(true); |
|
|
|
|
RunValidBinaryInputTest(setting2, serialized_input); |
|
|
|
|
suite_.RunValidBinaryInputTest(setting2, serialized_input); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunSuiteImpl() { |
|
|
|
|
if (!performance_) { |
|
|
|
|
RunValidTextFormatTest("HelloWorld", REQUIRED, |
|
|
|
|
"optional_string: 'Hello, World!'"); |
|
|
|
|
// Integer fields.
|
|
|
|
|
RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_int32: 2147483647"); |
|
|
|
|
RunValidTextFormatTest("Int32FieldMinValue", REQUIRED, |
|
|
|
|
"optional_int32: -2147483648"); |
|
|
|
|
RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_uint32: 4294967295"); |
|
|
|
|
RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_int64: 9223372036854775807"); |
|
|
|
|
RunValidTextFormatTest("Int64FieldMinValue", REQUIRED, |
|
|
|
|
"optional_int64: -9223372036854775808"); |
|
|
|
|
RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_uint64: 18446744073709551615"); |
|
|
|
|
|
|
|
|
|
// Parsers reject out-of-bound integer values.
|
|
|
|
|
ExpectParseFailure("Int32FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_int32: 2147483648"); |
|
|
|
|
ExpectParseFailure("Int32FieldTooSmall", REQUIRED, |
|
|
|
|
"optional_int32: -2147483649"); |
|
|
|
|
ExpectParseFailure("Uint32FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_uint32: 4294967296"); |
|
|
|
|
ExpectParseFailure("Int64FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_int64: 9223372036854775808"); |
|
|
|
|
ExpectParseFailure("Int64FieldTooSmall", REQUIRED, |
|
|
|
|
"optional_int64: -9223372036854775809"); |
|
|
|
|
ExpectParseFailure("Uint64FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_uint64: 18446744073709551616"); |
|
|
|
|
|
|
|
|
|
// Floating point fields
|
|
|
|
|
RunValidTextFormatTest("FloatField", REQUIRED, "optional_float: 3.192837"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED, |
|
|
|
|
"optional_float: 3.123456789123456789"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED, |
|
|
|
|
"optional_float: 3.4028235e+38"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldMinValue", REQUIRED, |
|
|
|
|
"optional_float: 1.17549e-38"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED, |
|
|
|
|
"optional_float: NaN"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED, |
|
|
|
|
"optional_float: inf"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED, |
|
|
|
|
"optional_float: -inf"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED, |
|
|
|
|
"optional_float: 4294967296"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED, |
|
|
|
|
"optional_float: 9223372036854775808"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED, |
|
|
|
|
"optional_float: 3.4028235e+39"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED, |
|
|
|
|
"optional_float: 1.17549e-39"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED, |
|
|
|
|
"optional_float: 18446744073709551616"); |
|
|
|
|
|
|
|
|
|
// String literals x {Strings, Bytes}
|
|
|
|
|
for (const auto& field_type : std::vector<std::string>{"String", "Bytes"}) { |
|
|
|
|
const std::string field_name = |
|
|
|
|
field_type == "String" ? "optional_string" : "optional_bytes"; |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralConcat", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": 'first' \"second\"\n'third'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralBasicEscapes", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": '\\341\\210\\264'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralHexEscapes", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscape", field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\u1234'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapes", field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'")); |
|
|
|
|
// String literals don't include line feeds.
|
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralIncludesLF", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": 'first line\nsecond line'")); |
|
|
|
|
// Unicode escapes don't include code points that lie beyond the planes
|
|
|
|
|
// (> 0x10ffff).
|
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type), |
|
|
|
|
REQUIRED, absl::StrCat(field_name, ": '\\U00110000'")); |
|
|
|
|
// Unicode escapes don't include surrogates.
|
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscapeSurrogatePair", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\udc37'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\ud800'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\udc00'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d800'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\udc37'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\U0000dc37'")); |
|
|
|
|
|
|
|
|
|
// The following method depend on the type of field, as strings have extra
|
|
|
|
|
// validation.
|
|
|
|
|
const auto test_method = |
|
|
|
|
field_type == "String" |
|
|
|
|
? &TextFormatConformanceTestSuite::ExpectParseFailure |
|
|
|
|
: &TextFormatConformanceTestSuite::RunValidTextFormatTest; |
|
|
|
|
|
|
|
|
|
// String fields reject invalid UTF-8 byte sequences; bytes fields don't.
|
|
|
|
|
(this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"), |
|
|
|
|
REQUIRED, absl::StrCat(field_name, ": '\\300'")); |
|
|
|
|
(this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"), |
|
|
|
|
REQUIRED, absl::StrCat(field_name, ": '\\xc0'")); |
|
|
|
|
} |
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl<MessageType>::RunGroupTests() { |
|
|
|
|
RunValidTextFormatTest("GroupFieldNoColon", REQUIRED, |
|
|
|
|
"Data { group_int32: 1 }"); |
|
|
|
|
RunValidTextFormatTest("GroupFieldWithColon", REQUIRED, |
|
|
|
|
"Data: { group_int32: 1 }"); |
|
|
|
|
RunValidTextFormatTest("GroupFieldEmpty", REQUIRED, "Data {}"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Group fields
|
|
|
|
|
RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED, |
|
|
|
|
"Data { group_int32: 1 }"); |
|
|
|
|
RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED, |
|
|
|
|
"Data: { group_int32: 1 }"); |
|
|
|
|
RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED, "Data {}"); |
|
|
|
|
|
|
|
|
|
// Unknown Fields
|
|
|
|
|
UnknownToTestAllTypes message; |
|
|
|
|
// Unable to print unknown Fixed32/Fixed64 fields as if they are known.
|
|
|
|
|
// Fixed32/Fixed64 fields are not added in the tests.
|
|
|
|
|
message.set_optional_int32(123); |
|
|
|
|
message.set_optional_string("hello"); |
|
|
|
|
message.set_optional_bool(true); |
|
|
|
|
RunValidUnknownTextFormatTest("ScalarUnknownFields", message); |
|
|
|
|
|
|
|
|
|
message.Clear(); |
|
|
|
|
message.mutable_nested_message()->set_c(111); |
|
|
|
|
RunValidUnknownTextFormatTest("MessageUnknownFields", message); |
|
|
|
|
|
|
|
|
|
message.Clear(); |
|
|
|
|
message.mutable_optionalgroup()->set_a(321); |
|
|
|
|
RunValidUnknownTextFormatTest("GroupUnknownFields", message); |
|
|
|
|
|
|
|
|
|
message.add_repeated_int32(1); |
|
|
|
|
message.add_repeated_int32(2); |
|
|
|
|
message.add_repeated_int32(3); |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
)"); |
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl<MessageType>::RunAllTests() { |
|
|
|
|
RunValidTextFormatTest("HelloWorld", REQUIRED, |
|
|
|
|
"optional_string: 'Hello, World!'"); |
|
|
|
|
// Integer fields.
|
|
|
|
|
RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_int32: 2147483647"); |
|
|
|
|
RunValidTextFormatTest("Int32FieldMinValue", REQUIRED, |
|
|
|
|
"optional_int32: -2147483648"); |
|
|
|
|
RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_uint32: 4294967295"); |
|
|
|
|
RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_int64: 9223372036854775807"); |
|
|
|
|
RunValidTextFormatTest("Int64FieldMinValue", REQUIRED, |
|
|
|
|
"optional_int64: -9223372036854775808"); |
|
|
|
|
RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED, |
|
|
|
|
"optional_uint64: 18446744073709551615"); |
|
|
|
|
|
|
|
|
|
// Parsers reject out-of-bound integer values.
|
|
|
|
|
ExpectParseFailure("Int32FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_int32: 2147483648"); |
|
|
|
|
ExpectParseFailure("Int32FieldTooSmall", REQUIRED, |
|
|
|
|
"optional_int32: -2147483649"); |
|
|
|
|
ExpectParseFailure("Uint32FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_uint32: 4294967296"); |
|
|
|
|
ExpectParseFailure("Int64FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_int64: 9223372036854775808"); |
|
|
|
|
ExpectParseFailure("Int64FieldTooSmall", REQUIRED, |
|
|
|
|
"optional_int64: -9223372036854775809"); |
|
|
|
|
ExpectParseFailure("Uint64FieldTooLarge", REQUIRED, |
|
|
|
|
"optional_uint64: 18446744073709551616"); |
|
|
|
|
|
|
|
|
|
// Floating point fields
|
|
|
|
|
RunValidTextFormatTest("FloatField", REQUIRED, "optional_float: 3.192837"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED, |
|
|
|
|
"optional_float: 3.123456789123456789"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED, |
|
|
|
|
"optional_float: 3.4028235e+38"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldMinValue", REQUIRED, |
|
|
|
|
"optional_float: 1.17549e-38"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED, "optional_float: NaN"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED, |
|
|
|
|
"optional_float: inf"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED, |
|
|
|
|
"optional_float: -inf"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED, |
|
|
|
|
"optional_float: 4294967296"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED, |
|
|
|
|
"optional_float: 9223372036854775808"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED, |
|
|
|
|
"optional_float: 3.4028235e+39"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED, |
|
|
|
|
"optional_float: 1.17549e-39"); |
|
|
|
|
RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED, |
|
|
|
|
"optional_float: 18446744073709551616"); |
|
|
|
|
|
|
|
|
|
// String literals x {Strings, Bytes}
|
|
|
|
|
for (const auto& field_type : std::vector<std::string>{"String", "Bytes"}) { |
|
|
|
|
const std::string field_name = |
|
|
|
|
field_type == "String" ? "optional_string" : "optional_bytes"; |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralConcat", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": 'first' \"second\"\n'third'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralBasicEscapes", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": '\\341\\210\\264'")); |
|
|
|
|
RunValidTextFormatTest(absl::StrCat("StringLiteralHexEscapes", field_type), |
|
|
|
|
REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscape", field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\u1234'")); |
|
|
|
|
RunValidTextFormatTest( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapes", field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'")); |
|
|
|
|
// String literals don't include line feeds.
|
|
|
|
|
ExpectParseFailure(absl::StrCat("StringLiteralIncludesLF", field_type), |
|
|
|
|
REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": 'first line\nsecond line'")); |
|
|
|
|
// Unicode escapes don't include code points that lie beyond the planes
|
|
|
|
|
// (> 0x10ffff).
|
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type), |
|
|
|
|
REQUIRED, absl::StrCat(field_name, ": '\\U00110000'")); |
|
|
|
|
// Unicode escapes don't include surrogates.
|
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscapeSurrogatePair", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\udc37'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\ud800'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\udc00'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d800'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\udc37'")); |
|
|
|
|
ExpectParseFailure( |
|
|
|
|
absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong", |
|
|
|
|
field_type), |
|
|
|
|
RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\U0000dc37'")); |
|
|
|
|
|
|
|
|
|
// The following method depend on the type of field, as strings have extra
|
|
|
|
|
// validation.
|
|
|
|
|
const auto test_method = |
|
|
|
|
field_type == "String" |
|
|
|
|
? &TextFormatConformanceTestSuiteImpl::ExpectParseFailure |
|
|
|
|
: &TextFormatConformanceTestSuiteImpl::RunValidTextFormatTest; |
|
|
|
|
|
|
|
|
|
// String fields reject invalid UTF-8 byte sequences; bytes fields don't.
|
|
|
|
|
(this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"), |
|
|
|
|
REQUIRED, absl::StrCat(field_name, ": '\\300'")); |
|
|
|
|
(this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"), REQUIRED, |
|
|
|
|
absl::StrCat(field_name, ": '\\xc0'")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Map fields
|
|
|
|
|
TestAllTypesProto3 prototype; |
|
|
|
|
(*prototype.mutable_map_string_string())["c"] = "value"; |
|
|
|
|
(*prototype.mutable_map_string_string())["b"] = "value"; |
|
|
|
|
(*prototype.mutable_map_string_string())["a"] = "value"; |
|
|
|
|
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys", |
|
|
|
|
REQUIRED, |
|
|
|
|
R"( |
|
|
|
|
// Unknown Fields
|
|
|
|
|
UnknownToTestAllTypes message; |
|
|
|
|
// Unable to print unknown Fixed32/Fixed64 fields as if they are known.
|
|
|
|
|
// Fixed32/Fixed64 fields are not added in the tests.
|
|
|
|
|
message.set_optional_int32(123); |
|
|
|
|
message.set_optional_string("hello"); |
|
|
|
|
message.set_optional_bool(true); |
|
|
|
|
RunValidUnknownTextFormatTest("ScalarUnknownFields", message); |
|
|
|
|
|
|
|
|
|
message.Clear(); |
|
|
|
|
message.mutable_nested_message()->set_c(111); |
|
|
|
|
RunValidUnknownTextFormatTest("MessageUnknownFields", message); |
|
|
|
|
|
|
|
|
|
message.Clear(); |
|
|
|
|
message.mutable_optionalgroup()->set_a(321); |
|
|
|
|
RunValidUnknownTextFormatTest("GroupUnknownFields", message); |
|
|
|
|
|
|
|
|
|
message.add_repeated_int32(1); |
|
|
|
|
message.add_repeated_int32(2); |
|
|
|
|
message.add_repeated_int32(3); |
|
|
|
|
RunValidUnknownTextFormatTest("RepeatedUnknownFields", message); |
|
|
|
|
|
|
|
|
|
// Map fields
|
|
|
|
|
MessageType prototype; |
|
|
|
|
(*prototype.mutable_map_string_string())["c"] = "value"; |
|
|
|
|
(*prototype.mutable_map_string_string())["b"] = "value"; |
|
|
|
|
(*prototype.mutable_map_string_string())["a"] = "value"; |
|
|
|
|
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys", |
|
|
|
|
REQUIRED, |
|
|
|
|
R"( |
|
|
|
|
map_string_string { |
|
|
|
|
key: "a" |
|
|
|
|
value: "value" |
|
|
|
@ -423,15 +421,14 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { |
|
|
|
|
value: "value" |
|
|
|
|
} |
|
|
|
|
)", |
|
|
|
|
prototype); |
|
|
|
|
|
|
|
|
|
prototype.Clear(); |
|
|
|
|
(*prototype.mutable_map_int32_int32())[3] = 0; |
|
|
|
|
(*prototype.mutable_map_int32_int32())[2] = 0; |
|
|
|
|
(*prototype.mutable_map_int32_int32())[1] = 0; |
|
|
|
|
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", |
|
|
|
|
REQUIRED, |
|
|
|
|
R"( |
|
|
|
|
prototype); |
|
|
|
|
|
|
|
|
|
prototype.Clear(); |
|
|
|
|
(*prototype.mutable_map_int32_int32())[3] = 0; |
|
|
|
|
(*prototype.mutable_map_int32_int32())[2] = 0; |
|
|
|
|
(*prototype.mutable_map_int32_int32())[1] = 0; |
|
|
|
|
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", REQUIRED, |
|
|
|
|
R"( |
|
|
|
|
map_int32_int32 { |
|
|
|
|
key: 1 |
|
|
|
|
value: 0 |
|
|
|
@ -445,14 +442,13 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { |
|
|
|
|
value: 0 |
|
|
|
|
} |
|
|
|
|
)", |
|
|
|
|
prototype); |
|
|
|
|
|
|
|
|
|
prototype.Clear(); |
|
|
|
|
(*prototype.mutable_map_bool_bool())[true] = false; |
|
|
|
|
(*prototype.mutable_map_bool_bool())[false] = false; |
|
|
|
|
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", |
|
|
|
|
REQUIRED, |
|
|
|
|
R"( |
|
|
|
|
prototype); |
|
|
|
|
|
|
|
|
|
prototype.Clear(); |
|
|
|
|
(*prototype.mutable_map_bool_bool())[true] = false; |
|
|
|
|
(*prototype.mutable_map_bool_bool())[false] = false; |
|
|
|
|
RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", REQUIRED, |
|
|
|
|
R"( |
|
|
|
|
map_bool_bool { |
|
|
|
|
key: false |
|
|
|
|
value: false |
|
|
|
@ -462,12 +458,12 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { |
|
|
|
|
value: false |
|
|
|
|
} |
|
|
|
|
)", |
|
|
|
|
prototype); |
|
|
|
|
prototype); |
|
|
|
|
|
|
|
|
|
prototype.Clear(); |
|
|
|
|
ConformanceRequestSetting setting_map( |
|
|
|
|
REQUIRED, conformance::TEXT_FORMAT, conformance::PROTOBUF, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, "DuplicateMapKey", R"( |
|
|
|
|
prototype.Clear(); |
|
|
|
|
ConformanceRequestSetting setting_map( |
|
|
|
|
REQUIRED, conformance::TEXT_FORMAT, conformance::PROTOBUF, |
|
|
|
|
conformance::TEXT_FORMAT_TEST, prototype, "DuplicateMapKey", R"( |
|
|
|
|
map_string_nested_message { |
|
|
|
|
key: "duplicate" |
|
|
|
|
value: { a: 123 } |
|
|
|
@ -477,21 +473,47 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { |
|
|
|
|
value: { corecursive: {} } |
|
|
|
|
} |
|
|
|
|
)"); |
|
|
|
|
// The last-specified value will be retained in a parsed map
|
|
|
|
|
RunValidInputTest(setting_map, R"( |
|
|
|
|
// The last-specified value will be retained in a parsed map
|
|
|
|
|
suite_.RunValidInputTest(setting_map, R"( |
|
|
|
|
map_string_nested_message { |
|
|
|
|
key: "duplicate" |
|
|
|
|
value: { corecursive: {} } |
|
|
|
|
} |
|
|
|
|
)"); |
|
|
|
|
} |
|
|
|
|
// Flag control performance tests to keep them internal and opt-in only
|
|
|
|
|
if (performance_) { |
|
|
|
|
RunTextFormatPerformanceTests(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() { |
|
|
|
|
template <typename MessageType> |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
)"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl< |
|
|
|
|
MessageType>::RunTextFormatPerformanceTests() { |
|
|
|
|
TestTextFormatPerformanceMergeMessageWithRepeatedField("Bool", |
|
|
|
|
"repeated_bool: true"); |
|
|
|
|
TestTextFormatPerformanceMergeMessageWithRepeatedField( |
|
|
|
@ -507,30 +529,27 @@ void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This is currently considered valid input by some languages but not others
|
|
|
|
|
void TextFormatConformanceTestSuite:: |
|
|
|
|
template <typename MessageType> |
|
|
|
|
void TextFormatConformanceTestSuiteImpl<MessageType>:: |
|
|
|
|
TestTextFormatPerformanceMergeMessageWithRepeatedField( |
|
|
|
|
const string& test_type_name, const string& message_field) { |
|
|
|
|
string recursive_message = |
|
|
|
|
const std::string& test_type_name, const std::string& message_field) { |
|
|
|
|
std::string recursive_message = |
|
|
|
|
absl::StrCat("recursive_message { ", message_field, " }"); |
|
|
|
|
|
|
|
|
|
string input; |
|
|
|
|
std::string input; |
|
|
|
|
for (size_t i = 0; i < kPerformanceRepeatCount; i++) { |
|
|
|
|
absl::StrAppend(&input, recursive_message); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string expected = "recursive_message { "; |
|
|
|
|
std::string expected = "recursive_message { "; |
|
|
|
|
for (size_t i = 0; i < kPerformanceRepeatCount; i++) { |
|
|
|
|
absl::StrAppend(&expected, message_field, " "); |
|
|
|
|
} |
|
|
|
|
absl::StrAppend(&expected, "}"); |
|
|
|
|
|
|
|
|
|
RunValidTextFormatTestProto2WithExpected( |
|
|
|
|
absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField", |
|
|
|
|
test_type_name, "Proto2"), |
|
|
|
|
RECOMMENDED, input, expected); |
|
|
|
|
RunValidTextFormatTestWithExpected( |
|
|
|
|
absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField", |
|
|
|
|
test_type_name, "Proto3"), |
|
|
|
|
test_type_name), |
|
|
|
|
RECOMMENDED, input, expected); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|