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