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