• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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