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.DescriptorProtos.DescriptorProto;
     34 import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
     35 import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
     36 import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
     37 import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
     38 import com.google.protobuf.Descriptors.DescriptorValidationException;
     39 import com.google.protobuf.Descriptors.FileDescriptor;
     40 import com.google.protobuf.Descriptors.Descriptor;
     41 import com.google.protobuf.Descriptors.FieldDescriptor;
     42 import com.google.protobuf.Descriptors.OneofDescriptor;
     43 import com.google.protobuf.Descriptors.EnumDescriptor;
     44 import com.google.protobuf.Descriptors.EnumValueDescriptor;
     45 import com.google.protobuf.Descriptors.ServiceDescriptor;
     46 import com.google.protobuf.Descriptors.MethodDescriptor;
     47 
     48 import com.google.protobuf.test.UnittestImport;
     49 import com.google.protobuf.test.UnittestImport.ImportEnum;
     50 import com.google.protobuf.test.UnittestImport.ImportMessage;
     51 import protobuf_unittest.UnittestProto;
     52 import protobuf_unittest.UnittestProto.ForeignEnum;
     53 import protobuf_unittest.UnittestProto.ForeignMessage;
     54 import protobuf_unittest.UnittestProto.TestAllTypes;
     55 import protobuf_unittest.UnittestProto.TestAllExtensions;
     56 import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
     57 import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
     58 import protobuf_unittest.UnittestProto.TestRequired;
     59 import protobuf_unittest.UnittestProto.TestService;
     60 import protobuf_unittest.UnittestCustomOptions;
     61 
     62 import protobuf_unittest.TestCustomOptions;
     63 
     64 
     65 import junit.framework.TestCase;
     66 
     67 import java.util.Arrays;
     68 import java.util.Collections;
     69 import java.util.List;
     70 
     71 /**
     72  * Unit test for {@link Descriptors}.
     73  *
     74  * @author kenton (at) google.com Kenton Varda
     75  */
     76 public class DescriptorsTest extends TestCase {
     77 
     78   // Regression test for bug where referencing a FieldDescriptor.Type value
     79   // before a FieldDescriptorProto.Type value would yield a
     80   // ExceptionInInitializerError.
     81   @SuppressWarnings("unused")
     82   private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
     83 
     84   public void testFieldTypeEnumMapping() throws Exception {
     85     assertEquals(FieldDescriptor.Type.values().length,
     86         FieldDescriptorProto.Type.values().length);
     87     for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
     88       FieldDescriptorProto.Type protoType = type.toProto();
     89       assertEquals("TYPE_" + type.name(), protoType.name());
     90       assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
     91     }
     92   }
     93 
     94   public void testFileDescriptor() throws Exception {
     95     FileDescriptor file = UnittestProto.getDescriptor();
     96 
     97     assertEquals("google/protobuf/unittest.proto", file.getName());
     98     assertEquals("protobuf_unittest", file.getPackage());
     99 
    100     assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
    101     assertEquals("google/protobuf/unittest.proto",
    102                  file.toProto().getName());
    103 
    104     assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
    105                  file.getDependencies());
    106 
    107     Descriptor messageType = TestAllTypes.getDescriptor();
    108     assertEquals(messageType, file.getMessageTypes().get(0));
    109     assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
    110     assertNull(file.findMessageTypeByName("NoSuchType"));
    111     assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
    112     for (int i = 0; i < file.getMessageTypes().size(); i++) {
    113       assertEquals(i, file.getMessageTypes().get(i).getIndex());
    114     }
    115 
    116     EnumDescriptor enumType = ForeignEnum.getDescriptor();
    117     assertEquals(enumType, file.getEnumTypes().get(0));
    118     assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
    119     assertNull(file.findEnumTypeByName("NoSuchType"));
    120     assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
    121     assertEquals(Arrays.asList(ImportEnum.getDescriptor()),
    122                  UnittestImport.getDescriptor().getEnumTypes());
    123     for (int i = 0; i < file.getEnumTypes().size(); i++) {
    124       assertEquals(i, file.getEnumTypes().get(i).getIndex());
    125     }
    126 
    127     ServiceDescriptor service = TestService.getDescriptor();
    128     assertEquals(service, file.getServices().get(0));
    129     assertEquals(service, file.findServiceByName("TestService"));
    130     assertNull(file.findServiceByName("NoSuchType"));
    131     assertNull(file.findServiceByName("protobuf_unittest.TestService"));
    132     assertEquals(Collections.emptyList(),
    133                  UnittestImport.getDescriptor().getServices());
    134     for (int i = 0; i < file.getServices().size(); i++) {
    135       assertEquals(i, file.getServices().get(i).getIndex());
    136     }
    137 
    138     FieldDescriptor extension =
    139       UnittestProto.optionalInt32Extension.getDescriptor();
    140     assertEquals(extension, file.getExtensions().get(0));
    141     assertEquals(extension,
    142                  file.findExtensionByName("optional_int32_extension"));
    143     assertNull(file.findExtensionByName("no_such_ext"));
    144     assertNull(file.findExtensionByName(
    145       "protobuf_unittest.optional_int32_extension"));
    146     assertEquals(Collections.emptyList(),
    147                  UnittestImport.getDescriptor().getExtensions());
    148     for (int i = 0; i < file.getExtensions().size(); i++) {
    149       assertEquals(i, file.getExtensions().get(i).getIndex());
    150     }
    151   }
    152 
    153   public void testDescriptor() throws Exception {
    154     Descriptor messageType = TestAllTypes.getDescriptor();
    155     Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();
    156 
    157     assertEquals("TestAllTypes", messageType.getName());
    158     assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
    159     assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
    160     assertNull(messageType.getContainingType());
    161     assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
    162                  messageType.getOptions());
    163     assertEquals("TestAllTypes", messageType.toProto().getName());
    164 
    165     assertEquals("NestedMessage", nestedType.getName());
    166     assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
    167                  nestedType.getFullName());
    168     assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
    169     assertEquals(messageType, nestedType.getContainingType());
    170 
    171     FieldDescriptor field = messageType.getFields().get(0);
    172     assertEquals("optional_int32", field.getName());
    173     assertEquals(field, messageType.findFieldByName("optional_int32"));
    174     assertNull(messageType.findFieldByName("no_such_field"));
    175     assertEquals(field, messageType.findFieldByNumber(1));
    176     assertNull(messageType.findFieldByNumber(571283));
    177     for (int i = 0; i < messageType.getFields().size(); i++) {
    178       assertEquals(i, messageType.getFields().get(i).getIndex());
    179     }
    180 
    181     assertEquals(nestedType, messageType.getNestedTypes().get(0));
    182     assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
    183     assertNull(messageType.findNestedTypeByName("NoSuchType"));
    184     for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
    185       assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
    186     }
    187 
    188     EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
    189     assertEquals(enumType, messageType.getEnumTypes().get(0));
    190     assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
    191     assertNull(messageType.findEnumTypeByName("NoSuchType"));
    192     for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
    193       assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
    194     }
    195   }
    196 
    197   public void testFieldDescriptor() throws Exception {
    198     Descriptor messageType = TestAllTypes.getDescriptor();
    199     FieldDescriptor primitiveField =
    200       messageType.findFieldByName("optional_int32");
    201     FieldDescriptor enumField =
    202       messageType.findFieldByName("optional_nested_enum");
    203     FieldDescriptor messageField =
    204       messageType.findFieldByName("optional_foreign_message");
    205     FieldDescriptor cordField =
    206       messageType.findFieldByName("optional_cord");
    207     FieldDescriptor extension =
    208       UnittestProto.optionalInt32Extension.getDescriptor();
    209     FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
    210 
    211     assertEquals("optional_int32", primitiveField.getName());
    212     assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
    213                  primitiveField.getFullName());
    214     assertEquals(1, primitiveField.getNumber());
    215     assertEquals(messageType, primitiveField.getContainingType());
    216     assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
    217     assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
    218     assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
    219     assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
    220                  primitiveField.getOptions());
    221     assertFalse(primitiveField.isExtension());
    222     assertEquals("optional_int32", primitiveField.toProto().getName());
    223 
    224     assertEquals("optional_nested_enum", enumField.getName());
    225     assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
    226     assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
    227     assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
    228                  enumField.getEnumType());
    229 
    230     assertEquals("optional_foreign_message", messageField.getName());
    231     assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
    232     assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
    233     assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
    234 
    235     assertEquals("optional_cord", cordField.getName());
    236     assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
    237     assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
    238     assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
    239                  cordField.getOptions().getCtype());
    240 
    241     assertEquals("optional_int32_extension", extension.getName());
    242     assertEquals("protobuf_unittest.optional_int32_extension",
    243                  extension.getFullName());
    244     assertEquals(1, extension.getNumber());
    245     assertEquals(TestAllExtensions.getDescriptor(),
    246                  extension.getContainingType());
    247     assertEquals(UnittestProto.getDescriptor(), extension.getFile());
    248     assertEquals(FieldDescriptor.Type.INT32, extension.getType());
    249     assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
    250     assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
    251                  extension.getOptions());
    252     assertTrue(extension.isExtension());
    253     assertEquals(null, extension.getExtensionScope());
    254     assertEquals("optional_int32_extension", extension.toProto().getName());
    255 
    256     assertEquals("single", nestedExtension.getName());
    257     assertEquals("protobuf_unittest.TestRequired.single",
    258                  nestedExtension.getFullName());
    259     assertEquals(TestRequired.getDescriptor(),
    260                  nestedExtension.getExtensionScope());
    261   }
    262 
    263   public void testFieldDescriptorLabel() throws Exception {
    264     FieldDescriptor requiredField =
    265       TestRequired.getDescriptor().findFieldByName("a");
    266     FieldDescriptor optionalField =
    267       TestAllTypes.getDescriptor().findFieldByName("optional_int32");
    268     FieldDescriptor repeatedField =
    269       TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
    270 
    271     assertTrue(requiredField.isRequired());
    272     assertFalse(requiredField.isRepeated());
    273     assertFalse(optionalField.isRequired());
    274     assertFalse(optionalField.isRepeated());
    275     assertFalse(repeatedField.isRequired());
    276     assertTrue(repeatedField.isRepeated());
    277   }
    278 
    279   public void testFieldDescriptorDefault() throws Exception {
    280     Descriptor d = TestAllTypes.getDescriptor();
    281     assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
    282     assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
    283     assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
    284     assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());
    285 
    286     d = TestExtremeDefaultValues.getDescriptor();
    287     assertEquals(
    288       ByteString.copyFrom(
    289         "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes("ISO-8859-1")),
    290       d.findFieldByName("escaped_bytes").getDefaultValue());
    291     assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
    292     assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
    293   }
    294 
    295   public void testEnumDescriptor() throws Exception {
    296     EnumDescriptor enumType = ForeignEnum.getDescriptor();
    297     EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();
    298 
    299     assertEquals("ForeignEnum", enumType.getName());
    300     assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
    301     assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
    302     assertNull(enumType.getContainingType());
    303     assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
    304                  enumType.getOptions());
    305 
    306     assertEquals("NestedEnum", nestedType.getName());
    307     assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
    308                  nestedType.getFullName());
    309     assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
    310     assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
    311 
    312     EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
    313     assertEquals(value, enumType.getValues().get(0));
    314     assertEquals("FOREIGN_FOO", value.getName());
    315     assertEquals("FOREIGN_FOO", value.toString());
    316     assertEquals(4, value.getNumber());
    317     assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
    318     assertEquals(value, enumType.findValueByNumber(4));
    319     assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
    320     for (int i = 0; i < enumType.getValues().size(); i++) {
    321       assertEquals(i, enumType.getValues().get(i).getIndex());
    322     }
    323   }
    324 
    325   public void testServiceDescriptor() throws Exception {
    326     ServiceDescriptor service = TestService.getDescriptor();
    327 
    328     assertEquals("TestService", service.getName());
    329     assertEquals("protobuf_unittest.TestService", service.getFullName());
    330     assertEquals(UnittestProto.getDescriptor(), service.getFile());
    331 
    332 
    333     MethodDescriptor fooMethod = service.getMethods().get(0);
    334     assertEquals("Foo", fooMethod.getName());
    335     assertEquals(UnittestProto.FooRequest.getDescriptor(),
    336                  fooMethod.getInputType());
    337     assertEquals(UnittestProto.FooResponse.getDescriptor(),
    338                  fooMethod.getOutputType());
    339     assertEquals(fooMethod, service.findMethodByName("Foo"));
    340 
    341     MethodDescriptor barMethod = service.getMethods().get(1);
    342     assertEquals("Bar", barMethod.getName());
    343     assertEquals(UnittestProto.BarRequest.getDescriptor(),
    344                  barMethod.getInputType());
    345     assertEquals(UnittestProto.BarResponse.getDescriptor(),
    346                  barMethod.getOutputType());
    347     assertEquals(barMethod, service.findMethodByName("Bar"));
    348 
    349     assertNull(service.findMethodByName("NoSuchMethod"));
    350 
    351     for (int i = 0; i < service.getMethods().size(); i++) {
    352       assertEquals(i, service.getMethods().get(i).getIndex());
    353     }
    354   }
    355 
    356 
    357   public void testCustomOptions() throws Exception {
    358     // Get the descriptor indirectly from a dependent proto class. This is to
    359     // ensure that when a proto class is loaded, custom options defined in its
    360     // dependencies are also properly initialized.
    361     Descriptor descriptor =
    362         TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor()
    363         .findFieldByName("field").getMessageType();
    364 
    365     assertTrue(
    366       descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
    367     assertEquals(Integer.valueOf(-56),
    368       descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
    369 
    370     FieldDescriptor field = descriptor.findFieldByName("field1");
    371     assertNotNull(field);
    372 
    373     assertTrue(
    374       field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
    375     assertEquals(Long.valueOf(8765432109L),
    376       field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
    377 
    378     EnumDescriptor enumType =
    379       UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
    380 
    381     assertTrue(
    382       enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
    383     assertEquals(Integer.valueOf(-789),
    384       enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
    385 
    386     ServiceDescriptor service =
    387       UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
    388 
    389     assertTrue(
    390       service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
    391     assertEquals(Long.valueOf(-9876543210L),
    392       service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
    393 
    394     MethodDescriptor method = service.findMethodByName("Foo");
    395     assertNotNull(method);
    396 
    397     assertTrue(
    398       method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
    399     assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
    400       method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
    401   }
    402 
    403   /**
    404    * Test that the FieldDescriptor.Type enum is the same as the
    405    * WireFormat.FieldType enum.
    406    */
    407   public void testFieldTypeTablesMatch() throws Exception {
    408     FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
    409     WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
    410 
    411     assertEquals(values1.length, values2.length);
    412 
    413     for (int i = 0; i < values1.length; i++) {
    414       assertEquals(values1[i].toString(), values2[i].toString());
    415     }
    416   }
    417 
    418   /**
    419    * Test that the FieldDescriptor.JavaType enum is the same as the
    420    * WireFormat.JavaType enum.
    421    */
    422   public void testJavaTypeTablesMatch() throws Exception {
    423     FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
    424     WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
    425 
    426     assertEquals(values1.length, values2.length);
    427 
    428     for (int i = 0; i < values1.length; i++) {
    429       assertEquals(values1[i].toString(), values2[i].toString());
    430     }
    431   }
    432 
    433   public void testEnormousDescriptor() throws Exception {
    434     // The descriptor for this file is larger than 64k, yet it did not cause
    435     // a compiler error due to an over-long string literal.
    436     assertTrue(
    437         UnittestEnormousDescriptor.getDescriptor()
    438           .toProto().getSerializedSize() > 65536);
    439   }
    440 
    441   /**
    442    * Tests that the DescriptorValidationException works as intended.
    443    */
    444   public void testDescriptorValidatorException() throws Exception {
    445     FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
    446       .setName("foo.proto")
    447       .addMessageType(DescriptorProto.newBuilder()
    448       .setName("Foo")
    449         .addField(FieldDescriptorProto.newBuilder()
    450           .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
    451           .setType(FieldDescriptorProto.Type.TYPE_INT32)
    452           .setName("foo")
    453           .setNumber(1)
    454           .setDefaultValue("invalid")
    455           .build())
    456         .build())
    457       .build();
    458     try {
    459       Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
    460           new FileDescriptor[0]);
    461       fail("DescriptorValidationException expected");
    462     } catch (DescriptorValidationException e) {
    463       // Expected; check that the error message contains some useful hints
    464       assertTrue(e.getMessage().indexOf("foo") != -1);
    465       assertTrue(e.getMessage().indexOf("Foo") != -1);
    466       assertTrue(e.getMessage().indexOf("invalid") != -1);
    467       assertTrue(e.getCause() instanceof NumberFormatException);
    468       assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
    469     }
    470   }
    471 
    472   /**
    473    * Tests the translate/crosslink for an example where a message field's name
    474    * and type name are the same.
    475    */
    476   public void testDescriptorComplexCrosslink() throws Exception {
    477     FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
    478       .setName("foo.proto")
    479       .addMessageType(DescriptorProto.newBuilder()
    480         .setName("Foo")
    481         .addField(FieldDescriptorProto.newBuilder()
    482           .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
    483           .setType(FieldDescriptorProto.Type.TYPE_INT32)
    484           .setName("foo")
    485           .setNumber(1)
    486           .build())
    487         .build())
    488       .addMessageType(DescriptorProto.newBuilder()
    489         .setName("Bar")
    490         .addField(FieldDescriptorProto.newBuilder()
    491           .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
    492           .setTypeName("Foo")
    493           .setName("Foo")
    494           .setNumber(1)
    495           .build())
    496         .build())
    497       .build();
    498     // translate and crosslink
    499     FileDescriptor file =
    500       Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
    501           new FileDescriptor[0]);
    502     // verify resulting descriptors
    503     assertNotNull(file);
    504     List<Descriptor> msglist = file.getMessageTypes();
    505     assertNotNull(msglist);
    506     assertTrue(msglist.size() == 2);
    507     boolean barFound = false;
    508     for (Descriptor desc : msglist) {
    509       if (desc.getName().equals("Bar")) {
    510         barFound = true;
    511         assertNotNull(desc.getFields());
    512         List<FieldDescriptor> fieldlist = desc.getFields();
    513         assertNotNull(fieldlist);
    514         assertTrue(fieldlist.size() == 1);
    515         assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
    516         assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
    517       }
    518     }
    519     assertTrue(barFound);
    520   }
    521 
    522   public void testDependencyOrder() throws Exception {
    523     FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
    524         .setName("foo.proto").build();
    525     FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
    526         .setName("bar.proto")
    527         .addDependency("foo.proto")
    528         .build();
    529     FileDescriptorProto bazProto = FileDescriptorProto.newBuilder()
    530         .setName("baz.proto")
    531         .addDependency("foo.proto")
    532         .addDependency("bar.proto")
    533         .addPublicDependency(0)
    534         .addPublicDependency(1)
    535         .build();
    536     FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
    537         new FileDescriptor[0]);
    538     FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto,
    539         new FileDescriptor[] {fooFile});
    540 
    541     // Items in the FileDescriptor array can be in any order.
    542     Descriptors.FileDescriptor.buildFrom(bazProto,
    543         new FileDescriptor[] {fooFile, barFile});
    544     Descriptors.FileDescriptor.buildFrom(bazProto,
    545         new FileDescriptor[] {barFile, fooFile});
    546   }
    547 
    548   public void testInvalidPublicDependency() throws Exception {
    549     FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
    550         .setName("foo.proto").build();
    551     FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
    552         .setName("boo.proto")
    553         .addDependency("foo.proto")
    554         .addPublicDependency(1)  // Error, should be 0.
    555         .build();
    556     FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
    557         new FileDescriptor[0]);
    558     try {
    559       Descriptors.FileDescriptor.buildFrom(barProto,
    560           new FileDescriptor[] {fooFile});
    561       fail("DescriptorValidationException expected");
    562     } catch (DescriptorValidationException e) {
    563       assertTrue(
    564           e.getMessage().indexOf("Invalid public dependency index.") != -1);
    565     }
    566   }
    567 
    568   public void testHiddenDependency() throws Exception {
    569     FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
    570         .setName("bar.proto")
    571         .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
    572         .build();
    573     FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
    574         .setName("forward.proto")
    575         .addDependency("bar.proto")
    576         .build();
    577     FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
    578         .setName("foo.proto")
    579         .addDependency("forward.proto")
    580         .addMessageType(DescriptorProto.newBuilder()
    581             .setName("Foo")
    582             .addField(FieldDescriptorProto.newBuilder()
    583                 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
    584                 .setTypeName("Bar")
    585                 .setName("bar")
    586                 .setNumber(1)))
    587         .build();
    588     FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
    589         barProto, new FileDescriptor[0]);
    590     FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
    591         forwardProto, new FileDescriptor[] {barFile});
    592 
    593     try {
    594       Descriptors.FileDescriptor.buildFrom(
    595           fooProto, new FileDescriptor[] {forwardFile});
    596       fail("DescriptorValidationException expected");
    597     } catch (DescriptorValidationException e) {
    598       assertTrue(e.getMessage().indexOf("Bar") != -1);
    599       assertTrue(e.getMessage().indexOf("is not defined") != -1);
    600     }
    601   }
    602 
    603   public void testPublicDependency() throws Exception {
    604     FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
    605         .setName("bar.proto")
    606         .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
    607         .build();
    608     FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
    609         .setName("forward.proto")
    610         .addDependency("bar.proto")
    611         .addPublicDependency(0)
    612         .build();
    613     FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
    614         .setName("foo.proto")
    615         .addDependency("forward.proto")
    616         .addMessageType(DescriptorProto.newBuilder()
    617             .setName("Foo")
    618             .addField(FieldDescriptorProto.newBuilder()
    619                 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
    620                 .setTypeName("Bar")
    621                 .setName("bar")
    622                 .setNumber(1)))
    623         .build();
    624     FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
    625         barProto, new FileDescriptor[0]);
    626     FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
    627         forwardProto, new FileDescriptor[]{barFile});
    628     Descriptors.FileDescriptor.buildFrom(
    629         fooProto, new FileDescriptor[] {forwardFile});
    630   }
    631 
    632   /**
    633    * Tests the translate/crosslink for an example with a more complex namespace
    634    * referencing.
    635    */
    636   public void testComplexNamespacePublicDependency() throws Exception {
    637     FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
    638         .setName("bar.proto")
    639         .setPackage("a.b.c.d.bar.shared")
    640         .addEnumType(EnumDescriptorProto.newBuilder()
    641             .setName("MyEnum")
    642             .addValue(EnumValueDescriptorProto.newBuilder()
    643                 .setName("BLAH")
    644                 .setNumber(1)))
    645         .build();
    646     FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
    647         .setName("foo.proto")
    648         .addDependency("bar.proto")
    649         .setPackage("a.b.c.d.foo.shared")
    650         .addMessageType(DescriptorProto.newBuilder()
    651             .setName("MyMessage")
    652             .addField(FieldDescriptorProto.newBuilder()
    653                 .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
    654                 .setTypeName("bar.shared.MyEnum")
    655                 .setName("MyField")
    656                 .setNumber(1)))
    657         .build();
    658     // translate and crosslink
    659     FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
    660         fooProto, new FileDescriptor[0]);
    661     FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
    662         barProto, new FileDescriptor[]{fooFile});
    663     // verify resulting descriptors
    664     assertNotNull(barFile);
    665     List<Descriptor> msglist = barFile.getMessageTypes();
    666     assertNotNull(msglist);
    667     assertTrue(msglist.size() == 1);
    668     Descriptor desc = msglist.get(0);
    669     if (desc.getName().equals("MyMessage")) {
    670       assertNotNull(desc.getFields());
    671       List<FieldDescriptor> fieldlist = desc.getFields();
    672       assertNotNull(fieldlist);
    673       assertTrue(fieldlist.size() == 1);
    674       FieldDescriptor field = fieldlist.get(0);
    675       assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
    676       assertTrue(field.getEnumType().getName().equals("MyEnum"));
    677       assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
    678       assertTrue(field.getEnumType().getFile().getPackage().equals(
    679           "a.b.c.d.bar.shared"));
    680     }
    681   }
    682 
    683   public void testOneofDescriptor() throws Exception {
    684     Descriptor messageType = TestAllTypes.getDescriptor();
    685     FieldDescriptor field =
    686         messageType.findFieldByName("oneof_nested_message");
    687     OneofDescriptor oneofDescriptor = field.getContainingOneof();
    688     assertNotNull(oneofDescriptor);
    689     assertSame(oneofDescriptor, messageType.getOneofs().get(0));
    690     assertEquals("oneof_field", oneofDescriptor.getName());
    691 
    692     assertEquals(4, oneofDescriptor.getFieldCount());
    693     assertSame(oneofDescriptor.getField(1), field);
    694   }
    695 
    696   public void testMessageDescriptorExtensions() throws Exception {
    697     assertFalse(TestAllTypes.getDescriptor().isExtendable());
    698     assertTrue(TestAllExtensions.getDescriptor().isExtendable());
    699     assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtendable());
    700 
    701     assertFalse(TestAllTypes.getDescriptor().isExtensionNumber(3));
    702     assertTrue(TestAllExtensions.getDescriptor().isExtensionNumber(3));
    703     assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42));
    704     assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43));
    705     assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142));
    706     assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143));
    707   }
    708 
    709   public void testPackedEnumField() throws Exception {
    710     FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
    711         .setName("foo.proto")
    712         .addEnumType(EnumDescriptorProto.newBuilder()
    713           .setName("Enum")
    714           .addValue(EnumValueDescriptorProto.newBuilder()
    715             .setName("FOO")
    716             .setNumber(1)
    717             .build())
    718           .build())
    719         .addMessageType(DescriptorProto.newBuilder()
    720           .setName("Message")
    721           .addField(FieldDescriptorProto.newBuilder()
    722             .setName("foo")
    723             .setTypeName("Enum")
    724             .setNumber(1)
    725             .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
    726             .setOptions(DescriptorProtos.FieldOptions.newBuilder()
    727               .setPacked(true)
    728               .build())
    729             .build())
    730           .build())
    731         .build();
    732     Descriptors.FileDescriptor.buildFrom(
    733         fileDescriptorProto, new FileDescriptor[0]);
    734   }
    735 }
    736