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