• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import junit.framework.TestCase;
34 
35 import java.io.ByteArrayInputStream;
36 import java.io.ByteArrayOutputStream;
37 
38 import protobuf_unittest.UnittestProto;
39 import protobuf_unittest.UnittestProto.TestAllExtensions;
40 import protobuf_unittest.UnittestProto.TestAllTypes;
41 import protobuf_unittest.UnittestProto.TestFieldOrderings;
42 import protobuf_unittest.UnittestProto.TestPackedExtensions;
43 import protobuf_unittest.UnittestProto.TestPackedTypes;
44 import protobuf_unittest.UnittestMset.TestMessageSet;
45 import protobuf_unittest.UnittestMset.RawMessageSet;
46 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
47 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
48 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
49 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
50 
51 /**
52  * Tests related to parsing and serialization.
53  *
54  * @author kenton@google.com (Kenton Varda)
55  */
56 public class WireFormatTest extends TestCase {
testSerialization()57   public void testSerialization() throws Exception {
58     TestAllTypes message = TestUtil.getAllSet();
59 
60     ByteString rawBytes = message.toByteString();
61     assertEquals(rawBytes.size(), message.getSerializedSize());
62 
63     TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
64 
65     TestUtil.assertAllFieldsSet(message2);
66   }
67 
testSerializationPacked()68   public void testSerializationPacked() throws Exception {
69     TestPackedTypes message = TestUtil.getPackedSet();
70 
71     ByteString rawBytes = message.toByteString();
72     assertEquals(rawBytes.size(), message.getSerializedSize());
73 
74     TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
75 
76     TestUtil.assertPackedFieldsSet(message2);
77   }
78 
testSerializeExtensions()79   public void testSerializeExtensions() throws Exception {
80     // TestAllTypes and TestAllExtensions should have compatible wire formats,
81     // so if we serialize a TestAllExtensions then parse it as TestAllTypes
82     // it should work.
83 
84     TestAllExtensions message = TestUtil.getAllExtensionsSet();
85     ByteString rawBytes = message.toByteString();
86     assertEquals(rawBytes.size(), message.getSerializedSize());
87 
88     TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
89 
90     TestUtil.assertAllFieldsSet(message2);
91   }
92 
testSerializePackedExtensions()93   public void testSerializePackedExtensions() throws Exception {
94     // TestPackedTypes and TestPackedExtensions should have compatible wire
95     // formats; check that they serialize to the same string.
96     TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
97     ByteString rawBytes = message.toByteString();
98 
99     TestPackedTypes message2 = TestUtil.getPackedSet();
100     ByteString rawBytes2 = message2.toByteString();
101 
102     assertEquals(rawBytes, rawBytes2);
103   }
104 
testSerializationPackedWithoutGetSerializedSize()105   public void testSerializationPackedWithoutGetSerializedSize()
106       throws Exception {
107     // Write directly to an OutputStream, without invoking getSerializedSize()
108     // This used to be a bug where the size of a packed field was incorrect,
109     // since getSerializedSize() was never invoked.
110     TestPackedTypes message = TestUtil.getPackedSet();
111 
112     // Directly construct a CodedOutputStream around the actual OutputStream,
113     // in case writeTo(OutputStream output) invokes getSerializedSize();
114     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
115     CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
116 
117     message.writeTo(codedOutput);
118 
119     codedOutput.flush();
120 
121     TestPackedTypes message2 = TestPackedTypes.parseFrom(
122         outputStream.toByteArray());
123 
124     TestUtil.assertPackedFieldsSet(message2);
125   }
126 
testSerializeExtensionsLite()127   public void testSerializeExtensionsLite() throws Exception {
128     // TestAllTypes and TestAllExtensions should have compatible wire formats,
129     // so if we serialize a TestAllExtensions then parse it as TestAllTypes
130     // it should work.
131 
132     TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet();
133     ByteString rawBytes = message.toByteString();
134     assertEquals(rawBytes.size(), message.getSerializedSize());
135 
136     TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
137 
138     TestUtil.assertAllFieldsSet(message2);
139   }
140 
testSerializePackedExtensionsLite()141   public void testSerializePackedExtensionsLite() throws Exception {
142     // TestPackedTypes and TestPackedExtensions should have compatible wire
143     // formats; check that they serialize to the same string.
144     TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
145     ByteString rawBytes = message.toByteString();
146 
147     TestPackedTypes message2 = TestUtil.getPackedSet();
148     ByteString rawBytes2 = message2.toByteString();
149 
150     assertEquals(rawBytes, rawBytes2);
151   }
152 
testParseExtensions()153   public void testParseExtensions() throws Exception {
154     // TestAllTypes and TestAllExtensions should have compatible wire formats,
155     // so if we serialize a TestAllTypes then parse it as TestAllExtensions
156     // it should work.
157 
158     TestAllTypes message = TestUtil.getAllSet();
159     ByteString rawBytes = message.toByteString();
160 
161     ExtensionRegistry registry = TestUtil.getExtensionRegistry();
162 
163     TestAllExtensions message2 =
164       TestAllExtensions.parseFrom(rawBytes, registry);
165 
166     TestUtil.assertAllExtensionsSet(message2);
167   }
168 
testParsePackedExtensions()169   public void testParsePackedExtensions() throws Exception {
170     // Ensure that packed extensions can be properly parsed.
171     TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
172     ByteString rawBytes = message.toByteString();
173 
174     ExtensionRegistry registry = TestUtil.getExtensionRegistry();
175 
176     TestPackedExtensions message2 =
177         TestPackedExtensions.parseFrom(rawBytes, registry);
178 
179     TestUtil.assertPackedExtensionsSet(message2);
180   }
181 
testParseExtensionsLite()182   public void testParseExtensionsLite() throws Exception {
183     // TestAllTypes and TestAllExtensions should have compatible wire formats,
184     // so if we serialize a TestAllTypes then parse it as TestAllExtensions
185     // it should work.
186 
187     TestAllTypes message = TestUtil.getAllSet();
188     ByteString rawBytes = message.toByteString();
189 
190     ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite();
191 
192     TestAllExtensionsLite message2 =
193       TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
194 
195     TestUtil.assertAllExtensionsSet(message2);
196 
197     // Try again using a full extension registry.
198     ExtensionRegistry registry = TestUtil.getExtensionRegistry();
199 
200     TestAllExtensionsLite message3 =
201       TestAllExtensionsLite.parseFrom(rawBytes, registry);
202 
203     TestUtil.assertAllExtensionsSet(message3);
204   }
205 
testParsePackedExtensionsLite()206   public void testParsePackedExtensionsLite() throws Exception {
207     // Ensure that packed extensions can be properly parsed.
208     TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
209     ByteString rawBytes = message.toByteString();
210 
211     ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite();
212 
213     TestPackedExtensionsLite message2 =
214         TestPackedExtensionsLite.parseFrom(rawBytes, registry);
215 
216     TestUtil.assertPackedExtensionsSet(message2);
217   }
218 
testExtensionsSerializedSize()219   public void testExtensionsSerializedSize() throws Exception {
220     assertEquals(TestUtil.getAllSet().getSerializedSize(),
221                  TestUtil.getAllExtensionsSet().getSerializedSize());
222   }
223 
testSerializeDelimited()224   public void testSerializeDelimited() throws Exception {
225     ByteArrayOutputStream output = new ByteArrayOutputStream();
226     TestUtil.getAllSet().writeDelimitedTo(output);
227     output.write(12);
228     TestUtil.getPackedSet().writeDelimitedTo(output);
229     output.write(34);
230 
231     ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
232 
233     TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
234     assertEquals(12, input.read());
235     TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
236     assertEquals(34, input.read());
237     assertEquals(-1, input.read());
238 
239     // We're at EOF, so parsing again should return null.
240     assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
241   }
242 
assertFieldsInOrder(ByteString data)243   private void assertFieldsInOrder(ByteString data) throws Exception {
244     CodedInputStream input = data.newCodedInput();
245     int previousTag = 0;
246 
247     while (true) {
248       int tag = input.readTag();
249       if (tag == 0) {
250         break;
251       }
252 
253       assertTrue(tag > previousTag);
254       previousTag = tag;
255       input.skipField(tag);
256     }
257   }
258 
testInterleavedFieldsAndExtensions()259   public void testInterleavedFieldsAndExtensions() throws Exception {
260     // Tests that fields are written in order even when extension ranges
261     // are interleaved with field numbers.
262     ByteString data =
263       TestFieldOrderings.newBuilder()
264         .setMyInt(1)
265         .setMyString("foo")
266         .setMyFloat(1.0F)
267         .setExtension(UnittestProto.myExtensionInt, 23)
268         .setExtension(UnittestProto.myExtensionString, "bar")
269         .build().toByteString();
270     assertFieldsInOrder(data);
271 
272     Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
273     ByteString dynamic_data =
274       DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
275         .setField(descriptor.findFieldByName("my_int"), 1L)
276         .setField(descriptor.findFieldByName("my_string"), "foo")
277         .setField(descriptor.findFieldByName("my_float"), 1.0F)
278         .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
279         .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
280         .build().toByteString();
281     assertFieldsInOrder(dynamic_data);
282   }
283 
getTestFieldOrderingsRegistry()284   private ExtensionRegistry getTestFieldOrderingsRegistry() {
285     ExtensionRegistry result = ExtensionRegistry.newInstance();
286     result.add(UnittestProto.myExtensionInt);
287     result.add(UnittestProto.myExtensionString);
288     return result;
289   }
290 
testParseMultipleExtensionRanges()291   public void testParseMultipleExtensionRanges() throws Exception {
292     // Make sure we can parse a message that contains multiple extensions
293     // ranges.
294     TestFieldOrderings source =
295       TestFieldOrderings.newBuilder()
296         .setMyInt(1)
297         .setMyString("foo")
298         .setMyFloat(1.0F)
299         .setExtension(UnittestProto.myExtensionInt, 23)
300         .setExtension(UnittestProto.myExtensionString, "bar")
301         .build();
302     TestFieldOrderings dest =
303       TestFieldOrderings.parseFrom(source.toByteString(),
304                                    getTestFieldOrderingsRegistry());
305     assertEquals(source, dest);
306   }
307 
testParseMultipleExtensionRangesDynamic()308   public void testParseMultipleExtensionRangesDynamic() throws Exception {
309     // Same as above except with DynamicMessage.
310     Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
311     DynamicMessage source =
312       DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
313         .setField(descriptor.findFieldByName("my_int"), 1L)
314         .setField(descriptor.findFieldByName("my_string"), "foo")
315         .setField(descriptor.findFieldByName("my_float"), 1.0F)
316         .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
317         .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
318         .build();
319     DynamicMessage dest =
320       DynamicMessage.parseFrom(descriptor, source.toByteString(),
321                                getTestFieldOrderingsRegistry());
322     assertEquals(source, dest);
323   }
324 
325   private static final int UNKNOWN_TYPE_ID = 1550055;
326   private static final int TYPE_ID_1 =
327     TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
328   private static final int TYPE_ID_2 =
329     TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
330 
testSerializeMessageSet()331   public void testSerializeMessageSet() throws Exception {
332     // Set up a TestMessageSet with two known messages and an unknown one.
333     TestMessageSet messageSet =
334       TestMessageSet.newBuilder()
335         .setExtension(
336           TestMessageSetExtension1.messageSetExtension,
337           TestMessageSetExtension1.newBuilder().setI(123).build())
338         .setExtension(
339           TestMessageSetExtension2.messageSetExtension,
340           TestMessageSetExtension2.newBuilder().setStr("foo").build())
341         .setUnknownFields(
342           UnknownFieldSet.newBuilder()
343             .addField(UNKNOWN_TYPE_ID,
344               UnknownFieldSet.Field.newBuilder()
345                 .addLengthDelimited(ByteString.copyFromUtf8("bar"))
346                 .build())
347             .build())
348         .build();
349 
350     ByteString data = messageSet.toByteString();
351 
352     // Parse back using RawMessageSet and check the contents.
353     RawMessageSet raw = RawMessageSet.parseFrom(data);
354 
355     assertTrue(raw.getUnknownFields().asMap().isEmpty());
356 
357     assertEquals(3, raw.getItemCount());
358     assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
359     assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
360     assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
361 
362     TestMessageSetExtension1 message1 =
363       TestMessageSetExtension1.parseFrom(
364         raw.getItem(0).getMessage().toByteArray());
365     assertEquals(123, message1.getI());
366 
367     TestMessageSetExtension2 message2 =
368       TestMessageSetExtension2.parseFrom(
369         raw.getItem(1).getMessage().toByteArray());
370     assertEquals("foo", message2.getStr());
371 
372     assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
373   }
374 
testParseMessageSet()375   public void testParseMessageSet() throws Exception {
376     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
377     extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
378     extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
379 
380     // Set up a RawMessageSet with two known messages and an unknown one.
381     RawMessageSet raw =
382       RawMessageSet.newBuilder()
383         .addItem(
384           RawMessageSet.Item.newBuilder()
385             .setTypeId(TYPE_ID_1)
386             .setMessage(
387               TestMessageSetExtension1.newBuilder()
388                 .setI(123)
389                 .build().toByteString())
390             .build())
391         .addItem(
392           RawMessageSet.Item.newBuilder()
393             .setTypeId(TYPE_ID_2)
394             .setMessage(
395               TestMessageSetExtension2.newBuilder()
396                 .setStr("foo")
397                 .build().toByteString())
398             .build())
399         .addItem(
400           RawMessageSet.Item.newBuilder()
401             .setTypeId(UNKNOWN_TYPE_ID)
402             .setMessage(ByteString.copyFromUtf8("bar"))
403             .build())
404         .build();
405 
406     ByteString data = raw.toByteString();
407 
408     // Parse as a TestMessageSet and check the contents.
409     TestMessageSet messageSet =
410       TestMessageSet.parseFrom(data, extensionRegistry);
411 
412     assertEquals(123, messageSet.getExtension(
413       TestMessageSetExtension1.messageSetExtension).getI());
414     assertEquals("foo", messageSet.getExtension(
415       TestMessageSetExtension2.messageSetExtension).getStr());
416 
417     // Check for unknown field with type LENGTH_DELIMITED,
418     //   number UNKNOWN_TYPE_ID, and contents "bar".
419     UnknownFieldSet unknownFields = messageSet.getUnknownFields();
420     assertEquals(1, unknownFields.asMap().size());
421     assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
422 
423     UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
424     assertEquals(1, field.getLengthDelimitedList().size());
425     assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
426   }
427 }
428