1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "text_format_conformance_suite.h"
9
10 #include <cstddef>
11 #include <string>
12 #include <utility>
13 #include <vector>
14
15 #include "absl/log/absl_log.h"
16 #include "absl/log/die_if_null.h"
17 #include "absl/strings/str_cat.h"
18 #include "absl/strings/str_format.h"
19 #include "conformance_test.h"
20 #include "conformance/test_protos/test_messages_edition2023.pb.h"
21 #include "editions/golden/test_messages_proto2_editions.pb.h"
22 #include "editions/golden/test_messages_proto3_editions.pb.h"
23 #include "google/protobuf/test_messages_proto2.pb.h"
24 #include "google/protobuf/test_messages_proto3.pb.h"
25 #include "google/protobuf/text_format.h"
26
27 using conformance::ConformanceRequest;
28 using conformance::ConformanceResponse;
29 using conformance::TestStatus;
30 using conformance::WireFormat;
31 using protobuf_test_messages::editions::TestAllTypesEdition2023;
32 using protobuf_test_messages::proto2::TestAllTypesProto2;
33 using protobuf_test_messages::proto2::UnknownToTestAllTypes;
34 using protobuf_test_messages::proto3::TestAllTypesProto3;
35 using TestAllTypesProto2Editions =
36 protobuf_test_messages::editions::proto2::TestAllTypesProto2;
37 using TestAllTypesProto3Editions =
38 protobuf_test_messages::editions::proto3::TestAllTypesProto3;
39
40 namespace google {
41 namespace protobuf {
42
43 // The number of repetitions to use for performance tests.
44 // Corresponds approx to 500KB wireformat bytes.
45 static const size_t kPerformanceRepeatCount = 50000;
46
TextFormatConformanceTestSuite()47 TextFormatConformanceTestSuite::TextFormatConformanceTestSuite() {
48 SetFailureListFlagName("--text_format_failure_list");
49 }
50
ParseTextFormatResponse(const ConformanceResponse & response,const ConformanceRequestSetting & setting,Message * test_message)51 bool TextFormatConformanceTestSuite::ParseTextFormatResponse(
52 const ConformanceResponse& response,
53 const ConformanceRequestSetting& setting, Message* test_message) {
54 TextFormat::Parser parser;
55 const ConformanceRequest& request = setting.GetRequest();
56 if (request.print_unknown_fields()) {
57 parser.AllowFieldNumber(true);
58 }
59 if (!parser.ParseFromString(response.text_payload(), test_message)) {
60 ABSL_LOG(ERROR) << "INTERNAL ERROR: internal text->protobuf transcode "
61 << "yielded unparseable proto. Text payload: "
62 << response.text_payload();
63 return false;
64 }
65
66 return true;
67 }
68
ParseResponse(const ConformanceResponse & response,const ConformanceRequestSetting & setting,Message * test_message)69 bool TextFormatConformanceTestSuite::ParseResponse(
70 const ConformanceResponse& response,
71 const ConformanceRequestSetting& setting, Message* test_message) {
72 const ConformanceRequest& request = setting.GetRequest();
73 WireFormat requested_output = request.requested_output_format();
74 const std::string& test_name = setting.GetTestName();
75 ConformanceLevel level = setting.GetLevel();
76
77 TestStatus test;
78 test.set_name(test_name);
79 switch (response.result_case()) {
80 case ConformanceResponse::kProtobufPayload: {
81 if (requested_output != conformance::PROTOBUF) {
82 test.set_failure_message(absl::StrCat(
83 "Test was asked for ", WireFormatToString(requested_output),
84 " output but provided PROTOBUF instead."));
85 ReportFailure(test, level, request, response);
86 return false;
87 }
88
89 if (!test_message->ParseFromString(response.protobuf_payload())) {
90 test.set_failure_message(
91 "Protobuf output we received from test was unparseable.");
92 ReportFailure(test, level, request, response);
93 return false;
94 }
95
96 break;
97 }
98
99 case ConformanceResponse::kTextPayload: {
100 if (requested_output != conformance::TEXT_FORMAT) {
101 test.set_failure_message(absl::StrCat(
102 "Test was asked for ", WireFormatToString(requested_output),
103 " output but provided TEXT_FORMAT instead."));
104 ReportFailure(test, level, request, response);
105 return false;
106 }
107
108 if (!ParseTextFormatResponse(response, setting, test_message)) {
109 test.set_failure_message(
110 "TEXT_FORMAT output we received from test was unparseable.");
111 ReportFailure(test, level, request, response);
112 return false;
113 }
114
115 break;
116 }
117
118 default:
119 ABSL_LOG(FATAL) << test_name
120 << ": unknown payload type: " << response.result_case();
121 }
122
123 return true;
124 }
125
RunSuiteImpl()126 void TextFormatConformanceTestSuite::RunSuiteImpl() {
127 TextFormatConformanceTestSuiteImpl<TestAllTypesProto2>(this);
128 TextFormatConformanceTestSuiteImpl<TestAllTypesProto3>(this);
129 if (maximum_edition_ >= Edition::EDITION_2023) {
130 TextFormatConformanceTestSuiteImpl<TestAllTypesProto2Editions>(this);
131 TextFormatConformanceTestSuiteImpl<TestAllTypesProto3Editions>(this);
132 TextFormatConformanceTestSuiteImpl<TestAllTypesEdition2023>(this);
133 }
134 }
135
136 template <typename MessageType>
137 TextFormatConformanceTestSuiteImpl<MessageType>::
TextFormatConformanceTestSuiteImpl(TextFormatConformanceTestSuite * suite)138 TextFormatConformanceTestSuiteImpl(TextFormatConformanceTestSuite* suite)
139 : suite_(*ABSL_DIE_IF_NULL(suite)) {
140 // Flag control performance tests to keep them internal and opt-in only
141 if (suite_.performance_) {
142 if (MessageType::GetDescriptor()->name() == "TestAllTypesEdition2023") {
143 // There are no editions-sensitive performance tests.
144 return;
145 }
146 RunTextFormatPerformanceTests();
147 } else {
148 if (MessageType::GetDescriptor()->name() == "TestAllTypesProto2") {
149 RunGroupTests();
150 RunClosedEnumTests();
151 }
152 if (MessageType::GetDescriptor()->name() == "TestAllTypesEdition2023") {
153 RunDelimitedTests();
154 }
155 if (MessageType::GetDescriptor()->name() == "TestAllTypesProto3") {
156 RunAnyTests();
157 RunOpenEnumTests();
158 // TODO Run these over proto2 also.
159 RunAllTests();
160 }
161 }
162 }
163
164 template <typename MessageType>
ExpectParseFailure(const std::string & test_name,ConformanceLevel level,const std::string & input)165 void TextFormatConformanceTestSuiteImpl<MessageType>::ExpectParseFailure(
166 const std::string& test_name, ConformanceLevel level,
167 const std::string& input) {
168 MessageType prototype;
169 // We don't expect output, but if the program erroneously accepts the protobuf
170 // we let it send its response as this. We must not leave it unspecified.
171 ConformanceRequestSetting setting(
172 level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
173 conformance::TEXT_FORMAT_TEST, prototype, test_name, input);
174 const ConformanceRequest& request = setting.GetRequest();
175 ConformanceResponse response;
176 std::string effective_test_name = absl::StrCat(
177 setting.ConformanceLevelToString(level), ".",
178 setting.GetSyntaxIdentifier(), ".TextFormatInput.", test_name);
179
180 if (!suite_.RunTest(effective_test_name, request, &response)) {
181 return;
182 }
183
184 TestStatus test;
185 test.set_name(effective_test_name);
186 if (response.result_case() == ConformanceResponse::kParseError) {
187 suite_.ReportSuccess(test);
188 } else if (response.result_case() == ConformanceResponse::kSkipped) {
189 suite_.ReportSkip(test, request, response);
190 } else {
191 test.set_failure_message("Should have failed to parse, but didn't.");
192 suite_.ReportFailure(test, level, request, response);
193 }
194 }
195
196 template <typename MessageType>
RunValidTextFormatTest(const std::string & test_name,ConformanceLevel level,const std::string & input_text)197 void TextFormatConformanceTestSuiteImpl<MessageType>::RunValidTextFormatTest(
198 const std::string& test_name, ConformanceLevel level,
199 const std::string& input_text) {
200 MessageType prototype;
201 RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype);
202 }
203
204 template <typename MessageType>
205 void TextFormatConformanceTestSuiteImpl<MessageType>::
RunValidTextFormatTestWithMessage(const std::string & test_name,ConformanceLevel level,const std::string & input_text,const Message & message)206 RunValidTextFormatTestWithMessage(const std::string& test_name,
207 ConformanceLevel level,
208 const std::string& input_text,
209 const Message& message) {
210 ConformanceRequestSetting setting1(
211 level, conformance::TEXT_FORMAT, conformance::PROTOBUF,
212 conformance::TEXT_FORMAT_TEST, message, test_name, input_text);
213 suite_.RunValidInputTest(setting1, input_text);
214 ConformanceRequestSetting setting2(
215 level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
216 conformance::TEXT_FORMAT_TEST, message, test_name, input_text);
217 suite_.RunValidInputTest(setting2, input_text);
218 }
219
220 template <typename MessageType>
221 void TextFormatConformanceTestSuiteImpl<MessageType>::
RunValidTextFormatTestWithExpected(const std::string & test_name,ConformanceLevel level,const std::string & input_text,const std::string & expected_text)222 RunValidTextFormatTestWithExpected(const std::string& test_name,
223 ConformanceLevel level,
224 const std::string& input_text,
225 const std::string& expected_text) {
226 MessageType prototype;
227 ConformanceRequestSetting setting1(
228 level, conformance::TEXT_FORMAT, conformance::PROTOBUF,
229 conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
230 suite_.RunValidInputTest(setting1, expected_text);
231 ConformanceRequestSetting setting2(
232 level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
233 conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
234 suite_.RunValidInputTest(setting2, expected_text);
235 }
236
237 template <typename MessageType>
238 void TextFormatConformanceTestSuiteImpl<
RunValidUnknownTextFormatTest(const std::string & test_name,const Message & message)239 MessageType>::RunValidUnknownTextFormatTest(const std::string& test_name,
240 const Message& message) {
241 std::string serialized_input;
242 message.SerializeToString(&serialized_input);
243 MessageType prototype;
244 ConformanceRequestSetting setting1(
245 RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
246 conformance::TEXT_FORMAT_TEST, prototype,
247 absl::StrCat(test_name, "_Drop"), serialized_input);
248 setting1.SetPrototypeMessageForCompare(message);
249 suite_.RunValidBinaryInputTest(setting1, "");
250
251 ConformanceRequestSetting setting2(
252 RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT,
253 conformance::TEXT_FORMAT_TEST, prototype,
254 absl::StrCat(test_name, "_Print"), serialized_input);
255 setting2.SetPrototypeMessageForCompare(message);
256 setting2.SetPrintUnknownFields(true);
257 suite_.RunValidBinaryInputTest(setting2, serialized_input);
258 }
259
260 template <typename MessageType>
RunDelimitedTests()261 void TextFormatConformanceTestSuiteImpl<MessageType>::RunDelimitedTests() {
262 RunValidTextFormatTest("GroupFieldNoColon", REQUIRED,
263 "GroupLikeType { group_int32: 1 }");
264 RunValidTextFormatTest("GroupFieldWithColon", REQUIRED,
265 "GroupLikeType: { group_int32: 1 }");
266 RunValidTextFormatTest("GroupFieldEmpty", REQUIRED, "GroupLikeType {}");
267 RunValidTextFormatTest(
268 "GroupFieldExtension", REQUIRED,
269 "[protobuf_test_messages.editions.groupliketype] { c: 1 }");
270 RunValidTextFormatTest(
271 "DelimitedFieldExtension", REQUIRED,
272 "[protobuf_test_messages.editions.delimited_ext] { c: 1 }");
273
274
275 // Test that lower-cased group name (i.e. implicit field name) are accepted.
276 RunValidTextFormatTest("DelimitedFieldLowercased", REQUIRED,
277 "groupliketype { group_int32: 1 }");
278 RunValidTextFormatTest("DelimitedFieldLowercasedDifferent", REQUIRED,
279 "delimited_field { group_int32: 1 }");
280
281 // Extensions always used the field name, and should never accept the message
282 // name.
283 ExpectParseFailure(
284 "DelimitedFieldExtensionMessageName", REQUIRED,
285 "[protobuf_test_messages.editions.GroupLikeType] { group_int32: 1 }");
286 }
287
288 template <typename MessageType>
RunGroupTests()289 void TextFormatConformanceTestSuiteImpl<MessageType>::RunGroupTests() {
290 RunValidTextFormatTest("GroupFieldNoColon", REQUIRED,
291 "Data { group_int32: 1 }");
292 RunValidTextFormatTest("GroupFieldWithColon", REQUIRED,
293 "Data: { group_int32: 1 }");
294 RunValidTextFormatTest("GroupFieldEmpty", REQUIRED, "Data {}");
295 RunValidTextFormatTest("GroupFieldMultiWord", REQUIRED,
296 "MultiWordGroupField { group_int32: 1 }");
297
298 // Test that lower-cased group name (i.e. implicit field name) is accepted
299 RunValidTextFormatTest("GroupFieldLowercased", REQUIRED,
300 "data { group_int32: 1 }");
301 RunValidTextFormatTest("GroupFieldLowercasedMultiWord", REQUIRED,
302 "multiwordgroupfield { group_int32: 1 }");
303
304 // Test extensions of group type
305 RunValidTextFormatTest("GroupFieldExtension", REQUIRED,
306 absl::StrFormat("[%s] { group_int32: 1 }",
307 MessageType::GetDescriptor()
308 ->file()
309 ->FindExtensionByName("groupfield")
310 ->PrintableNameForExtension()));
311 ExpectParseFailure("GroupFieldExtensionGroupName", REQUIRED,
312 absl::StrFormat("[%s] { group_int32: 1 }",
313 MessageType::GetDescriptor()
314 ->file()
315 ->FindMessageTypeByName("GroupField")
316 ->full_name()));
317 }
318
319 template <typename MessageType>
RunAllTests()320 void TextFormatConformanceTestSuiteImpl<MessageType>::RunAllTests() {
321 RunValidTextFormatTest("HelloWorld", REQUIRED,
322 "optional_string: 'Hello, World!'");
323 // Integer fields.
324 RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED,
325 "optional_int32: 2147483647");
326 RunValidTextFormatTest("Int32FieldMinValue", REQUIRED,
327 "optional_int32: -2147483648");
328 RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED,
329 "optional_uint32: 4294967295");
330 RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED,
331 "optional_int64: 9223372036854775807");
332 RunValidTextFormatTest("Int64FieldMinValue", REQUIRED,
333 "optional_int64: -9223372036854775808");
334 RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED,
335 "optional_uint64: 18446744073709551615");
336 // Integer fields - Hex
337 RunValidTextFormatTestWithExpected("Int32FieldMaxValueHex", REQUIRED,
338 "optional_int32: 0x7FFFFFFF",
339 "optional_int32: 2147483647");
340 RunValidTextFormatTestWithExpected("Int32FieldMinValueHex", REQUIRED,
341 "optional_int32: -0x80000000",
342 "optional_int32: -2147483648");
343 RunValidTextFormatTestWithExpected("Uint32FieldMaxValueHex", REQUIRED,
344 "optional_uint32: 0xFFFFFFFF",
345 "optional_uint32: 4294967295");
346 RunValidTextFormatTestWithExpected("Int64FieldMaxValueHex", REQUIRED,
347 "optional_int64: 0x7FFFFFFFFFFFFFFF",
348 "optional_int64: 9223372036854775807");
349 RunValidTextFormatTestWithExpected("Int64FieldMinValueHex", REQUIRED,
350 "optional_int64: -0x8000000000000000",
351 "optional_int64: -9223372036854775808");
352 RunValidTextFormatTestWithExpected("Uint64FieldMaxValueHex", REQUIRED,
353 "optional_uint64: 0xFFFFFFFFFFFFFFFF",
354 "optional_uint64: 18446744073709551615");
355 // Integer fields - Octal
356 RunValidTextFormatTestWithExpected("Int32FieldMaxValueOctal", REQUIRED,
357 "optional_int32: 017777777777",
358 "optional_int32: 2147483647");
359 RunValidTextFormatTestWithExpected("Int32FieldMinValueOctal", REQUIRED,
360 "optional_int32: -020000000000",
361 "optional_int32: -2147483648");
362 RunValidTextFormatTestWithExpected("Uint32FieldMaxValueOctal", REQUIRED,
363 "optional_uint32: 037777777777",
364 "optional_uint32: 4294967295");
365 RunValidTextFormatTestWithExpected("Int64FieldMaxValueOctal", REQUIRED,
366 "optional_int64: 0777777777777777777777",
367 "optional_int64: 9223372036854775807");
368 RunValidTextFormatTestWithExpected("Int64FieldMinValueOctal", REQUIRED,
369 "optional_int64: -01000000000000000000000",
370 "optional_int64: -9223372036854775808");
371 RunValidTextFormatTestWithExpected("Uint64FieldMaxValueOctal", REQUIRED,
372 "optional_uint64: 01777777777777777777777",
373 "optional_uint64: 18446744073709551615");
374
375 // Parsers reject out-of-bound integer values.
376 ExpectParseFailure("Int32FieldTooLarge", REQUIRED,
377 "optional_int32: 2147483648");
378 ExpectParseFailure("Int32FieldTooSmall", REQUIRED,
379 "optional_int32: -2147483649");
380 ExpectParseFailure("Uint32FieldTooLarge", REQUIRED,
381 "optional_uint32: 4294967296");
382 ExpectParseFailure("Int64FieldTooLarge", REQUIRED,
383 "optional_int64: 9223372036854775808");
384 ExpectParseFailure("Int64FieldTooSmall", REQUIRED,
385 "optional_int64: -9223372036854775809");
386 ExpectParseFailure("Uint64FieldTooLarge", REQUIRED,
387 "optional_uint64: 18446744073709551616");
388 // Parsers reject out-of-bound integer values - Hex
389 ExpectParseFailure("Int32FieldTooLargeHex", REQUIRED,
390 "optional_int32: 0x80000000");
391 ExpectParseFailure("Int32FieldTooSmallHex", REQUIRED,
392 "optional_int32: -0x80000001");
393 ExpectParseFailure("Uint32FieldTooLargeHex", REQUIRED,
394 "optional_uint32: 0x100000000");
395 ExpectParseFailure("Int64FieldTooLargeHex", REQUIRED,
396 "optional_int64: 0x8000000000000000");
397 ExpectParseFailure("Int64FieldTooSmallHex", REQUIRED,
398 "optional_int64: -0x8000000000000001");
399 ExpectParseFailure("Uint64FieldTooLargeHex", REQUIRED,
400 "optional_uint64: 0x10000000000000000");
401 // Parsers reject out-of-bound integer values - Octal
402 ExpectParseFailure("Int32FieldTooLargeOctal", REQUIRED,
403 "optional_int32: 020000000000");
404 ExpectParseFailure("Int32FieldTooSmallOctal", REQUIRED,
405 "optional_int32: -020000000001");
406 ExpectParseFailure("Uint32FieldTooLargeOctal", REQUIRED,
407 "optional_uint32: 040000000000");
408 ExpectParseFailure("Int64FieldTooLargeOctal", REQUIRED,
409 "optional_int64: 01000000000000000000000");
410 ExpectParseFailure("Int64FieldTooSmallOctal", REQUIRED,
411 "optional_int64: -01000000000000000000001");
412 ExpectParseFailure("Uint64FieldTooLargeOctal", REQUIRED,
413 "optional_uint64: 02000000000000000000000");
414
415 // Floating point fields
416 for (const auto& suffix : std::vector<std::string>{"", "f", "F"}) {
417 const std::string name_suffix =
418 suffix.empty() ? "" : absl::StrCat("_", suffix);
419
420 RunValidTextFormatTest(absl::StrCat("FloatField", name_suffix), REQUIRED,
421 absl::StrCat("optional_float: 3.192837", suffix));
422 RunValidTextFormatTestWithExpected(
423 absl::StrCat("FloatFieldZero", name_suffix), REQUIRED,
424 absl::StrCat("optional_float: 0", suffix),
425 "" /* implicit presence, so zero means unset*/);
426 RunValidTextFormatTest(absl::StrCat("FloatFieldNegative", name_suffix),
427 REQUIRED,
428 absl::StrCat("optional_float: -3.192837", suffix));
429 RunValidTextFormatTest(
430 absl::StrCat("FloatFieldWithVeryPreciseNumber", name_suffix), REQUIRED,
431 absl::StrCat("optional_float: 3.123456789123456789", suffix));
432 RunValidTextFormatTest(
433 absl::StrCat("FloatFieldMaxValue", name_suffix), REQUIRED,
434 absl::StrCat("optional_float: 3.4028235e+38", suffix));
435 RunValidTextFormatTest(absl::StrCat("FloatFieldMinValue", name_suffix),
436 REQUIRED,
437 absl::StrCat("optional_float: 1.17549e-38", suffix));
438 RunValidTextFormatTest(absl::StrCat("FloatFieldWithInt32Max", name_suffix),
439 REQUIRED,
440 absl::StrCat("optional_float: 4294967296", suffix));
441 RunValidTextFormatTest(
442 absl::StrCat("FloatFieldLargerThanInt64", name_suffix), REQUIRED,
443 absl::StrCat("optional_float: 9223372036854775808", suffix));
444 RunValidTextFormatTest(
445 absl::StrCat("FloatFieldTooLarge", name_suffix), REQUIRED,
446 absl::StrCat("optional_float: 3.4028235e+39", suffix));
447 RunValidTextFormatTest(absl::StrCat("FloatFieldTooSmall", name_suffix),
448 REQUIRED,
449 absl::StrCat("optional_float: 1.17549e-39", suffix));
450 RunValidTextFormatTest(
451 absl::StrCat("FloatFieldLargerThanUint64", name_suffix), REQUIRED,
452 absl::StrCat("optional_float: 18446744073709551616", suffix));
453 // https://protobuf.dev/reference/protobuf/textformat-spec/#literals says
454 // "-0" is a valid float literal. -0 should be considered not the same as 0
455 // when considering implicit presence, and so should round trip.
456 RunValidTextFormatTest(absl::StrCat("FloatFieldNegativeZero", name_suffix),
457 REQUIRED,
458 absl::StrCat("optional_float: -0", suffix));
459 // https://protobuf.dev/reference/protobuf/textformat-spec/#literals says
460 // ".123", "-.123", ".123e2" are a valid float literal.
461 RunValidTextFormatTest(absl::StrCat("FloatFieldNoLeadingZero", name_suffix),
462 REQUIRED,
463 absl::StrCat("optional_float: .123", suffix));
464 RunValidTextFormatTest(
465 absl::StrCat("FloatFieldNegativeNoLeadingZero", name_suffix), REQUIRED,
466 absl::StrCat("optional_float: -.123", suffix));
467 RunValidTextFormatTest(
468 absl::StrCat("FloatFieldNoLeadingZeroWithExponent", name_suffix),
469 REQUIRED, absl::StrCat("optional_float: .123e2", suffix));
470 }
471 // https://protobuf.dev/reference/protobuf/textformat-spec/#value say case
472 // doesn't matter for special values, test a few
473 for (const auto& value : std::vector<std::string>{"nan", "NaN", "nAn"}) {
474 RunValidTextFormatTest(absl::StrCat("FloatFieldValue_", value), REQUIRED,
475 absl::StrCat("optional_float: ", value));
476 }
477 for (const auto& value : std::vector<std::string>{
478 "inf", "infinity", "INF", "INFINITY", "iNF", "inFINITY"}) {
479 RunValidTextFormatTest(absl::StrCat("FloatFieldValue_Pos", value), REQUIRED,
480 absl::StrCat("optional_float: ", value));
481 RunValidTextFormatTest(absl::StrCat("FloatFieldValue_Neg", value), REQUIRED,
482 absl::StrCat("optional_float: -", value));
483 }
484 // https://protobuf.dev/reference/protobuf/textformat-spec/#numeric and
485 // https://protobuf.dev/reference/protobuf/textformat-spec/#value says
486 // hex or octal float literals are invalid.
487 ExpectParseFailure("FloatFieldNoHex", REQUIRED, "optional_float: 0x1");
488 ExpectParseFailure("FloatFieldNoNegativeHex", REQUIRED,
489 "optional_float: -0x1");
490 ExpectParseFailure("FloatFieldNoOctal", REQUIRED, "optional_float: 012");
491 ExpectParseFailure("FloatFieldNoNegativeOctal", REQUIRED,
492 "optional_float: -012");
493 // https://protobuf.dev/reference/protobuf/textformat-spec/#value says
494 // overflows are mapped to infinity/-infinity.
495 RunValidTextFormatTestWithExpected("FloatFieldOverflowInfinity", REQUIRED,
496 "optional_float: 1e50",
497 "optional_float: inf");
498 RunValidTextFormatTestWithExpected("FloatFieldOverflowNegativeInfinity",
499 REQUIRED, "optional_float: -1e50",
500 "optional_float: -inf");
501 RunValidTextFormatTestWithExpected("DoubleFieldOverflowInfinity", REQUIRED,
502 "optional_double: 1e9999",
503 "optional_double: inf");
504 RunValidTextFormatTestWithExpected("DoubleFieldOverflowNegativeInfinity",
505 REQUIRED, "optional_double: -1e9999",
506 "optional_double: -inf");
507 // Exponent is one more than uint64 max.
508 RunValidTextFormatTestWithExpected(
509 "FloatFieldOverflowInfinityHugeExponent", REQUIRED,
510 "optional_float: 1e18446744073709551616", "optional_float: inf");
511 RunValidTextFormatTestWithExpected(
512 "DoubleFieldOverflowInfinityHugeExponent", REQUIRED,
513 "optional_double: 1e18446744073709551616", "optional_double: inf");
514 RunValidTextFormatTestWithExpected(
515 "DoubleFieldLargeNegativeExponentParsesAsZero", REQUIRED,
516 "optional_double: 1e-18446744073709551616", "");
517 RunValidTextFormatTestWithExpected(
518 "NegDoubleFieldLargeNegativeExponentParsesAsNegZero", REQUIRED,
519 "optional_double: -1e-18446744073709551616", "optional_double: -0");
520
521 RunValidTextFormatTestWithExpected(
522 "FloatFieldLargeNegativeExponentParsesAsZero", REQUIRED,
523 "optional_float: 1e-50", "");
524 RunValidTextFormatTestWithExpected(
525 "NegFloatFieldLargeNegativeExponentParsesAsNegZero", REQUIRED,
526 "optional_float: -1e-50", "optional_float: -0");
527
528 // String literals x {Strings, Bytes}
529 for (const auto& field_type : std::vector<std::string>{"String", "Bytes"}) {
530 const std::string field_name =
531 field_type == "String" ? "optional_string" : "optional_bytes";
532 RunValidTextFormatTest(
533 absl::StrCat("StringLiteralConcat", field_type), REQUIRED,
534 absl::StrCat(field_name, ": 'first' \"second\"\n'third'"));
535 RunValidTextFormatTest(
536 absl::StrCat("StringLiteralBasicEscapes", field_type), REQUIRED,
537 absl::StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'"));
538 RunValidTextFormatTest(
539 absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED,
540 absl::StrCat(field_name, ": '\\341\\210\\264'"));
541 RunValidTextFormatTest(absl::StrCat("StringLiteralHexEscapes", field_type),
542 REQUIRED,
543 absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'"));
544 RunValidTextFormatTest(
545 absl::StrCat("StringLiteralShortUnicodeEscape", field_type),
546 RECOMMENDED, absl::StrCat(field_name, ": '\\u1234'"));
547 RunValidTextFormatTest(
548 absl::StrCat("StringLiteralLongUnicodeEscapes", field_type),
549 RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'"));
550 // String literals don't include line feeds.
551 ExpectParseFailure(absl::StrCat("StringLiteralIncludesLF", field_type),
552 REQUIRED,
553 absl::StrCat(field_name, ": 'first line\nsecond line'"));
554 // Unicode escapes don't include code points that lie beyond the planes
555 // (> 0x10ffff).
556 ExpectParseFailure(
557 absl::StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type),
558 REQUIRED, absl::StrCat(field_name, ": '\\U00110000'"));
559 // Unicode escapes don't include surrogates.
560 ExpectParseFailure(
561 absl::StrCat("StringLiteralShortUnicodeEscapeSurrogatePair",
562 field_type),
563 RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\udc37'"));
564 ExpectParseFailure(
565 absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly",
566 field_type),
567 RECOMMENDED, absl::StrCat(field_name, ": '\\ud800'"));
568 ExpectParseFailure(
569 absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly",
570 field_type),
571 RECOMMENDED, absl::StrCat(field_name, ": '\\udc00'"));
572 ExpectParseFailure(
573 absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly",
574 field_type),
575 RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d800'"));
576 ExpectParseFailure(
577 absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly",
578 field_type),
579 RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'"));
580 ExpectParseFailure(
581 absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type),
582 RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'"));
583 ExpectParseFailure(
584 absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort",
585 field_type),
586 RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\udc37'"));
587 ExpectParseFailure(
588 absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong",
589 field_type),
590 RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\U0000dc37'"));
591
592 // The following method depend on the type of field, as strings have extra
593 // validation.
594 const auto test_method =
595 field_type == "String"
596 ? &TextFormatConformanceTestSuiteImpl::ExpectParseFailure
597 : &TextFormatConformanceTestSuiteImpl::RunValidTextFormatTest;
598
599 // String fields reject invalid UTF-8 byte sequences; bytes fields don't.
600 (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"),
601 REQUIRED, absl::StrCat(field_name, ": '\\300'"));
602 (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"), REQUIRED,
603 absl::StrCat(field_name, ": '\\xc0'"));
604 }
605
606 // Separators
607 for (const auto& test_case : std::vector<std::pair<std::string, std::string>>{
608 {"string", "\"abc\""},
609 {"bytes", "\"abc\""},
610 {"int32", "123"},
611 {"bool", "true"},
612 {"double", "1.23"},
613 {"fixed32", "0x123"},
614 }) {
615 // Optional Field Separators
616 for (const auto& field_type :
617 std::vector<std::string>{"Single", "Repeated"}) {
618 std::string field_name, field_value;
619 if (field_type == "Single") {
620 field_name = absl::StrCat("optional_", test_case.first);
621 field_value = test_case.second;
622 } else {
623 field_name = absl::StrCat("repeated_", test_case.first);
624 field_value = absl::StrCat("[", test_case.second, "]");
625 }
626
627 RunValidTextFormatTest(absl::StrCat("FieldSeparatorCommaTopLevel",
628 field_type, "_", test_case.first),
629 REQUIRED,
630 absl::StrCat(field_name, ": ", field_value, ","));
631 RunValidTextFormatTest(absl::StrCat("FieldSeparatorSemiTopLevelSingle",
632 field_type, "_", test_case.first),
633 REQUIRED,
634 absl::StrCat(field_name, ": ", field_value, ";"));
635
636 ExpectParseFailure(
637 absl::StrCat("FieldSeparatorCommaTopLevelDuplicatesFails", field_type,
638 "_", test_case.first),
639 REQUIRED, absl::StrCat(field_name, ": ", field_value, ",,"));
640 ExpectParseFailure(
641 absl::StrCat("FieldSeparatorSemiTopLevelDuplicateFails", field_type,
642 "_", test_case.first),
643 REQUIRED, absl::StrCat(field_name, ": ", field_value, ";;"));
644 }
645
646 // Required List Separators
647 RunValidTextFormatTest(
648 absl::StrCat("ListSeparator_", test_case.first), REQUIRED,
649 absl::StrCat("repeated_", test_case.first, ": [", test_case.second, ",",
650 test_case.second, "]"));
651 ExpectParseFailure(
652 absl::StrCat("ListSeparatorSemiFails_", test_case.first), REQUIRED,
653 absl::StrCat("repeated_", test_case.first, ": [", test_case.second, ";",
654 test_case.second, "]"));
655 // For string and bytes, if we skip the separator, the parser will treat
656 // the two values as a single value.
657 if (test_case.first == "string" || test_case.first == "bytes") {
658 RunValidTextFormatTest(
659 absl::StrCat("ListSeparatorMissingIsOneValue_", test_case.first),
660 REQUIRED,
661 absl::StrCat("repeated_", test_case.first, ": [", test_case.second,
662 " ", test_case.second, "]"));
663 } else {
664 ExpectParseFailure(
665 absl::StrCat("ListSeparatorMissingFails_", test_case.first), REQUIRED,
666 absl::StrCat("repeated_", test_case.first, ": [", test_case.second,
667 " ", test_case.second, "]"));
668 }
669 ExpectParseFailure(
670 absl::StrCat("ListSeparatorDuplicateFails_", test_case.first), REQUIRED,
671 absl::StrCat("repeated_", test_case.first, ": [", test_case.second,
672 ",,", test_case.second, "]"));
673 ExpectParseFailure(
674 absl::StrCat("ListSeparatorSingleTrailingFails_", test_case.first),
675 REQUIRED,
676 absl::StrCat("repeated_", test_case.first, ": [", test_case.second,
677 ",]"));
678 ExpectParseFailure(
679 absl::StrCat("ListSeparatorTwoValuesTrailingFails_", test_case.first),
680 REQUIRED,
681 absl::StrCat("repeated_", test_case.first, ": [", test_case.second, ",",
682 test_case.second, ",]"));
683 }
684 // The test message don't really have all types nested, so just check one
685 // data type for the nested field separator support
686 RunValidTextFormatTest("FieldSeparatorCommaNested", REQUIRED,
687 "optional_nested_message: { a: 123, }");
688 RunValidTextFormatTest("FieldSeparatorSemiNested", REQUIRED,
689 "optional_nested_message: { a: 123; }");
690 ExpectParseFailure("FieldSeparatorCommaNestedDuplicates", REQUIRED,
691 "optional_nested_message: { a: 123,, }");
692 ExpectParseFailure("FieldSeparatorSemiNestedDuplicates", REQUIRED,
693 "optional_nested_message: { a: 123;; }");
694
695 // Unknown Fields
696 UnknownToTestAllTypes message;
697 // Unable to print unknown Fixed32/Fixed64 fields as if they are known.
698 // Fixed32/Fixed64 fields are not added in the tests.
699 message.set_optional_int32(123);
700 message.set_optional_string("hello");
701 message.set_optional_bool(true);
702 RunValidUnknownTextFormatTest("ScalarUnknownFields", message);
703
704 message.Clear();
705 message.mutable_nested_message()->set_c(111);
706 RunValidUnknownTextFormatTest("MessageUnknownFields", message);
707
708 message.Clear();
709 message.mutable_optionalgroup()->set_a(321);
710 RunValidUnknownTextFormatTest("GroupUnknownFields", message);
711
712 message.add_repeated_int32(1);
713 message.add_repeated_int32(2);
714 message.add_repeated_int32(3);
715 RunValidUnknownTextFormatTest("RepeatedUnknownFields", message);
716
717 // Map fields
718 MessageType prototype;
719 (*prototype.mutable_map_string_string())["c"] = "value";
720 (*prototype.mutable_map_string_string())["b"] = "value";
721 (*prototype.mutable_map_string_string())["a"] = "value";
722 RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys",
723 REQUIRED,
724 R"(
725 map_string_string {
726 key: "a"
727 value: "value"
728 }
729 map_string_string {
730 key: "b"
731 value: "value"
732 }
733 map_string_string {
734 key: "c"
735 value: "value"
736 }
737 )",
738 prototype);
739
740 prototype.Clear();
741 (*prototype.mutable_map_int32_int32())[3] = 0;
742 (*prototype.mutable_map_int32_int32())[2] = 0;
743 (*prototype.mutable_map_int32_int32())[1] = 0;
744 RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", REQUIRED,
745 R"(
746 map_int32_int32 {
747 key: 1
748 value: 0
749 }
750 map_int32_int32 {
751 key: 2
752 value: 0
753 }
754 map_int32_int32 {
755 key: 3
756 value: 0
757 }
758 )",
759 prototype);
760
761 prototype.Clear();
762 (*prototype.mutable_map_bool_bool())[true] = false;
763 (*prototype.mutable_map_bool_bool())[false] = false;
764 RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", REQUIRED,
765 R"(
766 map_bool_bool {
767 key: false
768 value: false
769 }
770 map_bool_bool {
771 key: true
772 value: false
773 }
774 )",
775 prototype);
776
777 prototype.Clear();
778 ConformanceRequestSetting setting_map(
779 REQUIRED, conformance::TEXT_FORMAT, conformance::PROTOBUF,
780 conformance::TEXT_FORMAT_TEST, prototype, "DuplicateMapKey", R"(
781 map_string_nested_message {
782 key: "duplicate"
783 value: { a: 123 }
784 }
785 map_string_nested_message {
786 key: "duplicate"
787 value: { corecursive: {} }
788 }
789 )");
790 // The last-specified value will be retained in a parsed map
791 suite_.RunValidInputTest(setting_map, R"(
792 map_string_nested_message {
793 key: "duplicate"
794 value: { corecursive: {} }
795 }
796 )");
797 }
798
799 template <typename MessageType>
RunAnyTests()800 void TextFormatConformanceTestSuiteImpl<MessageType>::RunAnyTests() {
801 // Any fields
802 RunValidTextFormatTest("AnyField", REQUIRED,
803 R"(
804 optional_any: {
805 [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3]
806 { optional_int32: 12345
807 }
808 }
809 )");
810 RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED,
811 R"(
812 optional_any: {
813 type_url:
814 "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" value:
815 "\b\271`"
816 }
817 )");
818 ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED,
819 R"(
820 optional_any: {
821 [type.googleapis.com/unknown] {
822 optional_int32: 12345
823 }
824 }
825 )");
826 }
827
828 template <typename MessageType>
829 void TextFormatConformanceTestSuiteImpl<
RunTextFormatPerformanceTests()830 MessageType>::RunTextFormatPerformanceTests() {
831 TestTextFormatPerformanceMergeMessageWithRepeatedField("Bool",
832 "repeated_bool: true");
833 TestTextFormatPerformanceMergeMessageWithRepeatedField(
834 "Double", "repeated_double: 123");
835 TestTextFormatPerformanceMergeMessageWithRepeatedField(
836 "Int32", "repeated_uint32: 123");
837 TestTextFormatPerformanceMergeMessageWithRepeatedField(
838 "Int64", "repeated_uint64: 123");
839 TestTextFormatPerformanceMergeMessageWithRepeatedField(
840 "String", R"(repeated_string: "foo")");
841 TestTextFormatPerformanceMergeMessageWithRepeatedField(
842 "Bytes", R"(repeated_bytes: "foo")");
843 }
844
845 // This is currently considered valid input by some languages but not others
846 template <typename MessageType>
847 void TextFormatConformanceTestSuiteImpl<MessageType>::
TestTextFormatPerformanceMergeMessageWithRepeatedField(const std::string & test_type_name,const std::string & message_field)848 TestTextFormatPerformanceMergeMessageWithRepeatedField(
849 const std::string& test_type_name, const std::string& message_field) {
850 std::string recursive_message =
851 absl::StrCat("recursive_message { ", message_field, " }");
852
853 std::string input;
854 for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
855 absl::StrAppend(&input, recursive_message);
856 }
857
858 std::string expected = "recursive_message { ";
859 for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
860 absl::StrAppend(&expected, message_field, " ");
861 }
862 absl::StrAppend(&expected, "}");
863
864 RunValidTextFormatTestWithExpected(
865 absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField",
866 test_type_name),
867 RECOMMENDED, input, expected);
868 }
869
870 template <typename MessageType>
RunOpenEnumTests()871 void TextFormatConformanceTestSuiteImpl<MessageType>::RunOpenEnumTests() {
872 RunValidTextFormatTest("ClosedEnumFieldByNumber", REQUIRED,
873 R"(
874 optional_nested_enum: 1
875 )");
876 RunValidTextFormatTest("ClosedEnumFieldWithUnknownNumber", REQUIRED,
877 R"(
878 optional_nested_enum: 42
879 )");
880 }
881
882 template <typename MessageType>
RunClosedEnumTests()883 void TextFormatConformanceTestSuiteImpl<MessageType>::RunClosedEnumTests() {
884 RunValidTextFormatTest("ClosedEnumFieldByNumber", REQUIRED,
885 R"(
886 optional_nested_enum: 1
887 )");
888 ExpectParseFailure("ClosedEnumFieldWithUnknownNumber", REQUIRED,
889 R"(
890 optional_nested_enum: 42
891 )");
892 }
893
894 } // namespace protobuf
895 } // namespace google
896