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 com.google.protobuf.UnittestLite.TestAllTypesLite;
34 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
35 import com.google.protobuf.UnittestLite.TestParsingMergeLite;
36 import protobuf_unittest.UnittestOptimizeFor;
37 import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
38 import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
39 import protobuf_unittest.UnittestProto;
40 import protobuf_unittest.UnittestProto.ForeignMessage;
41 import protobuf_unittest.UnittestProto.TestAllTypes;
42 import protobuf_unittest.UnittestProto.TestEmptyMessage;
43 import protobuf_unittest.UnittestProto.TestParsingMerge;
44 import protobuf_unittest.UnittestProto.TestRequired;
45 
46 import junit.framework.TestCase;
47 
48 import java.io.ByteArrayInputStream;
49 import java.io.ByteArrayOutputStream;
50 import java.io.IOException;
51 import java.io.InputStream;
52 
53 /**
54  * Unit test for {@link Parser}.
55  *
56  * @author liujisi@google.com (Pherl Liu)
57  */
58 public class ParserTest extends TestCase {
testGeneratedMessageParserSingleton()59   public void testGeneratedMessageParserSingleton() throws Exception {
60     for (int i = 0; i < 10; i++) {
61       assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType());
62     }
63   }
64 
assertRoundTripEquals(MessageLite message, ExtensionRegistryLite registry)65   private void assertRoundTripEquals(MessageLite message,
66                                      ExtensionRegistryLite registry)
67       throws Exception {
68     final byte[] data = message.toByteArray();
69     final int offset = 20;
70     final int length = data.length;
71     final int padding = 30;
72     Parser<? extends MessageLite> parser = message.getParserForType();
73     assertMessageEquals(message, parser.parseFrom(data, registry));
74     assertMessageEquals(message, parser.parseFrom(
75         generatePaddingArray(data, offset, padding),
76         offset, length, registry));
77     assertMessageEquals(message, parser.parseFrom(
78         message.toByteString(), registry));
79     assertMessageEquals(message, parser.parseFrom(
80         new ByteArrayInputStream(data), registry));
81     assertMessageEquals(message, parser.parseFrom(
82         CodedInputStream.newInstance(data), registry));
83   }
84 
85   @SuppressWarnings("unchecked")
assertRoundTripEquals(MessageLite message)86   private void assertRoundTripEquals(MessageLite message) throws Exception {
87     final byte[] data = message.toByteArray();
88     final int offset = 20;
89     final int length = data.length;
90     final int padding = 30;
91 
92     Parser<MessageLite> parser =
93         (Parser<MessageLite>) message.getParserForType();
94     assertMessageEquals(message, parser.parseFrom(data));
95     assertMessageEquals(message, parser.parseFrom(
96         generatePaddingArray(data, offset, padding),
97         offset, length));
98     assertMessageEquals(message, parser.parseFrom(message.toByteString()));
99     assertMessageEquals(message, parser.parseFrom(
100         new ByteArrayInputStream(data)));
101     assertMessageEquals(message, parser.parseFrom(
102         CodedInputStream.newInstance(data)));
103   }
104 
assertMessageEquals( MessageLite expected, MessageLite actual)105   private void assertMessageEquals(
106       MessageLite expected, MessageLite actual)
107       throws Exception {
108     if (expected instanceof Message) {
109       assertEquals(expected, actual);
110     } else {
111       assertEquals(expected.toByteString(), actual.toByteString());
112     }
113   }
114 
generatePaddingArray(byte[] data, int offset, int padding)115   private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
116     byte[] result = new byte[offset + data.length + padding];
117     System.arraycopy(data, 0, result, offset, data.length);
118     return result;
119   }
120 
testNormalMessage()121   public void testNormalMessage() throws Exception {
122     assertRoundTripEquals(TestUtil.getAllSet());
123   }
124 
125 
testParsePartial()126   public void testParsePartial() throws Exception {
127     assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
128   }
129 
assertParsePartial( Parser<T> parser, T partialMessage)130   private <T extends MessageLite> void assertParsePartial(
131       Parser<T> parser, T partialMessage) throws Exception {
132     final String errorString =
133         "Should throw exceptions when the parsed message isn't initialized.";
134 
135     // parsePartialFrom should pass.
136     byte[] data = partialMessage.toByteArray();
137     assertEquals(partialMessage, parser.parsePartialFrom(data));
138     assertEquals(partialMessage, parser.parsePartialFrom(
139         partialMessage.toByteString()));
140     assertEquals(partialMessage, parser.parsePartialFrom(
141         new ByteArrayInputStream(data)));
142     assertEquals(partialMessage, parser.parsePartialFrom(
143         CodedInputStream.newInstance(data)));
144 
145     // parseFrom(ByteArray)
146     try {
147       parser.parseFrom(partialMessage.toByteArray());
148       fail(errorString);
149     } catch (InvalidProtocolBufferException e) {
150       // pass.
151     }
152 
153     // parseFrom(ByteString)
154     try {
155       parser.parseFrom(partialMessage.toByteString());
156       fail(errorString);
157     } catch (InvalidProtocolBufferException e) {
158       // pass.
159     }
160 
161     // parseFrom(InputStream)
162     try {
163       parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
164       fail(errorString);
165     } catch (IOException e) {
166       // pass.
167     }
168 
169     // parseFrom(CodedInputStream)
170     try {
171       parser.parseFrom(CodedInputStream.newInstance(
172           partialMessage.toByteArray()));
173       fail(errorString);
174     } catch (IOException e) {
175       // pass.
176     }
177   }
178 
testParseExtensions()179   public void testParseExtensions() throws Exception {
180     assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
181                           TestUtil.getExtensionRegistry());
182     assertRoundTripEquals(
183         TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
184   }
185 
testParsePacked()186   public void testParsePacked() throws Exception {
187     assertRoundTripEquals(TestUtil.getPackedSet());
188     assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
189                           TestUtil.getExtensionRegistry());
190     assertRoundTripEquals(
191         TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
192   }
193 
testParseDelimitedTo()194   public void testParseDelimitedTo() throws Exception {
195     // Write normal Message.
196     TestAllTypes normalMessage = TestUtil.getAllSet();
197     ByteArrayOutputStream output = new ByteArrayOutputStream();
198     normalMessage.writeDelimitedTo(output);
199 
200     // Write MessageLite with packed extension fields.
201     TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet();
202     packedMessage.writeDelimitedTo(output);
203 
204     InputStream input = new ByteArrayInputStream(output.toByteArray());
205     assertMessageEquals(
206         normalMessage,
207         normalMessage.getParserForType().parseDelimitedFrom(input));
208     assertMessageEquals(
209         packedMessage,
210         packedMessage
211             .getParserForType()
212             .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite()));
213   }
214 
testParseUnknownFields()215   public void testParseUnknownFields() throws Exception {
216     // All fields will be treated as unknown fields in emptyMessage.
217     TestEmptyMessage emptyMessage =
218         TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString());
219     assertEquals(
220         TestUtil.getAllSet().toByteString(),
221         emptyMessage.toByteString());
222   }
223 
224 
testOptimizeForSize()225   public void testOptimizeForSize() throws Exception {
226     TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
227     builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
228     builder.setExtension(TestOptimizedForSize.testExtension, 56);
229     builder.setExtension(TestOptimizedForSize.testExtension2,
230         TestRequiredOptimizedForSize.newBuilder().setX(78).build());
231 
232     TestOptimizedForSize message = builder.build();
233     ExtensionRegistry registry = ExtensionRegistry.newInstance();
234     UnittestOptimizeFor.registerAllExtensions(registry);
235 
236     assertRoundTripEquals(message, registry);
237   }
238 
239   /** Helper method for {@link #testParsingMerge()}.*/
assertMessageMerged(TestAllTypes allTypes)240   private void assertMessageMerged(TestAllTypes allTypes)
241       throws Exception {
242     assertEquals(3, allTypes.getOptionalInt32());
243     assertEquals(2, allTypes.getOptionalInt64());
244     assertEquals("hello", allTypes.getOptionalString());
245   }
246 
247   /** Helper method for {@link #testParsingMergeLite()}.*/
assertMessageMerged(TestAllTypesLite allTypes)248   private void assertMessageMerged(TestAllTypesLite allTypes)
249       throws Exception {
250     assertEquals(3, allTypes.getOptionalInt32());
251     assertEquals(2, allTypes.getOptionalInt64());
252     assertEquals("hello", allTypes.getOptionalString());
253   }
254 
testParsingMerge()255   public void testParsingMerge() throws Exception {
256     // Build messages.
257     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
258     TestAllTypes msg1 = builder.setOptionalInt32(1).build();
259     builder.clear();
260     TestAllTypes msg2 = builder.setOptionalInt64(2).build();
261     builder.clear();
262     TestAllTypes msg3 = builder.setOptionalInt32(3)
263         .setOptionalString("hello").build();
264 
265     // Build groups.
266     TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
267         TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
268         .setField1(msg1).build();
269     TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
270         TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
271         .setField1(msg2).build();
272     TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
273         TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
274         .setField1(msg3).build();
275     TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
276         TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
277         .setField1(msg1).build();
278     TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
279         TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
280         .setField1(msg2).build();
281     TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
282         TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
283         .setField1(msg3).build();
284 
285     // Assign and serialize RepeatedFieldsGenerator.
286     ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
287         .addField1(msg1).addField1(msg2).addField1(msg3)
288         .addField2(msg1).addField2(msg2).addField2(msg3)
289         .addField3(msg1).addField3(msg2).addField3(msg3)
290         .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
291         .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
292         .addExt1(msg1).addExt1(msg2).addExt1(msg3)
293         .addExt2(msg1).addExt2(msg2).addExt2(msg3)
294         .build().toByteString();
295 
296     // Parse TestParsingMerge.
297     ExtensionRegistry registry = ExtensionRegistry.newInstance();
298     UnittestProto.registerAllExtensions(registry);
299     TestParsingMerge parsingMerge = TestParsingMerge.parser().parseFrom(data, registry);
300 
301     // Required and optional fields should be merged.
302     assertMessageMerged(parsingMerge.getRequiredAllTypes());
303     assertMessageMerged(parsingMerge.getOptionalAllTypes());
304     assertMessageMerged(
305         parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
306     assertMessageMerged(parsingMerge.getExtension(
307         TestParsingMerge.optionalExt));
308 
309     // Repeated fields should not be merged.
310     assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
311     assertEquals(3, parsingMerge.getRepeatedGroupCount());
312     assertEquals(3, parsingMerge.getExtensionCount(
313         TestParsingMerge.repeatedExt));
314   }
315 
testParsingMergeLite()316   public void testParsingMergeLite() throws Exception {
317     // Build messages.
318     TestAllTypesLite.Builder builder =
319         TestAllTypesLite.newBuilder();
320     TestAllTypesLite msg1 = builder.setOptionalInt32(1).build();
321     builder.clear();
322     TestAllTypesLite msg2 = builder.setOptionalInt64(2).build();
323     builder.clear();
324     TestAllTypesLite msg3 = builder.setOptionalInt32(3)
325         .setOptionalString("hello").build();
326 
327     // Build groups.
328     TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 =
329         TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
330         .setField1(msg1).build();
331     TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 =
332         TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
333         .setField1(msg2).build();
334     TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 =
335         TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
336         .setField1(msg3).build();
337     TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 =
338         TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
339         .setField1(msg1).build();
340     TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 =
341         TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
342         .setField1(msg2).build();
343     TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 =
344         TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
345         .setField1(msg3).build();
346 
347     // Assign and serialize RepeatedFieldsGenerator.
348     ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder()
349         .addField1(msg1).addField1(msg2).addField1(msg3)
350         .addField2(msg1).addField2(msg2).addField2(msg3)
351         .addField3(msg1).addField3(msg2).addField3(msg3)
352         .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
353         .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
354         .addExt1(msg1).addExt1(msg2).addExt1(msg3)
355         .addExt2(msg1).addExt2(msg2).addExt2(msg3)
356         .build().toByteString();
357 
358     // Parse TestParsingMergeLite.
359     ExtensionRegistry registry = ExtensionRegistry.newInstance();
360     UnittestLite.registerAllExtensions(registry);
361     TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry);
362 
363     // Required and optional fields should be merged.
364     assertMessageMerged(parsingMerge.getRequiredAllTypes());
365     assertMessageMerged(parsingMerge.getOptionalAllTypes());
366     assertMessageMerged(
367         parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
368     assertMessageMerged(parsingMerge.getExtension(
369         TestParsingMergeLite.optionalExt));
370 
371     // Repeated fields should not be merged.
372     assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
373     assertEquals(3, parsingMerge.getRepeatedGroupCount());
374     assertEquals(3, parsingMerge.getExtensionCount(
375         TestParsingMergeLite.repeatedExt));
376   }
377 }
378