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