• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import 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@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 
testFieldTypeEnumMapping()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 
testFileDescriptor()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 
testDescriptor()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 
testFieldDescriptor()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 
testFieldDescriptorLabel()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 
testFieldDescriptorDefault()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 
testEnumDescriptor()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 
testServiceDescriptor()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 
testCustomOptions()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    */
testFieldTypeTablesMatch()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    */
testJavaTypeTablesMatch()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 
testEnormousDescriptor()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    */
testDescriptorValidatorException()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    */
testDescriptorComplexCrosslink()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 
testDependencyOrder()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 
testInvalidPublicDependency()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 
testHiddenDependency()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 
testPublicDependency()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    */
testComplexNamespacePublicDependency()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 
testOneofDescriptor()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 
testMessageDescriptorExtensions()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 
testPackedEnumField()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