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.UnittestLite.optionalForeignEnumExtensionLite; 13 14 import com.google.protobuf.UnittestLite.ForeignEnumLite; 15 import com.google.protobuf.UnittestLite.TestAllExtensionsLite; 16 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; 17 import map_test.MapForProto2TestProto; 18 import map_test.MapTestProto.TestMap; 19 import protobuf_unittest.UnittestMset.RawMessageSet; 20 import protobuf_unittest.UnittestMset.TestMessageSetExtension1; 21 import protobuf_unittest.UnittestMset.TestMessageSetExtension2; 22 import protobuf_unittest.UnittestProto; 23 import protobuf_unittest.UnittestProto.TestAllExtensions; 24 import protobuf_unittest.UnittestProto.TestAllTypes; 25 import protobuf_unittest.UnittestProto.TestExtensionInsideTable; 26 import protobuf_unittest.UnittestProto.TestFieldOrderings; 27 import protobuf_unittest.UnittestProto.TestOneof2; 28 import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible; 29 import protobuf_unittest.UnittestProto.TestPackedExtensions; 30 import protobuf_unittest.UnittestProto.TestPackedTypes; 31 import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet; 32 import proto3_unittest.UnittestProto3; 33 import java.io.ByteArrayInputStream; 34 import java.io.ByteArrayOutputStream; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.util.List; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.junit.runners.JUnit4; 41 42 @RunWith(JUnit4.class) 43 public class WireFormatLiteTest { 44 45 @Test testSerializeExtensionsLite()46 public void testSerializeExtensionsLite() throws Exception { 47 // TestAllTypes and TestAllExtensions should have compatible wire formats, 48 // so if we serialize a TestAllExtensions then parse it as TestAllTypes 49 // it should work. 50 51 TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet(); 52 ByteString rawBytes = message.toByteString(); 53 assertThat(message.getSerializedSize()).isEqualTo(rawBytes.size()); 54 55 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); 56 57 TestUtil.assertAllFieldsSet(message2); 58 } 59 60 @Test testSerializePackedExtensionsLite()61 public void testSerializePackedExtensionsLite() throws Exception { 62 // TestPackedTypes and TestPackedExtensions should have compatible wire 63 // formats; check that they serialize to the same string. 64 TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); 65 ByteString rawBytes = message.toByteString(); 66 67 TestPackedTypes message2 = TestUtil.getPackedSet(); 68 ByteString rawBytes2 = message2.toByteString(); 69 70 assertThat(rawBytes2).isEqualTo(rawBytes); 71 } 72 73 @Test testParseExtensionsLite()74 public void testParseExtensionsLite() throws Exception { 75 // TestAllTypes and TestAllExtensions should have compatible wire formats, 76 // so if we serialize a TestAllTypes then parse it as TestAllExtensions 77 // it should work. 78 79 TestAllTypes message = TestUtil.getAllSet(); 80 ByteString rawBytes = message.toByteString(); 81 82 ExtensionRegistryLite registryLite = TestUtilLite.getExtensionRegistryLite(); 83 84 TestAllExtensionsLite message2 = TestAllExtensionsLite.parseFrom(rawBytes, registryLite); 85 TestUtil.assertAllExtensionsSet(message2); 86 message2 = TestAllExtensionsLite.parseFrom(message.toByteArray(), registryLite); 87 TestUtil.assertAllExtensionsSet(message2); 88 } 89 90 @Test testParsePackedExtensionsLite()91 public void testParsePackedExtensionsLite() throws Exception { 92 // Ensure that packed extensions can be properly parsed. 93 TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet(); 94 ByteString rawBytes = message.toByteString(); 95 96 ExtensionRegistryLite registry = TestUtilLite.getExtensionRegistryLite(); 97 98 TestPackedExtensionsLite message2 = TestPackedExtensionsLite.parseFrom(rawBytes, registry); 99 TestUtil.assertPackedExtensionsSet(message2); 100 message2 = TestPackedExtensionsLite.parseFrom(message.toByteArray(), registry); 101 TestUtil.assertPackedExtensionsSet(message2); 102 } 103 104 @Test testSerialization()105 public void testSerialization() throws Exception { 106 TestAllTypes message = TestUtil.getAllSet(); 107 108 ByteString rawBytes = message.toByteString(); 109 assertThat(message.getSerializedSize()).isEqualTo(rawBytes.size()); 110 111 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); 112 113 TestUtil.assertAllFieldsSet(message2); 114 } 115 116 @Test testSerializationPacked()117 public void testSerializationPacked() throws Exception { 118 TestPackedTypes message = TestUtil.getPackedSet(); 119 120 ByteString rawBytes = message.toByteString(); 121 assertThat(message.getSerializedSize()).isEqualTo(rawBytes.size()); 122 123 TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes); 124 125 TestUtil.assertPackedFieldsSet(message2); 126 } 127 128 @Test testSerializeExtensions()129 public void testSerializeExtensions() throws Exception { 130 // TestAllTypes and TestAllExtensions should have compatible wire formats, 131 // so if we serialize a TestAllExtensions then parse it as TestAllTypes 132 // it should work. 133 134 TestAllExtensions message = TestUtil.getAllExtensionsSet(); 135 ByteString rawBytes = message.toByteString(); 136 assertThat(message.getSerializedSize()).isEqualTo(rawBytes.size()); 137 138 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); 139 140 TestUtil.assertAllFieldsSet(message2); 141 } 142 143 @Test testSerializePackedExtensions()144 public void testSerializePackedExtensions() throws Exception { 145 // TestPackedTypes and TestPackedExtensions should have compatible wire 146 // formats; check that they serialize to the same string. 147 TestPackedExtensions message = TestUtil.getPackedExtensionsSet(); 148 ByteString rawBytes = message.toByteString(); 149 150 TestPackedTypes message2 = TestUtil.getPackedSet(); 151 ByteString rawBytes2 = message2.toByteString(); 152 153 assertThat(rawBytes2).isEqualTo(rawBytes); 154 } 155 156 @Test testSerializationPackedWithoutGetSerializedSize()157 public void testSerializationPackedWithoutGetSerializedSize() throws Exception { 158 // Write directly to an OutputStream, without invoking getSerializedSize() 159 // This used to be a bug where the size of a packed field was incorrect, 160 // since getSerializedSize() was never invoked. 161 TestPackedTypes message = TestUtil.getPackedSet(); 162 163 // Directly construct a CodedOutputStream around the actual OutputStream, 164 // in case writeTo(OutputStream output) invokes getSerializedSize(); 165 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 166 CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream); 167 168 message.writeTo(codedOutput); 169 170 codedOutput.flush(); 171 172 TestPackedTypes message2 = TestPackedTypes.parseFrom(outputStream.toByteArray()); 173 174 TestUtil.assertPackedFieldsSet(message2); 175 } 176 177 @Test testParseExtensions()178 public void testParseExtensions() throws Exception { 179 // TestAllTypes and TestAllExtensions should have compatible wire formats, 180 // so if we serialize a TestAllTypes then parse it as TestAllExtensions 181 // it should work. 182 183 TestAllTypes message = TestUtil.getAllSet(); 184 ByteString rawBytes = message.toByteString(); 185 186 ExtensionRegistryLite registry = TestUtil.getExtensionRegistry(); 187 188 TestAllExtensions message2 = TestAllExtensions.parseFrom(rawBytes, registry); 189 190 TestUtil.assertAllExtensionsSet(message2); 191 } 192 193 @Test testParsePackedExtensions()194 public void testParsePackedExtensions() throws Exception { 195 // Ensure that packed extensions can be properly parsed. 196 TestPackedExtensions message = TestUtil.getPackedExtensionsSet(); 197 ByteString rawBytes = message.toByteString(); 198 199 ExtensionRegistryLite registry = TestUtil.getExtensionRegistry(); 200 201 TestPackedExtensions message2 = TestPackedExtensions.parseFrom(rawBytes, registry); 202 203 TestUtil.assertPackedExtensionsSet(message2); 204 } 205 206 @Test testSerializeDelimited()207 public void testSerializeDelimited() throws Exception { 208 ByteArrayOutputStream output = new ByteArrayOutputStream(); 209 TestUtil.getAllSet().writeDelimitedTo(output); 210 output.write(12); 211 TestUtil.getPackedSet().writeDelimitedTo(output); 212 output.write(34); 213 214 ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); 215 216 TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input)); 217 assertThat(input.read()).isEqualTo(12); 218 TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input)); 219 assertThat(input.read()).isEqualTo(34); 220 assertThat(input.read()).isEqualTo(-1); 221 222 // We're at EOF, so parsing again should return null. 223 assertThat(TestAllTypes.parseDelimitedFrom(input)).isNull(); 224 } 225 getTestFieldOrderingsRegistry()226 private ExtensionRegistryLite getTestFieldOrderingsRegistry() { 227 ExtensionRegistryLite result = ExtensionRegistryLite.newInstance(); 228 result.add(UnittestProto.myExtensionInt); 229 result.add(UnittestProto.myExtensionString); 230 return result; 231 } 232 233 @Test testParseMultipleExtensionRanges()234 public void testParseMultipleExtensionRanges() throws Exception { 235 // Make sure we can parse a message that contains multiple extensions 236 // ranges. 237 TestFieldOrderings source = 238 TestFieldOrderings.newBuilder() 239 .setMyInt(1) 240 .setMyString("foo") 241 .setMyFloat(1.0F) 242 .setExtension(UnittestProto.myExtensionInt, 23) 243 .setExtension(UnittestProto.myExtensionString, "bar") 244 .build(); 245 TestFieldOrderings dest = 246 TestFieldOrderings.parseFrom(source.toByteString(), getTestFieldOrderingsRegistry()); 247 assertThat(dest).isEqualTo(source); 248 } 249 getTestExtensionInsideTableRegistry()250 private static ExtensionRegistryLite getTestExtensionInsideTableRegistry() { 251 ExtensionRegistryLite result = ExtensionRegistryLite.newInstance(); 252 result.add(UnittestProto.testExtensionInsideTableExtension); 253 return result; 254 } 255 256 @Test testExtensionInsideTable()257 public void testExtensionInsideTable() throws Exception { 258 // Make sure the extension within the range of table is parsed correctly in experimental 259 // runtime. 260 TestExtensionInsideTable source = 261 TestExtensionInsideTable.newBuilder() 262 .setField1(1) 263 .setExtension(UnittestProto.testExtensionInsideTableExtension, 23) 264 .build(); 265 TestExtensionInsideTable dest = 266 TestExtensionInsideTable.parseFrom( 267 source.toByteString(), getTestExtensionInsideTableRegistry()); 268 assertThat(dest).isEqualTo(source); 269 } 270 271 private static final int UNKNOWN_TYPE_ID = 1550055; 272 private static final int TYPE_ID_1 = 1545008; 273 private static final int TYPE_ID_2 = 1547769; 274 275 @Test testSerializeMessageSetEagerly()276 public void testSerializeMessageSetEagerly() throws Exception { 277 testSerializeMessageSetWithFlag(true); 278 } 279 280 @Test testSerializeMessageSetNotEagerly()281 public void testSerializeMessageSetNotEagerly() throws Exception { 282 testSerializeMessageSetWithFlag(false); 283 } 284 testSerializeMessageSetWithFlag(boolean eagerParsing)285 private void testSerializeMessageSetWithFlag(boolean eagerParsing) throws Exception { 286 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 287 CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream); 288 output.writeRawMessageSetExtension(UNKNOWN_TYPE_ID, ByteString.copyFromUtf8("bar")); 289 output.flush(); 290 byte[] messageSetBytes = byteArrayOutputStream.toByteArray(); 291 292 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); 293 // Set up a TestMessageSet with two known messages and an unknown one. 294 TestMessageSet messageSet = 295 TestMessageSet.newBuilder() 296 .setExtension( 297 TestMessageSetExtension1.messageSetExtension, 298 TestMessageSetExtension1.newBuilder().setI(123).build()) 299 .setExtension( 300 TestMessageSetExtension2.messageSetExtension, 301 TestMessageSetExtension2.newBuilder().setStr("foo").build()) 302 .mergeFrom(messageSetBytes) 303 .build(); 304 305 ByteString data = messageSet.toByteString(); 306 307 // Parse back using RawMessageSet and check the contents. 308 RawMessageSet raw = RawMessageSet.parseFrom(data); 309 310 assertThat(raw.getItemCount()).isEqualTo(3); 311 assertThat(raw.getItem(0).getTypeId()).isEqualTo(TYPE_ID_1); 312 assertThat(raw.getItem(1).getTypeId()).isEqualTo(TYPE_ID_2); 313 assertThat(raw.getItem(2).getTypeId()).isEqualTo(UNKNOWN_TYPE_ID); 314 315 TestMessageSetExtension1 message1 = 316 TestMessageSetExtension1.parseFrom(raw.getItem(0).getMessage()); 317 assertThat(message1.getI()).isEqualTo(123); 318 319 TestMessageSetExtension2 message2 = 320 TestMessageSetExtension2.parseFrom(raw.getItem(1).getMessage()); 321 assertThat(message2.getStr()).isEqualTo("foo"); 322 323 assertThat(raw.getItem(2).getMessage().toStringUtf8()).isEqualTo("bar"); 324 } 325 326 @Test testParseMessageSetEagerly()327 public void testParseMessageSetEagerly() throws Exception { 328 testParseMessageSetWithFlag(true); 329 } 330 331 @Test testParseMessageSetNotEagerly()332 public void testParseMessageSetNotEagerly() throws Exception { 333 testParseMessageSetWithFlag(false); 334 } 335 testParseMessageSetWithFlag(boolean eagerParsing)336 private void testParseMessageSetWithFlag(boolean eagerParsing) throws Exception { 337 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); 338 ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); 339 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); 340 extensionRegistry.add(TestMessageSetExtension2.messageSetExtension); 341 342 // Set up a RawMessageSet with two known messages and an unknown one. 343 RawMessageSet raw = 344 RawMessageSet.newBuilder() 345 .addItem( 346 RawMessageSet.Item.newBuilder() 347 .setTypeId(TYPE_ID_1) 348 .setMessage( 349 TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) 350 .build()) 351 .addItem( 352 RawMessageSet.Item.newBuilder() 353 .setTypeId(TYPE_ID_2) 354 .setMessage( 355 TestMessageSetExtension2.newBuilder().setStr("foo").build().toByteString()) 356 .build()) 357 .addItem( 358 RawMessageSet.Item.newBuilder() 359 .setTypeId(UNKNOWN_TYPE_ID) 360 .setMessage(ByteString.copyFromUtf8("bar")) 361 .build()) 362 .build(); 363 364 ByteString data = raw.toByteString(); 365 366 // Parse as a TestMessageSet and check the contents. 367 TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); 368 369 assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()) 370 .isEqualTo(123); 371 assertThat(messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr()) 372 .isEqualTo("foo"); 373 } 374 375 @Test testParseMessageSetExtensionEagerly()376 public void testParseMessageSetExtensionEagerly() throws Exception { 377 testParseMessageSetExtensionWithFlag(true); 378 } 379 380 @Test testParseMessageSetExtensionNotEagerly()381 public void testParseMessageSetExtensionNotEagerly() throws Exception { 382 testParseMessageSetExtensionWithFlag(false); 383 } 384 testParseMessageSetExtensionWithFlag(boolean eagerParsing)385 private void testParseMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { 386 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); 387 ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); 388 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); 389 390 // Set up a RawMessageSet with a known messages. 391 int typeId1 = 1545008; 392 RawMessageSet raw = 393 RawMessageSet.newBuilder() 394 .addItem( 395 RawMessageSet.Item.newBuilder() 396 .setTypeId(typeId1) 397 .setMessage( 398 TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) 399 .build()) 400 .build(); 401 402 ByteString data = raw.toByteString(); 403 404 // Parse as a TestMessageSet and check the contents. 405 TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); 406 assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()) 407 .isEqualTo(123); 408 } 409 410 @Test testMergeLazyMessageSetExtensionEagerly()411 public void testMergeLazyMessageSetExtensionEagerly() throws Exception { 412 testMergeLazyMessageSetExtensionWithFlag(true); 413 } 414 415 @Test testMergeLazyMessageSetExtensionNotEagerly()416 public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception { 417 testMergeLazyMessageSetExtensionWithFlag(false); 418 } 419 testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)420 private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { 421 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); 422 ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); 423 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); 424 425 // Set up a RawMessageSet with a known messages. 426 int typeId1 = 1545008; 427 RawMessageSet raw = 428 RawMessageSet.newBuilder() 429 .addItem( 430 RawMessageSet.Item.newBuilder() 431 .setTypeId(typeId1) 432 .setMessage( 433 TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) 434 .build()) 435 .build(); 436 437 ByteString data = raw.toByteString(); 438 439 // Parse as a TestMessageSet and store value into lazy field 440 TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry); 441 // Merge lazy field check the contents. 442 messageSet = messageSet.toBuilder().mergeFrom(data, extensionRegistry).build(); 443 assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()) 444 .isEqualTo(123); 445 } 446 447 @Test testMergeMessageSetExtensionEagerly()448 public void testMergeMessageSetExtensionEagerly() throws Exception { 449 testMergeMessageSetExtensionWithFlag(true); 450 } 451 452 @Test testMergeMessageSetExtensionNotEagerly()453 public void testMergeMessageSetExtensionNotEagerly() throws Exception { 454 testMergeMessageSetExtensionWithFlag(false); 455 } 456 testMergeMessageSetExtensionWithFlag(boolean eagerParsing)457 private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception { 458 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing); 459 ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance(); 460 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); 461 462 // Set up a RawMessageSet with a known messages. 463 int typeId1 = 1545008; 464 RawMessageSet raw = 465 RawMessageSet.newBuilder() 466 .addItem( 467 RawMessageSet.Item.newBuilder() 468 .setTypeId(typeId1) 469 .setMessage( 470 TestMessageSetExtension1.newBuilder().setI(123).build().toByteString()) 471 .build()) 472 .build(); 473 474 // Serialize RawMessageSet unnormally (message value before type id) 475 ByteString.CodedBuilder out = ByteString.newCodedBuilder(raw.getSerializedSize()); 476 CodedOutputStream output = out.getCodedOutput(); 477 List<RawMessageSet.Item> items = raw.getItemList(); 478 for (RawMessageSet.Item item : items) { 479 output.writeTag(1, WireFormat.WIRETYPE_START_GROUP); 480 output.writeBytes(3, item.getMessage()); 481 output.writeInt32(2, item.getTypeId()); 482 output.writeTag(1, WireFormat.WIRETYPE_END_GROUP); 483 } 484 ByteString data = out.build(); 485 486 // Merge bytes into TestMessageSet and check the contents. 487 TestMessageSet messageSet = 488 TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build(); 489 assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI()) 490 .isEqualTo(123); 491 } 492 493 // ================================================================ 494 // oneof 495 @Test testOneofWireFormat()496 public void testOneofWireFormat() throws Exception { 497 TestOneof2.Builder builder = TestOneof2.newBuilder(); 498 TestUtil.setOneof(builder); 499 TestOneof2 message = builder.build(); 500 ByteString rawBytes = message.toByteString(); 501 502 assertThat(message.getSerializedSize()).isEqualTo(rawBytes.size()); 503 504 TestOneof2 message2 = TestOneof2.parseFrom(rawBytes); 505 TestUtil.assertOneofSet(message2); 506 } 507 508 @Test testOneofOnlyLastSet()509 public void testOneofOnlyLastSet() throws Exception { 510 TestOneofBackwardsCompatible source = 511 TestOneofBackwardsCompatible.newBuilder().setFooInt(100).setFooString("101").build(); 512 513 ByteString rawBytes = source.toByteString(); 514 TestOneof2 message = TestOneof2.parseFrom(rawBytes); 515 assertThat(message.hasFooInt()).isFalse(); 516 assertThat(message.hasFooString()).isTrue(); 517 } 518 assertInvalidWireFormat( MessageLite defaultInstance, byte[] data, int offset, int length)519 private void assertInvalidWireFormat( 520 MessageLite defaultInstance, byte[] data, int offset, int length) { 521 // Test all combinations: (builder vs parser) x (byte[] vs. InputStream). 522 try { 523 defaultInstance.newBuilderForType().mergeFrom(data, offset, length); 524 assertWithMessage("Expected exception").fail(); 525 } catch (InvalidProtocolBufferException e) { 526 // Pass. 527 } 528 try { 529 defaultInstance.getParserForType().parseFrom(data, offset, length); 530 assertWithMessage("Expected exception").fail(); 531 } catch (InvalidProtocolBufferException e) { 532 // Pass. 533 } 534 try { 535 InputStream input = new ByteArrayInputStream(data, offset, length); 536 defaultInstance.newBuilderForType().mergeFrom(input); 537 assertWithMessage("Expected exception").fail(); 538 } catch (IOException e) { 539 // Pass. 540 } 541 try { 542 InputStream input = new ByteArrayInputStream(data, offset, length); 543 defaultInstance.getParserForType().parseFrom(input); 544 assertWithMessage("Expected exception").fail(); 545 } catch (IOException e) { 546 // Pass. 547 } 548 } 549 assertInvalidWireFormat(MessageLite defaultInstance, byte[] data)550 private void assertInvalidWireFormat(MessageLite defaultInstance, byte[] data) { 551 assertInvalidWireFormat(defaultInstance, data, 0, data.length); 552 } 553 assertInvalidWireFormat(byte[] data)554 private void assertInvalidWireFormat(byte[] data) { 555 assertInvalidWireFormat(TestAllTypes.getDefaultInstance(), data); 556 assertInvalidWireFormat(UnittestProto3.TestAllTypes.getDefaultInstance(), data); 557 } 558 559 @Test testParserRejectInvalidTag()560 public void testParserRejectInvalidTag() throws Exception { 561 byte[] invalidTags = 562 new byte[] { 563 // Zero tag is not allowed. 564 0, 565 // Invalid wire types. 566 (byte) WireFormat.makeTag(1, 6), 567 (byte) WireFormat.makeTag(1, 7), 568 // Field number 0 is not allowed. 569 (byte) WireFormat.makeTag(0, WireFormat.WIRETYPE_VARINT), 570 }; 571 for (byte invalidTag : invalidTags) { 572 // Add a trailing 0 to make sure the parsing actually fails on the tag. 573 byte[] data = new byte[] {invalidTag, 0}; 574 assertInvalidWireFormat(data); 575 576 // Invalid tag in an unknown group field. 577 data = 578 new byte[] { 579 (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_START_GROUP), 580 invalidTag, 581 0, 582 (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_END_GROUP), 583 }; 584 assertInvalidWireFormat(data); 585 586 // Invalid tag in a MessageSet item. 587 data = 588 new byte[] { 589 (byte) WireFormat.MESSAGE_SET_ITEM_TAG, 590 (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, 591 100, // TYPE_ID = 100 592 (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, 593 0, // empty payload 594 invalidTag, 595 0, 596 (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG, 597 }; 598 assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data); 599 600 // Invalid tag inside a MessageSet item's unknown group. 601 data = 602 new byte[] { 603 (byte) WireFormat.MESSAGE_SET_ITEM_TAG, 604 (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, 605 100, // TYPE_ID = 100 606 (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, 607 0, // empty payload 608 (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_START_GROUP), 609 invalidTag, 610 0, 611 (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_END_GROUP), 612 (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG, 613 }; 614 assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data); 615 616 // Invalid tag inside a map field. 617 data = 618 new byte[] { 619 (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), 2, invalidTag, 0, 620 }; 621 assertInvalidWireFormat(TestMap.getDefaultInstance(), data); 622 } 623 } 624 625 @Test testUnmatchedGroupTag()626 public void testUnmatchedGroupTag() throws Exception { 627 int startTag = WireFormat.makeTag(16, WireFormat.WIRETYPE_START_GROUP); 628 byte[] data = 629 new byte[] { 630 (byte) ((startTag & 0x7F) | 0x80), (byte) ((startTag >>> 7) & 0x7F), 631 }; 632 assertInvalidWireFormat(data); 633 634 // Unmatched group tags inside a MessageSet item. 635 data = 636 new byte[] { 637 (byte) WireFormat.MESSAGE_SET_ITEM_TAG, 638 (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, 639 100, // TYPE_ID = 100 640 (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, 641 0, // empty payload 642 (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_START_GROUP), 643 }; 644 assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data); 645 } 646 assertAccepted(MessageLite defaultInstance, byte[] data)647 private void assertAccepted(MessageLite defaultInstance, byte[] data) throws Exception { 648 MessageLite message1 = defaultInstance.newBuilderForType().mergeFrom(data).build(); 649 MessageLite message2 = defaultInstance.getParserForType().parseFrom(data); 650 MessageLite message3 = 651 defaultInstance.newBuilderForType().mergeFrom(new ByteArrayInputStream(data)).build(); 652 MessageLite message4 = 653 defaultInstance.getParserForType().parseFrom(new ByteArrayInputStream(data)); 654 assertThat(message2).isEqualTo(message1); 655 assertThat(message3).isEqualTo(message2); 656 assertThat(message4).isEqualTo(message3); 657 } 658 659 @Test testUnmatchedWireType()660 public void testUnmatchedWireType() throws Exception { 661 // Build a payload with all fields from 1 to 128 being varints. Parsing it into TestAllTypes 662 // or other message types should succeed even though the wire type doesn't match for some 663 // fields. 664 ByteArrayOutputStream output = new ByteArrayOutputStream(); 665 CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); 666 for (int i = 1; i <= 128; i++) { 667 codedOutput.writeInt32(i, 0); 668 } 669 codedOutput.flush(); 670 byte[] data = output.toByteArray(); 671 // It can be parsed into any message type that doesn't have required fields. 672 assertAccepted(TestAllTypes.getDefaultInstance(), data); 673 assertAccepted(UnittestProto3.TestAllTypes.getDefaultInstance(), data); 674 assertAccepted(TestMap.getDefaultInstance(), data); 675 assertAccepted(MapForProto2TestProto.TestMap.getDefaultInstance(), data); 676 } 677 678 @Test testParseTruncatedPackedFields()679 public void testParseTruncatedPackedFields() throws Exception { 680 TestPackedTypes all = TestUtil.getPackedSet(); 681 TestPackedTypes[] messages = 682 new TestPackedTypes[] { 683 TestPackedTypes.newBuilder().addAllPackedInt32(all.getPackedInt32List()).build(), 684 TestPackedTypes.newBuilder().addAllPackedInt64(all.getPackedInt64List()).build(), 685 TestPackedTypes.newBuilder().addAllPackedUint32(all.getPackedUint32List()).build(), 686 TestPackedTypes.newBuilder().addAllPackedUint64(all.getPackedUint64List()).build(), 687 TestPackedTypes.newBuilder().addAllPackedSint32(all.getPackedSint32List()).build(), 688 TestPackedTypes.newBuilder().addAllPackedSint64(all.getPackedSint64List()).build(), 689 TestPackedTypes.newBuilder().addAllPackedFixed32(all.getPackedFixed32List()).build(), 690 TestPackedTypes.newBuilder().addAllPackedFixed64(all.getPackedFixed64List()).build(), 691 TestPackedTypes.newBuilder().addAllPackedSfixed32(all.getPackedSfixed32List()).build(), 692 TestPackedTypes.newBuilder().addAllPackedSfixed64(all.getPackedSfixed64List()).build(), 693 TestPackedTypes.newBuilder().addAllPackedFloat(all.getPackedFloatList()).build(), 694 TestPackedTypes.newBuilder().addAllPackedDouble(all.getPackedDoubleList()).build(), 695 TestPackedTypes.newBuilder().addAllPackedEnum(all.getPackedEnumList()).build(), 696 }; 697 for (TestPackedTypes message : messages) { 698 byte[] data = message.toByteArray(); 699 // Parsing truncated payload should fail. 700 for (int i = 1; i < data.length; i++) { 701 assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data, 0, i); 702 } 703 } 704 } 705 706 @Test testParsePackedFieldsWithIncorrectLength()707 public void testParsePackedFieldsWithIncorrectLength() throws Exception { 708 // Set the length-prefix to 1 with a 4-bytes payload to test what happens when reading a packed 709 // element moves the reading position past the given length limit. It should result in an 710 // InvalidProtocolBufferException but an implementation may forget to check it especially for 711 // packed varint fields. 712 byte[] data = 713 new byte[] { 714 0, 715 0, // first two bytes is reserved for the tag. 716 1, // length is 1 717 (byte) 0x80, 718 (byte) 0x80, 719 (byte) 0x80, 720 (byte) 0x01, // a 4-bytes varint 721 }; 722 // All fields that can read a 4-bytes varint (all varint fields and fixed 32-bit fields). 723 int[] fieldNumbers = 724 new int[] { 725 TestPackedTypes.PACKED_INT32_FIELD_NUMBER, 726 TestPackedTypes.PACKED_INT64_FIELD_NUMBER, 727 TestPackedTypes.PACKED_UINT32_FIELD_NUMBER, 728 TestPackedTypes.PACKED_UINT64_FIELD_NUMBER, 729 TestPackedTypes.PACKED_SINT32_FIELD_NUMBER, 730 TestPackedTypes.PACKED_SINT64_FIELD_NUMBER, 731 TestPackedTypes.PACKED_FIXED32_FIELD_NUMBER, 732 TestPackedTypes.PACKED_SFIXED32_FIELD_NUMBER, 733 TestPackedTypes.PACKED_FLOAT_FIELD_NUMBER, 734 TestPackedTypes.PACKED_BOOL_FIELD_NUMBER, 735 TestPackedTypes.PACKED_ENUM_FIELD_NUMBER, 736 }; 737 for (int number : fieldNumbers) { 738 // Set the tag. 739 data[0] = 740 (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) & 0x7F) | 0x80); 741 data[1] = 742 (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) >>> 7) & 0x7F); 743 assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data); 744 } 745 746 // Data with 8-bytes payload to test some fixed 64-bit fields. 747 byte[] data8Bytes = 748 new byte[] { 749 0, 750 0, // first two bytes is reserved for the tag. 751 1, // length is 1 752 (byte) 0x80, 753 (byte) 0x80, 754 (byte) 0x80, 755 (byte) 0x80, 756 (byte) 0x80, 757 (byte) 0x80, 758 (byte) 0x80, 759 (byte) 0x01, // a 8-bytes varint 760 }; 761 // All fields that can only read 8-bytes data. 762 int[] fieldNumbers8Bytes = 763 new int[] { 764 TestPackedTypes.PACKED_FIXED64_FIELD_NUMBER, 765 TestPackedTypes.PACKED_SFIXED64_FIELD_NUMBER, 766 TestPackedTypes.PACKED_DOUBLE_FIELD_NUMBER, 767 }; 768 for (int number : fieldNumbers8Bytes) { 769 // Set the tag. 770 data8Bytes[0] = 771 (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) & 0x7F) | 0x80); 772 data8Bytes[1] = 773 (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) >>> 7) & 0x7F); 774 assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data8Bytes); 775 } 776 } 777 778 @Test testParseVarintMinMax()779 public void testParseVarintMinMax() throws Exception { 780 TestAllTypes message = 781 TestAllTypes.newBuilder() 782 .setOptionalInt32(Integer.MIN_VALUE) 783 .addRepeatedInt32(Integer.MAX_VALUE) 784 .setOptionalInt64(Long.MIN_VALUE) 785 .addRepeatedInt64(Long.MAX_VALUE) 786 .build(); 787 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 788 assertThat(parsed.getOptionalInt32()).isEqualTo(Integer.MIN_VALUE); 789 assertThat(parsed.getRepeatedInt32(0)).isEqualTo(Integer.MAX_VALUE); 790 assertThat(parsed.getOptionalInt64()).isEqualTo(Long.MIN_VALUE); 791 assertThat(parsed.getRepeatedInt64(0)).isEqualTo(Long.MAX_VALUE); 792 } 793 794 @Test testParseAllVarintBits()795 public void testParseAllVarintBits() throws Exception { 796 for (int i = 0; i < 32; i++) { 797 final int value = 1 << i; 798 TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(value).build(); 799 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 800 assertThat(parsed.getOptionalInt32()).isEqualTo(value); 801 } 802 for (int i = 0; i < 64; i++) { 803 final long value = 1L << i; 804 TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt64(value).build(); 805 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 806 assertThat(parsed.getOptionalInt64()).isEqualTo(value); 807 } 808 } 809 810 @Test testParseEmptyUnknownLengthDelimitedField()811 public void testParseEmptyUnknownLengthDelimitedField() throws Exception { 812 byte[] data = 813 new byte[] {(byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), 0}; 814 TestAllTypes parsed = TestAllTypes.parseFrom(data); 815 assertThat(parsed.toByteArray()).isEqualTo(data); 816 } 817 818 @Test testParseEmptyString()819 public void testParseEmptyString() throws Exception { 820 TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("").build(); 821 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 822 assertThat(parsed.getOptionalString()).isEmpty(); 823 } 824 825 @Test testParseEmptyStringProto3()826 public void testParseEmptyStringProto3() throws Exception { 827 TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("").build(); 828 // Note that we are parsing from a proto2 proto to a proto3 proto because empty string field is 829 // not serialized in proto3. 830 UnittestProto3.TestAllTypes parsed = 831 UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); 832 assertThat(parsed.getOptionalString()).isEmpty(); 833 } 834 835 @Test testParseEmptyBytes()836 public void testParseEmptyBytes() throws Exception { 837 TestAllTypes message = TestAllTypes.newBuilder().setOptionalBytes(ByteString.EMPTY).build(); 838 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 839 assertThat(parsed.getOptionalBytes()).isEqualTo(ByteString.EMPTY); 840 } 841 842 @Test testParseEmptyRepeatedStringField()843 public void testParseEmptyRepeatedStringField() throws Exception { 844 TestAllTypes message = 845 TestAllTypes.newBuilder() 846 .addRepeatedString("") 847 .addRepeatedString("") 848 .addRepeatedString("0") 849 .build(); 850 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 851 assertThat(parsed.getRepeatedStringCount()).isEqualTo(3); 852 assertThat(parsed.getRepeatedString(0)).isEmpty(); 853 assertThat(parsed.getRepeatedString(1)).isEmpty(); 854 assertThat(parsed.getRepeatedString(2)).isEqualTo("0"); 855 } 856 857 @Test testParseEmptyRepeatedStringFieldProto3()858 public void testParseEmptyRepeatedStringFieldProto3() throws Exception { 859 TestAllTypes message = 860 TestAllTypes.newBuilder() 861 .addRepeatedString("") 862 .addRepeatedString("") 863 .addRepeatedString("0") 864 .addRepeatedBytes(ByteString.EMPTY) 865 .build(); 866 UnittestProto3.TestAllTypes parsed = 867 UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); 868 assertThat(parsed.getRepeatedStringCount()).isEqualTo(3); 869 assertThat(parsed.getRepeatedString(0)).isEmpty(); 870 assertThat(parsed.getRepeatedString(1)).isEmpty(); 871 assertThat(parsed.getRepeatedString(2)).isEqualTo("0"); 872 } 873 874 @Test testParseEmptyRepeatedBytesField()875 public void testParseEmptyRepeatedBytesField() throws Exception { 876 ByteString oneByte = ByteString.copyFrom(new byte[] {1}); 877 TestAllTypes message = 878 TestAllTypes.newBuilder() 879 .addRepeatedBytes(ByteString.EMPTY) 880 .addRepeatedBytes(ByteString.EMPTY) 881 .addRepeatedBytes(oneByte) 882 .build(); 883 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 884 assertThat(parsed.getRepeatedBytesCount()).isEqualTo(3); 885 assertThat(parsed.getRepeatedBytes(0)).isEqualTo(ByteString.EMPTY); 886 assertThat(parsed.getRepeatedBytes(1)).isEqualTo(ByteString.EMPTY); 887 assertThat(parsed.getRepeatedBytes(2)).isEqualTo(oneByte); 888 } 889 890 @Test testSkipUnknownFieldInMessageSetItem()891 public void testSkipUnknownFieldInMessageSetItem() throws Exception { 892 ByteArrayOutputStream output = new ByteArrayOutputStream(); 893 // MessageSet item's start tag. 894 output.write((byte) WireFormat.MESSAGE_SET_ITEM_TAG); 895 // Put all field types into the item. 896 TestUtil.getAllSet().writeTo(output); 897 // Closing the item with the real payload and closing tag. 898 output.write( 899 new byte[] { 900 (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG, 901 100, // TYPE_ID = 100 902 (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG, 903 0, // empty payload 904 (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG, 905 }); 906 byte[] data = output.toByteArray(); 907 TestMessageSet parsed = TestMessageSet.parseFrom(data); 908 909 // Convert to RawMessageSet for inspection. 910 RawMessageSet raw = RawMessageSet.parseFrom(parsed.toByteArray()); 911 assertThat(raw.getItemCount()).isEqualTo(1); 912 assertThat(raw.getItem(0).getTypeId()).isEqualTo(100); 913 assertThat(raw.getItem(0).getMessage().size()).isEqualTo(0); 914 } 915 916 @Test testProto2UnknownEnumValuesInOptionalField()917 public void testProto2UnknownEnumValuesInOptionalField() throws Exception { 918 // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with 919 // unknown enum values 920 UnittestProto3.TestAllTypes message = 921 UnittestProto3.TestAllTypes.newBuilder().setOptionalNestedEnumValue(4321).build(); 922 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 923 assertThat(parsed.hasOptionalNestedEnum()).isFalse(); 924 // Make sure unknown enum values are preserved. 925 UnittestProto3.TestAllTypes actual = 926 UnittestProto3.TestAllTypes.parseFrom(parsed.toByteArray()); 927 assertThat(actual.getOptionalNestedEnumValue()).isEqualTo(4321); 928 } 929 930 @Test testProto2UnknownEnumValuesInRepeatedField()931 public void testProto2UnknownEnumValuesInRepeatedField() throws Exception { 932 // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with 933 // unknown enum values 934 UnittestProto3.TestAllTypes message = 935 UnittestProto3.TestAllTypes.newBuilder().addRepeatedNestedEnumValue(5432).build(); 936 TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray()); 937 assertThat(parsed.getRepeatedNestedEnumCount()).isEqualTo(0); 938 // Make sure unknown enum values are preserved. 939 UnittestProto3.TestAllTypes actual = 940 UnittestProto3.TestAllTypes.parseFrom(parsed.toByteArray()); 941 assertThat(actual.getRepeatedNestedEnumCount()).isEqualTo(1); 942 assertThat(actual.getRepeatedNestedEnumValue(0)).isEqualTo(5432); 943 } 944 945 @Test testProto2UnknownEnumValuesInMapField()946 public void testProto2UnknownEnumValuesInMapField() throws Exception { 947 // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with 948 // unknown enum values 949 TestMap message = TestMap.newBuilder().putInt32ToEnumFieldValue(1, 4321).build(); 950 MapForProto2TestProto.TestMap parsed = 951 MapForProto2TestProto.TestMap.parseFrom(message.toByteArray()); 952 assertThat(parsed.getInt32ToEnumFieldMap()).isEmpty(); 953 // Make sure unknown enum values are preserved. 954 TestMap actual = TestMap.parseFrom(parsed.toByteArray()); 955 assertThat(actual.getInt32ToEnumFieldMap()).hasSize(1); 956 assertThat(actual.getInt32ToEnumFieldValueOrThrow(1)).isEqualTo(4321); 957 } 958 959 @Test testProto2UnknownEnumValuesInOneof()960 public void testProto2UnknownEnumValuesInOneof() throws Exception { 961 // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with 962 // unknown enum values 963 UnittestProto3.TestOneof2 message = 964 UnittestProto3.TestOneof2.newBuilder().setFooEnumValue(1234).build(); 965 TestOneof2 parsed = TestOneof2.parseFrom(message.toByteArray()); 966 assertThat(parsed.hasFooEnum()).isFalse(); 967 // Make sure unknown enum values are preserved. 968 UnittestProto3.TestOneof2 actual = UnittestProto3.TestOneof2.parseFrom(parsed.toByteArray()); 969 assertThat(actual.getFooEnumValue()).isEqualTo(1234); 970 } 971 972 @Test testProto2UnknownEnumValuesInExtension()973 public void testProto2UnknownEnumValuesInExtension() throws Exception { 974 ExtensionRegistryLite extensionRegistry = TestUtilLite.getExtensionRegistryLite(); 975 // Raw bytes for "[.optional_foreign_enum_extension_lite]: 10" 976 final byte[] rawBytes = new byte[]{-80, 1, 10}; 977 TestAllExtensionsLite testAllExtensionsLite = 978 TestAllExtensionsLite.parseFrom(rawBytes, extensionRegistry); 979 assertThat(testAllExtensionsLite.getExtension(optionalForeignEnumExtensionLite)) 980 .isEqualTo(ForeignEnumLite.FOREIGN_LITE_FOO); 981 final byte[] resultRawBytes = testAllExtensionsLite.toByteArray(); 982 assertThat(resultRawBytes).hasLength(rawBytes.length); 983 for (int i = 0; i < rawBytes.length; i++) { 984 assertThat(resultRawBytes[i]).isEqualTo(rawBytes[i]); 985 } 986 } 987 988 @Test testProto3UnknownEnumValuesInOptionalField()989 public void testProto3UnknownEnumValuesInOptionalField() throws Exception { 990 UnittestProto3.TestAllTypes message = 991 UnittestProto3.TestAllTypes.newBuilder().setOptionalNestedEnumValue(4321).build(); 992 UnittestProto3.TestAllTypes parsed = 993 UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); 994 assertThat(parsed.getOptionalNestedEnumValue()).isEqualTo(4321); 995 } 996 997 @Test testProto3UnknownEnumValuesInRepeatedField()998 public void testProto3UnknownEnumValuesInRepeatedField() throws Exception { 999 UnittestProto3.TestAllTypes message = 1000 UnittestProto3.TestAllTypes.newBuilder().addRepeatedNestedEnumValue(5432).build(); 1001 UnittestProto3.TestAllTypes parsed = 1002 UnittestProto3.TestAllTypes.parseFrom(message.toByteArray()); 1003 assertThat(parsed.getRepeatedNestedEnumCount()).isEqualTo(1); 1004 assertThat(parsed.getRepeatedNestedEnumValue(0)).isEqualTo(5432); 1005 } 1006 1007 @Test testProto3UnknownEnumValuesInMapField()1008 public void testProto3UnknownEnumValuesInMapField() throws Exception { 1009 TestMap message = TestMap.newBuilder().putInt32ToEnumFieldValue(1, 4321).build(); 1010 TestMap parsed = TestMap.parseFrom(message.toByteArray()); 1011 assertThat(parsed.getInt32ToEnumFieldMap()).hasSize(1); 1012 assertThat(parsed.getInt32ToEnumFieldValueOrThrow(1)).isEqualTo(4321); 1013 } 1014 1015 @Test testProto3UnknownEnumValuesInOneof()1016 public void testProto3UnknownEnumValuesInOneof() throws Exception { 1017 UnittestProto3.TestOneof2 message = 1018 UnittestProto3.TestOneof2.newBuilder().setFooEnumValue(1234).build(); 1019 UnittestProto3.TestOneof2 parsed = UnittestProto3.TestOneof2.parseFrom(message.toByteArray()); 1020 assertThat(parsed.getFooEnumValue()).isEqualTo(1234); 1021 } 1022 1023 @Test testProto3MessageFieldMergeBehavior()1024 public void testProto3MessageFieldMergeBehavior() throws Exception { 1025 UnittestProto3.NestedTestAllTypes message1 = 1026 UnittestProto3.NestedTestAllTypes.newBuilder() 1027 .setPayload( 1028 UnittestProto3.TestAllTypes.newBuilder() 1029 .setOptionalInt32(1234) 1030 .setOptionalInt64(5678)) 1031 .build(); 1032 UnittestProto3.NestedTestAllTypes message2 = 1033 UnittestProto3.NestedTestAllTypes.newBuilder() 1034 .setPayload( 1035 UnittestProto3.TestAllTypes.newBuilder() 1036 .setOptionalInt32(4321) 1037 .setOptionalUint32(8765)) 1038 .build(); 1039 1040 UnittestProto3.NestedTestAllTypes merged = 1041 UnittestProto3.NestedTestAllTypes.newBuilder() 1042 .mergeFrom(message1.toByteArray()) 1043 .mergeFrom(message2.toByteArray()) 1044 .build(); 1045 // Field values coming later in the stream override earlier values. 1046 assertThat(merged.getPayload().getOptionalInt32()).isEqualTo(4321); 1047 // Field values present in either message should be present in the merged result. 1048 assertThat(merged.getPayload().getOptionalInt64()).isEqualTo(5678); 1049 assertThat(merged.getPayload().getOptionalUint32()).isEqualTo(8765); 1050 } 1051 1052 @Test testMergeFromPartialByteArray()1053 public void testMergeFromPartialByteArray() throws Exception { 1054 byte[] data = TestUtil.getAllSet().toByteArray(); 1055 byte[] dataWithPaddings = new byte[data.length + 2]; 1056 System.arraycopy(data, 0, dataWithPaddings, 1, data.length); 1057 // Parsing will fail if the builder (or parser) interprets offset or length incorrectly. 1058 TestAllTypes.newBuilder().mergeFrom(dataWithPaddings, 1, data.length); 1059 TestAllTypes.parser().parseFrom(dataWithPaddings, 1, data.length); 1060 } 1061 } 1062