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