Home | History | Annotate | Download | only in protobuf
      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 (at) google.com (Pherl Liu)
     57  */
     58 public class ParserTest extends TestCase {
     59   public void testGeneratedMessageParserSingleton() throws Exception {
     60     for (int i = 0; i < 10; i++) {
     61       assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType());
     62     }
     63   }
     64 
     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")
     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 
    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 
    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 
    121   public void testNormalMessage() throws Exception {
    122     assertRoundTripEquals(TestUtil.getAllSet());
    123   }
    124 
    125 
    126   public void testParsePartial() throws Exception {
    127     assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
    128   }
    129 
    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 
    179   public void testParseExtensions() throws Exception {
    180     assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
    181                           TestUtil.getExtensionRegistry());
    182     assertRoundTripEquals(
    183         TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
    184   }
    185 
    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 
    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 
    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 
    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()}.*/
    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()}.*/
    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 
    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 
    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