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