• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
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.FieldDescriptorProto;
35 import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
36 import com.google.protobuf.Descriptors.DescriptorValidationException;
37 import com.google.protobuf.Descriptors.FileDescriptor;
38 import com.google.protobuf.Descriptors.Descriptor;
39 import com.google.protobuf.Descriptors.FieldDescriptor;
40 import com.google.protobuf.Descriptors.EnumDescriptor;
41 import com.google.protobuf.Descriptors.EnumValueDescriptor;
42 import com.google.protobuf.Descriptors.ServiceDescriptor;
43 import com.google.protobuf.Descriptors.MethodDescriptor;
44 
45 import com.google.protobuf.test.UnittestImport;
46 import com.google.protobuf.test.UnittestImport.ImportEnum;
47 import com.google.protobuf.test.UnittestImport.ImportMessage;
48 import protobuf_unittest.UnittestProto;
49 import protobuf_unittest.UnittestProto.ForeignEnum;
50 import protobuf_unittest.UnittestProto.ForeignMessage;
51 import protobuf_unittest.UnittestProto.TestAllTypes;
52 import protobuf_unittest.UnittestProto.TestAllExtensions;
53 import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
54 import protobuf_unittest.UnittestProto.TestRequired;
55 import protobuf_unittest.UnittestProto.TestService;
56 import protobuf_unittest.UnittestCustomOptions;
57 
58 
59 import junit.framework.TestCase;
60 
61 import java.util.Arrays;
62 import java.util.Collections;
63 
64 /**
65  * Unit test for {@link Descriptors}.
66  *
67  * @author kenton@google.com Kenton Varda
68  */
69 public class DescriptorsTest extends TestCase {
70 
71   // Regression test for bug where referencing a FieldDescriptor.Type value
72   // before a FieldDescriptorProto.Type value would yield a
73   // ExceptionInInitializerError.
74   private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
75 
testFieldTypeEnumMapping()76   public void testFieldTypeEnumMapping() throws Exception {
77     assertEquals(FieldDescriptor.Type.values().length,
78         FieldDescriptorProto.Type.values().length);
79     for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
80       FieldDescriptorProto.Type protoType = type.toProto();
81       assertEquals("TYPE_" + type.name(), protoType.name());
82       assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
83     }
84   }
85 
testFileDescriptor()86   public void testFileDescriptor() throws Exception {
87     FileDescriptor file = UnittestProto.getDescriptor();
88 
89     assertEquals("google/protobuf/unittest.proto", file.getName());
90     assertEquals("protobuf_unittest", file.getPackage());
91 
92     assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
93     assertEquals("google/protobuf/unittest.proto",
94                  file.toProto().getName());
95 
96     assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
97                  file.getDependencies());
98 
99     Descriptor messageType = TestAllTypes.getDescriptor();
100     assertEquals(messageType, file.getMessageTypes().get(0));
101     assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
102     assertNull(file.findMessageTypeByName("NoSuchType"));
103     assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
104     for (int i = 0; i < file.getMessageTypes().size(); i++) {
105       assertEquals(i, file.getMessageTypes().get(i).getIndex());
106     }
107 
108     EnumDescriptor enumType = ForeignEnum.getDescriptor();
109     assertEquals(enumType, file.getEnumTypes().get(0));
110     assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
111     assertNull(file.findEnumTypeByName("NoSuchType"));
112     assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
113     assertEquals(Arrays.asList(ImportEnum.getDescriptor()),
114                  UnittestImport.getDescriptor().getEnumTypes());
115     for (int i = 0; i < file.getEnumTypes().size(); i++) {
116       assertEquals(i, file.getEnumTypes().get(i).getIndex());
117     }
118 
119     ServiceDescriptor service = TestService.getDescriptor();
120     assertEquals(service, file.getServices().get(0));
121     assertEquals(service, file.findServiceByName("TestService"));
122     assertNull(file.findServiceByName("NoSuchType"));
123     assertNull(file.findServiceByName("protobuf_unittest.TestService"));
124     assertEquals(Collections.emptyList(),
125                  UnittestImport.getDescriptor().getServices());
126     for (int i = 0; i < file.getServices().size(); i++) {
127       assertEquals(i, file.getServices().get(i).getIndex());
128     }
129 
130     FieldDescriptor extension =
131       UnittestProto.optionalInt32Extension.getDescriptor();
132     assertEquals(extension, file.getExtensions().get(0));
133     assertEquals(extension,
134                  file.findExtensionByName("optional_int32_extension"));
135     assertNull(file.findExtensionByName("no_such_ext"));
136     assertNull(file.findExtensionByName(
137       "protobuf_unittest.optional_int32_extension"));
138     assertEquals(Collections.emptyList(),
139                  UnittestImport.getDescriptor().getExtensions());
140     for (int i = 0; i < file.getExtensions().size(); i++) {
141       assertEquals(i, file.getExtensions().get(i).getIndex());
142     }
143   }
144 
testDescriptor()145   public void testDescriptor() throws Exception {
146     Descriptor messageType = TestAllTypes.getDescriptor();
147     Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();
148 
149     assertEquals("TestAllTypes", messageType.getName());
150     assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
151     assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
152     assertNull(messageType.getContainingType());
153     assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
154                  messageType.getOptions());
155     assertEquals("TestAllTypes", messageType.toProto().getName());
156 
157     assertEquals("NestedMessage", nestedType.getName());
158     assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
159                  nestedType.getFullName());
160     assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
161     assertEquals(messageType, nestedType.getContainingType());
162 
163     FieldDescriptor field = messageType.getFields().get(0);
164     assertEquals("optional_int32", field.getName());
165     assertEquals(field, messageType.findFieldByName("optional_int32"));
166     assertNull(messageType.findFieldByName("no_such_field"));
167     assertEquals(field, messageType.findFieldByNumber(1));
168     assertNull(messageType.findFieldByNumber(571283));
169     for (int i = 0; i < messageType.getFields().size(); i++) {
170       assertEquals(i, messageType.getFields().get(i).getIndex());
171     }
172 
173     assertEquals(nestedType, messageType.getNestedTypes().get(0));
174     assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
175     assertNull(messageType.findNestedTypeByName("NoSuchType"));
176     for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
177       assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
178     }
179 
180     EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
181     assertEquals(enumType, messageType.getEnumTypes().get(0));
182     assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
183     assertNull(messageType.findEnumTypeByName("NoSuchType"));
184     for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
185       assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
186     }
187   }
188 
testFieldDescriptor()189   public void testFieldDescriptor() throws Exception {
190     Descriptor messageType = TestAllTypes.getDescriptor();
191     FieldDescriptor primitiveField =
192       messageType.findFieldByName("optional_int32");
193     FieldDescriptor enumField =
194       messageType.findFieldByName("optional_nested_enum");
195     FieldDescriptor messageField =
196       messageType.findFieldByName("optional_foreign_message");
197     FieldDescriptor cordField =
198       messageType.findFieldByName("optional_cord");
199     FieldDescriptor extension =
200       UnittestProto.optionalInt32Extension.getDescriptor();
201     FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
202 
203     assertEquals("optional_int32", primitiveField.getName());
204     assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
205                  primitiveField.getFullName());
206     assertEquals(1, primitiveField.getNumber());
207     assertEquals(messageType, primitiveField.getContainingType());
208     assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
209     assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
210     assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
211     assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
212                  primitiveField.getOptions());
213     assertFalse(primitiveField.isExtension());
214     assertEquals("optional_int32", primitiveField.toProto().getName());
215 
216     assertEquals("optional_nested_enum", enumField.getName());
217     assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
218     assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
219     assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
220                  enumField.getEnumType());
221 
222     assertEquals("optional_foreign_message", messageField.getName());
223     assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
224     assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
225     assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
226 
227     assertEquals("optional_cord", cordField.getName());
228     assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
229     assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
230     assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
231                  cordField.getOptions().getCtype());
232 
233     assertEquals("optional_int32_extension", extension.getName());
234     assertEquals("protobuf_unittest.optional_int32_extension",
235                  extension.getFullName());
236     assertEquals(1, extension.getNumber());
237     assertEquals(TestAllExtensions.getDescriptor(),
238                  extension.getContainingType());
239     assertEquals(UnittestProto.getDescriptor(), extension.getFile());
240     assertEquals(FieldDescriptor.Type.INT32, extension.getType());
241     assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
242     assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
243                  extension.getOptions());
244     assertTrue(extension.isExtension());
245     assertEquals(null, extension.getExtensionScope());
246     assertEquals("optional_int32_extension", extension.toProto().getName());
247 
248     assertEquals("single", nestedExtension.getName());
249     assertEquals("protobuf_unittest.TestRequired.single",
250                  nestedExtension.getFullName());
251     assertEquals(TestRequired.getDescriptor(),
252                  nestedExtension.getExtensionScope());
253   }
254 
testFieldDescriptorLabel()255   public void testFieldDescriptorLabel() throws Exception {
256     FieldDescriptor requiredField =
257       TestRequired.getDescriptor().findFieldByName("a");
258     FieldDescriptor optionalField =
259       TestAllTypes.getDescriptor().findFieldByName("optional_int32");
260     FieldDescriptor repeatedField =
261       TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
262 
263     assertTrue(requiredField.isRequired());
264     assertFalse(requiredField.isRepeated());
265     assertFalse(optionalField.isRequired());
266     assertFalse(optionalField.isRepeated());
267     assertFalse(repeatedField.isRequired());
268     assertTrue(repeatedField.isRepeated());
269   }
270 
testFieldDescriptorDefault()271   public void testFieldDescriptorDefault() throws Exception {
272     Descriptor d = TestAllTypes.getDescriptor();
273     assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
274     assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
275     assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
276     assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());
277 
278     d = TestExtremeDefaultValues.getDescriptor();
279     assertEquals(
280       ByteString.copyFrom(
281         "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes("ISO-8859-1")),
282       d.findFieldByName("escaped_bytes").getDefaultValue());
283     assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
284     assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
285   }
286 
testEnumDescriptor()287   public void testEnumDescriptor() throws Exception {
288     EnumDescriptor enumType = ForeignEnum.getDescriptor();
289     EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();
290 
291     assertEquals("ForeignEnum", enumType.getName());
292     assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
293     assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
294     assertNull(enumType.getContainingType());
295     assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
296                  enumType.getOptions());
297 
298     assertEquals("NestedEnum", nestedType.getName());
299     assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
300                  nestedType.getFullName());
301     assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
302     assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
303 
304     EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
305     assertEquals(value, enumType.getValues().get(0));
306     assertEquals("FOREIGN_FOO", value.getName());
307     assertEquals(4, value.getNumber());
308     assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
309     assertEquals(value, enumType.findValueByNumber(4));
310     assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
311     for (int i = 0; i < enumType.getValues().size(); i++) {
312       assertEquals(i, enumType.getValues().get(i).getIndex());
313     }
314   }
315 
testServiceDescriptor()316   public void testServiceDescriptor() throws Exception {
317     ServiceDescriptor service = TestService.getDescriptor();
318 
319     assertEquals("TestService", service.getName());
320     assertEquals("protobuf_unittest.TestService", service.getFullName());
321     assertEquals(UnittestProto.getDescriptor(), service.getFile());
322 
323     assertEquals(2, service.getMethods().size());
324 
325     MethodDescriptor fooMethod = service.getMethods().get(0);
326     assertEquals("Foo", fooMethod.getName());
327     assertEquals(UnittestProto.FooRequest.getDescriptor(),
328                  fooMethod.getInputType());
329     assertEquals(UnittestProto.FooResponse.getDescriptor(),
330                  fooMethod.getOutputType());
331     assertEquals(fooMethod, service.findMethodByName("Foo"));
332 
333     MethodDescriptor barMethod = service.getMethods().get(1);
334     assertEquals("Bar", barMethod.getName());
335     assertEquals(UnittestProto.BarRequest.getDescriptor(),
336                  barMethod.getInputType());
337     assertEquals(UnittestProto.BarResponse.getDescriptor(),
338                  barMethod.getOutputType());
339     assertEquals(barMethod, service.findMethodByName("Bar"));
340 
341     assertNull(service.findMethodByName("NoSuchMethod"));
342 
343     for (int i = 0; i < service.getMethods().size(); i++) {
344       assertEquals(i, service.getMethods().get(i).getIndex());
345     }
346   }
347 
348 
testCustomOptions()349   public void testCustomOptions() throws Exception {
350     Descriptor descriptor =
351       UnittestCustomOptions.TestMessageWithCustomOptions.getDescriptor();
352 
353     assertTrue(
354       descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
355     assertEquals(Integer.valueOf(-56),
356       descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
357 
358     FieldDescriptor field = descriptor.findFieldByName("field1");
359     assertNotNull(field);
360 
361     assertTrue(
362       field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
363     assertEquals(Long.valueOf(8765432109L),
364       field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
365 
366     EnumDescriptor enumType =
367       UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
368 
369     assertTrue(
370       enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
371     assertEquals(Integer.valueOf(-789),
372       enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
373 
374     ServiceDescriptor service =
375       UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
376 
377     assertTrue(
378       service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
379     assertEquals(Long.valueOf(-9876543210L),
380       service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
381 
382     MethodDescriptor method = service.findMethodByName("Foo");
383     assertNotNull(method);
384 
385     assertTrue(
386       method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
387     assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
388       method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
389   }
390 
391   /**
392    * Test that the FieldDescriptor.Type enum is the same as the
393    * WireFormat.FieldType enum.
394    */
testFieldTypeTablesMatch()395   public void testFieldTypeTablesMatch() throws Exception {
396     FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
397     WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
398 
399     assertEquals(values1.length, values2.length);
400 
401     for (int i = 0; i < values1.length; i++) {
402       assertEquals(values1[i].toString(), values2[i].toString());
403     }
404   }
405 
406   /**
407    * Test that the FieldDescriptor.JavaType enum is the same as the
408    * WireFormat.JavaType enum.
409    */
testJavaTypeTablesMatch()410   public void testJavaTypeTablesMatch() throws Exception {
411     FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
412     WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
413 
414     assertEquals(values1.length, values2.length);
415 
416     for (int i = 0; i < values1.length; i++) {
417       assertEquals(values1[i].toString(), values2[i].toString());
418     }
419   }
420 
testEnormousDescriptor()421   public void testEnormousDescriptor() throws Exception {
422     // The descriptor for this file is larger than 64k, yet it did not cause
423     // a compiler error due to an over-long string literal.
424     assertTrue(
425         UnittestEnormousDescriptor.getDescriptor()
426           .toProto().getSerializedSize() > 65536);
427   }
428 
429   /**
430    * Tests that the DescriptorValidationException works as intended.
431    */
testDescriptorValidatorException()432   public void testDescriptorValidatorException() throws Exception {
433     FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
434       .setName("foo.proto")
435       .addMessageType(DescriptorProto.newBuilder()
436       .setName("Foo")
437         .addField(FieldDescriptorProto.newBuilder()
438           .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
439           .setType(FieldDescriptorProto.Type.TYPE_INT32)
440           .setName("foo")
441           .setNumber(1)
442           .setDefaultValue("invalid")
443           .build())
444         .build())
445       .build();
446     try {
447       Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
448           new FileDescriptor[0]);
449       fail("DescriptorValidationException expected");
450     } catch (DescriptorValidationException e) {
451       // Expected; check that the error message contains some useful hints
452       assertTrue(e.getMessage().indexOf("foo") != -1);
453       assertTrue(e.getMessage().indexOf("Foo") != -1);
454       assertTrue(e.getMessage().indexOf("invalid") != -1);
455       assertTrue(e.getCause() instanceof NumberFormatException);
456       assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
457     }
458   }
459 }
460