PageRenderTime 79ms CodeModel.GetById 18ms app.highlight 55ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/third_party/protobuf/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java

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