1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 package com.google.protobuf;
33 import junit.framework.TestCase;
35 import java.io.ByteArrayInputStream;
36 import java.io.ByteArrayOutputStream;
37 import java.util.List;
39 import protobuf_unittest.UnittestProto;
40 import protobuf_unittest.UnittestProto.TestAllExtensions;
41 import protobuf_unittest.UnittestProto.TestAllTypes;
42 import protobuf_unittest.UnittestProto.TestFieldOrderings;
43 import protobuf_unittest.UnittestProto.TestPackedExtensions;
44 import protobuf_unittest.UnittestProto.TestPackedTypes;
45 import protobuf_unittest.UnittestMset.TestMessageSet;
46 import protobuf_unittest.UnittestMset.RawMessageSet;
47 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
48 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
49 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
50 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
53 * Tests related to parsing and serialization.
55 * @author kenton@google.com (Kenton Varda)
57 public class WireFormatTest extends TestCase {
58 public void testSerialization() throws Exception {
59 TestAllTypes message = TestUtil.getAllSet();
61 ByteString rawBytes = message.toByteString();
62 assertEquals(rawBytes.size(), message.getSerializedSize());
64 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
66 TestUtil.assertAllFieldsSet(message2);
69 public void testSerializationPacked() throws Exception {
70 TestPackedTypes message = TestUtil.getPackedSet();
72 ByteString rawBytes = message.toByteString();
73 assertEquals(rawBytes.size(), message.getSerializedSize());
75 TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
77 TestUtil.assertPackedFieldsSet(message2);
80 public void testSerializeExtensions() throws Exception {
81 // TestAllTypes and TestAllExtensions should have compatible wire formats,
82 // so if we serialize a TestAllExtensions then parse it as TestAllTypes
85 TestAllExtensions message = TestUtil.getAllExtensionsSet();
86 ByteString rawBytes = message.toByteString();
87 assertEquals(rawBytes.size(), message.getSerializedSize());
89 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
91 TestUtil.assertAllFieldsSet(message2);
94 public void testSerializePackedExtensions() throws Exception {
95 // TestPackedTypes and TestPackedExtensions should have compatible wire
96 // formats; check that they serialize to the same string.
97 TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
98 ByteString rawBytes = message.toByteString();
100 TestPackedTypes message2 = TestUtil.getPackedSet();
101 ByteString rawBytes2 = message2.toByteString();
103 assertEquals(rawBytes, rawBytes2);
106 public void testSerializationPackedWithoutGetSerializedSize()
108 // Write directly to an OutputStream, without invoking getSerializedSize()
109 // This used to be a bug where the size of a packed field was incorrect,
110 // since getSerializedSize() was never invoked.
111 TestPackedTypes message = TestUtil.getPackedSet();
113 // Directly construct a CodedOutputStream around the actual OutputStream,
114 // in case writeTo(OutputStream output) invokes getSerializedSize();
115 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
116 CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
118 message.writeTo(codedOutput);
122 TestPackedTypes message2 = TestPackedTypes.parseFrom(
123 outputStream.toByteArray());
125 TestUtil.assertPackedFieldsSet(message2);
128 public void testSerializeExtensionsLite() throws Exception {
129 // TestAllTypes and TestAllExtensions should have compatible wire formats,
130 // so if we serialize a TestAllExtensions then parse it as TestAllTypes
133 TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet();
134 ByteString rawBytes = message.toByteString();
135 assertEquals(rawBytes.size(), message.getSerializedSize());
137 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
139 TestUtil.assertAllFieldsSet(message2);
142 public void testSerializePackedExtensionsLite() throws Exception {
143 // TestPackedTypes and TestPackedExtensions should have compatible wire
144 // formats; check that they serialize to the same string.
145 TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
146 ByteString rawBytes = message.toByteString();
148 TestPackedTypes message2 = TestUtil.getPackedSet();
149 ByteString rawBytes2 = message2.toByteString();
151 assertEquals(rawBytes, rawBytes2);
154 public void testParseExtensions() throws Exception {
155 // TestAllTypes and TestAllExtensions should have compatible wire formats,
156 // so if we serialize a TestAllTypes then parse it as TestAllExtensions
159 TestAllTypes message = TestUtil.getAllSet();
160 ByteString rawBytes = message.toByteString();
162 ExtensionRegistry registry = TestUtil.getExtensionRegistry();
164 TestAllExtensions message2 =
165 TestAllExtensions.parseFrom(rawBytes, registry);
167 TestUtil.assertAllExtensionsSet(message2);
170 public void testParsePackedExtensions() throws Exception {
171 // Ensure that packed extensions can be properly parsed.
172 TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
173 ByteString rawBytes = message.toByteString();
175 ExtensionRegistry registry = TestUtil.getExtensionRegistry();
177 TestPackedExtensions message2 =
178 TestPackedExtensions.parseFrom(rawBytes, registry);
180 TestUtil.assertPackedExtensionsSet(message2);
183 public void testParseExtensionsLite() throws Exception {
184 // TestAllTypes and TestAllExtensions should have compatible wire formats,
185 // so if we serialize a TestAllTypes then parse it as TestAllExtensions
188 TestAllTypes message = TestUtil.getAllSet();
189 ByteString rawBytes = message.toByteString();
191 ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite();
193 TestAllExtensionsLite message2 =
194 TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
196 TestUtil.assertAllExtensionsSet(message2);
198 // Try again using a full extension registry.
199 ExtensionRegistry registry = TestUtil.getExtensionRegistry();
201 TestAllExtensionsLite message3 =
202 TestAllExtensionsLite.parseFrom(rawBytes, registry);
204 TestUtil.assertAllExtensionsSet(message3);
207 public void testParsePackedExtensionsLite() throws Exception {
208 // Ensure that packed extensions can be properly parsed.
209 TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
210 ByteString rawBytes = message.toByteString();
212 ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite();
214 TestPackedExtensionsLite message2 =
215 TestPackedExtensionsLite.parseFrom(rawBytes, registry);
217 TestUtil.assertPackedExtensionsSet(message2);
220 public void testExtensionsSerializedSize() throws Exception {
221 assertEquals(TestUtil.getAllSet().getSerializedSize(),
222 TestUtil.getAllExtensionsSet().getSerializedSize());
225 public void testSerializeDelimited() throws Exception {
226 ByteArrayOutputStream output = new ByteArrayOutputStream();
227 TestUtil.getAllSet().writeDelimitedTo(output);
229 TestUtil.getPackedSet().writeDelimitedTo(output);
232 ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
234 TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
235 assertEquals(12, input.read());
236 TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
237 assertEquals(34, input.read());
238 assertEquals(-1, input.read());
240 // We're at EOF, so parsing again should return null.
241 assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
244 private void assertFieldsInOrder(ByteString data) throws Exception {
245 CodedInputStream input = data.newCodedInput();
249 int tag = input.readTag();
254 assertTrue(tag > previousTag);
256 input.skipField(tag);
260 public void testInterleavedFieldsAndExtensions() throws Exception {
261 // Tests that fields are written in order even when extension ranges
262 // are interleaved with field numbers.
264 TestFieldOrderings.newBuilder()
268 .setExtension(UnittestProto.myExtensionInt, 23)
269 .setExtension(UnittestProto.myExtensionString, "bar")
270 .build().toByteString();
271 assertFieldsInOrder(data);
273 Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
274 ByteString dynamic_data =
275 DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
276 .setField(descriptor.findFieldByName("my_int"), 1L)
277 .setField(descriptor.findFieldByName("my_string"), "foo")
278 .setField(descriptor.findFieldByName("my_float"), 1.0F)
279 .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
280 .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
281 .build().toByteString();
282 assertFieldsInOrder(dynamic_data);
285 private ExtensionRegistry getTestFieldOrderingsRegistry() {
286 ExtensionRegistry result = ExtensionRegistry.newInstance();
287 result.add(UnittestProto.myExtensionInt);
288 result.add(UnittestProto.myExtensionString);
292 public void testParseMultipleExtensionRanges() throws Exception {
293 // Make sure we can parse a message that contains multiple extensions
295 TestFieldOrderings source =
296 TestFieldOrderings.newBuilder()
300 .setExtension(UnittestProto.myExtensionInt, 23)
301 .setExtension(UnittestProto.myExtensionString, "bar")
303 TestFieldOrderings dest =
304 TestFieldOrderings.parseFrom(source.toByteString(),
305 getTestFieldOrderingsRegistry());
306 assertEquals(source, dest);
309 public void testParseMultipleExtensionRangesDynamic() throws Exception {
310 // Same as above except with DynamicMessage.
311 Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
312 DynamicMessage source =
313 DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
314 .setField(descriptor.findFieldByName("my_int"), 1L)
315 .setField(descriptor.findFieldByName("my_string"), "foo")
316 .setField(descriptor.findFieldByName("my_float"), 1.0F)
317 .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
318 .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
320 DynamicMessage dest =
321 DynamicMessage.parseFrom(descriptor, source.toByteString(),
322 getTestFieldOrderingsRegistry());
323 assertEquals(source, dest);
326 private static final int UNKNOWN_TYPE_ID = 1550055;
327 private static final int TYPE_ID_1 =
328 TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
329 private static final int TYPE_ID_2 =
330 TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
332 public void testSerializeMessageSetEagerly() throws Exception {
333 testSerializeMessageSetWithFlag(true);
336 public void testSerializeMessageSetNotEagerly() throws Exception {
337 testSerializeMessageSetWithFlag(false);
340 private void testSerializeMessageSetWithFlag(boolean eagerParsing)
342 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
343 // Set up a TestMessageSet with two known messages and an unknown one.
344 TestMessageSet messageSet =
345 TestMessageSet.newBuilder()
347 TestMessageSetExtension1.messageSetExtension,
348 TestMessageSetExtension1.newBuilder().setI(123).build())
350 TestMessageSetExtension2.messageSetExtension,
351 TestMessageSetExtension2.newBuilder().setStr("foo").build())
353 UnknownFieldSet.newBuilder()
354 .addField(UNKNOWN_TYPE_ID,
355 UnknownFieldSet.Field.newBuilder()
356 .addLengthDelimited(ByteString.copyFromUtf8("bar"))
361 ByteString data = messageSet.toByteString();
363 // Parse back using RawMessageSet and check the contents.
364 RawMessageSet raw = RawMessageSet.parseFrom(data);
366 assertTrue(raw.getUnknownFields().asMap().isEmpty());
368 assertEquals(3, raw.getItemCount());
369 assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
370 assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
371 assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
373 TestMessageSetExtension1 message1 =
374 TestMessageSetExtension1.parseFrom(
375 raw.getItem(0).getMessage().toByteArray());
376 assertEquals(123, message1.getI());
378 TestMessageSetExtension2 message2 =
379 TestMessageSetExtension2.parseFrom(
380 raw.getItem(1).getMessage().toByteArray());
381 assertEquals("foo", message2.getStr());
383 assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
386 public void testParseMessageSetEagerly() throws Exception {
387 testParseMessageSetWithFlag(true);
390 public void testParseMessageSetNotEagerly()throws Exception {
391 testParseMessageSetWithFlag(false);
394 private void testParseMessageSetWithFlag(boolean eagerParsing)
396 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
397 ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
398 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
399 extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
401 // Set up a RawMessageSet with two known messages and an unknown one.
403 RawMessageSet.newBuilder()
405 RawMessageSet.Item.newBuilder()
406 .setTypeId(TYPE_ID_1)
408 TestMessageSetExtension1.newBuilder()
410 .build().toByteString())
413 RawMessageSet.Item.newBuilder()
414 .setTypeId(TYPE_ID_2)
416 TestMessageSetExtension2.newBuilder()
418 .build().toByteString())
421 RawMessageSet.Item.newBuilder()
422 .setTypeId(UNKNOWN_TYPE_ID)
423 .setMessage(ByteString.copyFromUtf8("bar"))
427 ByteString data = raw.toByteString();
429 // Parse as a TestMessageSet and check the contents.
430 TestMessageSet messageSet =
431 TestMessageSet.parseFrom(data, extensionRegistry);
433 assertEquals(123, messageSet.getExtension(
434 TestMessageSetExtension1.messageSetExtension).getI());
435 assertEquals("foo", messageSet.getExtension(
436 TestMessageSetExtension2.messageSetExtension).getStr());
438 // Check for unknown field with type LENGTH_DELIMITED,
439 // number UNKNOWN_TYPE_ID, and contents "bar".
440 UnknownFieldSet unknownFields = messageSet.getUnknownFields();
441 assertEquals(1, unknownFields.asMap().size());
442 assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
444 UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
445 assertEquals(1, field.getLengthDelimitedList().size());
446 assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
449 public void testParseMessageSetExtensionEagerly() throws Exception {
450 testParseMessageSetExtensionWithFlag(true);
453 public void testParseMessageSetExtensionNotEagerly() throws Exception {
454 testParseMessageSetExtensionWithFlag(false);
457 private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
459 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
460 ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
461 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
463 // Set up a RawMessageSet with a known messages.
465 TestMessageSetExtension1
466 .getDescriptor().getExtensions().get(0).getNumber();
468 RawMessageSet.newBuilder()
470 RawMessageSet.Item.newBuilder()
471 .setTypeId(TYPE_ID_1)
473 TestMessageSetExtension1.newBuilder()
475 .build().toByteString())
479 ByteString data = raw.toByteString();
481 // Parse as a TestMessageSet and check the contents.
482 TestMessageSet messageSet =
483 TestMessageSet.parseFrom(data, extensionRegistry);
484 assertEquals(123, messageSet.getExtension(
485 TestMessageSetExtension1.messageSetExtension).getI());
488 public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
489 testMergeLazyMessageSetExtensionWithFlag(true);
492 public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
493 testMergeLazyMessageSetExtensionWithFlag(false);
496 private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
498 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
499 ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
500 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
502 // Set up a RawMessageSet with a known messages.
504 TestMessageSetExtension1
505 .getDescriptor().getExtensions().get(0).getNumber();
507 RawMessageSet.newBuilder()
509 RawMessageSet.Item.newBuilder()
510 .setTypeId(TYPE_ID_1)
512 TestMessageSetExtension1.newBuilder()
514 .build().toByteString())
518 ByteString data = raw.toByteString();
520 // Parse as a TestMessageSet and store value into lazy field
521 TestMessageSet messageSet =
522 TestMessageSet.parseFrom(data, extensionRegistry);
523 // Merge lazy field check the contents.
525 messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
526 assertEquals(123, messageSet.getExtension(
527 TestMessageSetExtension1.messageSetExtension).getI());
530 public void testMergeMessageSetExtensionEagerly() throws Exception {
531 testMergeMessageSetExtensionWithFlag(true);
534 public void testMergeMessageSetExtensionNotEagerly() throws Exception {
535 testMergeMessageSetExtensionWithFlag(false);
538 private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing)
540 ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
541 ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
542 extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
544 // Set up a RawMessageSet with a known messages.
546 TestMessageSetExtension1
547 .getDescriptor().getExtensions().get(0).getNumber();
549 RawMessageSet.newBuilder()
551 RawMessageSet.Item.newBuilder()
552 .setTypeId(TYPE_ID_1)
554 TestMessageSetExtension1.newBuilder()
556 .build().toByteString())
560 // Serialize RawMessageSet unnormally (message value before type id)
561 ByteString.CodedBuilder out = ByteString.newCodedBuilder(
562 raw.getSerializedSize());
563 CodedOutputStream output = out.getCodedOutput();
564 List<RawMessageSet.Item> items = raw.getItemList();
565 for (int i = 0; i < items.size(); i++) {
566 RawMessageSet.Item item = items.get(i);
567 output.writeTag(1, WireFormat.WIRETYPE_START_GROUP);
568 output.writeBytes(3, item.getMessage());
569 output.writeInt32(2, item.getTypeId());
570 output.writeTag(1, WireFormat.WIRETYPE_END_GROUP);
572 ByteString data = out.build();
574 // Merge bytes into TestMessageSet and check the contents.
575 TestMessageSet messageSet =
576 TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build();
577 assertEquals(123, messageSet.getExtension(
578 TestMessageSetExtension1.messageSetExtension).getI());