- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / java / src / test / java / com / google / protobuf / TextFormatTest.java
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 package com.google.protobuf;
32
33 import com.google.protobuf.Descriptors.FieldDescriptor;
34 import protobuf_unittest.UnittestMset.TestMessageSet;
35 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
36 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
37 import protobuf_unittest.UnittestProto.OneString;
38 import protobuf_unittest.UnittestProto.TestAllExtensions;
39 import protobuf_unittest.UnittestProto.TestAllTypes;
40 import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
41 import protobuf_unittest.UnittestProto.TestEmptyMessage;
42
43 import junit.framework.TestCase;
44
45 import java.io.StringReader;
46
47 /**
48  * Test case for {@link TextFormat}.
49  *
50  * TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc.
51  *
52  * @author wenboz@google.com (Wenbo Zhu)
53  */
54 public class TextFormatTest extends TestCase {
55
56   // A basic string with different escapable characters for testing.
57   private final static String kEscapeTestString =
58       "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
59           + "slashes \\";
60
61   // A representation of the above string with all the characters escaped.
62   private final static String kEscapeTestStringEscaped =
63       "\\\"A string with \\' characters \\n and \\r newlines "
64           + "and \\t tabs and \\001 slashes \\\\";
65
66   private static String allFieldsSetText = TestUtil.readTextFromFile(
67     "text_format_unittest_data.txt");
68   private static String allExtensionsSetText = TestUtil.readTextFromFile(
69     "text_format_unittest_extensions_data.txt");
70
71   private static String exoticText =
72     "repeated_int32: -1\n" +
73     "repeated_int32: -2147483648\n" +
74     "repeated_int64: -1\n" +
75     "repeated_int64: -9223372036854775808\n" +
76     "repeated_uint32: 4294967295\n" +
77     "repeated_uint32: 2147483648\n" +
78     "repeated_uint64: 18446744073709551615\n" +
79     "repeated_uint64: 9223372036854775808\n" +
80     "repeated_double: 123.0\n" +
81     "repeated_double: 123.5\n" +
82     "repeated_double: 0.125\n" +
83     "repeated_double: .125\n" +
84     "repeated_double: -.125\n" +
85     "repeated_double: 1.23E17\n" +
86     "repeated_double: 1.23E+17\n" +
87     "repeated_double: -1.23e-17\n" +
88     "repeated_double: .23e+17\n" +
89     "repeated_double: -.23E17\n" +
90     "repeated_double: 1.235E22\n" +
91     "repeated_double: 1.235E-18\n" +
92     "repeated_double: 123.456789\n" +
93     "repeated_double: Infinity\n" +
94     "repeated_double: -Infinity\n" +
95     "repeated_double: NaN\n" +
96     "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
97       "\\341\\210\\264\"\n" +
98     "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
99
100   private static String canonicalExoticText =
101       exoticText.replace(": .", ": 0.").replace(": -.", ": -0.")   // short-form double
102       .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16");
103
104   private String messageSetText =
105     "[protobuf_unittest.TestMessageSetExtension1] {\n" +
106     "  i: 123\n" +
107     "}\n" +
108     "[protobuf_unittest.TestMessageSetExtension2] {\n" +
109     "  str: \"foo\"\n" +
110     "}\n";
111
112   /** Print TestAllTypes and compare with golden file. */
113   public void testPrintMessage() throws Exception {
114     String javaText = TextFormat.printToString(TestUtil.getAllSet());
115
116     // Java likes to add a trailing ".0" to floats and doubles.  C printf
117     // (with %g format) does not.  Our golden files are used for both
118     // C++ and Java TextFormat classes, so we need to conform.
119     javaText = javaText.replace(".0\n", "\n");
120
121     assertEquals(allFieldsSetText, javaText);
122   }
123
124   /** Print TestAllTypes as Builder and compare with golden file. */
125   public void testPrintMessageBuilder() throws Exception {
126     String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
127
128     // Java likes to add a trailing ".0" to floats and doubles.  C printf
129     // (with %g format) does not.  Our golden files are used for both
130     // C++ and Java TextFormat classes, so we need to conform.
131     javaText = javaText.replace(".0\n", "\n");
132
133     assertEquals(allFieldsSetText, javaText);
134   }
135
136   /** Print TestAllExtensions and compare with golden file. */
137   public void testPrintExtensions() throws Exception {
138     String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
139
140     // Java likes to add a trailing ".0" to floats and doubles.  C printf
141     // (with %g format) does not.  Our golden files are used for both
142     // C++ and Java TextFormat classes, so we need to conform.
143     javaText = javaText.replace(".0\n", "\n");
144
145     assertEquals(allExtensionsSetText, javaText);
146   }
147
148   // Creates an example unknown field set.
149   private UnknownFieldSet makeUnknownFieldSet() {
150     return UnknownFieldSet.newBuilder()
151         .addField(5,
152             UnknownFieldSet.Field.newBuilder()
153             .addVarint(1)
154             .addFixed32(2)
155             .addFixed64(3)
156             .addLengthDelimited(ByteString.copyFromUtf8("4"))
157             .addGroup(
158                 UnknownFieldSet.newBuilder()
159                 .addField(10,
160                     UnknownFieldSet.Field.newBuilder()
161                     .addVarint(5)
162                     .build())
163                 .build())
164             .build())
165         .addField(8,
166             UnknownFieldSet.Field.newBuilder()
167             .addVarint(1)
168             .addVarint(2)
169             .addVarint(3)
170             .build())
171         .addField(15,
172             UnknownFieldSet.Field.newBuilder()
173             .addVarint(0xABCDEF1234567890L)
174             .addFixed32(0xABCD1234)
175             .addFixed64(0xABCDEF1234567890L)
176             .build())
177         .build();
178   }
179
180   public void testPrintUnknownFields() throws Exception {
181     // Test printing of unknown fields in a message.
182
183     TestEmptyMessage message =
184       TestEmptyMessage.newBuilder()
185         .setUnknownFields(makeUnknownFieldSet())
186         .build();
187
188     assertEquals(
189       "5: 1\n" +
190       "5: 0x00000002\n" +
191       "5: 0x0000000000000003\n" +
192       "5: \"4\"\n" +
193       "5 {\n" +
194       "  10: 5\n" +
195       "}\n" +
196       "8: 1\n" +
197       "8: 2\n" +
198       "8: 3\n" +
199       "15: 12379813812177893520\n" +
200       "15: 0xabcd1234\n" +
201       "15: 0xabcdef1234567890\n",
202       TextFormat.printToString(message));
203   }
204
205   public void testPrintField() throws Exception {
206     final FieldDescriptor dataField =
207       OneString.getDescriptor().findFieldByName("data");
208     assertEquals(
209       "data: \"test data\"\n",
210       TextFormat.printFieldToString(dataField, "test data"));
211
212     final FieldDescriptor optionalField =
213       TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
214     final Object value = NestedMessage.newBuilder().setBb(42).build();
215
216     assertEquals(
217       "optional_nested_message {\n  bb: 42\n}\n",
218       TextFormat.printFieldToString(optionalField, value));
219   }
220
221   /**
222    * Helper to construct a ByteString from a String containing only 8-bit
223    * characters.  The characters are converted directly to bytes, *not*
224    * encoded using UTF-8.
225    */
226   private ByteString bytes(String str) throws Exception {
227     return ByteString.copyFrom(str.getBytes("ISO-8859-1"));
228   }
229
230   /**
231    * Helper to construct a ByteString from a bunch of bytes.  The inputs are
232    * actually ints so that I can use hex notation and not get stupid errors
233    * about precision.
234    */
235   private ByteString bytes(int... bytesAsInts) {
236     byte[] bytes = new byte[bytesAsInts.length];
237     for (int i = 0; i < bytesAsInts.length; i++) {
238       bytes[i] = (byte) bytesAsInts[i];
239     }
240     return ByteString.copyFrom(bytes);
241   }
242
243   public void testPrintExotic() throws Exception {
244     Message message = TestAllTypes.newBuilder()
245       // Signed vs. unsigned numbers.
246       .addRepeatedInt32 (-1)
247       .addRepeatedUint32(-1)
248       .addRepeatedInt64 (-1)
249       .addRepeatedUint64(-1)
250
251       .addRepeatedInt32 (1  << 31)
252       .addRepeatedUint32(1  << 31)
253       .addRepeatedInt64 (1l << 63)
254       .addRepeatedUint64(1l << 63)
255
256       // Floats of various precisions and exponents.
257       .addRepeatedDouble(123)
258       .addRepeatedDouble(123.5)
259       .addRepeatedDouble(0.125)
260       .addRepeatedDouble(.125)
261       .addRepeatedDouble(-.125)
262       .addRepeatedDouble(123e15)
263       .addRepeatedDouble(123e15)
264       .addRepeatedDouble(-1.23e-17)
265       .addRepeatedDouble(.23e17)
266       .addRepeatedDouble(-23e15)
267       .addRepeatedDouble(123.5e20)
268       .addRepeatedDouble(123.5e-20)
269       .addRepeatedDouble(123.456789)
270       .addRepeatedDouble(Double.POSITIVE_INFINITY)
271       .addRepeatedDouble(Double.NEGATIVE_INFINITY)
272       .addRepeatedDouble(Double.NaN)
273
274       // Strings and bytes that needing escaping.
275       .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234")
276       .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
277       .build();
278
279     assertEquals(canonicalExoticText, message.toString());
280   }
281
282   public void testPrintMessageSet() throws Exception {
283     TestMessageSet messageSet =
284       TestMessageSet.newBuilder()
285         .setExtension(
286           TestMessageSetExtension1.messageSetExtension,
287           TestMessageSetExtension1.newBuilder().setI(123).build())
288         .setExtension(
289           TestMessageSetExtension2.messageSetExtension,
290           TestMessageSetExtension2.newBuilder().setStr("foo").build())
291         .build();
292
293     assertEquals(messageSetText, messageSet.toString());
294   }
295
296   // =================================================================
297
298   public void testParse() throws Exception {
299     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
300     TextFormat.merge(allFieldsSetText, builder);
301     TestUtil.assertAllFieldsSet(builder.build());
302   }
303
304   public void testParseReader() throws Exception {
305     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
306     TextFormat.merge(new StringReader(allFieldsSetText), builder);
307     TestUtil.assertAllFieldsSet(builder.build());
308   }
309
310   public void testParseExtensions() throws Exception {
311     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
312     TextFormat.merge(allExtensionsSetText,
313                      TestUtil.getExtensionRegistry(),
314                      builder);
315     TestUtil.assertAllExtensionsSet(builder.build());
316   }
317
318   public void testParseCompatibility() throws Exception {
319     String original = "repeated_float: inf\n" +
320                       "repeated_float: -inf\n" +
321                       "repeated_float: nan\n" +
322                       "repeated_float: inff\n" +
323                       "repeated_float: -inff\n" +
324                       "repeated_float: nanf\n" +
325                       "repeated_float: 1.0f\n" +
326                       "repeated_float: infinityf\n" +
327                       "repeated_float: -Infinityf\n" +
328                       "repeated_double: infinity\n" +
329                       "repeated_double: -infinity\n" +
330                       "repeated_double: nan\n";
331     String canonical =  "repeated_float: Infinity\n" +
332                         "repeated_float: -Infinity\n" +
333                         "repeated_float: NaN\n" +
334                         "repeated_float: Infinity\n" +
335                         "repeated_float: -Infinity\n" +
336                         "repeated_float: NaN\n" +
337                         "repeated_float: 1.0\n" +
338                         "repeated_float: Infinity\n" +
339                         "repeated_float: -Infinity\n" +
340                         "repeated_double: Infinity\n" +
341                         "repeated_double: -Infinity\n" +
342                         "repeated_double: NaN\n";
343     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
344     TextFormat.merge(original, builder);
345     assertEquals(canonical, builder.build().toString());
346   }
347
348   public void testParseExotic() throws Exception {
349     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
350     TextFormat.merge(exoticText, builder);
351
352     // Too lazy to check things individually.  Don't try to debug this
353     // if testPrintExotic() is failing.
354     assertEquals(canonicalExoticText, builder.build().toString());
355   }
356
357   public void testParseMessageSet() throws Exception {
358     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
359     extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
360     extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
361
362     TestMessageSet.Builder builder = TestMessageSet.newBuilder();
363     TextFormat.merge(messageSetText, extensionRegistry, builder);
364     TestMessageSet messageSet = builder.build();
365
366     assertTrue(messageSet.hasExtension(
367       TestMessageSetExtension1.messageSetExtension));
368     assertEquals(123, messageSet.getExtension(
369       TestMessageSetExtension1.messageSetExtension).getI());
370     assertTrue(messageSet.hasExtension(
371       TestMessageSetExtension2.messageSetExtension));
372     assertEquals("foo", messageSet.getExtension(
373       TestMessageSetExtension2.messageSetExtension).getStr());
374   }
375
376   public void testParseNumericEnum() throws Exception {
377     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
378     TextFormat.merge("optional_nested_enum: 2", builder);
379     assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum());
380   }
381
382   public void testParseAngleBrackets() throws Exception {
383     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
384     TextFormat.merge("OptionalGroup: < a: 1 >", builder);
385     assertTrue(builder.hasOptionalGroup());
386     assertEquals(1, builder.getOptionalGroup().getA());
387   }
388
389   public void testParseComment() throws Exception {
390     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
391     TextFormat.merge(
392       "# this is a comment\n" +
393       "optional_int32: 1  # another comment\n" +
394       "optional_int64: 2\n" +
395       "# EOF comment", builder);
396     assertEquals(1, builder.getOptionalInt32());
397     assertEquals(2, builder.getOptionalInt64());
398   }
399
400   private void assertParseError(String error, String text) {
401     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
402     try {
403       TextFormat.merge(text, TestUtil.getExtensionRegistry(), builder);
404       fail("Expected parse exception.");
405     } catch (TextFormat.ParseException e) {
406       assertEquals(error, e.getMessage());
407     }
408   }
409
410   public void testParseErrors() throws Exception {
411     assertParseError(
412       "1:16: Expected \":\".",
413       "optional_int32 123");
414     assertParseError(
415       "1:23: Expected identifier.",
416       "optional_nested_enum: ?");
417     assertParseError(
418       "1:18: Couldn't parse integer: Number must be positive: -1",
419       "optional_uint32: -1");
420     assertParseError(
421       "1:17: Couldn't parse integer: Number out of range for 32-bit signed " +
422         "integer: 82301481290849012385230157",
423       "optional_int32: 82301481290849012385230157");
424     assertParseError(
425       "1:16: Expected \"true\" or \"false\".",
426       "optional_bool: maybe");
427     assertParseError(
428       "1:16: Expected \"true\" or \"false\".",
429       "optional_bool: 2");
430     assertParseError(
431       "1:18: Expected string.",
432       "optional_string: 123");
433     assertParseError(
434       "1:18: String missing ending quote.",
435       "optional_string: \"ueoauaoe");
436     assertParseError(
437       "1:18: String missing ending quote.",
438       "optional_string: \"ueoauaoe\n" +
439       "optional_int32: 123");
440     assertParseError(
441       "1:18: Invalid escape sequence: '\\z'",
442       "optional_string: \"\\z\"");
443     assertParseError(
444       "1:18: String missing ending quote.",
445       "optional_string: \"ueoauaoe\n" +
446       "optional_int32: 123");
447     assertParseError(
448       "1:2: Extension \"nosuchext\" not found in the ExtensionRegistry.",
449       "[nosuchext]: 123");
450     assertParseError(
451       "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " +
452         "not extend message type \"protobuf_unittest.TestAllTypes\".",
453       "[protobuf_unittest.optional_int32_extension]: 123");
454     assertParseError(
455       "1:1: Message type \"protobuf_unittest.TestAllTypes\" has no field " +
456         "named \"nosuchfield\".",
457       "nosuchfield: 123");
458     assertParseError(
459       "1:21: Expected \">\".",
460       "OptionalGroup < a: 1");
461     assertParseError(
462       "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
463         "value named \"NO_SUCH_VALUE\".",
464       "optional_nested_enum: NO_SUCH_VALUE");
465     assertParseError(
466       "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
467         "value with number 123.",
468       "optional_nested_enum: 123");
469
470     // Delimiters must match.
471     assertParseError(
472       "1:22: Expected identifier.",
473       "OptionalGroup < a: 1 }");
474     assertParseError(
475       "1:22: Expected identifier.",
476       "OptionalGroup { a: 1 >");
477   }
478
479   // =================================================================
480
481   public void testEscape() throws Exception {
482     // Escape sequences.
483     assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
484       TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"")));
485     assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
486       TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\""));
487     assertEquals(bytes("\0\001\007\b\f\n\r\t\013\\\'\""),
488       TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
489     assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"",
490       TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
491     assertEquals(kEscapeTestStringEscaped,
492       TextFormat.escapeText(kEscapeTestString));
493     assertEquals(kEscapeTestString,
494       TextFormat.unescapeText(kEscapeTestStringEscaped));
495
496     // Unicode handling.
497     assertEquals("\\341\\210\\264", TextFormat.escapeText("\u1234"));
498     assertEquals("\\341\\210\\264",
499                  TextFormat.escapeBytes(bytes(0xe1, 0x88, 0xb4)));
500     assertEquals("\u1234", TextFormat.unescapeText("\\341\\210\\264"));
501     assertEquals(bytes(0xe1, 0x88, 0xb4),
502                  TextFormat.unescapeBytes("\\341\\210\\264"));
503     assertEquals("\u1234", TextFormat.unescapeText("\\xe1\\x88\\xb4"));
504     assertEquals(bytes(0xe1, 0x88, 0xb4),
505                  TextFormat.unescapeBytes("\\xe1\\x88\\xb4"));
506
507     // Handling of strings with unescaped Unicode characters > 255.
508     final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
509     ByteString zhByteString = ByteString.copyFromUtf8(zh);
510     assertEquals(zhByteString, TextFormat.unescapeBytes(zh));
511
512     // Errors.
513     try {
514       TextFormat.unescapeText("\\x");
515       fail("Should have thrown an exception.");
516     } catch (TextFormat.InvalidEscapeSequenceException e) {
517       // success
518     }
519
520     try {
521       TextFormat.unescapeText("\\z");
522       fail("Should have thrown an exception.");
523     } catch (TextFormat.InvalidEscapeSequenceException e) {
524       // success
525     }
526
527     try {
528       TextFormat.unescapeText("\\");
529       fail("Should have thrown an exception.");
530     } catch (TextFormat.InvalidEscapeSequenceException e) {
531       // success
532     }
533   }
534
535   public void testParseInteger() throws Exception {
536     assertEquals(          0, TextFormat.parseInt32(          "0"));
537     assertEquals(          1, TextFormat.parseInt32(          "1"));
538     assertEquals(         -1, TextFormat.parseInt32(         "-1"));
539     assertEquals(      12345, TextFormat.parseInt32(      "12345"));
540     assertEquals(     -12345, TextFormat.parseInt32(     "-12345"));
541     assertEquals( 2147483647, TextFormat.parseInt32( "2147483647"));
542     assertEquals(-2147483648, TextFormat.parseInt32("-2147483648"));
543
544     assertEquals(                0, TextFormat.parseUInt32(         "0"));
545     assertEquals(                1, TextFormat.parseUInt32(         "1"));
546     assertEquals(            12345, TextFormat.parseUInt32(     "12345"));
547     assertEquals(       2147483647, TextFormat.parseUInt32("2147483647"));
548     assertEquals((int) 2147483648L, TextFormat.parseUInt32("2147483648"));
549     assertEquals((int) 4294967295L, TextFormat.parseUInt32("4294967295"));
550
551     assertEquals(          0L, TextFormat.parseInt64(          "0"));
552     assertEquals(          1L, TextFormat.parseInt64(          "1"));
553     assertEquals(         -1L, TextFormat.parseInt64(         "-1"));
554     assertEquals(      12345L, TextFormat.parseInt64(      "12345"));
555     assertEquals(     -12345L, TextFormat.parseInt64(     "-12345"));
556     assertEquals( 2147483647L, TextFormat.parseInt64( "2147483647"));
557     assertEquals(-2147483648L, TextFormat.parseInt64("-2147483648"));
558     assertEquals( 4294967295L, TextFormat.parseInt64( "4294967295"));
559     assertEquals( 4294967296L, TextFormat.parseInt64( "4294967296"));
560     assertEquals(9223372036854775807L,
561                  TextFormat.parseInt64("9223372036854775807"));
562     assertEquals(-9223372036854775808L,
563                  TextFormat.parseInt64("-9223372036854775808"));
564
565     assertEquals(          0L, TextFormat.parseUInt64(          "0"));
566     assertEquals(          1L, TextFormat.parseUInt64(          "1"));
567     assertEquals(      12345L, TextFormat.parseUInt64(      "12345"));
568     assertEquals( 2147483647L, TextFormat.parseUInt64( "2147483647"));
569     assertEquals( 4294967295L, TextFormat.parseUInt64( "4294967295"));
570     assertEquals( 4294967296L, TextFormat.parseUInt64( "4294967296"));
571     assertEquals(9223372036854775807L,
572                  TextFormat.parseUInt64("9223372036854775807"));
573     assertEquals(-9223372036854775808L,
574                  TextFormat.parseUInt64("9223372036854775808"));
575     assertEquals(-1L, TextFormat.parseUInt64("18446744073709551615"));
576
577     // Hex
578     assertEquals(0x1234abcd, TextFormat.parseInt32("0x1234abcd"));
579     assertEquals(-0x1234abcd, TextFormat.parseInt32("-0x1234abcd"));
580     assertEquals(-1, TextFormat.parseUInt64("0xffffffffffffffff"));
581     assertEquals(0x7fffffffffffffffL,
582                  TextFormat.parseInt64("0x7fffffffffffffff"));
583
584     // Octal
585     assertEquals(01234567, TextFormat.parseInt32("01234567"));
586
587     // Out-of-range
588     try {
589       TextFormat.parseInt32("2147483648");
590       fail("Should have thrown an exception.");
591     } catch (NumberFormatException e) {
592       // success
593     }
594
595     try {
596       TextFormat.parseInt32("-2147483649");
597       fail("Should have thrown an exception.");
598     } catch (NumberFormatException e) {
599       // success
600     }
601
602     try {
603       TextFormat.parseUInt32("4294967296");
604       fail("Should have thrown an exception.");
605     } catch (NumberFormatException e) {
606       // success
607     }
608
609     try {
610       TextFormat.parseUInt32("-1");
611       fail("Should have thrown an exception.");
612     } catch (NumberFormatException e) {
613       // success
614     }
615
616     try {
617       TextFormat.parseInt64("9223372036854775808");
618       fail("Should have thrown an exception.");
619     } catch (NumberFormatException e) {
620       // success
621     }
622
623     try {
624       TextFormat.parseInt64("-9223372036854775809");
625       fail("Should have thrown an exception.");
626     } catch (NumberFormatException e) {
627       // success
628     }
629
630     try {
631       TextFormat.parseUInt64("18446744073709551616");
632       fail("Should have thrown an exception.");
633     } catch (NumberFormatException e) {
634       // success
635     }
636
637     try {
638       TextFormat.parseUInt64("-1");
639       fail("Should have thrown an exception.");
640     } catch (NumberFormatException e) {
641       // success
642     }
643
644     // Not a number.
645     try {
646       TextFormat.parseInt32("abcd");
647       fail("Should have thrown an exception.");
648     } catch (NumberFormatException e) {
649       // success
650     }
651   }
652
653   public void testParseString() throws Exception {
654     final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
655     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
656     TextFormat.merge("optional_string: \"" + zh + "\"", builder);
657     assertEquals(zh, builder.getOptionalString());
658   }
659
660   public void testParseLongString() throws Exception {
661     String longText =
662       "123456789012345678901234567890123456789012345678901234567890" +
663       "123456789012345678901234567890123456789012345678901234567890" +
664       "123456789012345678901234567890123456789012345678901234567890" +
665       "123456789012345678901234567890123456789012345678901234567890" +
666       "123456789012345678901234567890123456789012345678901234567890" +
667       "123456789012345678901234567890123456789012345678901234567890" +
668       "123456789012345678901234567890123456789012345678901234567890" +
669       "123456789012345678901234567890123456789012345678901234567890" +
670       "123456789012345678901234567890123456789012345678901234567890" +
671       "123456789012345678901234567890123456789012345678901234567890" +
672       "123456789012345678901234567890123456789012345678901234567890" +
673       "123456789012345678901234567890123456789012345678901234567890" +
674       "123456789012345678901234567890123456789012345678901234567890" +
675       "123456789012345678901234567890123456789012345678901234567890" +
676       "123456789012345678901234567890123456789012345678901234567890" +
677       "123456789012345678901234567890123456789012345678901234567890" +
678       "123456789012345678901234567890123456789012345678901234567890" +
679       "123456789012345678901234567890123456789012345678901234567890" +
680       "123456789012345678901234567890123456789012345678901234567890" +
681       "123456789012345678901234567890123456789012345678901234567890";
682
683     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
684     TextFormat.merge("optional_string: \"" + longText + "\"", builder);
685     assertEquals(longText, builder.getOptionalString());
686   }
687
688   public void testParseBoolean() throws Exception {
689     String goodText =
690         "repeated_bool: t  repeated_bool : 0\n" +
691         "repeated_bool :f repeated_bool:1";
692     String goodTextCanonical =
693         "repeated_bool: true\n" +
694         "repeated_bool: false\n" +
695         "repeated_bool: false\n" +
696         "repeated_bool: true\n";
697     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
698     TextFormat.merge(goodText, builder);
699     assertEquals(goodTextCanonical, builder.build().toString());
700
701     try {
702       TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
703       TextFormat.merge("optional_bool:2", badBuilder);
704       fail("Should have thrown an exception.");
705     } catch (TextFormat.ParseException e) {
706       // success
707     }
708     try {
709       TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
710       TextFormat.merge("optional_bool: foo", badBuilder);
711       fail("Should have thrown an exception.");
712     } catch (TextFormat.ParseException e) {
713       // success
714     }
715   }
716
717   public void testParseAdjacentStringLiterals() throws Exception {
718     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
719     TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder);
720     assertEquals("foocorgegrault", builder.getOptionalString());
721   }
722
723   public void testPrintFieldValue() throws Exception {
724     assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string");
725     assertPrintFieldValue("123.0",  123f, "repeated_float");
726     assertPrintFieldValue("123.0",  123d, "repeated_double");
727     assertPrintFieldValue("123",  123, "repeated_int32");
728     assertPrintFieldValue("123",  123L, "repeated_int64");
729     assertPrintFieldValue("true",  true, "repeated_bool");
730     assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32");
731     assertPrintFieldValue("18446744073709551615",  0xFFFFFFFFFFFFFFFFL,
732         "repeated_uint64");
733     assertPrintFieldValue("\"\\001\\002\\003\"",
734         ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes");
735   }
736
737   private void assertPrintFieldValue(String expect, Object value,
738       String fieldName) throws Exception {
739     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
740     StringBuilder sb = new StringBuilder();
741     TextFormat.printFieldValue(
742         TestAllTypes.getDescriptor().findFieldByName(fieldName),
743         value, sb);
744     assertEquals(expect, sb.toString());
745   }
746
747   public void testShortDebugString() {
748     assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1"
749         + " repeated_uint32: 2",
750         TextFormat.shortDebugString(TestAllTypes.newBuilder()
751             .addRepeatedInt32(1)
752             .addRepeatedUint32(2)
753             .setOptionalNestedMessage(
754                 NestedMessage.newBuilder().setBb(42).build())
755             .build()));
756   }
757
758   public void testShortDebugString_unknown() {
759     assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
760         + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
761         + " 0xabcdef1234567890",
762         TextFormat.shortDebugString(makeUnknownFieldSet()));
763   }
764
765   public void testPrintToUnicodeString() {
766     assertEquals(
767         "optional_string: \"abc\u3042efg\"\n" +
768         "optional_bytes: \"\\343\\201\\202\"\n" +
769         "repeated_string: \"\u3093XYZ\"\n",
770         TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
771             .setOptionalString("abc\u3042efg")
772             .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
773             .addRepeatedString("\u3093XYZ")
774             .build()));
775   }
776
777   public void testPrintToUnicodeString_unknown() {
778     assertEquals(
779         "1: \"\\343\\201\\202\"\n",
780         TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
781             .addField(1,
782                 UnknownFieldSet.Field.newBuilder()
783                 .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
784             .build()));
785   }
786 }