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