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 protobuf_unittest.UnittestProto.ForeignMessage;
     34 import protobuf_unittest.UnittestProto.TestAllExtensions;
     35 import protobuf_unittest.UnittestProto.TestAllTypes;
     36 import protobuf_unittest.UnittestProto.TestRequired;
     37 import protobuf_unittest.UnittestProto.TestRequiredForeign;
     38 
     39 import junit.framework.TestCase;
     40 
     41 import java.util.List;
     42 
     43 /**
     44  * Misc. unit tests for message operations that apply to both generated
     45  * and dynamic messages.
     46  *
     47  * @author kenton (at) google.com Kenton Varda
     48  */
     49 public class MessageTest extends TestCase {
     50   // =================================================================
     51   // Message-merging tests.
     52 
     53   static final TestAllTypes MERGE_SOURCE =
     54     TestAllTypes.newBuilder()
     55       .setOptionalInt32(1)
     56       .setOptionalString("foo")
     57       .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
     58       .addRepeatedString("bar")
     59       .build();
     60 
     61   static final TestAllTypes MERGE_DEST =
     62     TestAllTypes.newBuilder()
     63       .setOptionalInt64(2)
     64       .setOptionalString("baz")
     65       .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
     66       .addRepeatedString("qux")
     67       .build();
     68 
     69   static final String MERGE_RESULT_TEXT =
     70       "optional_int32: 1\n" +
     71       "optional_int64: 2\n" +
     72       "optional_string: \"foo\"\n" +
     73       "optional_foreign_message {\n" +
     74       "  c: 3\n" +
     75       "}\n" +
     76       "repeated_string: \"qux\"\n" +
     77       "repeated_string: \"bar\"\n";
     78 
     79   public void testMergeFrom() throws Exception {
     80     TestAllTypes result =
     81       TestAllTypes.newBuilder(MERGE_DEST)
     82         .mergeFrom(MERGE_SOURCE).build();
     83 
     84     assertEquals(MERGE_RESULT_TEXT, result.toString());
     85   }
     86 
     87   /**
     88    * Test merging a DynamicMessage into a GeneratedMessage.  As long as they
     89    * have the same descriptor, this should work, but it is an entirely different
     90    * code path.
     91    */
     92   public void testMergeFromDynamic() throws Exception {
     93     TestAllTypes result =
     94       TestAllTypes.newBuilder(MERGE_DEST)
     95         .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
     96         .build();
     97 
     98     assertEquals(MERGE_RESULT_TEXT, result.toString());
     99   }
    100 
    101   /** Test merging two DynamicMessages. */
    102   public void testDynamicMergeFrom() throws Exception {
    103     DynamicMessage result =
    104       DynamicMessage.newBuilder(MERGE_DEST)
    105         .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
    106         .build();
    107 
    108     assertEquals(MERGE_RESULT_TEXT, result.toString());
    109   }
    110 
    111   // =================================================================
    112   // Required-field-related tests.
    113 
    114   private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
    115     TestRequired.getDefaultInstance();
    116   private static final TestRequired TEST_REQUIRED_INITIALIZED =
    117     TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
    118 
    119   public void testRequired() throws Exception {
    120     TestRequired.Builder builder = TestRequired.newBuilder();
    121 
    122     assertFalse(builder.isInitialized());
    123     builder.setA(1);
    124     assertFalse(builder.isInitialized());
    125     builder.setB(1);
    126     assertFalse(builder.isInitialized());
    127     builder.setC(1);
    128     assertTrue(builder.isInitialized());
    129   }
    130 
    131   public void testRequiredForeign() throws Exception {
    132     TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
    133 
    134     assertTrue(builder.isInitialized());
    135 
    136     builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
    137     assertFalse(builder.isInitialized());
    138 
    139     builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
    140     assertTrue(builder.isInitialized());
    141 
    142     builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
    143     assertFalse(builder.isInitialized());
    144 
    145     builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
    146     assertTrue(builder.isInitialized());
    147   }
    148 
    149   public void testRequiredExtension() throws Exception {
    150     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
    151 
    152     assertTrue(builder.isInitialized());
    153 
    154     builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED);
    155     assertFalse(builder.isInitialized());
    156 
    157     builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED);
    158     assertTrue(builder.isInitialized());
    159 
    160     builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED);
    161     assertFalse(builder.isInitialized());
    162 
    163     builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED);
    164     assertTrue(builder.isInitialized());
    165   }
    166 
    167   public void testRequiredDynamic() throws Exception {
    168     Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
    169     DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
    170 
    171     assertFalse(builder.isInitialized());
    172     builder.setField(descriptor.findFieldByName("a"), 1);
    173     assertFalse(builder.isInitialized());
    174     builder.setField(descriptor.findFieldByName("b"), 1);
    175     assertFalse(builder.isInitialized());
    176     builder.setField(descriptor.findFieldByName("c"), 1);
    177     assertTrue(builder.isInitialized());
    178   }
    179 
    180   public void testRequiredDynamicForeign() throws Exception {
    181     Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor();
    182     DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
    183 
    184     assertTrue(builder.isInitialized());
    185 
    186     builder.setField(descriptor.findFieldByName("optional_message"),
    187                      TEST_REQUIRED_UNINITIALIZED);
    188     assertFalse(builder.isInitialized());
    189 
    190     builder.setField(descriptor.findFieldByName("optional_message"),
    191                      TEST_REQUIRED_INITIALIZED);
    192     assertTrue(builder.isInitialized());
    193 
    194     builder.addRepeatedField(descriptor.findFieldByName("repeated_message"),
    195                              TEST_REQUIRED_UNINITIALIZED);
    196     assertFalse(builder.isInitialized());
    197 
    198     builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0,
    199                              TEST_REQUIRED_INITIALIZED);
    200     assertTrue(builder.isInitialized());
    201   }
    202 
    203   public void testUninitializedException() throws Exception {
    204     try {
    205       TestRequired.newBuilder().build();
    206       fail("Should have thrown an exception.");
    207     } catch (UninitializedMessageException e) {
    208       assertEquals("Message missing required fields: a, b, c", e.getMessage());
    209     }
    210   }
    211 
    212   public void testBuildPartial() throws Exception {
    213     // We're mostly testing that no exception is thrown.
    214     TestRequired message = TestRequired.newBuilder().buildPartial();
    215     assertFalse(message.isInitialized());
    216   }
    217 
    218   public void testNestedUninitializedException() throws Exception {
    219     try {
    220       TestRequiredForeign.newBuilder()
    221         .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
    222         .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
    223         .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
    224         .build();
    225       fail("Should have thrown an exception.");
    226     } catch (UninitializedMessageException e) {
    227       assertEquals(
    228         "Message missing required fields: " +
    229         "optional_message.a, " +
    230         "optional_message.b, " +
    231         "optional_message.c, " +
    232         "repeated_message[0].a, " +
    233         "repeated_message[0].b, " +
    234         "repeated_message[0].c, " +
    235         "repeated_message[1].a, " +
    236         "repeated_message[1].b, " +
    237         "repeated_message[1].c",
    238         e.getMessage());
    239     }
    240   }
    241 
    242   public void testBuildNestedPartial() throws Exception {
    243     // We're mostly testing that no exception is thrown.
    244     TestRequiredForeign message =
    245       TestRequiredForeign.newBuilder()
    246         .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
    247         .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
    248         .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
    249         .buildPartial();
    250     assertFalse(message.isInitialized());
    251   }
    252 
    253   public void testParseUnititialized() throws Exception {
    254     try {
    255       TestRequired.parseFrom(ByteString.EMPTY);
    256       fail("Should have thrown an exception.");
    257     } catch (InvalidProtocolBufferException e) {
    258       assertEquals("Message missing required fields: a, b, c", e.getMessage());
    259     }
    260   }
    261 
    262   public void testParseNestedUnititialized() throws Exception {
    263     ByteString data =
    264       TestRequiredForeign.newBuilder()
    265         .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
    266         .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
    267         .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
    268         .buildPartial().toByteString();
    269 
    270     try {
    271       TestRequiredForeign.parseFrom(data);
    272       fail("Should have thrown an exception.");
    273     } catch (InvalidProtocolBufferException e) {
    274       assertEquals(
    275         "Message missing required fields: " +
    276         "optional_message.a, " +
    277         "optional_message.b, " +
    278         "optional_message.c, " +
    279         "repeated_message[0].a, " +
    280         "repeated_message[0].b, " +
    281         "repeated_message[0].c, " +
    282         "repeated_message[1].a, " +
    283         "repeated_message[1].b, " +
    284         "repeated_message[1].c",
    285         e.getMessage());
    286     }
    287   }
    288 
    289   public void testDynamicUninitializedException() throws Exception {
    290     try {
    291       DynamicMessage.newBuilder(TestRequired.getDescriptor()).build();
    292       fail("Should have thrown an exception.");
    293     } catch (UninitializedMessageException e) {
    294       assertEquals("Message missing required fields: a, b, c", e.getMessage());
    295     }
    296   }
    297 
    298   public void testDynamicBuildPartial() throws Exception {
    299     // We're mostly testing that no exception is thrown.
    300     DynamicMessage message =
    301       DynamicMessage.newBuilder(TestRequired.getDescriptor())
    302         .buildPartial();
    303     assertFalse(message.isInitialized());
    304   }
    305 
    306   public void testDynamicParseUnititialized() throws Exception {
    307     try {
    308       Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
    309       DynamicMessage.parseFrom(descriptor, ByteString.EMPTY);
    310       fail("Should have thrown an exception.");
    311     } catch (InvalidProtocolBufferException e) {
    312       assertEquals("Message missing required fields: a, b, c", e.getMessage());
    313     }
    314   }
    315 
    316   /** Test reading unset repeated message from DynamicMessage. */
    317   public void testDynamicRepeatedMessageNull() throws Exception {
    318     Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
    319     DynamicMessage result =
    320       DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
    321         .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
    322         .build();
    323 
    324     assertTrue(result.getField(result.getDescriptorForType()
    325         .findFieldByName("repeated_foreign_message")) instanceof List<?>);
    326     assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
    327         .findFieldByName("repeated_foreign_message")), 0);
    328   }
    329 
    330   /** Test reading repeated message from DynamicMessage. */
    331   public void testDynamicRepeatedMessageNotNull() throws Exception {
    332 
    333     TestAllTypes REPEATED_NESTED =
    334       TestAllTypes.newBuilder()
    335         .setOptionalInt32(1)
    336         .setOptionalString("foo")
    337         .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
    338         .addRepeatedString("bar")
    339         .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
    340         .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
    341         .build();
    342     Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
    343     DynamicMessage result =
    344       DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
    345         .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
    346         .build();
    347 
    348     assertTrue(result.getField(result.getDescriptorForType()
    349         .findFieldByName("repeated_foreign_message")) instanceof List<?>);
    350     assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
    351         .findFieldByName("repeated_foreign_message")), 2);
    352   }
    353 }
    354