1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.common.truth.Truth.assertThat; 11 import static com.google.common.truth.Truth.assertWithMessage; 12 import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED; 13 import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED; 14 import static protobuf_unittest.UnittestProto.optionalInt32Extension; 15 import static org.junit.Assert.assertThrows; 16 17 import com.google.protobuf.DescriptorProtos.DescriptorProto; 18 import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; 19 import com.google.protobuf.DescriptorProtos.FileDescriptorProto; 20 import com.google.protobuf.Descriptors.Descriptor; 21 import com.google.protobuf.Descriptors.FieldDescriptor; 22 import com.google.protobuf.Descriptors.FileDescriptor; 23 import com.google.protobuf.TextFormat.InvalidEscapeSequenceException; 24 import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy; 25 import com.google.protobuf.testing.proto.TestProto3Optional; 26 import com.google.protobuf.testing.proto.TestProto3Optional.NestedEnum; 27 import any_test.AnyTestProto.TestAny; 28 import editions_unittest.GroupLikeFileScope; 29 import editions_unittest.MessageImport; 30 import editions_unittest.NotGroupLikeScope; 31 import editions_unittest.TestDelimited; 32 import editions_unittest.UnittestDelimited; 33 import map_test.MapTestProto.TestMap; 34 import protobuf_unittest.UnittestMset.TestMessageSetExtension1; 35 import protobuf_unittest.UnittestMset.TestMessageSetExtension2; 36 import protobuf_unittest.UnittestProto.OneString; 37 import protobuf_unittest.UnittestProto.TestAllExtensions; 38 import protobuf_unittest.UnittestProto.TestAllTypes; 39 import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; 40 import protobuf_unittest.UnittestProto.TestEmptyMessage; 41 import protobuf_unittest.UnittestProto.TestOneof2; 42 import protobuf_unittest.UnittestProto.TestRecursiveMessage; 43 import protobuf_unittest.UnittestProto.TestRequired; 44 import protobuf_unittest.UnittestProto.TestReservedFields; 45 import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet; 46 import java.io.StringReader; 47 import java.util.Arrays; 48 import java.util.List; 49 import java.util.logging.Logger; 50 import org.junit.Test; 51 import org.junit.function.ThrowingRunnable; 52 import org.junit.runner.RunWith; 53 import org.junit.runners.JUnit4; 54 55 /** Test case for {@link TextFormat}. */ 56 @RunWith(JUnit4.class) 57 public class TextFormatTest { 58 59 // A basic string with different escapable characters for testing. 60 private static final String ESCAPE_TEST_STRING = 61 "\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\"; 62 63 // A representation of the above string with all the characters escaped. 64 private static final String ESCAPE_TEST_STRING_ESCAPED = 65 "\\\"A string with \\' characters \\n and \\r newlines " 66 + "and \\t tabs and \\001 slashes \\\\"; 67 68 private static final String EXOTIC_TEXT = 69 "" 70 + "repeated_int32: -1\n" 71 + "repeated_int32: -2147483648\n" 72 + "repeated_int64: -1,\n" 73 + "repeated_int64: -9223372036854775808\n" 74 + "repeated_uint32: 4294967295\n" 75 + "repeated_uint32: 2147483648\n" 76 + "repeated_uint64: 18446744073709551615\n" 77 + "repeated_uint64: 9223372036854775808\n" 78 + "repeated_double: 123.0\n" 79 + "repeated_double: 123.5\n" 80 + "repeated_double: 0.125\n" 81 + "repeated_double: .125\n" 82 + "repeated_double: -.125\n" 83 + "repeated_double: 1.23E17\n" 84 + "repeated_double: 1.23E+17\n" 85 + "repeated_double: -1.23e-17\n" 86 + "repeated_double: .23e+17\n" 87 + "repeated_double: -.23E17\n" 88 + "repeated_double: 1.235E22\n" 89 + "repeated_double: 1.235E-18\n" 90 + "repeated_double: 123.456789\n" 91 + "repeated_double: Infinity\n" 92 + "repeated_double: -Infinity\n" 93 + "repeated_double: NaN\n" 94 + "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" 95 + "\\341\\210\\264\"\n" 96 + "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n"; 97 98 private static final String CANONICAL_EXOTIC_TEXT = 99 EXOTIC_TEXT 100 .replace(": .", ": 0.") 101 .replace(": -.", ": -0.") // short-form double 102 .replace("23e", "23E") 103 .replace("E+", "E") 104 .replace("0.23E17", "2.3E16") 105 .replace(",", ""); 106 107 private static final String MESSAGE_SET_TEXT = 108 "" 109 + "[protobuf_unittest.TestMessageSetExtension1] {\n" 110 + " i: 123\n" 111 + "}\n" 112 + "[protobuf_unittest.TestMessageSetExtension2] {\n" 113 + " str: \"foo\"\n" 114 + "}\n"; 115 116 private static final String MESSAGE_SET_TEXT_WITH_REPEATED_EXTENSION = 117 "" 118 + "[protobuf_unittest.TestMessageSetExtension1] {\n" 119 + " i: 123\n" 120 + "}\n" 121 + "[protobuf_unittest.TestMessageSetExtension1] {\n" 122 + " i: 456\n" 123 + "}\n"; 124 125 private static final TextFormat.Parser PARSER_ALLOWING_UNKNOWN_FIELDS = 126 TextFormat.Parser.newBuilder().setAllowUnknownFields(true).build(); 127 128 private static final TextFormat.Parser PARSER_ALLOWING_UNKNOWN_EXTENSIONS = 129 TextFormat.Parser.newBuilder().setAllowUnknownExtensions(true).build(); 130 131 private static final TextFormat.Parser PARSER_WITH_OVERWRITE_FORBIDDEN = 132 TextFormat.Parser.newBuilder() 133 .setSingularOverwritePolicy(SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES) 134 .build(); 135 136 private static final TextFormat.Parser DEFAULT_PARSER = TextFormat.Parser.newBuilder().build(); 137 138 /** Print TestAllTypes and compare with golden file. */ 139 @Test testPrintMessage()140 public void testPrintMessage() throws Exception { 141 String javaText = TextFormat.printer().printToString(TestUtil.getAllSet()); 142 143 assertThat(javaText).isEqualTo(TestUtil.ALL_FIELDS_SET_TEXT); 144 } 145 146 @Test 147 // https://github.com/protocolbuffers/protobuf/issues/9447 testCharacterNotInUnicodeBlock()148 public void testCharacterNotInUnicodeBlock() throws TextFormat.InvalidEscapeSequenceException { 149 ByteString actual = TextFormat.unescapeBytes("\\U000358da"); 150 assertThat(actual.size()).isEqualTo(4); 151 } 152 153 /** Print TestAllTypes as Builder and compare with golden file. */ 154 @Test testPrintMessageBuilder()155 public void testPrintMessageBuilder() throws Exception { 156 String javaText = TextFormat.printer().printToString(TestUtil.getAllSetBuilder()); 157 158 assertThat(javaText).isEqualTo(TestUtil.ALL_FIELDS_SET_TEXT); 159 } 160 161 /** Print TestAllExtensions and compare with golden file. */ 162 @Test testPrintExtensions()163 public void testPrintExtensions() throws Exception { 164 String javaText = TextFormat.printer().printToString(TestUtil.getAllExtensionsSet()); 165 166 assertThat(javaText).isEqualTo(TestUtil.ALL_EXTENSIONS_SET_TEXT); 167 } 168 169 // Creates an example unknown field set. makeUnknownFieldSet()170 private UnknownFieldSet makeUnknownFieldSet() { 171 172 return UnknownFieldSet.newBuilder() 173 .addField( 174 5, 175 UnknownFieldSet.Field.newBuilder() 176 .addVarint(1) 177 .addFixed32(2) 178 .addFixed64(3) 179 .addLengthDelimited(ByteString.copyFromUtf8("4")) 180 .addLengthDelimited( 181 UnknownFieldSet.newBuilder() 182 .addField(12, UnknownFieldSet.Field.newBuilder().addVarint(6).build()) 183 .build() 184 .toByteString()) 185 .addGroup( 186 UnknownFieldSet.newBuilder() 187 .addField(10, UnknownFieldSet.Field.newBuilder().addVarint(5).build()) 188 .build()) 189 .build()) 190 .addField( 191 8, UnknownFieldSet.Field.newBuilder().addVarint(1).addVarint(2).addVarint(3).build()) 192 .addField( 193 15, 194 UnknownFieldSet.Field.newBuilder() 195 .addVarint(0xABCDEF1234567890L) 196 .addFixed32(0xABCD1234) 197 .addFixed64(0xABCDEF1234567890L) 198 .build()) 199 .build(); 200 } 201 202 @Test testPrintUnknownFields()203 public void testPrintUnknownFields() throws Exception { 204 // Test printing of unknown fields in a message. 205 206 TestEmptyMessage message = 207 TestEmptyMessage.newBuilder().setUnknownFields(makeUnknownFieldSet()).build(); 208 209 assertThat(TextFormat.printer().printToString(message)) 210 .isEqualTo( 211 "5: 1\n" 212 + "5: 0x00000002\n" 213 + "5: 0x0000000000000003\n" 214 + "5: \"4\"\n" 215 + "5: {\n" 216 + " 12: 6\n" 217 + "}\n" 218 + "5 {\n" 219 + " 10: 5\n" 220 + "}\n" 221 + "8: 1\n" 222 + "8: 2\n" 223 + "8: 3\n" 224 + "15: 12379813812177893520\n" 225 + "15: 0xabcd1234\n" 226 + "15: 0xabcdef1234567890\n"); 227 } 228 229 @Test testPrintField()230 public void testPrintField() throws Exception { 231 final FieldDescriptor dataField = OneString.getDescriptor().findFieldByName("data"); 232 assertThat(TextFormat.printer().printFieldToString(dataField, "test data")) 233 .isEqualTo("data: \"test data\"\n"); 234 235 final FieldDescriptor optionalField = 236 TestAllTypes.getDescriptor().findFieldByName("optional_nested_message"); 237 final Object value = NestedMessage.newBuilder().setBb(42).build(); 238 239 assertThat(TextFormat.printer().printFieldToString(optionalField, value)) 240 .isEqualTo("optional_nested_message {\n bb: 42\n}\n"); 241 } 242 243 /** 244 * Helper to construct a ByteString from a String containing only 8-bit characters. The characters 245 * are converted directly to bytes, *not* encoded using UTF-8. 246 */ bytes(String str)247 private ByteString bytes(String str) { 248 return ByteString.copyFrom(str.getBytes(Internal.ISO_8859_1)); 249 } 250 251 /** 252 * Helper to construct a ByteString from a bunch of bytes. The inputs are actually ints so that I 253 * can use hex notation and not get stupid errors about precision. 254 */ bytes(int... bytesAsInts)255 private ByteString bytes(int... bytesAsInts) { 256 byte[] bytes = new byte[bytesAsInts.length]; 257 for (int i = 0; i < bytesAsInts.length; i++) { 258 bytes[i] = (byte) bytesAsInts[i]; 259 } 260 return ByteString.copyFrom(bytes); 261 } 262 263 @Test testPrintExotic()264 public void testPrintExotic() throws Exception { 265 Message message = 266 TestAllTypes.newBuilder() 267 // Signed vs. unsigned numbers. 268 .addRepeatedInt32(-1) 269 .addRepeatedUint32(-1) 270 .addRepeatedInt64(-1) 271 .addRepeatedUint64(-1) 272 .addRepeatedInt32(1 << 31) 273 .addRepeatedUint32(1 << 31) 274 .addRepeatedInt64(1L << 63) 275 .addRepeatedUint64(1L << 63) 276 277 // Floats of various precisions and exponents. 278 .addRepeatedDouble(123) 279 .addRepeatedDouble(123.5) 280 .addRepeatedDouble(0.125) 281 .addRepeatedDouble(.125) 282 .addRepeatedDouble(-.125) 283 .addRepeatedDouble(123e15) 284 .addRepeatedDouble(123e15) 285 .addRepeatedDouble(-1.23e-17) 286 .addRepeatedDouble(.23e17) 287 .addRepeatedDouble(-23e15) 288 .addRepeatedDouble(123.5e20) 289 .addRepeatedDouble(123.5e-20) 290 .addRepeatedDouble(123.456789) 291 .addRepeatedDouble(Double.POSITIVE_INFINITY) 292 .addRepeatedDouble(Double.NEGATIVE_INFINITY) 293 .addRepeatedDouble(Double.NaN) 294 295 // Strings and bytes that needing escaping. 296 .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234") 297 .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe")) 298 .build(); 299 300 assertThat(message.toString()).isEqualTo(CANONICAL_EXOTIC_TEXT); 301 } 302 303 @Test testRoundtripProto3Optional()304 public void testRoundtripProto3Optional() throws Exception { 305 Message message = 306 TestProto3Optional.newBuilder() 307 .setOptionalInt32(1) 308 .setOptionalInt64(2) 309 .setOptionalNestedEnum(NestedEnum.BAZ) 310 .build(); 311 TestProto3Optional.Builder message2 = TestProto3Optional.newBuilder(); 312 TextFormat.merge(message.toString(), message2); 313 314 assertThat(message2.hasOptionalInt32()).isTrue(); 315 assertThat(message2.hasOptionalInt64()).isTrue(); 316 assertThat(message2.hasOptionalNestedEnum()).isTrue(); 317 assertThat(message2.getOptionalInt32()).isEqualTo(1); 318 assertThat(message2.getOptionalInt64()).isEqualTo(2); 319 assertThat(message2.getOptionalNestedEnum()).isEqualTo(NestedEnum.BAZ); 320 } 321 322 @Test testPrintMessageSet()323 public void testPrintMessageSet() throws Exception { 324 TestMessageSet messageSet = 325 TestMessageSet.newBuilder() 326 .setExtension( 327 TestMessageSetExtension1.messageSetExtension, 328 TestMessageSetExtension1.newBuilder().setI(123).build()) 329 .setExtension( 330 TestMessageSetExtension2.messageSetExtension, 331 TestMessageSetExtension2.newBuilder().setStr("foo").build()) 332 .build(); 333 334 assertThat(messageSet.toString()).isEqualTo(MESSAGE_SET_TEXT); 335 } 336 337 // ================================================================= 338 339 @Test testMerge()340 public void testMerge() throws Exception { 341 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 342 TextFormat.merge(TestUtil.ALL_FIELDS_SET_TEXT, builder); 343 TestUtil.assertAllFieldsSet(builder.build()); 344 } 345 346 @Test testParse()347 public void testParse() throws Exception { 348 TestUtil.assertAllFieldsSet(TextFormat.parse(TestUtil.ALL_FIELDS_SET_TEXT, TestAllTypes.class)); 349 } 350 351 @Test testMergeInitialized()352 public void testMergeInitialized() throws Exception { 353 TestRequired.Builder builder = TestRequired.newBuilder(); 354 TextFormat.merge(TEST_REQUIRED_INITIALIZED.toString(), builder); 355 assertThat(builder.buildPartial().toString()).isEqualTo(TEST_REQUIRED_INITIALIZED.toString()); 356 assertThat(builder.isInitialized()).isTrue(); 357 } 358 359 @Test testParseInitialized()360 public void testParseInitialized() throws Exception { 361 TestRequired parsed = 362 TextFormat.parse(TEST_REQUIRED_INITIALIZED.toString(), TestRequired.class); 363 assertThat(parsed.toString()).isEqualTo(TEST_REQUIRED_INITIALIZED.toString()); 364 assertThat(parsed.isInitialized()).isTrue(); 365 } 366 367 @Test testMergeUninitialized()368 public void testMergeUninitialized() throws Exception { 369 TestRequired.Builder builder = TestRequired.newBuilder(); 370 TextFormat.merge(TEST_REQUIRED_UNINITIALIZED.toString(), builder); 371 assertThat(builder.buildPartial().toString()).isEqualTo(TEST_REQUIRED_UNINITIALIZED.toString()); 372 assertThat(builder.isInitialized()).isFalse(); 373 } 374 375 @Test testParseUninitialized()376 public void testParseUninitialized() throws Exception { 377 try { 378 TextFormat.parse(TEST_REQUIRED_UNINITIALIZED.toString(), TestRequired.class); 379 assertWithMessage("Expected UninitializedMessageException.").fail(); 380 } catch (UninitializedMessageException e) { 381 assertThat(e).hasMessageThat().isEqualTo("Message missing required fields: b, c"); 382 } 383 } 384 385 @Test testMergeReader()386 public void testMergeReader() throws Exception { 387 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 388 TextFormat.merge(new StringReader(TestUtil.ALL_FIELDS_SET_TEXT), builder); 389 TestUtil.assertAllFieldsSet(builder.build()); 390 } 391 392 @Test testMergeExtensions()393 public void testMergeExtensions() throws Exception { 394 TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); 395 TextFormat.merge( 396 TestUtil.ALL_EXTENSIONS_SET_TEXT, TestUtil.getFullExtensionRegistry(), builder); 397 TestUtil.assertAllExtensionsSet(builder.build()); 398 } 399 400 @Test testParseExtensions()401 public void testParseExtensions() throws Exception { 402 TestUtil.assertAllExtensionsSet( 403 TextFormat.parse( 404 TestUtil.ALL_EXTENSIONS_SET_TEXT, 405 TestUtil.getFullExtensionRegistry(), 406 TestAllExtensions.class)); 407 } 408 409 @Test testMergeAndParseCompatibility()410 public void testMergeAndParseCompatibility() throws Exception { 411 String original = 412 "repeated_float: inf\n" 413 + "repeated_float: -inf\n" 414 + "repeated_float: nan\n" 415 + "repeated_float: inff\n" 416 + "repeated_float: -inff\n" 417 + "repeated_float: nanf\n" 418 + "repeated_float: 1.0f\n" 419 + "repeated_float: infinityf\n" 420 + "repeated_float: -Infinityf\n" 421 + "repeated_double: infinity\n" 422 + "repeated_double: -infinity\n" 423 + "repeated_double: nan\n"; 424 String canonical = 425 "repeated_float: Infinity\n" 426 + "repeated_float: -Infinity\n" 427 + "repeated_float: NaN\n" 428 + "repeated_float: Infinity\n" 429 + "repeated_float: -Infinity\n" 430 + "repeated_float: NaN\n" 431 + "repeated_float: 1.0\n" 432 + "repeated_float: Infinity\n" 433 + "repeated_float: -Infinity\n" 434 + "repeated_double: Infinity\n" 435 + "repeated_double: -Infinity\n" 436 + "repeated_double: NaN\n"; 437 438 // Test merge(). 439 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 440 TextFormat.merge(original, builder); 441 assertThat(builder.build().toString()).isEqualTo(canonical); 442 443 // Test parse(). 444 assertThat(TextFormat.parse(original, TestAllTypes.class).toString()).isEqualTo(canonical); 445 } 446 447 @Test testMergeAndParseExotic()448 public void testMergeAndParseExotic() throws Exception { 449 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 450 TextFormat.merge(EXOTIC_TEXT, builder); 451 452 // Too lazy to check things individually. Don't try to debug this 453 // if testPrintExotic() is failing. 454 assertThat(builder.build().toString()).isEqualTo(CANONICAL_EXOTIC_TEXT); 455 assertThat(TextFormat.parse(EXOTIC_TEXT, TestAllTypes.class).toString()) 456 .isEqualTo(CANONICAL_EXOTIC_TEXT); 457 } 458 459 @Test testMergeMessageSet()460 public void testMergeMessageSet() throws Exception { 461 ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); 462 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); 463 extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); 464 465 TestMessageSet.Builder builder = TestMessageSet.newBuilder(); 466 TextFormat.merge(MESSAGE_SET_TEXT, extensionRegistry, builder); 467 TestMessageSet messageSet = builder.build(); 468 469 assertThat(messageSet.hasExtension(TestMessageSetExtension1.messageSetExtension)).isTrue(); 470 assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()) 471 .isEqualTo(123); 472 assertThat(messageSet.hasExtension(TestMessageSetExtension2.messageSetExtension)).isTrue(); 473 assertThat(messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr()) 474 .isEqualTo("foo"); 475 476 builder = TestMessageSet.newBuilder(); 477 TextFormat.merge(MESSAGE_SET_TEXT_WITH_REPEATED_EXTENSION, extensionRegistry, builder); 478 messageSet = builder.build(); 479 assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()) 480 .isEqualTo(456); 481 } 482 483 @Test testMergeMessageSetWithOverwriteForbidden()484 public void testMergeMessageSetWithOverwriteForbidden() throws Exception { 485 ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); 486 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); 487 extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); 488 489 TestMessageSet.Builder builder = TestMessageSet.newBuilder(); 490 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(MESSAGE_SET_TEXT, extensionRegistry, builder); 491 TestMessageSet messageSet = builder.build(); 492 assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()) 493 .isEqualTo(123); 494 assertThat(messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr()) 495 .isEqualTo("foo"); 496 497 builder = TestMessageSet.newBuilder(); 498 try { 499 PARSER_WITH_OVERWRITE_FORBIDDEN.merge( 500 MESSAGE_SET_TEXT_WITH_REPEATED_EXTENSION, extensionRegistry, builder); 501 assertWithMessage("expected parse exception").fail(); 502 } catch (TextFormat.ParseException e) { 503 assertThat(e) 504 .hasMessageThat() 505 .isEqualTo( 506 "4:44: Non-repeated field " 507 + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\"" 508 + " cannot be overwritten."); 509 } 510 } 511 512 @Test testMergeNumericEnum()513 public void testMergeNumericEnum() throws Exception { 514 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 515 TextFormat.merge("optional_nested_enum: 2", builder); 516 assertThat(builder.getOptionalNestedEnum()).isEqualTo(TestAllTypes.NestedEnum.BAR); 517 } 518 519 @Test testMergeAngleBrackets()520 public void testMergeAngleBrackets() throws Exception { 521 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 522 TextFormat.merge("OptionalGroup: < a: 1 >", builder); 523 assertThat(builder.hasOptionalGroup()).isTrue(); 524 assertThat(builder.getOptionalGroup().getA()).isEqualTo(1); 525 } 526 527 @Test testMergeComment()528 public void testMergeComment() throws Exception { 529 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 530 TextFormat.merge( 531 "# this is a comment\n" 532 + "optional_int32: 1 # another comment\n" 533 + "optional_int64: 2\n" 534 + "# EOF comment", 535 builder); 536 assertThat(builder.getOptionalInt32()).isEqualTo(1); 537 assertThat(builder.getOptionalInt64()).isEqualTo(2); 538 } 539 540 @Test testPrintAny_customBuiltTypeRegistry()541 public void testPrintAny_customBuiltTypeRegistry() throws Exception { 542 TestAny testAny = 543 TestAny.newBuilder() 544 .setValue( 545 Any.newBuilder() 546 .setTypeUrl("type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) 547 .setValue( 548 TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString()) 549 .build()) 550 .build(); 551 String actual = 552 TextFormat.printer() 553 .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 554 .printToString(testAny); 555 String expected = 556 "value {\n" 557 + " [type.googleapis.com/protobuf_unittest.TestAllTypes] {\n" 558 + " optional_int32: 12345\n" 559 + " }\n" 560 + "}\n"; 561 assertThat(actual).isEqualTo(expected); 562 } 563 createDescriptorForAny(FieldDescriptorProto... fields)564 private static Descriptor createDescriptorForAny(FieldDescriptorProto... fields) 565 throws Exception { 566 FileDescriptor fileDescriptor = 567 FileDescriptor.buildFrom( 568 FileDescriptorProto.newBuilder() 569 .setName("any.proto") 570 .setPackage("google.protobuf") 571 .setSyntax("proto3") 572 .addMessageType( 573 DescriptorProto.newBuilder().setName("Any").addAllField(Arrays.asList(fields))) 574 .build(), 575 new FileDescriptor[0]); 576 return fileDescriptor.getMessageTypes().get(0); 577 } 578 579 @Test testPrintAny_anyWithDynamicMessage()580 public void testPrintAny_anyWithDynamicMessage() throws Exception { 581 Descriptor descriptor = 582 createDescriptorForAny( 583 FieldDescriptorProto.newBuilder() 584 .setName("type_url") 585 .setNumber(1) 586 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 587 .setType(FieldDescriptorProto.Type.TYPE_STRING) 588 .build(), 589 FieldDescriptorProto.newBuilder() 590 .setName("value") 591 .setNumber(2) 592 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 593 .setType(FieldDescriptorProto.Type.TYPE_BYTES) 594 .build()); 595 DynamicMessage testAny = 596 DynamicMessage.newBuilder(descriptor) 597 .setField( 598 descriptor.findFieldByNumber(1), 599 "type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) 600 .setField( 601 descriptor.findFieldByNumber(2), 602 TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString()) 603 .build(); 604 String actual = 605 TextFormat.printer() 606 .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 607 .printToString(testAny); 608 String expected = 609 "[type.googleapis.com/protobuf_unittest.TestAllTypes] {\n" 610 + " optional_int32: 12345\n" 611 + "}\n"; 612 assertThat(actual).isEqualTo(expected); 613 } 614 615 @Test testPrintAny_anyWithDynamicMessageContainingExtensionTreatedAsUnknown()616 public void testPrintAny_anyWithDynamicMessageContainingExtensionTreatedAsUnknown() 617 throws Exception { 618 Descriptor descriptor = 619 createDescriptorForAny( 620 FieldDescriptorProto.newBuilder() 621 .setName("type_url") 622 .setNumber(1) 623 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 624 .setType(FieldDescriptorProto.Type.TYPE_STRING) 625 .build(), 626 FieldDescriptorProto.newBuilder() 627 .setName("value") 628 .setNumber(2) 629 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 630 .setType(FieldDescriptorProto.Type.TYPE_BYTES) 631 .build()); 632 DynamicMessage testAny = 633 DynamicMessage.newBuilder(descriptor) 634 .setField( 635 descriptor.findFieldByNumber(1), 636 "type.googleapis.com/" + TestAllExtensions.getDescriptor().getFullName()) 637 .setField( 638 descriptor.findFieldByNumber(2), 639 TestAllExtensions.newBuilder() 640 .setExtension(optionalInt32Extension, 12345) 641 .build() 642 .toByteString()) 643 .build(); 644 String actual = 645 TextFormat.printer() 646 .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 647 .printToString(testAny); 648 String expected = "[type.googleapis.com/protobuf_unittest.TestAllExtensions] {\n 1: 12345\n}\n"; 649 assertThat(actual).isEqualTo(expected); 650 } 651 652 @Test testPrintAny_anyWithDynamicMessageContainingExtensionWithRegistry()653 public void testPrintAny_anyWithDynamicMessageContainingExtensionWithRegistry() throws Exception { 654 Descriptor descriptor = 655 createDescriptorForAny( 656 FieldDescriptorProto.newBuilder() 657 .setName("type_url") 658 .setNumber(1) 659 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 660 .setType(FieldDescriptorProto.Type.TYPE_STRING) 661 .build(), 662 FieldDescriptorProto.newBuilder() 663 .setName("value") 664 .setNumber(2) 665 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 666 .setType(FieldDescriptorProto.Type.TYPE_BYTES) 667 .build()); 668 DynamicMessage testAny = 669 DynamicMessage.newBuilder(descriptor) 670 .setField( 671 descriptor.findFieldByNumber(1), 672 "type.googleapis.com/" + TestAllExtensions.getDescriptor().getFullName()) 673 .setField( 674 descriptor.findFieldByNumber(2), 675 TestAllExtensions.newBuilder() 676 .setExtension(optionalInt32Extension, 12345) 677 .build() 678 .toByteString()) 679 .build(); 680 String actual = 681 TextFormat.printer() 682 .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 683 .usingExtensionRegistry(TestUtil.getFullExtensionRegistry()) 684 .printToString(testAny); 685 String expected = 686 "[type.googleapis.com/protobuf_unittest.TestAllExtensions] {\n" 687 + " [protobuf_unittest.optional_int32_extension]: 12345\n" 688 + "}\n"; 689 assertThat(actual).isEqualTo(expected); 690 } 691 692 @Test testPrintAny_anyFromWithNoValueField()693 public void testPrintAny_anyFromWithNoValueField() throws Exception { 694 Descriptor descriptor = 695 createDescriptorForAny( 696 FieldDescriptorProto.newBuilder() 697 .setName("type_url") 698 .setNumber(1) 699 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 700 .setType(FieldDescriptorProto.Type.TYPE_STRING) 701 .build()); 702 DynamicMessage testAny = 703 DynamicMessage.newBuilder(descriptor) 704 .setField( 705 descriptor.findFieldByNumber(1), 706 "type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) 707 .build(); 708 String actual = 709 TextFormat.printer() 710 .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 711 .printToString(testAny); 712 String expected = "type_url: \"type.googleapis.com/protobuf_unittest.TestAllTypes\"\n"; 713 assertThat(actual).isEqualTo(expected); 714 } 715 716 @Test testPrintAny_anyFromWithNoTypeUrlField()717 public void testPrintAny_anyFromWithNoTypeUrlField() throws Exception { 718 Descriptor descriptor = 719 createDescriptorForAny( 720 FieldDescriptorProto.newBuilder() 721 .setName("value") 722 .setNumber(2) 723 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 724 .setType(FieldDescriptorProto.Type.TYPE_BYTES) 725 .build()); 726 DynamicMessage testAny = 727 DynamicMessage.newBuilder(descriptor) 728 .setField( 729 descriptor.findFieldByNumber(2), 730 TestAllTypes.newBuilder().setOptionalInt32(12345).build().toByteString()) 731 .build(); 732 String actual = 733 TextFormat.printer() 734 .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 735 .printToString(testAny); 736 String expected = "value: \"\\b\\271`\"\n"; 737 assertThat(actual).isEqualTo(expected); 738 } 739 740 @Test testPrintAny_anyWithInvalidFieldType()741 public void testPrintAny_anyWithInvalidFieldType() throws Exception { 742 Descriptor descriptor = 743 createDescriptorForAny( 744 FieldDescriptorProto.newBuilder() 745 .setName("type_url") 746 .setNumber(1) 747 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 748 .setType(FieldDescriptorProto.Type.TYPE_STRING) 749 .build(), 750 FieldDescriptorProto.newBuilder() 751 .setName("value") 752 .setNumber(2) 753 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 754 .setType(FieldDescriptorProto.Type.TYPE_STRING) 755 .build()); 756 DynamicMessage testAny = 757 DynamicMessage.newBuilder(descriptor) 758 .setField( 759 descriptor.findFieldByNumber(1), 760 "type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) 761 .setField(descriptor.findFieldByNumber(2), "test") 762 .build(); 763 String actual = 764 TextFormat.printer() 765 .usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 766 .printToString(testAny); 767 String expected = 768 "type_url: \"type.googleapis.com/protobuf_unittest.TestAllTypes\"\n" + "value: \"test\"\n"; 769 assertThat(actual).isEqualTo(expected); 770 } 771 772 @Test testMergeAny_customBuiltTypeRegistry()773 public void testMergeAny_customBuiltTypeRegistry() throws Exception { 774 TestAny.Builder builder = TestAny.newBuilder(); 775 TextFormat.Parser.newBuilder() 776 .setTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 777 .build() 778 .merge( 779 "value: {\n" 780 + "[type.googleapis.com/protobuf_unittest.TestAllTypes] {\n" 781 + "optional_int32: 12345\n" 782 + "optional_nested_message {\n" 783 + " bb: 123\n" 784 + "}\n" 785 + "}\n" 786 + "}", 787 builder); 788 assertThat(builder.build()) 789 .isEqualTo( 790 TestAny.newBuilder() 791 .setValue( 792 Any.newBuilder() 793 .setTypeUrl( 794 "type.googleapis.com/" + TestAllTypes.getDescriptor().getFullName()) 795 .setValue( 796 TestAllTypes.newBuilder() 797 .setOptionalInt32(12345) 798 .setOptionalNestedMessage( 799 TestAllTypes.NestedMessage.newBuilder().setBb(123)) 800 .build() 801 .toByteString()) 802 .build()) 803 .build()); 804 } 805 assertParseError(String error, String text)806 private void assertParseError(String error, String text) { 807 // Test merge(). 808 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 809 try { 810 TextFormat.merge(text, TestUtil.getFullExtensionRegistry(), builder); 811 assertWithMessage("Expected parse exception.").fail(); 812 } catch (TextFormat.ParseException e) { 813 assertThat(e).hasMessageThat().isEqualTo(error); 814 } 815 816 // Test parse(). 817 try { 818 TextFormat.parse(text, TestUtil.getFullExtensionRegistry(), TestAllTypes.class); 819 assertWithMessage("Expected parse exception.").fail(); 820 } catch (TextFormat.ParseException e) { 821 assertThat(e).hasMessageThat().isEqualTo(error); 822 } 823 } 824 assertParseErrorWithUnknownFields(String error, String text)825 private void assertParseErrorWithUnknownFields(String error, String text) { 826 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 827 try { 828 PARSER_ALLOWING_UNKNOWN_FIELDS.merge(text, TestUtil.getFullExtensionRegistry(), builder); 829 assertWithMessage("Expected parse exception.").fail(); 830 } catch (TextFormat.ParseException e) { 831 assertThat(e).hasMessageThat().isEqualTo(error); 832 } 833 } 834 assertParseSuccessWithUnknownFields(String text)835 private TestAllTypes assertParseSuccessWithUnknownFields(String text) 836 throws TextFormat.ParseException { 837 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 838 PARSER_ALLOWING_UNKNOWN_FIELDS.merge(text, TestUtil.getFullExtensionRegistry(), builder); 839 return builder.build(); 840 } 841 assertParseErrorWithUnknownExtensions(String error, String text)842 private void assertParseErrorWithUnknownExtensions(String error, String text) { 843 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 844 try { 845 PARSER_ALLOWING_UNKNOWN_EXTENSIONS.merge(text, builder); 846 assertWithMessage("Expected parse exception.").fail(); 847 } catch (TextFormat.ParseException e) { 848 assertThat(e).hasMessageThat().isEqualTo(error); 849 } 850 } 851 assertParseSuccessWithUnknownExtensions(String text)852 private TestAllTypes assertParseSuccessWithUnknownExtensions(String text) 853 throws TextFormat.ParseException { 854 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 855 PARSER_ALLOWING_UNKNOWN_EXTENSIONS.merge(text, builder); 856 return builder.build(); 857 } 858 assertParseErrorWithOverwriteForbidden(String error, String text)859 private void assertParseErrorWithOverwriteForbidden(String error, String text) { 860 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 861 try { 862 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, TestUtil.getFullExtensionRegistry(), builder); 863 assertWithMessage("Expected parse exception.").fail(); 864 } catch (TextFormat.ParseException e) { 865 assertThat(e).hasMessageThat().isEqualTo(error); 866 } 867 } 868 869 @CanIgnoreReturnValue assertParseSuccessWithOverwriteForbidden(String text)870 private TestAllTypes assertParseSuccessWithOverwriteForbidden(String text) 871 throws TextFormat.ParseException { 872 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 873 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, TestUtil.getFullExtensionRegistry(), builder); 874 return builder.build(); 875 } 876 877 @Test testParseErrors()878 public void testParseErrors() throws Exception { 879 assertParseError("1:16: Expected \":\".", "optional_int32 123"); 880 assertParseError("1:23: Expected identifier. Found '?'", "optional_nested_enum: ?"); 881 assertParseError( 882 "1:18: Couldn't parse integer: Number must be positive: -1", "optional_uint32: -1"); 883 assertParseError( 884 "1:17: Couldn't parse integer: Number out of range for 32-bit signed " 885 + "integer: 82301481290849012385230157", 886 "optional_int32: 82301481290849012385230157"); 887 assertParseError( 888 "1:16: Expected \"true\" or \"false\". Found \"maybe\".", "optional_bool: maybe"); 889 assertParseError("1:16: Expected \"true\" or \"false\". Found \"2\".", "optional_bool: 2"); 890 assertParseError("1:18: Expected string.", "optional_string: 123"); 891 assertParseError("1:18: String missing ending quote.", "optional_string: \"ueoauaoe"); 892 assertParseError( 893 "1:18: String missing ending quote.", "optional_string: \"ueoauaoe\noptional_int32: 123"); 894 assertParseError("1:18: Invalid escape sequence: '\\z'", "optional_string: \"\\z\""); 895 assertParseError( 896 "1:18: String missing ending quote.", "optional_string: \"ueoauaoe\noptional_int32: 123"); 897 assertParseError( 898 "1:2: Input contains unknown fields and/or extensions:\n" 899 + "1:2:\tprotobuf_unittest.TestAllTypes.[nosuchext]", 900 "[nosuchext]: 123"); 901 assertParseError( 902 "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " 903 + "not extend message type \"protobuf_unittest.TestAllTypes\".", 904 "[protobuf_unittest.optional_int32_extension]: 123"); 905 assertParseError( 906 "1:1: Input contains unknown fields and/or extensions:\n" 907 + "1:1:\tprotobuf_unittest.TestAllTypes.nosuchfield", 908 "nosuchfield: 123"); 909 assertParseError("1:21: Expected \">\".", "OptionalGroup < a: 1"); 910 assertParseError( 911 "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " 912 + "value named \"NO_SUCH_VALUE\".", 913 "optional_nested_enum: NO_SUCH_VALUE"); 914 assertParseError( 915 "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " 916 + "value with number 123.", 917 "optional_nested_enum: 123"); 918 919 // Delimiters must match. 920 assertParseError("1:22: Expected identifier. Found '}'", "OptionalGroup < a: 1 }"); 921 assertParseError("1:22: Expected identifier. Found '>'", "OptionalGroup { a: 1 >"); 922 } 923 924 // ================================================================= 925 @Test testEscapeQuestionMark()926 public void testEscapeQuestionMark() throws InvalidEscapeSequenceException { 927 assertThat(TextFormat.unescapeText("?")).isEqualTo("?"); 928 assertThat(TextFormat.unescapeText("\\?")).isEqualTo("?"); 929 } 930 931 @Test testEscape()932 public void testEscape() throws Exception { 933 // Escape sequences. 934 assertThat(TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\177"))) 935 .isEqualTo("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177"); 936 assertThat(TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\"\177")) 937 .isEqualTo("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177"); 938 assertThat(TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")) 939 .isEqualTo(bytes("\0\001\007\b\f\n\r\t\013\\\'\"")); 940 assertThat(TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"")) 941 .isEqualTo("\0\001\007\b\f\n\r\t\013\\\'\""); 942 assertThat(TextFormat.escapeText(ESCAPE_TEST_STRING)).isEqualTo(ESCAPE_TEST_STRING_ESCAPED); 943 assertThat(TextFormat.unescapeText(ESCAPE_TEST_STRING_ESCAPED)).isEqualTo(ESCAPE_TEST_STRING); 944 945 // Invariant 946 assertThat(TextFormat.escapeBytes(bytes("hello"))).isEqualTo("hello"); 947 assertThat(TextFormat.escapeText("hello")).isEqualTo("hello"); 948 assertThat(TextFormat.unescapeBytes("hello")).isEqualTo(bytes("hello")); 949 assertThat(TextFormat.unescapeText("hello")).isEqualTo("hello"); 950 951 // Unicode handling. 952 assertThat(TextFormat.escapeText("\u1234")).isEqualTo("\\341\\210\\264"); 953 assertThat(TextFormat.escapeBytes(bytes(0xe1, 0x88, 0xb4))).isEqualTo("\\341\\210\\264"); 954 assertThat(TextFormat.unescapeText("\\341\\210\\264")).isEqualTo("\u1234"); 955 assertThat(TextFormat.unescapeBytes("\\341\\210\\264")).isEqualTo(bytes(0xe1, 0x88, 0xb4)); 956 assertThat(TextFormat.unescapeText("\\xe1\\x88\\xb4")).isEqualTo("\u1234"); 957 assertThat(TextFormat.unescapeBytes("\\xe1\\x88\\xb4")).isEqualTo(bytes(0xe1, 0x88, 0xb4)); 958 assertThat(TextFormat.unescapeText("\\u1234")).isEqualTo("\u1234"); 959 assertThat(TextFormat.unescapeBytes("\\u1234")).isEqualTo(bytes(0xe1, 0x88, 0xb4)); 960 assertThat(TextFormat.unescapeBytes("\\U00001234")).isEqualTo(bytes(0xe1, 0x88, 0xb4)); 961 assertThat(TextFormat.unescapeText("\\xf0\\x90\\x90\\xb7")) 962 .isEqualTo(new String(new int[] {0x10437}, 0, 1)); 963 assertThat(TextFormat.unescapeBytes("\\U00010437")).isEqualTo(bytes(0xf0, 0x90, 0x90, 0xb7)); 964 965 // Handling of strings with unescaped Unicode characters > 255. 966 final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c"; 967 ByteString zhByteString = ByteString.copyFromUtf8(zh); 968 assertThat(TextFormat.unescapeBytes(zh)).isEqualTo(zhByteString); 969 970 // Errors. 971 try { 972 TextFormat.unescapeText("\\x"); 973 assertWithMessage("Should have thrown an exception.").fail(); 974 } catch (TextFormat.InvalidEscapeSequenceException e) { 975 // success 976 } 977 978 try { 979 TextFormat.unescapeText("\\z"); 980 assertWithMessage("Should have thrown an exception.").fail(); 981 } catch (TextFormat.InvalidEscapeSequenceException e) { 982 // success 983 } 984 985 try { 986 TextFormat.unescapeText("\\"); 987 assertWithMessage("Should have thrown an exception.").fail(); 988 } catch (TextFormat.InvalidEscapeSequenceException e) { 989 // success 990 } 991 992 try { 993 TextFormat.unescapeText("\\u"); 994 assertWithMessage("Should have thrown an exception.").fail(); 995 } catch (TextFormat.InvalidEscapeSequenceException e) { 996 assertThat(e) 997 .hasMessageThat() 998 .isEqualTo("Invalid escape sequence: '\\u' with too few hex chars"); 999 } 1000 1001 try { 1002 TextFormat.unescapeText("\\ud800"); 1003 assertWithMessage("Should have thrown an exception.").fail(); 1004 } catch (TextFormat.InvalidEscapeSequenceException e) { 1005 assertThat(e) 1006 .hasMessageThat() 1007 .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); 1008 } 1009 1010 try { 1011 TextFormat.unescapeText("\\ud800\\u1234"); 1012 assertWithMessage("Should have thrown an exception.").fail(); 1013 } catch (TextFormat.InvalidEscapeSequenceException e) { 1014 assertThat(e) 1015 .hasMessageThat() 1016 .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); 1017 } 1018 1019 try { 1020 TextFormat.unescapeText("\\udc00"); 1021 assertWithMessage("Should have thrown an exception.").fail(); 1022 } catch (TextFormat.InvalidEscapeSequenceException e) { 1023 assertThat(e) 1024 .hasMessageThat() 1025 .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); 1026 } 1027 1028 try { 1029 TextFormat.unescapeText("\\ud801\\udc37"); 1030 assertWithMessage("Should have thrown an exception.").fail(); 1031 } catch (TextFormat.InvalidEscapeSequenceException e) { 1032 assertThat(e) 1033 .hasMessageThat() 1034 .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); 1035 } 1036 1037 try { 1038 TextFormat.unescapeText("\\U1234"); 1039 assertWithMessage("Should have thrown an exception.").fail(); 1040 } catch (TextFormat.InvalidEscapeSequenceException e) { 1041 assertThat(e) 1042 .hasMessageThat() 1043 .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars"); 1044 } 1045 1046 try { 1047 TextFormat.unescapeText("\\U1234no more hex"); 1048 assertWithMessage("Should have thrown an exception.").fail(); 1049 } catch (TextFormat.InvalidEscapeSequenceException e) { 1050 assertThat(e) 1051 .hasMessageThat() 1052 .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars"); 1053 } 1054 1055 try { 1056 TextFormat.unescapeText("\\U00110000"); 1057 assertWithMessage("Should have thrown an exception.").fail(); 1058 } catch (TextFormat.InvalidEscapeSequenceException e) { 1059 assertThat(e) 1060 .hasMessageThat() 1061 .isEqualTo("Invalid escape sequence: '\\U00110000' is not a valid code point value"); 1062 } 1063 1064 try { 1065 TextFormat.unescapeText("\\U0000d801\\U00000dc37"); 1066 assertWithMessage("Should have thrown an exception.").fail(); 1067 } catch (TextFormat.InvalidEscapeSequenceException e) { 1068 assertThat(e) 1069 .hasMessageThat() 1070 .isEqualTo("Invalid escape sequence: '\\U0000d801' refers to a surrogate code unit"); 1071 } 1072 } 1073 1074 @Test testParseInteger()1075 public void testParseInteger() throws Exception { 1076 assertThat(TextFormat.parseInt32("0")).isEqualTo(0); 1077 assertThat(TextFormat.parseInt32("1")).isEqualTo(1); 1078 assertThat(TextFormat.parseInt32("-1")).isEqualTo(-1); 1079 assertThat(TextFormat.parseInt32("12345")).isEqualTo(12345); 1080 assertThat(TextFormat.parseInt32("-12345")).isEqualTo(-12345); 1081 assertThat(TextFormat.parseInt32("2147483647")).isEqualTo(2147483647); 1082 assertThat(TextFormat.parseInt32("-2147483648")).isEqualTo(-2147483648); 1083 1084 assertThat(TextFormat.parseUInt32("0")).isEqualTo(0); 1085 assertThat(TextFormat.parseUInt32("1")).isEqualTo(1); 1086 assertThat(TextFormat.parseUInt32("12345")).isEqualTo(12345); 1087 assertThat(TextFormat.parseUInt32("2147483647")).isEqualTo(2147483647); 1088 assertThat(TextFormat.parseUInt32("2147483648")).isEqualTo((int) 2147483648L); 1089 assertThat(TextFormat.parseUInt32("4294967295")).isEqualTo((int) 4294967295L); 1090 1091 assertThat(TextFormat.parseInt64("0")).isEqualTo(0L); 1092 assertThat(TextFormat.parseInt64("1")).isEqualTo(1L); 1093 assertThat(TextFormat.parseInt64("-1")).isEqualTo(-1L); 1094 assertThat(TextFormat.parseInt64("12345")).isEqualTo(12345L); 1095 assertThat(TextFormat.parseInt64("-12345")).isEqualTo(-12345L); 1096 assertThat(TextFormat.parseInt64("2147483647")).isEqualTo(2147483647L); 1097 assertThat(TextFormat.parseInt64("-2147483648")).isEqualTo(-2147483648L); 1098 assertThat(TextFormat.parseInt64("4294967295")).isEqualTo(4294967295L); 1099 assertThat(TextFormat.parseInt64("4294967296")).isEqualTo(4294967296L); 1100 assertThat(TextFormat.parseInt64("9223372036854775807")).isEqualTo(9223372036854775807L); 1101 assertThat(TextFormat.parseInt64("-9223372036854775808")).isEqualTo(-9223372036854775808L); 1102 1103 assertThat(TextFormat.parseUInt64("0")).isEqualTo(0L); 1104 assertThat(TextFormat.parseUInt64("1")).isEqualTo(1L); 1105 assertThat(TextFormat.parseUInt64("12345")).isEqualTo(12345L); 1106 assertThat(TextFormat.parseUInt64("2147483647")).isEqualTo(2147483647L); 1107 assertThat(TextFormat.parseUInt64("4294967295")).isEqualTo(4294967295L); 1108 assertThat(TextFormat.parseUInt64("4294967296")).isEqualTo(4294967296L); 1109 assertThat(TextFormat.parseUInt64("9223372036854775807")).isEqualTo(9223372036854775807L); 1110 assertThat(TextFormat.parseUInt64("9223372036854775808")).isEqualTo(-9223372036854775808L); 1111 assertThat(TextFormat.parseUInt64("18446744073709551615")).isEqualTo(-1L); 1112 1113 // Hex 1114 assertThat(TextFormat.parseInt32("0x1234abcd")).isEqualTo(0x1234abcd); 1115 assertThat(TextFormat.parseInt32("-0x1234abcd")).isEqualTo(-0x1234abcd); 1116 assertThat(TextFormat.parseUInt64("0xffffffffffffffff")).isEqualTo(-1); 1117 assertThat(TextFormat.parseInt64("0x7fffffffffffffff")).isEqualTo(0x7fffffffffffffffL); 1118 1119 // Octal 1120 assertThat(TextFormat.parseInt32("01234567")).isEqualTo(01234567); 1121 1122 // Out-of-range 1123 try { 1124 TextFormat.parseInt32("2147483648"); 1125 assertWithMessage("Should have thrown an exception.").fail(); 1126 } catch (NumberFormatException e) { 1127 // success 1128 } 1129 1130 try { 1131 TextFormat.parseInt32("-2147483649"); 1132 assertWithMessage("Should have thrown an exception.").fail(); 1133 } catch (NumberFormatException e) { 1134 // success 1135 } 1136 1137 try { 1138 TextFormat.parseUInt32("4294967296"); 1139 assertWithMessage("Should have thrown an exception.").fail(); 1140 } catch (NumberFormatException e) { 1141 // success 1142 } 1143 1144 try { 1145 TextFormat.parseUInt32("-1"); 1146 assertWithMessage("Should have thrown an exception.").fail(); 1147 } catch (NumberFormatException e) { 1148 // success 1149 } 1150 1151 try { 1152 TextFormat.parseInt64("9223372036854775808"); 1153 assertWithMessage("Should have thrown an exception.").fail(); 1154 } catch (NumberFormatException e) { 1155 // success 1156 } 1157 1158 try { 1159 TextFormat.parseInt64("-9223372036854775809"); 1160 assertWithMessage("Should have thrown an exception.").fail(); 1161 } catch (NumberFormatException e) { 1162 // success 1163 } 1164 1165 try { 1166 TextFormat.parseUInt64("18446744073709551616"); 1167 assertWithMessage("Should have thrown an exception.").fail(); 1168 } catch (NumberFormatException e) { 1169 // success 1170 } 1171 1172 try { 1173 TextFormat.parseUInt64("-1"); 1174 assertWithMessage("Should have thrown an exception.").fail(); 1175 } catch (NumberFormatException e) { 1176 // success 1177 } 1178 1179 // Not a number. 1180 try { 1181 TextFormat.parseInt32("abcd"); 1182 assertWithMessage("Should have thrown an exception.").fail(); 1183 } catch (NumberFormatException e) { 1184 // success 1185 } 1186 } 1187 1188 @Test testParseString()1189 public void testParseString() throws Exception { 1190 final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c"; 1191 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 1192 TextFormat.merge("optional_string: \"" + zh + "\"", builder); 1193 assertThat(builder.getOptionalString()).isEqualTo(zh); 1194 } 1195 1196 @Test testParseLongString()1197 public void testParseLongString() throws Exception { 1198 String longText = 1199 "123456789012345678901234567890123456789012345678901234567890" 1200 + "123456789012345678901234567890123456789012345678901234567890" 1201 + "123456789012345678901234567890123456789012345678901234567890" 1202 + "123456789012345678901234567890123456789012345678901234567890" 1203 + "123456789012345678901234567890123456789012345678901234567890" 1204 + "123456789012345678901234567890123456789012345678901234567890" 1205 + "123456789012345678901234567890123456789012345678901234567890" 1206 + "123456789012345678901234567890123456789012345678901234567890" 1207 + "123456789012345678901234567890123456789012345678901234567890" 1208 + "123456789012345678901234567890123456789012345678901234567890" 1209 + "123456789012345678901234567890123456789012345678901234567890" 1210 + "123456789012345678901234567890123456789012345678901234567890" 1211 + "123456789012345678901234567890123456789012345678901234567890" 1212 + "123456789012345678901234567890123456789012345678901234567890" 1213 + "123456789012345678901234567890123456789012345678901234567890" 1214 + "123456789012345678901234567890123456789012345678901234567890" 1215 + "123456789012345678901234567890123456789012345678901234567890" 1216 + "123456789012345678901234567890123456789012345678901234567890" 1217 + "123456789012345678901234567890123456789012345678901234567890" 1218 + "123456789012345678901234567890123456789012345678901234567890"; 1219 1220 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 1221 TextFormat.merge("optional_string: \"" + longText + "\"", builder); 1222 assertThat(builder.getOptionalString()).isEqualTo(longText); 1223 } 1224 1225 @Test testParseBoolean()1226 public void testParseBoolean() throws Exception { 1227 String goodText = 1228 "repeated_bool: t repeated_bool : 0\n" 1229 + "repeated_bool :f repeated_bool:1\n" 1230 + "repeated_bool: False repeated_bool: True"; 1231 String goodTextCanonical = 1232 "repeated_bool: true\n" 1233 + "repeated_bool: false\n" 1234 + "repeated_bool: false\n" 1235 + "repeated_bool: true\n" 1236 + "repeated_bool: false\n" 1237 + "repeated_bool: true\n"; 1238 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 1239 TextFormat.merge(goodText, builder); 1240 assertThat(builder.build().toString()).isEqualTo(goodTextCanonical); 1241 1242 try { 1243 TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder(); 1244 TextFormat.merge("optional_bool:2", badBuilder); 1245 assertWithMessage("Should have thrown an exception.").fail(); 1246 } catch (TextFormat.ParseException e) { 1247 // success 1248 } 1249 try { 1250 TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder(); 1251 TextFormat.merge("optional_bool: foo", badBuilder); 1252 assertWithMessage("Should have thrown an exception.").fail(); 1253 } catch (TextFormat.ParseException e) { 1254 // success 1255 } 1256 } 1257 1258 @Test testParseAdjacentStringLiterals()1259 public void testParseAdjacentStringLiterals() throws Exception { 1260 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 1261 TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder); 1262 assertThat(builder.getOptionalString()).isEqualTo("foocorgegrault"); 1263 } 1264 1265 @Test testPrintFieldValue()1266 public void testPrintFieldValue() throws Exception { 1267 assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string"); 1268 assertPrintFieldValue("123.0", 123f, "repeated_float"); 1269 assertPrintFieldValue("123.0", 123d, "repeated_double"); 1270 assertPrintFieldValue("123", 123, "repeated_int32"); 1271 assertPrintFieldValue("123", 123L, "repeated_int64"); 1272 assertPrintFieldValue("true", true, "repeated_bool"); 1273 assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32"); 1274 assertPrintFieldValue("18446744073709551615", 0xFFFFFFFFFFFFFFFFL, "repeated_uint64"); 1275 assertPrintFieldValue( 1276 "\"\\001\\002\\003\"", ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes"); 1277 } 1278 assertPrintFieldValue(String expect, Object value, String fieldName)1279 private void assertPrintFieldValue(String expect, Object value, String fieldName) 1280 throws Exception { 1281 StringBuilder sb = new StringBuilder(); 1282 TextFormat.printer() 1283 .printFieldValue(TestAllTypes.getDescriptor().findFieldByName(fieldName), value, sb); 1284 assertThat(sb.toString()).isEqualTo(expect); 1285 } 1286 1287 @Test testPrintFieldValueThrows()1288 public void testPrintFieldValueThrows() throws Exception { 1289 assertPrintFieldThrowsClassCastException(5, "repeated_string"); 1290 assertPrintFieldThrowsClassCastException(5L, "repeated_string"); 1291 assertPrintFieldThrowsClassCastException(ByteString.EMPTY, "repeated_string"); 1292 assertPrintFieldThrowsClassCastException(5, "repeated_float"); 1293 assertPrintFieldThrowsClassCastException(5D, "repeated_float"); 1294 assertPrintFieldThrowsClassCastException("text", "repeated_float"); 1295 assertPrintFieldThrowsClassCastException(5, "repeated_double"); 1296 assertPrintFieldThrowsClassCastException(5F, "repeated_double"); 1297 assertPrintFieldThrowsClassCastException("text", "repeated_double"); 1298 assertPrintFieldThrowsClassCastException(123L, "repeated_int32"); 1299 assertPrintFieldThrowsClassCastException(123, "repeated_int64"); 1300 assertPrintFieldThrowsClassCastException(1, "repeated_bytes"); 1301 } 1302 assertPrintFieldThrowsClassCastException(final Object value, String fieldName)1303 private void assertPrintFieldThrowsClassCastException(final Object value, String fieldName) 1304 throws Exception { 1305 final StringBuilder stringBuilder = new StringBuilder(); 1306 final FieldDescriptor fieldDescriptor = TestAllTypes.getDescriptor().findFieldByName(fieldName); 1307 assertThrows( 1308 ClassCastException.class, 1309 new ThrowingRunnable() { 1310 @Override 1311 public void run() throws Throwable { 1312 TextFormat.printer().printFieldValue(fieldDescriptor, value, stringBuilder); 1313 } 1314 }); 1315 } 1316 1317 @Test testShortDebugString()1318 public void testShortDebugString() { 1319 assertThat( 1320 TextFormat.shortDebugString( 1321 TestAllTypes.newBuilder() 1322 .addRepeatedInt32(1) 1323 .addRepeatedUint32(2) 1324 .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(42).build()) 1325 .build())) 1326 .isEqualTo("optional_nested_message { bb: 42 } repeated_int32: 1 repeated_uint32: 2"); 1327 } 1328 1329 @Test testShortDebugString_field()1330 public void testShortDebugString_field() { 1331 final FieldDescriptor dataField = OneString.getDescriptor().findFieldByName("data"); 1332 assertThat(TextFormat.printer().shortDebugString(dataField, "test data")) 1333 .isEqualTo("data: \"test data\""); 1334 1335 final FieldDescriptor optionalField = 1336 TestAllTypes.getDescriptor().findFieldByName("optional_nested_message"); 1337 final Object value = NestedMessage.newBuilder().setBb(42).build(); 1338 1339 assertThat(TextFormat.printer().shortDebugString(optionalField, value)) 1340 .isEqualTo("optional_nested_message { bb: 42 }"); 1341 } 1342 1343 @Test testShortDebugString_unknown()1344 public void testShortDebugString_unknown() { 1345 assertThat(TextFormat.printer().shortDebugString(makeUnknownFieldSet())) 1346 .isEqualTo( 1347 "5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5: { 12: 6 } 5 { 10: 5 }" 1348 + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:" 1349 + " 0xabcdef1234567890"); 1350 } 1351 1352 @Test testPrintToUnicodeString()1353 public void testPrintToUnicodeString() throws Exception { 1354 assertThat( 1355 TextFormat.printer() 1356 .escapingNonAscii(false) 1357 .printToString( 1358 TestAllTypes.newBuilder() 1359 .setOptionalString("abc\u3042efg") 1360 .setOptionalBytes(bytes(0xe3, 0x81, 0x82)) 1361 .addRepeatedString("\u3093XYZ") 1362 .build())) 1363 .isEqualTo( 1364 "optional_string: \"abc\u3042efg\"\n" 1365 + "optional_bytes: \"\\343\\201\\202\"\n" 1366 + "repeated_string: \"\u3093XYZ\"\n"); 1367 1368 // Double quotes and backslashes should be escaped 1369 assertThat( 1370 TextFormat.printer() 1371 .escapingNonAscii(false) 1372 .printToString(TestAllTypes.newBuilder().setOptionalString("a\\bc\"ef\"g").build())) 1373 .isEqualTo("optional_string: \"a\\\\bc\\\"ef\\\"g\"\n"); 1374 1375 // Test escaping roundtrip 1376 TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("a\\bc\\\"ef\"g").build(); 1377 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 1378 TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), builder); 1379 assertThat(builder.getOptionalString()).isEqualTo(message.getOptionalString()); 1380 } 1381 1382 @Test testPrintToUnicodeStringWithNewlines()1383 public void testPrintToUnicodeStringWithNewlines() throws Exception { 1384 // No newlines at start and end 1385 assertThat( 1386 TextFormat.printer() 1387 .escapingNonAscii(false) 1388 .printToString( 1389 TestAllTypes.newBuilder() 1390 .setOptionalString("test newlines\n\nin\nstring") 1391 .build())) 1392 .isEqualTo("optional_string: \"test newlines\\n\\nin\\nstring\"\n"); 1393 1394 // Newlines at start and end 1395 assertThat( 1396 TextFormat.printer() 1397 .escapingNonAscii(false) 1398 .printToString( 1399 TestAllTypes.newBuilder() 1400 .setOptionalString("\ntest\nnewlines\n\nin\nstring\n") 1401 .build())) 1402 .isEqualTo("optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n"); 1403 1404 // Strings with 0, 1 and 2 newlines. 1405 assertThat( 1406 TextFormat.printer() 1407 .escapingNonAscii(false) 1408 .printToString(TestAllTypes.newBuilder().setOptionalString("").build())) 1409 .isEqualTo("optional_string: \"\"\n"); 1410 assertThat( 1411 TextFormat.printer() 1412 .escapingNonAscii(false) 1413 .printToString(TestAllTypes.newBuilder().setOptionalString("\n").build())) 1414 .isEqualTo("optional_string: \"\\n\"\n"); 1415 assertThat( 1416 TextFormat.printer() 1417 .escapingNonAscii(false) 1418 .printToString(TestAllTypes.newBuilder().setOptionalString("\n\n").build())) 1419 .isEqualTo("optional_string: \"\\n\\n\"\n"); 1420 1421 // Test escaping roundtrip 1422 TestAllTypes message = 1423 TestAllTypes.newBuilder().setOptionalString("\ntest\nnewlines\n\nin\nstring\n").build(); 1424 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 1425 TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), builder); 1426 assertThat(builder.getOptionalString()).isEqualTo(message.getOptionalString()); 1427 } 1428 1429 @Test testPrintToUnicodeString_unknown()1430 public void testPrintToUnicodeString_unknown() { 1431 assertThat( 1432 TextFormat.printer() 1433 .escapingNonAscii(false) 1434 .printToString( 1435 UnknownFieldSet.newBuilder() 1436 .addField( 1437 1, 1438 UnknownFieldSet.Field.newBuilder() 1439 .addLengthDelimited(bytes(0xe3, 0x81, 0x82)) 1440 .build()) 1441 .build())) 1442 .isEqualTo("1: \"\\343\\201\\202\"\n"); 1443 } 1444 1445 @Test testParseUnknownExtensions()1446 public void testParseUnknownExtensions() throws Exception { 1447 TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler(); 1448 Logger logger = Logger.getLogger(TextFormat.class.getName()); 1449 logger.addHandler(logHandler); 1450 // Test unknown extension can pass. 1451 assertParseSuccessWithUnknownExtensions("[unknown_extension]: 123"); 1452 assertParseSuccessWithUnknownExtensions( 1453 "[unknown_extension]: 123\n" + "[unknown_ext]: inf\n" + "[unknown]: 1.234"); 1454 // Test warning messages. 1455 assertThat(logHandler.getStoredLogRecords().get(0).getMessage()) 1456 .isEqualTo( 1457 "Input contains unknown fields and/or extensions:\n" 1458 + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]"); 1459 assertThat(logHandler.getStoredLogRecords().get(1).getMessage()) 1460 .isEqualTo( 1461 "Input contains unknown fields and/or extensions:\n" 1462 + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n" 1463 + "2:2:\tprotobuf_unittest.TestAllTypes.[unknown_ext]\n" 1464 + "3:2:\tprotobuf_unittest.TestAllTypes.[unknown]"); 1465 1466 // Test unknown field can not pass. 1467 assertParseErrorWithUnknownExtensions( 1468 "2:1: Input contains unknown fields and/or extensions:\n" 1469 + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n" 1470 + "2:1:\tprotobuf_unittest.TestAllTypes.unknown_field", 1471 "[unknown_extension]: 1\n" + "unknown_field: 12345"); 1472 assertParseErrorWithUnknownExtensions( 1473 "3:1: Input contains unknown fields and/or extensions:\n" 1474 + "1:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension1]\n" 1475 + "2:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension2]\n" 1476 + "3:1:\tprotobuf_unittest.TestAllTypes.unknown_field\n" 1477 + "4:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension3]", 1478 "[unknown_extension1]: 1\n" 1479 + "[unknown_extension2]: 2\n" 1480 + "unknown_field: 12345\n" 1481 + "[unknown_extension3]: 3\n"); 1482 assertParseErrorWithUnknownExtensions( 1483 "1:1: Input contains unknown fields and/or extensions:\n" 1484 + "1:1:\tprotobuf_unittest.TestAllTypes.unknown_field1\n" 1485 + "2:1:\tprotobuf_unittest.TestAllTypes.unknown_field2\n" 1486 + "3:2:\tprotobuf_unittest.TestAllTypes.[unknown_extension]\n" 1487 + "4:1:\tprotobuf_unittest.TestAllTypes.unknown_field3", 1488 "unknown_field1: 1\n" 1489 + "unknown_field2: 2\n" 1490 + "[unknown_extension]: 12345\n" 1491 + "unknown_field3: 3\n"); 1492 } 1493 1494 @Test testParseUnknownExtensionWithAnyMessage()1495 public void testParseUnknownExtensionWithAnyMessage() throws Exception { 1496 assertParseSuccessWithUnknownExtensions( 1497 "[unknown_extension]: { " 1498 + " any_value { " 1499 + " [type.googleapis.com/protobuf_unittest.OneString] { " 1500 + " data: 123 " 1501 + " } " 1502 + " } " 1503 + "}"); 1504 } 1505 1506 // See additional coverage in testOneofOverwriteForbidden and testMapOverwriteForbidden. 1507 @Test testParseNonRepeatedFields()1508 public void testParseNonRepeatedFields() throws Exception { 1509 assertParseSuccessWithOverwriteForbidden("repeated_int32: 1\nrepeated_int32: 2\n"); 1510 assertParseSuccessWithOverwriteForbidden("RepeatedGroup { a: 1 }\nRepeatedGroup { a: 2 }\n"); 1511 assertParseSuccessWithOverwriteForbidden( 1512 "repeated_nested_message { bb: 1 }\nrepeated_nested_message { bb: 2 }\n"); 1513 1514 assertParseErrorWithOverwriteForbidden( 1515 "3:15: Non-repeated field " 1516 + "\"protobuf_unittest.TestAllTypes.optional_int32\" " 1517 + "cannot be overwritten.", 1518 "optional_int32: 1\noptional_bool: true\noptional_int32: 1\n"); 1519 assertParseErrorWithOverwriteForbidden( 1520 "2:1: Non-repeated field " 1521 + "\"protobuf_unittest.TestAllTypes.optionalgroup\" " 1522 + "cannot be overwritten.", 1523 "OptionalGroup { a: 1 }\nOptionalGroup { }\n"); 1524 assertParseErrorWithOverwriteForbidden( 1525 "2:1: Non-repeated field " 1526 + "\"protobuf_unittest.TestAllTypes.optional_nested_message\" " 1527 + "cannot be overwritten.", 1528 "optional_nested_message { }\noptional_nested_message { bb: 3 }\n"); 1529 assertParseErrorWithOverwriteForbidden( 1530 "2:14: Non-repeated field " 1531 + "\"protobuf_unittest.TestAllTypes.default_int32\" " 1532 + "cannot be overwritten.", 1533 "default_int32: 41\n" 1534 + // the default value 1535 "default_int32: 41\n"); 1536 assertParseErrorWithOverwriteForbidden( 1537 "2:15: Non-repeated field " 1538 + "\"protobuf_unittest.TestAllTypes.default_string\" " 1539 + "cannot be overwritten.", 1540 "default_string: \"zxcv\"\ndefault_string: \"asdf\"\n"); 1541 } 1542 1543 @Test testParseShortRepeatedFormOfRepeatedFields()1544 public void testParseShortRepeatedFormOfRepeatedFields() throws Exception { 1545 assertParseSuccessWithOverwriteForbidden("repeated_foreign_enum: [FOREIGN_FOO, FOREIGN_BAR]"); 1546 assertParseSuccessWithOverwriteForbidden("repeated_int32: [ 1, 2 ]\n"); 1547 assertParseSuccessWithOverwriteForbidden("RepeatedGroup [{ a: 1 },{ a: 2 }]\n"); 1548 assertParseSuccessWithOverwriteForbidden("repeated_nested_message [{ bb: 1 }, { bb: 2 }]\n"); 1549 // See also testMapShortForm. 1550 } 1551 1552 @Test testParseShortRepeatedFormOfEmptyRepeatedFields()1553 public void testParseShortRepeatedFormOfEmptyRepeatedFields() throws Exception { 1554 assertParseSuccessWithOverwriteForbidden("repeated_foreign_enum: []"); 1555 assertParseSuccessWithOverwriteForbidden("repeated_int32: []\n"); 1556 assertParseSuccessWithOverwriteForbidden("RepeatedGroup []\n"); 1557 assertParseSuccessWithOverwriteForbidden("repeated_nested_message []\n"); 1558 // See also testMapShortFormEmpty. 1559 } 1560 1561 @Test testParseShortRepeatedFormWithTrailingComma()1562 public void testParseShortRepeatedFormWithTrailingComma() throws Exception { 1563 assertParseErrorWithOverwriteForbidden( 1564 "1:38: Expected identifier. Found \']\'", "repeated_foreign_enum: [FOREIGN_FOO, ]\n"); 1565 assertParseErrorWithOverwriteForbidden( 1566 "1:22: Couldn't parse integer: For input string: \"]\"", "repeated_int32: [ 1, ]\n"); 1567 assertParseErrorWithOverwriteForbidden("1:25: Expected \"{\".", "RepeatedGroup [{ a: 1 },]\n"); 1568 assertParseErrorWithOverwriteForbidden( 1569 "1:37: Expected \"{\".", "repeated_nested_message [{ bb: 1 }, ]\n"); 1570 // See also testMapShortFormTrailingComma. 1571 } 1572 1573 @Test testParseShortRepeatedFormOfNonRepeatedFields()1574 public void testParseShortRepeatedFormOfNonRepeatedFields() throws Exception { 1575 assertParseErrorWithOverwriteForbidden( 1576 "1:17: Couldn't parse integer: For input string: \"[\"", "optional_int32: [1]\n"); 1577 assertParseErrorWithOverwriteForbidden( 1578 "1:17: Couldn't parse integer: For input string: \"[\"", "optional_int32: []\n"); 1579 } 1580 1581 // ======================================================================= 1582 // test delimited 1583 1584 @Test testPrintGroupLikeDelimited()1585 public void testPrintGroupLikeDelimited() throws Exception { 1586 TestDelimited message = 1587 TestDelimited.newBuilder() 1588 .setGroupLike(TestDelimited.GroupLike.newBuilder().setA(1).build()) 1589 .build(); 1590 assertThat(TextFormat.printer().printToString(message)).isEqualTo("GroupLike {\n a: 1\n}\n"); 1591 } 1592 1593 @Test testPrintGroupLikeDelimitedExtension()1594 public void testPrintGroupLikeDelimitedExtension() throws Exception { 1595 TestDelimited message = 1596 TestDelimited.newBuilder() 1597 .setExtension( 1598 UnittestDelimited.groupLikeFileScope, 1599 GroupLikeFileScope.newBuilder().setA(1).build()) 1600 .build(); 1601 assertThat(TextFormat.printer().printToString(message)) 1602 .isEqualTo("[editions_unittest.grouplikefilescope] {\n a: 1\n}\n"); 1603 } 1604 1605 @Test testPrintGroupLikeNotDelimited()1606 public void testPrintGroupLikeNotDelimited() throws Exception { 1607 TestDelimited message = 1608 TestDelimited.newBuilder() 1609 .setLengthprefixed(TestDelimited.LengthPrefixed.newBuilder().setA(1).build()) 1610 .build(); 1611 assertThat(TextFormat.printer().printToString(message)) 1612 .isEqualTo("lengthprefixed {\n a: 1\n}\n"); 1613 } 1614 1615 @Test testPrintGroupLikeMismatchedName()1616 public void testPrintGroupLikeMismatchedName() throws Exception { 1617 TestDelimited message = 1618 TestDelimited.newBuilder() 1619 .setNotgrouplike(TestDelimited.GroupLike.newBuilder().setA(1).build()) 1620 .build(); 1621 assertThat(TextFormat.printer().printToString(message)) 1622 .isEqualTo("notgrouplike {\n a: 1\n}\n"); 1623 } 1624 1625 @Test testPrintGroupLikeExtensionMismatchedName()1626 public void testPrintGroupLikeExtensionMismatchedName() throws Exception { 1627 TestDelimited message = 1628 TestDelimited.newBuilder() 1629 .setExtension( 1630 UnittestDelimited.notGroupLikeScope, NotGroupLikeScope.newBuilder().setA(1).build()) 1631 .build(); 1632 assertThat(TextFormat.printer().printToString(message)) 1633 .isEqualTo("[editions_unittest.not_group_like_scope] {\n a: 1\n}\n"); 1634 } 1635 1636 @Test testPrintGroupLikeMismatchedScope()1637 public void testPrintGroupLikeMismatchedScope() throws Exception { 1638 TestDelimited message = 1639 TestDelimited.newBuilder() 1640 .setNotgrouplikescope(NotGroupLikeScope.newBuilder().setA(1).build()) 1641 .build(); 1642 assertThat(TextFormat.printer().printToString(message)) 1643 .isEqualTo("notgrouplikescope {\n a: 1\n}\n"); 1644 } 1645 1646 @Test testPrintGroupLikeExtensionMismatchedScope()1647 public void testPrintGroupLikeExtensionMismatchedScope() throws Exception { 1648 TestDelimited message = 1649 TestDelimited.newBuilder() 1650 .setExtension( 1651 UnittestDelimited.grouplike, TestDelimited.GroupLike.newBuilder().setA(1).build()) 1652 .build(); 1653 assertThat(TextFormat.printer().printToString(message)) 1654 .isEqualTo("[editions_unittest.grouplike] {\n a: 1\n}\n"); 1655 } 1656 1657 @Test testPrintGroupLikeMismatchedFile()1658 public void testPrintGroupLikeMismatchedFile() throws Exception { 1659 TestDelimited message = 1660 TestDelimited.newBuilder() 1661 .setMessageimport(MessageImport.newBuilder().setA(1).build()) 1662 .build(); 1663 assertThat(TextFormat.printer().printToString(message)) 1664 .isEqualTo("messageimport {\n a: 1\n}\n"); 1665 } 1666 1667 @Test testParseDelimitedGroupLikeType()1668 public void testParseDelimitedGroupLikeType() throws Exception { 1669 TestDelimited.Builder message = TestDelimited.newBuilder(); 1670 TextFormat.merge("GroupLike { a: 1 }", message); 1671 assertThat(message.build()) 1672 .isEqualTo( 1673 TestDelimited.newBuilder() 1674 .setGroupLike(TestDelimited.GroupLike.newBuilder().setA(1).build()) 1675 .build()); 1676 } 1677 1678 @Test testParseDelimitedGroupLikeField()1679 public void testParseDelimitedGroupLikeField() throws Exception { 1680 TestDelimited.Builder message = TestDelimited.newBuilder(); 1681 TextFormat.merge("grouplike { a: 2 }", message); 1682 assertThat(message.build()) 1683 .isEqualTo( 1684 TestDelimited.newBuilder() 1685 .setGroupLike(TestDelimited.GroupLike.newBuilder().setA(2).build()) 1686 .build()); 1687 } 1688 1689 @Test testParseDelimitedGroupLikeExtension()1690 public void testParseDelimitedGroupLikeExtension() throws Exception { 1691 TestDelimited.Builder message = TestDelimited.newBuilder(); 1692 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 1693 registry.add(UnittestDelimited.grouplike); 1694 TextFormat.merge("[editions_unittest.grouplike] { a: 2 }", registry, message); 1695 assertThat(message.build()) 1696 .isEqualTo( 1697 TestDelimited.newBuilder() 1698 .setExtension( 1699 UnittestDelimited.grouplike, 1700 TestDelimited.GroupLike.newBuilder().setA(2).build()) 1701 .build()); 1702 } 1703 1704 @Test testParseDelimitedGroupLikeInvalid()1705 public void testParseDelimitedGroupLikeInvalid() throws Exception { 1706 TestDelimited.Builder message = TestDelimited.newBuilder(); 1707 try { 1708 TextFormat.merge("GROUPlike { a: 3 }", message); 1709 assertWithMessage("Expected parse exception.").fail(); 1710 } catch (TextFormat.ParseException e) { 1711 assertThat(e) 1712 .hasMessageThat() 1713 .isEqualTo( 1714 "1:1: Input contains unknown fields and/or extensions:\n" 1715 + "1:1:\teditions_unittest.TestDelimited.GROUPlike"); 1716 } 1717 } 1718 1719 @Test testParseDelimitedGroupLikeInvalidExtension()1720 public void testParseDelimitedGroupLikeInvalidExtension() throws Exception { 1721 TestDelimited.Builder message = TestDelimited.newBuilder(); 1722 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 1723 registry.add(UnittestDelimited.grouplike); 1724 try { 1725 TextFormat.merge("[editions_unittest.GroupLike] { a: 2 }", registry, message); 1726 assertWithMessage("Expected parse exception.").fail(); 1727 } catch (TextFormat.ParseException e) { 1728 assertThat(e) 1729 .hasMessageThat() 1730 .isEqualTo( 1731 "1:20: Input contains unknown fields and/or extensions:\n" 1732 + "1:20:\teditions_unittest.TestDelimited.[editions_unittest.GroupLike]"); 1733 } 1734 } 1735 1736 @Test testParseDelimited()1737 public void testParseDelimited() throws Exception { 1738 TestDelimited.Builder message = TestDelimited.newBuilder(); 1739 TextFormat.merge("notgrouplike { b: 3 }", message); 1740 assertThat(message.build()) 1741 .isEqualTo( 1742 TestDelimited.newBuilder() 1743 .setNotgrouplike(TestDelimited.GroupLike.newBuilder().setB(3).build()) 1744 .build()); 1745 } 1746 1747 @Test testParseDelimitedInvalid()1748 public void testParseDelimitedInvalid() throws Exception { 1749 TestDelimited.Builder message = TestDelimited.newBuilder(); 1750 try { 1751 TextFormat.merge("NotGroupLike { a: 3 }", message); 1752 assertWithMessage("Expected parse exception.").fail(); 1753 } catch (TextFormat.ParseException e) { 1754 assertThat(e) 1755 .hasMessageThat() 1756 .isEqualTo( 1757 "1:1: Input contains unknown fields and/or extensions:\n" 1758 + "1:1:\teditions_unittest.TestDelimited.NotGroupLike"); 1759 } 1760 } 1761 1762 @Test testParseDelimitedInvalidScope()1763 public void testParseDelimitedInvalidScope() throws Exception { 1764 TestDelimited.Builder message = TestDelimited.newBuilder(); 1765 try { 1766 TextFormat.merge("NotGroupLikeScope { a: 3 }", message); 1767 assertWithMessage("Expected parse exception.").fail(); 1768 } catch (TextFormat.ParseException e) { 1769 assertThat(e) 1770 .hasMessageThat() 1771 .isEqualTo( 1772 "1:1: Input contains unknown fields and/or extensions:\n" 1773 + "1:1:\teditions_unittest.TestDelimited.NotGroupLikeScope"); 1774 } 1775 } 1776 1777 // ======================================================================= 1778 // test oneof 1779 1780 @Test testOneofTextFormat()1781 public void testOneofTextFormat() throws Exception { 1782 TestOneof2.Builder builder = TestOneof2.newBuilder(); 1783 TestUtil.setOneof(builder); 1784 TestOneof2 message = builder.build(); 1785 TestOneof2.Builder dest = TestOneof2.newBuilder(); 1786 TextFormat.merge(TextFormat.printer().escapingNonAscii(false).printToString(message), dest); 1787 TestUtil.assertOneofSet(dest.build()); 1788 } 1789 1790 @Test testOneofOverwriteForbidden()1791 public void testOneofOverwriteForbidden() throws Exception { 1792 String input = "foo_string: \"stringvalue\" foo_int: 123"; 1793 TestOneof2.Builder builder = TestOneof2.newBuilder(); 1794 try { 1795 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(input, TestUtil.getFullExtensionRegistry(), builder); 1796 assertWithMessage("Expected parse exception.").fail(); 1797 } catch (TextFormat.ParseException e) { 1798 assertThat(e) 1799 .hasMessageThat() 1800 .isEqualTo( 1801 "1:34: Field \"protobuf_unittest.TestOneof2.foo_int\"" 1802 + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\"," 1803 + " another member of oneof \"foo\"."); 1804 } 1805 } 1806 1807 @Test testOneofOverwriteAllowed()1808 public void testOneofOverwriteAllowed() throws Exception { 1809 String input = "foo_string: \"stringvalue\" foo_int: 123"; 1810 TestOneof2.Builder builder = TestOneof2.newBuilder(); 1811 DEFAULT_PARSER.merge(input, TestUtil.getFullExtensionRegistry(), builder); 1812 // Only the last value sticks. 1813 TestOneof2 oneof = builder.build(); 1814 assertThat(oneof.hasFooString()).isFalse(); 1815 assertThat(oneof.hasFooInt()).isTrue(); 1816 } 1817 1818 // ======================================================================= 1819 // test map 1820 1821 @Test testMapTextFormat()1822 public void testMapTextFormat() throws Exception { 1823 TestMap message = 1824 TestMap.newBuilder() 1825 .putInt32ToStringField(10, "apple") 1826 .putInt32ToStringField(20, "banana") 1827 .putInt32ToStringField(30, "cherry") 1828 .build(); 1829 String text = TextFormat.printer().escapingNonAscii(false).printToString(message); 1830 { 1831 TestMap.Builder dest = TestMap.newBuilder(); 1832 TextFormat.merge(text, dest); 1833 assertThat(dest.build()).isEqualTo(message); 1834 } 1835 { 1836 TestMap.Builder dest = TestMap.newBuilder(); 1837 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, dest); 1838 assertThat(dest.build()).isEqualTo(message); 1839 } 1840 } 1841 1842 @Test testMapDuplicateKeys()1843 public void testMapDuplicateKeys() throws Exception { 1844 String input = 1845 "int32_to_int32_field: {\n" 1846 + " key: 1\n" 1847 + " value: 1\n" 1848 + "}\n" 1849 + "int32_to_int32_field: {\n" 1850 + " key: -2147483647\n" 1851 + " value: 5\n" 1852 + "}\n" 1853 + "int32_to_int32_field: {\n" 1854 + " key: 1\n" 1855 + " value: -1\n" 1856 + "}\n"; 1857 TestMap msg = TextFormat.parse(input, TestMap.class); 1858 int i1 = msg.getInt32ToInt32FieldMap().get(1); 1859 TestMap msg2 = TextFormat.parse(msg.toString(), TestMap.class); 1860 int i2 = msg2.getInt32ToInt32FieldMap().get(1); 1861 assertThat(i1).isEqualTo(i2); 1862 } 1863 1864 @Test testMapShortForm()1865 public void testMapShortForm() throws Exception { 1866 String text = 1867 "string_to_int32_field [{ key: 'x' value: 10 }, { key: 'y' value: 20 }]\n" 1868 + "int32_to_message_field " 1869 + "[{ key: 1 value { value: 100 } }, { key: 2 value: { value: 200 } }]\n"; 1870 TestMap.Builder dest = TestMap.newBuilder(); 1871 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, dest); 1872 TestMap message = dest.build(); 1873 assertThat(message.getStringToInt32FieldMap()).hasSize(2); 1874 assertThat(message.getInt32ToMessageFieldMap()).hasSize(2); 1875 assertThat(message.getStringToInt32FieldMap().get("x").intValue()).isEqualTo(10); 1876 assertThat(message.getInt32ToMessageFieldMap().get(2).getValue()).isEqualTo(200); 1877 } 1878 1879 @Test testMapShortFormEmpty()1880 public void testMapShortFormEmpty() throws Exception { 1881 String text = "string_to_int32_field []\nint32_to_message_field: []\n"; 1882 TestMap.Builder dest = TestMap.newBuilder(); 1883 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, dest); 1884 TestMap message = dest.build(); 1885 assertThat(message.getStringToInt32FieldMap()).isEmpty(); 1886 assertThat(message.getInt32ToMessageFieldMap()).isEmpty(); 1887 } 1888 1889 @Test testMapShortFormTrailingComma()1890 public void testMapShortFormTrailingComma() throws Exception { 1891 String text = "string_to_int32_field [{ key: 'x' value: 10 }, ]\n"; 1892 TestMap.Builder dest = TestMap.newBuilder(); 1893 try { 1894 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, dest); 1895 assertWithMessage("Expected parse exception.").fail(); 1896 } catch (TextFormat.ParseException e) { 1897 assertThat(e).hasMessageThat().isEqualTo("1:48: Expected \"{\"."); 1898 } 1899 } 1900 1901 @Test testMapOverwrite()1902 public void testMapOverwrite() throws Exception { 1903 String text = 1904 "int32_to_int32_field { key: 1 value: 10 }\n" 1905 + "int32_to_int32_field { key: 2 value: 20 }\n" 1906 + "int32_to_int32_field { key: 1 value: 30 }\n"; 1907 1908 { 1909 // With default parser, last value set for the key holds. 1910 TestMap.Builder builder = TestMap.newBuilder(); 1911 DEFAULT_PARSER.merge(text, builder); 1912 TestMap map = builder.build(); 1913 assertThat(map.getInt32ToInt32FieldMap()).hasSize(2); 1914 assertThat(map.getInt32ToInt32FieldMap().get(1).intValue()).isEqualTo(30); 1915 } 1916 1917 { 1918 // With overwrite forbidden, same behavior. 1919 // TODO: Expect parse exception here. 1920 TestMap.Builder builder = TestMap.newBuilder(); 1921 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, builder); 1922 TestMap map = builder.build(); 1923 assertThat(map.getInt32ToInt32FieldMap()).hasSize(2); 1924 assertThat(map.getInt32ToInt32FieldMap().get(1).intValue()).isEqualTo(30); 1925 } 1926 1927 { 1928 // With overwrite forbidden and a dynamic message, same behavior. 1929 // TODO: Expect parse exception here. 1930 Message.Builder builder = DynamicMessage.newBuilder(TestMap.getDescriptor()); 1931 PARSER_WITH_OVERWRITE_FORBIDDEN.merge(text, builder); 1932 TestMap map = 1933 TestMap.parseFrom( 1934 builder.build().toByteString(), ExtensionRegistryLite.getEmptyRegistry()); 1935 assertThat(map.getInt32ToInt32FieldMap()).hasSize(2); 1936 assertThat(map.getInt32ToInt32FieldMap().get(1).intValue()).isEqualTo(30); 1937 } 1938 } 1939 1940 // ======================================================================= 1941 // test location information 1942 1943 @Test testParseInfoTreeBuilding()1944 public void testParseInfoTreeBuilding() throws Exception { 1945 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 1946 1947 Descriptor descriptor = TestAllTypes.getDescriptor(); 1948 TextFormatParseInfoTree.Builder treeBuilder = TextFormatParseInfoTree.builder(); 1949 // Set to allow unknown fields 1950 TextFormat.Parser parser = 1951 TextFormat.Parser.newBuilder() 1952 .setAllowUnknownFields(true) 1953 .setParseInfoTreeBuilder(treeBuilder) 1954 .build(); 1955 1956 final String stringData = 1957 "optional_int32: 1\n" 1958 + "optional_int64: 2\n" 1959 + " optional_double: 2.4\n" 1960 + "repeated_int32: 5\n" 1961 + "repeated_int32: 10\n" 1962 + "optional_nested_message <\n" 1963 + " bb: 78\n" 1964 + ">\n" 1965 + "repeated_nested_message <\n" 1966 + " bb: 79\n" 1967 + ">\n" 1968 + "repeated_nested_message <\n" 1969 + " bb: 80\n" 1970 + ">"; 1971 1972 parser.merge(stringData, builder); 1973 TextFormatParseInfoTree tree = treeBuilder.build(); 1974 1975 // Verify that the tree has the correct positions. 1976 assertLocation(tree, descriptor, "optional_int32", 0, 0, 0); 1977 assertLocation(tree, descriptor, "optional_int64", 0, 1, 0); 1978 assertLocation(tree, descriptor, "optional_double", 0, 2, 2); 1979 1980 assertLocation(tree, descriptor, "repeated_int32", 0, 3, 0); 1981 assertLocation(tree, descriptor, "repeated_int32", 1, 4, 0); 1982 1983 assertLocation(tree, descriptor, "optional_nested_message", 0, 5, 0); 1984 assertLocation(tree, descriptor, "repeated_nested_message", 0, 8, 0); 1985 assertLocation(tree, descriptor, "repeated_nested_message", 1, 11, 0); 1986 1987 // Check for fields not set. For an invalid field, the location returned should be -1, -1. 1988 assertLocation(tree, descriptor, "repeated_int64", 0, -1, -1); 1989 assertLocation(tree, descriptor, "repeated_int32", 6, -1, -1); 1990 1991 // Verify inside the nested message. 1992 FieldDescriptor nestedField = descriptor.findFieldByName("optional_nested_message"); 1993 1994 TextFormatParseInfoTree nestedTree = tree.getNestedTrees(nestedField).get(0); 1995 assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 6, 2); 1996 1997 // Verify inside another nested message. 1998 nestedField = descriptor.findFieldByName("repeated_nested_message"); 1999 nestedTree = tree.getNestedTrees(nestedField).get(0); 2000 assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 9, 2); 2001 2002 nestedTree = tree.getNestedTrees(nestedField).get(1); 2003 assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 12, 2); 2004 2005 // Verify a NULL tree for an unknown nested field. 2006 try { 2007 tree.getNestedTree(nestedField, 2); 2008 assertWithMessage("unknown nested field should throw").fail(); 2009 } catch (IllegalArgumentException unused) { 2010 // pass 2011 } 2012 } 2013 2014 @SuppressWarnings("LenientFormatStringValidation") assertLocation( TextFormatParseInfoTree tree, final Descriptor descriptor, final String fieldName, int index, int line, int column)2015 private void assertLocation( 2016 TextFormatParseInfoTree tree, 2017 final Descriptor descriptor, 2018 final String fieldName, 2019 int index, 2020 int line, 2021 int column) { 2022 List<TextFormatParseLocation> locs = tree.getLocations(descriptor.findFieldByName(fieldName)); 2023 if (index < locs.size()) { 2024 TextFormatParseLocation location = locs.get(index); 2025 TextFormatParseLocation expected = TextFormatParseLocation.create(line, column); 2026 assertThat(location).isEqualTo(expected); 2027 } else if (line != -1 && column != -1) { 2028 // Expected 0 args, but got 3. 2029 assertWithMessage( 2030 "Tree/descriptor/fieldname did not contain index %d, line %d column %d expected", 2031 index, line, column) 2032 .fail(); 2033 } 2034 } 2035 2036 @Test testSortMapFields()2037 public void testSortMapFields() throws Exception { 2038 TestMap message = 2039 TestMap.newBuilder() 2040 .putStringToInt32Field("cherry", 30) 2041 .putStringToInt32Field("banana", 20) 2042 .putStringToInt32Field("apple", 10) 2043 .putInt32ToStringField(30, "cherry") 2044 .putInt32ToStringField(20, "banana") 2045 .putInt32ToStringField(10, "apple") 2046 .build(); 2047 String text = 2048 "int32_to_string_field {\n" 2049 + " key: 10\n" 2050 + " value: \"apple\"\n" 2051 + "}\n" 2052 + "int32_to_string_field {\n" 2053 + " key: 20\n" 2054 + " value: \"banana\"\n" 2055 + "}\n" 2056 + "int32_to_string_field {\n" 2057 + " key: 30\n" 2058 + " value: \"cherry\"\n" 2059 + "}\n" 2060 + "string_to_int32_field {\n" 2061 + " key: \"apple\"\n" 2062 + " value: 10\n" 2063 + "}\n" 2064 + "string_to_int32_field {\n" 2065 + " key: \"banana\"\n" 2066 + " value: 20\n" 2067 + "}\n" 2068 + "string_to_int32_field {\n" 2069 + " key: \"cherry\"\n" 2070 + " value: 30\n" 2071 + "}\n"; 2072 assertThat(TextFormat.printer().printToString(message)).isEqualTo(text); 2073 } 2074 2075 @Test testPreservesFloatingPointNegative0()2076 public void testPreservesFloatingPointNegative0() throws Exception { 2077 proto3_unittest.UnittestProto3.TestAllTypes message = 2078 proto3_unittest.UnittestProto3.TestAllTypes.newBuilder() 2079 .setOptionalFloat(-0.0f) 2080 .setOptionalDouble(-0.0) 2081 .build(); 2082 assertThat(TextFormat.printer().printToString(message)) 2083 .isEqualTo("optional_float: -0.0\noptional_double: -0.0\n"); 2084 } 2085 makeRecursiveMessage(int depth)2086 private TestRecursiveMessage makeRecursiveMessage(int depth) { 2087 if (depth == 0) { 2088 return TestRecursiveMessage.newBuilder().setI(5).build(); 2089 } else { 2090 return TestRecursiveMessage.newBuilder().setA(makeRecursiveMessage(depth - 1)).build(); 2091 } 2092 } 2093 2094 @Test testDefaultRecursionLimit()2095 public void testDefaultRecursionLimit() throws Exception { 2096 String depth100 = TextFormat.printer().printToString(makeRecursiveMessage(100)); 2097 String depth101 = TextFormat.printer().printToString(makeRecursiveMessage(101)); 2098 TextFormat.parse(depth100, TestRecursiveMessage.class); 2099 try { 2100 TextFormat.parse(depth101, TestRecursiveMessage.class); 2101 assertWithMessage("Parsing deep message should have failed").fail(); 2102 } catch (TextFormat.ParseException e) { 2103 assertThat(e).hasMessageThat().contains("too deep"); 2104 } 2105 } 2106 2107 @Test testRecursionLimitWithUnknownFields()2108 public void testRecursionLimitWithUnknownFields() throws Exception { 2109 TextFormat.Parser parser = 2110 TextFormat.Parser.newBuilder().setAllowUnknownFields(true).setRecursionLimit(2).build(); 2111 TestRecursiveMessage.Builder depth2 = TestRecursiveMessage.newBuilder(); 2112 parser.merge("u { u { i: 0 } }", depth2); 2113 try { 2114 TestRecursiveMessage.Builder depth3 = TestRecursiveMessage.newBuilder(); 2115 parser.merge("u { u { u { } } }", depth3); 2116 assertWithMessage("Parsing deep message should have failed").fail(); 2117 } catch (TextFormat.ParseException e) { 2118 assertThat(e).hasMessageThat().contains("too deep"); 2119 } 2120 } 2121 2122 @Test testRecursionLimitWithKnownAndUnknownFields()2123 public void testRecursionLimitWithKnownAndUnknownFields() throws Exception { 2124 TextFormat.Parser parser = 2125 TextFormat.Parser.newBuilder().setAllowUnknownFields(true).setRecursionLimit(2).build(); 2126 TestRecursiveMessage.Builder depth2 = TestRecursiveMessage.newBuilder(); 2127 parser.merge("a { u { i: 0 } }", depth2); 2128 try { 2129 TestRecursiveMessage.Builder depth3 = TestRecursiveMessage.newBuilder(); 2130 parser.merge("a { u { u { } } }", depth3); 2131 assertWithMessage("Parsing deep message should have failed").fail(); 2132 } catch (TextFormat.ParseException e) { 2133 assertThat(e).hasMessageThat().contains("too deep"); 2134 } 2135 } 2136 2137 @Test testRecursionLimitWithAny()2138 public void testRecursionLimitWithAny() throws Exception { 2139 TextFormat.Parser parser = 2140 TextFormat.Parser.newBuilder() 2141 .setRecursionLimit(2) 2142 .setTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build()) 2143 .build(); 2144 TestAny.Builder depth2 = TestAny.newBuilder(); 2145 parser.merge( 2146 "value { [type.googleapis.com/protobuf_unittest.TestAllTypes] { optional_int32: 1 } }", 2147 depth2); 2148 try { 2149 TestAny.Builder depth3 = TestAny.newBuilder(); 2150 parser.merge( 2151 "value { [type.googleapis.com/protobuf_unittest.TestAllTypes] { optional_nested_message {" 2152 + "} } }", 2153 depth3); 2154 assertWithMessage("Parsing deep message should have failed").fail(); 2155 } catch (TextFormat.ParseException e) { 2156 assertThat(e).hasMessageThat().contains("too deep"); 2157 } 2158 } 2159 2160 @Test testRecursionLimitWithTopLevelAny()2161 public void testRecursionLimitWithTopLevelAny() throws Exception { 2162 TextFormat.Parser parser = 2163 TextFormat.Parser.newBuilder() 2164 .setRecursionLimit(2) 2165 .setTypeRegistry( 2166 TypeRegistry.newBuilder().add(TestRecursiveMessage.getDescriptor()).build()) 2167 .build(); 2168 Any.Builder depth2 = Any.newBuilder(); 2169 parser.merge( 2170 "[type.googleapis.com/protobuf_unittest.TestRecursiveMessage] { a { i: 0 } }", depth2); 2171 try { 2172 Any.Builder depth3 = Any.newBuilder(); 2173 parser.merge( 2174 "[type.googleapis.com/protobuf_unittest.TestRecursiveMessage] { a { a { i: 0 } } }", 2175 depth3); 2176 assertWithMessage("Parsing deep message should have failed").fail(); 2177 } catch (TextFormat.ParseException e) { 2178 assertThat(e).hasMessageThat().contains("too deep"); 2179 } 2180 } 2181 } 2182