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