1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: jschorr@google.com (Joseph Schorr)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <math.h>
36 #include <stdlib.h>
37 #include <limits>
38
39 #include <google/protobuf/text_format.h>
40 #include <google/protobuf/io/zero_copy_stream_impl.h>
41 #include <google/protobuf/io/tokenizer.h>
42 #include <google/protobuf/unittest.pb.h>
43 #include <google/protobuf/unittest_mset.pb.h>
44 #include <google/protobuf/test_util.h>
45
46 #include <google/protobuf/stubs/common.h>
47 #include <google/protobuf/testing/file.h>
48 #include <google/protobuf/testing/googletest.h>
49 #include <gtest/gtest.h>
50 #include <google/protobuf/stubs/strutil.h>
51 #include <google/protobuf/stubs/substitute.h>
52
53 namespace google {
54 namespace protobuf {
55
56 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
57 namespace text_format_unittest {
58
IsNaN(double value)59 inline bool IsNaN(double value) {
60 // NaN is never equal to anything, even itself.
61 return value != value;
62 }
63
64 // A basic string with different escapable characters for testing.
65 const string kEscapeTestString =
66 "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
67 "slashes \\ and multiple spaces";
68
69 // A representation of the above string with all the characters escaped.
70 const string kEscapeTestStringEscaped =
71 "\"\\\"A string with \\' characters \\n and \\r newlines "
72 "and \\t tabs and \\001 slashes \\\\ and multiple spaces\"";
73
74 class TextFormatTest : public testing::Test {
75 public:
SetUpTestCase()76 static void SetUpTestCase() {
77 File::ReadFileToStringOrDie(
78 TestSourceDir()
79 + "/google/protobuf/testdata/text_format_unittest_data.txt",
80 &static_proto_debug_string_);
81 }
82
TextFormatTest()83 TextFormatTest() : proto_debug_string_(static_proto_debug_string_) {}
84
85 protected:
86 // Debug string read from text_format_unittest_data.txt.
87 const string proto_debug_string_;
88 unittest::TestAllTypes proto_;
89
90 private:
91 static string static_proto_debug_string_;
92 };
93 string TextFormatTest::static_proto_debug_string_;
94
95 class TextFormatExtensionsTest : public testing::Test {
96 public:
SetUpTestCase()97 static void SetUpTestCase() {
98 File::ReadFileToStringOrDie(
99 TestSourceDir()
100 + "/google/protobuf/testdata/"
101 "text_format_unittest_extensions_data.txt",
102 &static_proto_debug_string_);
103 }
104
TextFormatExtensionsTest()105 TextFormatExtensionsTest()
106 : proto_debug_string_(static_proto_debug_string_) {}
107
108 protected:
109 // Debug string read from text_format_unittest_data.txt.
110 const string proto_debug_string_;
111 unittest::TestAllExtensions proto_;
112
113 private:
114 static string static_proto_debug_string_;
115 };
116 string TextFormatExtensionsTest::static_proto_debug_string_;
117
118
TEST_F(TextFormatTest,Basic)119 TEST_F(TextFormatTest, Basic) {
120 TestUtil::SetAllFields(&proto_);
121 EXPECT_EQ(proto_debug_string_, proto_.DebugString());
122 }
123
TEST_F(TextFormatExtensionsTest,Extensions)124 TEST_F(TextFormatExtensionsTest, Extensions) {
125 TestUtil::SetAllExtensions(&proto_);
126 EXPECT_EQ(proto_debug_string_, proto_.DebugString());
127 }
128
TEST_F(TextFormatTest,ShortDebugString)129 TEST_F(TextFormatTest, ShortDebugString) {
130 proto_.set_optional_int32(1);
131 proto_.set_optional_string("hello");
132 proto_.mutable_optional_nested_message()->set_bb(2);
133 proto_.mutable_optional_foreign_message();
134
135 EXPECT_EQ("optional_int32: 1 optional_string: \"hello\" "
136 "optional_nested_message { bb: 2 } "
137 "optional_foreign_message { }",
138 proto_.ShortDebugString());
139 }
140
TEST_F(TextFormatTest,ShortPrimitiveRepeateds)141 TEST_F(TextFormatTest, ShortPrimitiveRepeateds) {
142 proto_.set_optional_int32(123);
143 proto_.add_repeated_int32(456);
144 proto_.add_repeated_int32(789);
145 proto_.add_repeated_string("foo");
146 proto_.add_repeated_string("bar");
147 proto_.add_repeated_nested_message()->set_bb(2);
148 proto_.add_repeated_nested_message()->set_bb(3);
149 proto_.add_repeated_nested_enum(unittest::TestAllTypes::FOO);
150 proto_.add_repeated_nested_enum(unittest::TestAllTypes::BAR);
151
152 TextFormat::Printer printer;
153 printer.SetUseShortRepeatedPrimitives(true);
154 string text;
155 printer.PrintToString(proto_, &text);
156
157 EXPECT_EQ("optional_int32: 123\n"
158 "repeated_int32: [456, 789]\n"
159 "repeated_string: \"foo\"\n"
160 "repeated_string: \"bar\"\n"
161 "repeated_nested_message {\n bb: 2\n}\n"
162 "repeated_nested_message {\n bb: 3\n}\n"
163 "repeated_nested_enum: [FOO, BAR]\n",
164 text);
165
166 // Try in single-line mode.
167 printer.SetSingleLineMode(true);
168 printer.PrintToString(proto_, &text);
169
170 EXPECT_EQ("optional_int32: 123 "
171 "repeated_int32: [456, 789] "
172 "repeated_string: \"foo\" "
173 "repeated_string: \"bar\" "
174 "repeated_nested_message { bb: 2 } "
175 "repeated_nested_message { bb: 3 } "
176 "repeated_nested_enum: [FOO, BAR] ",
177 text);
178 }
179
180
TEST_F(TextFormatTest,StringEscape)181 TEST_F(TextFormatTest, StringEscape) {
182 // Set the string value to test.
183 proto_.set_optional_string(kEscapeTestString);
184
185 // Get the DebugString from the proto.
186 string debug_string = proto_.DebugString();
187 string utf8_debug_string = proto_.Utf8DebugString();
188
189 // Hardcode a correct value to test against.
190 string correct_string = "optional_string: "
191 + kEscapeTestStringEscaped
192 + "\n";
193
194 // Compare.
195 EXPECT_EQ(correct_string, debug_string);
196 // UTF-8 string is the same as non-UTF-8 because
197 // the protocol buffer contains no UTF-8 text.
198 EXPECT_EQ(correct_string, utf8_debug_string);
199
200 string expected_short_debug_string = "optional_string: "
201 + kEscapeTestStringEscaped;
202 EXPECT_EQ(expected_short_debug_string, proto_.ShortDebugString());
203 }
204
TEST_F(TextFormatTest,Utf8DebugString)205 TEST_F(TextFormatTest, Utf8DebugString) {
206 // Set the string value to test.
207 proto_.set_optional_string("\350\260\267\346\255\214");
208
209 // Get the DebugString from the proto.
210 string debug_string = proto_.DebugString();
211 string utf8_debug_string = proto_.Utf8DebugString();
212
213 // Hardcode a correct value to test against.
214 string correct_utf8_string = "optional_string: "
215 "\"\350\260\267\346\255\214\""
216 "\n";
217 string correct_string = "optional_string: "
218 "\"\\350\\260\\267\\346\\255\\214\""
219 "\n";
220
221 // Compare.
222 EXPECT_EQ(correct_utf8_string, utf8_debug_string);
223 EXPECT_EQ(correct_string, debug_string);
224 }
225
TEST_F(TextFormatTest,PrintUnknownFields)226 TEST_F(TextFormatTest, PrintUnknownFields) {
227 // Test printing of unknown fields in a message.
228
229 unittest::TestEmptyMessage message;
230 UnknownFieldSet* unknown_fields = message.mutable_unknown_fields();
231
232 unknown_fields->AddVarint(5, 1);
233 unknown_fields->AddFixed32(5, 2);
234 unknown_fields->AddFixed64(5, 3);
235 unknown_fields->AddLengthDelimited(5, "4");
236 unknown_fields->AddGroup(5)->AddVarint(10, 5);
237
238 unknown_fields->AddVarint(8, 1);
239 unknown_fields->AddVarint(8, 2);
240 unknown_fields->AddVarint(8, 3);
241
242 EXPECT_EQ(
243 "5: 1\n"
244 "5: 0x00000002\n"
245 "5: 0x0000000000000003\n"
246 "5: \"4\"\n"
247 "5 {\n"
248 " 10: 5\n"
249 "}\n"
250 "8: 1\n"
251 "8: 2\n"
252 "8: 3\n",
253 message.DebugString());
254 }
255
TEST_F(TextFormatTest,PrintUnknownMessage)256 TEST_F(TextFormatTest, PrintUnknownMessage) {
257 // Test heuristic printing of messages in an UnknownFieldSet.
258
259 protobuf_unittest::TestAllTypes message;
260
261 // Cases which should not be interpreted as sub-messages.
262
263 // 'a' is a valid FIXED64 tag, so for the string to be parseable as a message
264 // it should be followed by 8 bytes. Since this string only has two
265 // subsequent bytes, it should be treated as a string.
266 message.add_repeated_string("abc");
267
268 // 'd' happens to be a valid ENDGROUP tag. So,
269 // UnknownFieldSet::MergeFromCodedStream() will successfully parse "def", but
270 // the ConsumedEntireMessage() check should fail.
271 message.add_repeated_string("def");
272
273 // A zero-length string should never be interpreted as a message even though
274 // it is technically valid as one.
275 message.add_repeated_string("");
276
277 // Case which should be interpreted as a sub-message.
278
279 // An actual nested message with content should always be interpreted as a
280 // nested message.
281 message.add_repeated_nested_message()->set_bb(123);
282
283 string data;
284 message.SerializeToString(&data);
285
286 string text;
287 UnknownFieldSet unknown_fields;
288 EXPECT_TRUE(unknown_fields.ParseFromString(data));
289 EXPECT_TRUE(TextFormat::PrintUnknownFieldsToString(unknown_fields, &text));
290 EXPECT_EQ(
291 "44: \"abc\"\n"
292 "44: \"def\"\n"
293 "44: \"\"\n"
294 "48 {\n"
295 " 1: 123\n"
296 "}\n",
297 text);
298 }
299
TEST_F(TextFormatTest,PrintMessageWithIndent)300 TEST_F(TextFormatTest, PrintMessageWithIndent) {
301 // Test adding an initial indent to printing.
302
303 protobuf_unittest::TestAllTypes message;
304
305 message.add_repeated_string("abc");
306 message.add_repeated_string("def");
307 message.add_repeated_nested_message()->set_bb(123);
308
309 string text;
310 TextFormat::Printer printer;
311 printer.SetInitialIndentLevel(1);
312 EXPECT_TRUE(printer.PrintToString(message, &text));
313 EXPECT_EQ(
314 " repeated_string: \"abc\"\n"
315 " repeated_string: \"def\"\n"
316 " repeated_nested_message {\n"
317 " bb: 123\n"
318 " }\n",
319 text);
320 }
321
TEST_F(TextFormatTest,PrintMessageSingleLine)322 TEST_F(TextFormatTest, PrintMessageSingleLine) {
323 // Test printing a message on a single line.
324
325 protobuf_unittest::TestAllTypes message;
326
327 message.add_repeated_string("abc");
328 message.add_repeated_string("def");
329 message.add_repeated_nested_message()->set_bb(123);
330
331 string text;
332 TextFormat::Printer printer;
333 printer.SetInitialIndentLevel(1);
334 printer.SetSingleLineMode(true);
335 EXPECT_TRUE(printer.PrintToString(message, &text));
336 EXPECT_EQ(
337 " repeated_string: \"abc\" repeated_string: \"def\" "
338 "repeated_nested_message { bb: 123 } ",
339 text);
340 }
341
TEST_F(TextFormatTest,ParseBasic)342 TEST_F(TextFormatTest, ParseBasic) {
343 io::ArrayInputStream input_stream(proto_debug_string_.data(),
344 proto_debug_string_.size());
345 TextFormat::Parse(&input_stream, &proto_);
346 TestUtil::ExpectAllFieldsSet(proto_);
347 }
348
TEST_F(TextFormatExtensionsTest,ParseExtensions)349 TEST_F(TextFormatExtensionsTest, ParseExtensions) {
350 io::ArrayInputStream input_stream(proto_debug_string_.data(),
351 proto_debug_string_.size());
352 TextFormat::Parse(&input_stream, &proto_);
353 TestUtil::ExpectAllExtensionsSet(proto_);
354 }
355
TEST_F(TextFormatTest,ParseStringEscape)356 TEST_F(TextFormatTest, ParseStringEscape) {
357 // Create a parse string with escpaed characters in it.
358 string parse_string = "optional_string: "
359 + kEscapeTestStringEscaped
360 + "\n";
361
362 io::ArrayInputStream input_stream(parse_string.data(),
363 parse_string.size());
364 TextFormat::Parse(&input_stream, &proto_);
365
366 // Compare.
367 EXPECT_EQ(kEscapeTestString, proto_.optional_string());
368 }
369
TEST_F(TextFormatTest,ParseConcatenatedString)370 TEST_F(TextFormatTest, ParseConcatenatedString) {
371 // Create a parse string with multiple parts on one line.
372 string parse_string = "optional_string: \"foo\" \"bar\"\n";
373
374 io::ArrayInputStream input_stream1(parse_string.data(),
375 parse_string.size());
376 TextFormat::Parse(&input_stream1, &proto_);
377
378 // Compare.
379 EXPECT_EQ("foobar", proto_.optional_string());
380
381 // Create a parse string with multiple parts on seperate lines.
382 parse_string = "optional_string: \"foo\"\n"
383 "\"bar\"\n";
384
385 io::ArrayInputStream input_stream2(parse_string.data(),
386 parse_string.size());
387 TextFormat::Parse(&input_stream2, &proto_);
388
389 // Compare.
390 EXPECT_EQ("foobar", proto_.optional_string());
391 }
392
TEST_F(TextFormatTest,ParseFloatWithSuffix)393 TEST_F(TextFormatTest, ParseFloatWithSuffix) {
394 // Test that we can parse a floating-point value with 'f' appended to the
395 // end. This is needed for backwards-compatibility with proto1.
396
397 // Have it parse a float with the 'f' suffix.
398 string parse_string = "optional_float: 1.0f\n";
399
400 io::ArrayInputStream input_stream(parse_string.data(),
401 parse_string.size());
402
403 TextFormat::Parse(&input_stream, &proto_);
404
405 // Compare.
406 EXPECT_EQ(1.0, proto_.optional_float());
407 }
408
TEST_F(TextFormatTest,Comments)409 TEST_F(TextFormatTest, Comments) {
410 // Test that comments are ignored.
411
412 string parse_string = "optional_int32: 1 # a comment\n"
413 "optional_int64: 2 # another comment";
414
415 io::ArrayInputStream input_stream(parse_string.data(),
416 parse_string.size());
417
418 TextFormat::Parse(&input_stream, &proto_);
419
420 // Compare.
421 EXPECT_EQ(1, proto_.optional_int32());
422 EXPECT_EQ(2, proto_.optional_int64());
423 }
424
TEST_F(TextFormatTest,OptionalColon)425 TEST_F(TextFormatTest, OptionalColon) {
426 // Test that we can place a ':' after the field name of a nested message,
427 // even though we don't have to.
428
429 string parse_string = "optional_nested_message: { bb: 1}\n";
430
431 io::ArrayInputStream input_stream(parse_string.data(),
432 parse_string.size());
433
434 TextFormat::Parse(&input_stream, &proto_);
435
436 // Compare.
437 EXPECT_TRUE(proto_.has_optional_nested_message());
438 EXPECT_EQ(1, proto_.optional_nested_message().bb());
439 }
440
441 // Some platforms (e.g. Windows) insist on padding the exponent to three
442 // digits when one or two would be just fine.
RemoveRedundantZeros(string text)443 static string RemoveRedundantZeros(string text) {
444 text = StringReplace(text, "e+0", "e+", true);
445 text = StringReplace(text, "e-0", "e-", true);
446 return text;
447 }
448
TEST_F(TextFormatTest,PrintExotic)449 TEST_F(TextFormatTest, PrintExotic) {
450 unittest::TestAllTypes message;
451
452 // Note: In C, a negative integer literal is actually the unary negation
453 // operator being applied to a positive integer literal, and
454 // 9223372036854775808 is outside the range of int64. However, it is not
455 // outside the range of uint64. Confusingly, this means that everything
456 // works if we make the literal unsigned, even though we are negating it.
457 message.add_repeated_int64(-GOOGLE_ULONGLONG(9223372036854775808));
458 message.add_repeated_uint64(GOOGLE_ULONGLONG(18446744073709551615));
459 message.add_repeated_double(123.456);
460 message.add_repeated_double(1.23e21);
461 message.add_repeated_double(1.23e-18);
462 message.add_repeated_double(std::numeric_limits<double>::infinity());
463 message.add_repeated_double(-std::numeric_limits<double>::infinity());
464 message.add_repeated_double(std::numeric_limits<double>::quiet_NaN());
465 message.add_repeated_string(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12));
466
467 // Fun story: We used to use 1.23e22 instead of 1.23e21 above, but this
468 // seemed to trigger an odd case on MinGW/GCC 3.4.5 where GCC's parsing of
469 // the value differed from strtod()'s parsing. That is to say, the
470 // following assertion fails on MinGW:
471 // assert(1.23e22 == strtod("1.23e22", NULL));
472 // As a result, SimpleDtoa() would print the value as
473 // "1.2300000000000001e+22" to make sure strtod() produce the exact same
474 // result. Our goal is to test runtime parsing, not compile-time parsing,
475 // so this wasn't our problem. It was found that using 1.23e21 did not
476 // have this problem, so we switched to that instead.
477
478 EXPECT_EQ(
479 "repeated_int64: -9223372036854775808\n"
480 "repeated_uint64: 18446744073709551615\n"
481 "repeated_double: 123.456\n"
482 "repeated_double: 1.23e+21\n"
483 "repeated_double: 1.23e-18\n"
484 "repeated_double: inf\n"
485 "repeated_double: -inf\n"
486 "repeated_double: nan\n"
487 "repeated_string: \"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\'\\\"\"\n",
488 RemoveRedundantZeros(message.DebugString()));
489 }
490
TEST_F(TextFormatTest,PrintFloatPrecision)491 TEST_F(TextFormatTest, PrintFloatPrecision) {
492 unittest::TestAllTypes message;
493
494 message.add_repeated_float(1.2);
495 message.add_repeated_float(1.23);
496 message.add_repeated_float(1.234);
497 message.add_repeated_float(1.2345);
498 message.add_repeated_float(1.23456);
499 message.add_repeated_float(1.2e10);
500 message.add_repeated_float(1.23e10);
501 message.add_repeated_float(1.234e10);
502 message.add_repeated_float(1.2345e10);
503 message.add_repeated_float(1.23456e10);
504 message.add_repeated_double(1.2);
505 message.add_repeated_double(1.23);
506 message.add_repeated_double(1.234);
507 message.add_repeated_double(1.2345);
508 message.add_repeated_double(1.23456);
509 message.add_repeated_double(1.234567);
510 message.add_repeated_double(1.2345678);
511 message.add_repeated_double(1.23456789);
512 message.add_repeated_double(1.234567898);
513 message.add_repeated_double(1.2345678987);
514 message.add_repeated_double(1.23456789876);
515 message.add_repeated_double(1.234567898765);
516 message.add_repeated_double(1.2345678987654);
517 message.add_repeated_double(1.23456789876543);
518 message.add_repeated_double(1.2e100);
519 message.add_repeated_double(1.23e100);
520 message.add_repeated_double(1.234e100);
521 message.add_repeated_double(1.2345e100);
522 message.add_repeated_double(1.23456e100);
523 message.add_repeated_double(1.234567e100);
524 message.add_repeated_double(1.2345678e100);
525 message.add_repeated_double(1.23456789e100);
526 message.add_repeated_double(1.234567898e100);
527 message.add_repeated_double(1.2345678987e100);
528 message.add_repeated_double(1.23456789876e100);
529 message.add_repeated_double(1.234567898765e100);
530 message.add_repeated_double(1.2345678987654e100);
531 message.add_repeated_double(1.23456789876543e100);
532
533 EXPECT_EQ(
534 "repeated_float: 1.2\n"
535 "repeated_float: 1.23\n"
536 "repeated_float: 1.234\n"
537 "repeated_float: 1.2345\n"
538 "repeated_float: 1.23456\n"
539 "repeated_float: 1.2e+10\n"
540 "repeated_float: 1.23e+10\n"
541 "repeated_float: 1.234e+10\n"
542 "repeated_float: 1.2345e+10\n"
543 "repeated_float: 1.23456e+10\n"
544 "repeated_double: 1.2\n"
545 "repeated_double: 1.23\n"
546 "repeated_double: 1.234\n"
547 "repeated_double: 1.2345\n"
548 "repeated_double: 1.23456\n"
549 "repeated_double: 1.234567\n"
550 "repeated_double: 1.2345678\n"
551 "repeated_double: 1.23456789\n"
552 "repeated_double: 1.234567898\n"
553 "repeated_double: 1.2345678987\n"
554 "repeated_double: 1.23456789876\n"
555 "repeated_double: 1.234567898765\n"
556 "repeated_double: 1.2345678987654\n"
557 "repeated_double: 1.23456789876543\n"
558 "repeated_double: 1.2e+100\n"
559 "repeated_double: 1.23e+100\n"
560 "repeated_double: 1.234e+100\n"
561 "repeated_double: 1.2345e+100\n"
562 "repeated_double: 1.23456e+100\n"
563 "repeated_double: 1.234567e+100\n"
564 "repeated_double: 1.2345678e+100\n"
565 "repeated_double: 1.23456789e+100\n"
566 "repeated_double: 1.234567898e+100\n"
567 "repeated_double: 1.2345678987e+100\n"
568 "repeated_double: 1.23456789876e+100\n"
569 "repeated_double: 1.234567898765e+100\n"
570 "repeated_double: 1.2345678987654e+100\n"
571 "repeated_double: 1.23456789876543e+100\n",
572 RemoveRedundantZeros(message.DebugString()));
573 }
574
575
TEST_F(TextFormatTest,AllowPartial)576 TEST_F(TextFormatTest, AllowPartial) {
577 unittest::TestRequired message;
578 TextFormat::Parser parser;
579 parser.AllowPartialMessage(true);
580 EXPECT_TRUE(parser.ParseFromString("a: 1", &message));
581 EXPECT_EQ(1, message.a());
582 EXPECT_FALSE(message.has_b());
583 EXPECT_FALSE(message.has_c());
584 }
585
TEST_F(TextFormatTest,ParseExotic)586 TEST_F(TextFormatTest, ParseExotic) {
587 unittest::TestAllTypes message;
588 ASSERT_TRUE(TextFormat::ParseFromString(
589 "repeated_int32: -1\n"
590 "repeated_int32: -2147483648\n"
591 "repeated_int64: -1\n"
592 "repeated_int64: -9223372036854775808\n"
593 "repeated_uint32: 4294967295\n"
594 "repeated_uint32: 2147483648\n"
595 "repeated_uint64: 18446744073709551615\n"
596 "repeated_uint64: 9223372036854775808\n"
597 "repeated_double: 123.0\n"
598 "repeated_double: 123.5\n"
599 "repeated_double: 0.125\n"
600 "repeated_double: 1.23E17\n"
601 "repeated_double: 1.235E+22\n"
602 "repeated_double: 1.235e-18\n"
603 "repeated_double: 123.456789\n"
604 "repeated_double: inf\n"
605 "repeated_double: Infinity\n"
606 "repeated_double: -inf\n"
607 "repeated_double: -Infinity\n"
608 "repeated_double: nan\n"
609 "repeated_double: NaN\n"
610 "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\"\n",
611 &message));
612
613 ASSERT_EQ(2, message.repeated_int32_size());
614 EXPECT_EQ(-1, message.repeated_int32(0));
615 // Note: In C, a negative integer literal is actually the unary negation
616 // operator being applied to a positive integer literal, and 2147483648 is
617 // outside the range of int32. However, it is not outside the range of
618 // uint32. Confusingly, this means that everything works if we make the
619 // literal unsigned, even though we are negating it.
620 EXPECT_EQ(-2147483648u, message.repeated_int32(1));
621
622 ASSERT_EQ(2, message.repeated_int64_size());
623 EXPECT_EQ(-1, message.repeated_int64(0));
624 // Note: In C, a negative integer literal is actually the unary negation
625 // operator being applied to a positive integer literal, and
626 // 9223372036854775808 is outside the range of int64. However, it is not
627 // outside the range of uint64. Confusingly, this means that everything
628 // works if we make the literal unsigned, even though we are negating it.
629 EXPECT_EQ(-GOOGLE_ULONGLONG(9223372036854775808), message.repeated_int64(1));
630
631 ASSERT_EQ(2, message.repeated_uint32_size());
632 EXPECT_EQ(4294967295u, message.repeated_uint32(0));
633 EXPECT_EQ(2147483648u, message.repeated_uint32(1));
634
635 ASSERT_EQ(2, message.repeated_uint64_size());
636 EXPECT_EQ(GOOGLE_ULONGLONG(18446744073709551615), message.repeated_uint64(0));
637 EXPECT_EQ(GOOGLE_ULONGLONG(9223372036854775808), message.repeated_uint64(1));
638
639 ASSERT_EQ(13, message.repeated_double_size());
640 EXPECT_EQ(123.0 , message.repeated_double(0));
641 EXPECT_EQ(123.5 , message.repeated_double(1));
642 EXPECT_EQ(0.125 , message.repeated_double(2));
643 EXPECT_EQ(1.23E17 , message.repeated_double(3));
644 EXPECT_EQ(1.235E22 , message.repeated_double(4));
645 EXPECT_EQ(1.235E-18 , message.repeated_double(5));
646 EXPECT_EQ(123.456789, message.repeated_double(6));
647 EXPECT_EQ(message.repeated_double(7), numeric_limits<double>::infinity());
648 EXPECT_EQ(message.repeated_double(8), numeric_limits<double>::infinity());
649 EXPECT_EQ(message.repeated_double(9), -numeric_limits<double>::infinity());
650 EXPECT_EQ(message.repeated_double(10), -numeric_limits<double>::infinity());
651 EXPECT_TRUE(IsNaN(message.repeated_double(11)));
652 EXPECT_TRUE(IsNaN(message.repeated_double(12)));
653
654 // Note: Since these string literals have \0's in them, we must explicitly
655 // pass their sizes to string's constructor.
656 ASSERT_EQ(1, message.repeated_string_size());
657 EXPECT_EQ(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12),
658 message.repeated_string(0));
659 }
660
661 class TextFormatParserTest : public testing::Test {
662 protected:
ExpectFailure(const string & input,const string & message,int line,int col)663 void ExpectFailure(const string& input, const string& message, int line,
664 int col) {
665 scoped_ptr<unittest::TestAllTypes> proto(new unittest::TestAllTypes);
666 ExpectFailure(input, message, line, col, proto.get());
667 }
668
ExpectFailure(const string & input,const string & message,int line,int col,Message * proto)669 void ExpectFailure(const string& input, const string& message, int line,
670 int col, Message* proto) {
671 ExpectMessage(input, message, line, col, proto, false);
672 }
673
ExpectMessage(const string & input,const string & message,int line,int col,Message * proto,bool expected_result)674 void ExpectMessage(const string& input, const string& message, int line,
675 int col, Message* proto, bool expected_result) {
676 TextFormat::Parser parser;
677 MockErrorCollector error_collector;
678 parser.RecordErrorsTo(&error_collector);
679 EXPECT_EQ(parser.ParseFromString(input, proto), expected_result);
680 EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n",
681 error_collector.text_);
682 }
683
684 // An error collector which simply concatenates all its errors into a big
685 // block of text which can be checked.
686 class MockErrorCollector : public io::ErrorCollector {
687 public:
MockErrorCollector()688 MockErrorCollector() {}
~MockErrorCollector()689 ~MockErrorCollector() {}
690
691 string text_;
692
693 // implements ErrorCollector -------------------------------------
AddError(int line,int column,const string & message)694 void AddError(int line, int column, const string& message) {
695 strings::SubstituteAndAppend(&text_, "$0:$1: $2\n",
696 line + 1, column + 1, message);
697 }
698
AddWarning(int line,int column,const string & message)699 void AddWarning(int line, int column, const string& message) {
700 AddError(line, column, "WARNING:" + message);
701 }
702 };
703 };
704
TEST_F(TextFormatParserTest,ParseFieldValueFromString)705 TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
706 scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
707 const Descriptor* d = message->GetDescriptor();
708
709 #define EXPECT_FIELD(name, value, valuestring) \
710 EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
711 valuestring, d->FindFieldByName("optional_" #name), message.get())); \
712 EXPECT_EQ(value, message->optional_##name()); \
713 EXPECT_TRUE(message->has_optional_##name());
714
715 #define EXPECT_FLOAT_FIELD(name, value, valuestring) \
716 EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
717 valuestring, d->FindFieldByName("optional_" #name), message.get())); \
718 EXPECT_FLOAT_EQ(value, message->optional_##name()); \
719 EXPECT_TRUE(message->has_optional_##name());
720
721 #define EXPECT_DOUBLE_FIELD(name, value, valuestring) \
722 EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \
723 valuestring, d->FindFieldByName("optional_" #name), message.get())); \
724 EXPECT_DOUBLE_EQ(value, message->optional_##name()); \
725 EXPECT_TRUE(message->has_optional_##name());
726
727 #define EXPECT_INVALID(name, valuestring) \
728 EXPECT_FALSE(TextFormat::ParseFieldValueFromString( \
729 valuestring, d->FindFieldByName("optional_" #name), message.get()));
730
731 // int32
732 EXPECT_FIELD(int32, 1, "1");
733 EXPECT_FIELD(int32, -1, "-1");
734 EXPECT_FIELD(int32, 0x1234, "0x1234");
735 EXPECT_INVALID(int32, "a");
736 EXPECT_INVALID(int32, "999999999999999999999999999999999999");
737 EXPECT_INVALID(int32, "1,2");
738
739 // int64
740 EXPECT_FIELD(int64, 1, "1");
741 EXPECT_FIELD(int64, -1, "-1");
742 EXPECT_FIELD(int64, 0x1234567812345678LL, "0x1234567812345678");
743 EXPECT_INVALID(int64, "a");
744 EXPECT_INVALID(int64, "999999999999999999999999999999999999");
745 EXPECT_INVALID(int64, "1,2");
746
747 // uint64
748 EXPECT_FIELD(uint64, 1, "1");
749 EXPECT_FIELD(uint64, 0xf234567812345678ULL, "0xf234567812345678");
750 EXPECT_INVALID(uint64, "-1");
751 EXPECT_INVALID(uint64, "a");
752 EXPECT_INVALID(uint64, "999999999999999999999999999999999999");
753 EXPECT_INVALID(uint64, "1,2");
754
755 // fixed32
756 EXPECT_FIELD(fixed32, 1, "1");
757 EXPECT_FIELD(fixed32, 0x12345678, "0x12345678");
758 EXPECT_INVALID(fixed32, "-1");
759 EXPECT_INVALID(fixed32, "a");
760 EXPECT_INVALID(fixed32, "999999999999999999999999999999999999");
761 EXPECT_INVALID(fixed32, "1,2");
762
763 // fixed64
764 EXPECT_FIELD(fixed64, 1, "1");
765 EXPECT_FIELD(fixed64, 0x1234567812345678ULL, "0x1234567812345678");
766 EXPECT_INVALID(fixed64, "-1");
767 EXPECT_INVALID(fixed64, "a");
768 EXPECT_INVALID(fixed64, "999999999999999999999999999999999999");
769 EXPECT_INVALID(fixed64, "1,2");
770
771 // bool
772 EXPECT_FIELD(bool, true, "true");
773 EXPECT_FIELD(bool, false, "false");
774 EXPECT_INVALID(bool, "1");
775 EXPECT_INVALID(bool, "on");
776 EXPECT_INVALID(bool, "a");
777 EXPECT_INVALID(bool, "True");
778
779 // float
780 EXPECT_FIELD(float, 1, "1");
781 EXPECT_FLOAT_FIELD(float, 1.5, "1.5");
782 EXPECT_FLOAT_FIELD(float, 1.5e3, "1.5e3");
783 EXPECT_FLOAT_FIELD(float, -4.55, "-4.55");
784 EXPECT_INVALID(float, "a");
785 EXPECT_INVALID(float, "1,2");
786
787 // double
788 EXPECT_FIELD(double, 1, "1");
789 EXPECT_FIELD(double, -1, "-1");
790 EXPECT_DOUBLE_FIELD(double, 2.3, "2.3");
791 EXPECT_DOUBLE_FIELD(double, 3e5, "3e5");
792 EXPECT_INVALID(double, "a");
793 EXPECT_INVALID(double, "1,2");
794
795 // string
796 EXPECT_FIELD(string, "hello", "\"hello\"");
797 EXPECT_FIELD(string, "-1.87", "'-1.87'");
798 EXPECT_INVALID(string, "hello"); // without quote for value
799
800 // enum
801 EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR");
802 EXPECT_INVALID(nested_enum, "1"); // number not supported
803 EXPECT_INVALID(nested_enum, "FOOBAR");
804
805 // message
806 EXPECT_TRUE(TextFormat::ParseFieldValueFromString(
807 "<bb:12>", d->FindFieldByName("optional_nested_message"), message.get()));
808 EXPECT_EQ(12, message->optional_nested_message().bb()); \
809 EXPECT_TRUE(message->has_optional_nested_message());
810 EXPECT_INVALID(nested_message, "any");
811
812 #undef EXPECT_FIELD
813 #undef EXPECT_FLOAT_FIELD
814 #undef EXPECT_DOUBLE_FIELD
815 #undef EXPECT_INVALID
816 }
817
818
TEST_F(TextFormatParserTest,InvalidToken)819 TEST_F(TextFormatParserTest, InvalidToken) {
820 ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.",
821 2, 1);
822
823 ExpectFailure("optional_bool: true;\n", "Expected identifier.", 1, 20);
824 ExpectFailure("\"some string\"", "Expected identifier.", 1, 1);
825 }
826
TEST_F(TextFormatParserTest,InvalidFieldName)827 TEST_F(TextFormatParserTest, InvalidFieldName) {
828 ExpectFailure(
829 "invalid_field: somevalue\n",
830 "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
831 "\"invalid_field\".",
832 1, 14);
833 }
834
TEST_F(TextFormatParserTest,InvalidCapitalization)835 TEST_F(TextFormatParserTest, InvalidCapitalization) {
836 // We require that group names be exactly as they appear in the .proto.
837 ExpectFailure(
838 "optionalgroup {\na: 15\n}\n",
839 "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
840 "\"optionalgroup\".",
841 1, 15);
842 ExpectFailure(
843 "OPTIONALgroup {\na: 15\n}\n",
844 "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
845 "\"OPTIONALgroup\".",
846 1, 15);
847 ExpectFailure(
848 "Optional_Double: 10.0\n",
849 "Message type \"protobuf_unittest.TestAllTypes\" has no field named "
850 "\"Optional_Double\".",
851 1, 16);
852 }
853
TEST_F(TextFormatParserTest,InvalidFieldValues)854 TEST_F(TextFormatParserTest, InvalidFieldValues) {
855 // Invalid values for a double/float field.
856 ExpectFailure("optional_double: \"hello\"\n", "Expected double.", 1, 18);
857 ExpectFailure("optional_double: true\n", "Expected double.", 1, 18);
858 ExpectFailure("optional_double: !\n", "Expected double.", 1, 18);
859 ExpectFailure("optional_double {\n \n}\n", "Expected \":\", found \"{\".",
860 1, 17);
861
862 // Invalid values for a signed integer field.
863 ExpectFailure("optional_int32: \"hello\"\n", "Expected integer.", 1, 17);
864 ExpectFailure("optional_int32: true\n", "Expected integer.", 1, 17);
865 ExpectFailure("optional_int32: 4.5\n", "Expected integer.", 1, 17);
866 ExpectFailure("optional_int32: !\n", "Expected integer.", 1, 17);
867 ExpectFailure("optional_int32 {\n \n}\n", "Expected \":\", found \"{\".",
868 1, 16);
869 ExpectFailure("optional_int32: 0x80000000\n",
870 "Integer out of range.", 1, 17);
871 ExpectFailure("optional_int32: -0x80000001\n",
872 "Integer out of range.", 1, 18);
873 ExpectFailure("optional_int64: 0x8000000000000000\n",
874 "Integer out of range.", 1, 17);
875 ExpectFailure("optional_int64: -0x8000000000000001\n",
876 "Integer out of range.", 1, 18);
877
878 // Invalid values for an unsigned integer field.
879 ExpectFailure("optional_uint64: \"hello\"\n", "Expected integer.", 1, 18);
880 ExpectFailure("optional_uint64: true\n", "Expected integer.", 1, 18);
881 ExpectFailure("optional_uint64: 4.5\n", "Expected integer.", 1, 18);
882 ExpectFailure("optional_uint64: -5\n", "Expected integer.", 1, 18);
883 ExpectFailure("optional_uint64: !\n", "Expected integer.", 1, 18);
884 ExpectFailure("optional_uint64 {\n \n}\n", "Expected \":\", found \"{\".",
885 1, 17);
886 ExpectFailure("optional_uint32: 0x100000000\n",
887 "Integer out of range.", 1, 18);
888 ExpectFailure("optional_uint64: 0x10000000000000000\n",
889 "Integer out of range.", 1, 18);
890
891 // Invalid values for a boolean field.
892 ExpectFailure("optional_bool: \"hello\"\n", "Expected identifier.", 1, 16);
893 ExpectFailure("optional_bool: 5\n", "Expected identifier.", 1, 16);
894 ExpectFailure("optional_bool: -7.5\n", "Expected identifier.", 1, 16);
895 ExpectFailure("optional_bool: !\n", "Expected identifier.", 1, 16);
896
897 ExpectFailure(
898 "optional_bool: meh\n",
899 "Invalid value for boolean field \"optional_bool\". Value: \"meh\".",
900 2, 1);
901
902 ExpectFailure("optional_bool {\n \n}\n", "Expected \":\", found \"{\".",
903 1, 15);
904
905 // Invalid values for a string field.
906 ExpectFailure("optional_string: true\n", "Expected string.", 1, 18);
907 ExpectFailure("optional_string: 5\n", "Expected string.", 1, 18);
908 ExpectFailure("optional_string: -7.5\n", "Expected string.", 1, 18);
909 ExpectFailure("optional_string: !\n", "Expected string.", 1, 18);
910 ExpectFailure("optional_string {\n \n}\n", "Expected \":\", found \"{\".",
911 1, 17);
912
913 // Invalid values for an enumeration field.
914 ExpectFailure("optional_nested_enum: \"hello\"\n", "Expected identifier.",
915 1, 23);
916
917 ExpectFailure("optional_nested_enum: 5\n", "Expected identifier.", 1, 23);
918 ExpectFailure("optional_nested_enum: -7.5\n", "Expected identifier.", 1, 23);
919 ExpectFailure("optional_nested_enum: !\n", "Expected identifier.", 1, 23);
920
921 ExpectFailure(
922 "optional_nested_enum: grah\n",
923 "Unknown enumeration value of \"grah\" for field "
924 "\"optional_nested_enum\".", 2, 1);
925
926 ExpectFailure(
927 "optional_nested_enum {\n \n}\n",
928 "Expected \":\", found \"{\".", 1, 22);
929 }
930
TEST_F(TextFormatParserTest,MessageDelimeters)931 TEST_F(TextFormatParserTest, MessageDelimeters) {
932 // Non-matching delimeters.
933 ExpectFailure("OptionalGroup <\n \n}\n", "Expected \">\", found \"}\".",
934 3, 1);
935
936 // Invalid delimeters.
937 ExpectFailure("OptionalGroup [\n \n]\n", "Expected \"{\", found \"[\".",
938 1, 15);
939
940 // Unending message.
941 ExpectFailure("optional_nested_message {\n \nbb: 118\n",
942 "Expected identifier.",
943 4, 1);
944 }
945
TEST_F(TextFormatParserTest,UnknownExtension)946 TEST_F(TextFormatParserTest, UnknownExtension) {
947 // Non-matching delimeters.
948 ExpectFailure("[blahblah]: 123",
949 "Extension \"blahblah\" is not defined or is not an "
950 "extension of \"protobuf_unittest.TestAllTypes\".",
951 1, 11);
952 }
953
TEST_F(TextFormatParserTest,MissingRequired)954 TEST_F(TextFormatParserTest, MissingRequired) {
955 unittest::TestRequired message;
956 ExpectFailure("a: 1",
957 "Message missing required fields: b, c",
958 0, 1, &message);
959 }
960
TEST_F(TextFormatParserTest,ParseDuplicateRequired)961 TEST_F(TextFormatParserTest, ParseDuplicateRequired) {
962 unittest::TestRequired message;
963 ExpectFailure("a: 1 b: 2 c: 3 a: 1",
964 "Non-repeated field \"a\" is specified multiple times.",
965 1, 17, &message);
966 }
967
TEST_F(TextFormatParserTest,ParseDuplicateOptional)968 TEST_F(TextFormatParserTest, ParseDuplicateOptional) {
969 unittest::ForeignMessage message;
970 ExpectFailure("c: 1 c: 2",
971 "Non-repeated field \"c\" is specified multiple times.",
972 1, 7, &message);
973 }
974
TEST_F(TextFormatParserTest,MergeDuplicateRequired)975 TEST_F(TextFormatParserTest, MergeDuplicateRequired) {
976 unittest::TestRequired message;
977 TextFormat::Parser parser;
978 EXPECT_TRUE(parser.MergeFromString("a: 1 b: 2 c: 3 a: 4", &message));
979 EXPECT_EQ(4, message.a());
980 }
981
TEST_F(TextFormatParserTest,MergeDuplicateOptional)982 TEST_F(TextFormatParserTest, MergeDuplicateOptional) {
983 unittest::ForeignMessage message;
984 TextFormat::Parser parser;
985 EXPECT_TRUE(parser.MergeFromString("c: 1 c: 2", &message));
986 EXPECT_EQ(2, message.c());
987 }
988
TEST_F(TextFormatParserTest,PrintErrorsToStderr)989 TEST_F(TextFormatParserTest, PrintErrorsToStderr) {
990 vector<string> errors;
991
992 {
993 ScopedMemoryLog log;
994 unittest::TestAllTypes proto;
995 EXPECT_FALSE(TextFormat::ParseFromString("no_such_field: 1", &proto));
996 errors = log.GetMessages(ERROR);
997 }
998
999 ASSERT_EQ(1, errors.size());
1000 EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: "
1001 "1:14: Message type \"protobuf_unittest.TestAllTypes\" has no field "
1002 "named \"no_such_field\".",
1003 errors[0]);
1004 }
1005
TEST_F(TextFormatParserTest,FailsOnTokenizationError)1006 TEST_F(TextFormatParserTest, FailsOnTokenizationError) {
1007 vector<string> errors;
1008
1009 {
1010 ScopedMemoryLog log;
1011 unittest::TestAllTypes proto;
1012 EXPECT_FALSE(TextFormat::ParseFromString("\020", &proto));
1013 errors = log.GetMessages(ERROR);
1014 }
1015
1016 ASSERT_EQ(1, errors.size());
1017 EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: "
1018 "1:1: Invalid control characters encountered in text.",
1019 errors[0]);
1020 }
1021
TEST_F(TextFormatParserTest,ParseDeprecatedField)1022 TEST_F(TextFormatParserTest, ParseDeprecatedField) {
1023 unittest::TestDeprecatedFields message;
1024 ExpectMessage("deprecated_int32: 42",
1025 "WARNING:text format contains deprecated field "
1026 "\"deprecated_int32\"", 1, 21, &message, true);
1027 }
1028
1029 class TextFormatMessageSetTest : public testing::Test {
1030 protected:
1031 static const char proto_debug_string_[];
1032 };
1033 const char TextFormatMessageSetTest::proto_debug_string_[] =
1034 "message_set {\n"
1035 " [protobuf_unittest.TestMessageSetExtension1] {\n"
1036 " i: 23\n"
1037 " }\n"
1038 " [protobuf_unittest.TestMessageSetExtension2] {\n"
1039 " str: \"foo\"\n"
1040 " }\n"
1041 "}\n";
1042
1043
TEST_F(TextFormatMessageSetTest,Serialize)1044 TEST_F(TextFormatMessageSetTest, Serialize) {
1045 protobuf_unittest::TestMessageSetContainer proto;
1046 protobuf_unittest::TestMessageSetExtension1* item_a =
1047 proto.mutable_message_set()->MutableExtension(
1048 protobuf_unittest::TestMessageSetExtension1::message_set_extension);
1049 item_a->set_i(23);
1050 protobuf_unittest::TestMessageSetExtension2* item_b =
1051 proto.mutable_message_set()->MutableExtension(
1052 protobuf_unittest::TestMessageSetExtension2::message_set_extension);
1053 item_b->set_str("foo");
1054 EXPECT_EQ(proto_debug_string_, proto.DebugString());
1055 }
1056
TEST_F(TextFormatMessageSetTest,Deserialize)1057 TEST_F(TextFormatMessageSetTest, Deserialize) {
1058 protobuf_unittest::TestMessageSetContainer proto;
1059 ASSERT_TRUE(TextFormat::ParseFromString(proto_debug_string_, &proto));
1060 EXPECT_EQ(23, proto.message_set().GetExtension(
1061 protobuf_unittest::TestMessageSetExtension1::message_set_extension).i());
1062 EXPECT_EQ("foo", proto.message_set().GetExtension(
1063 protobuf_unittest::TestMessageSetExtension2::message_set_extension).str());
1064
1065 // Ensure that these are the only entries present.
1066 vector<const FieldDescriptor*> descriptors;
1067 proto.message_set().GetReflection()->ListFields(
1068 proto.message_set(), &descriptors);
1069 EXPECT_EQ(2, descriptors.size());
1070 }
1071
1072 } // namespace text_format_unittest
1073 } // namespace protobuf
1074 } // namespace google
1075