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 EnumDescriptor enumType = 386 UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor(); 387 388 assertTrue( 389 enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1)); 390 assertEquals(Integer.valueOf(-789), 391 enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1)); 392 393 ServiceDescriptor service = 394 UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor(); 395 396 assertTrue( 397 service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1)); 398 assertEquals(Long.valueOf(-9876543210L), 399 service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1)); 400 401 MethodDescriptor method = service.findMethodByName("Foo"); 402 assertNotNull(method); 403 404 assertTrue( 405 method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1)); 406 assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2, 407 method.getOptions().getExtension(UnittestCustomOptions.methodOpt1)); 408 } 409 410 /** 411 * Test that the FieldDescriptor.Type enum is the same as the 412 * WireFormat.FieldType enum. 413 */ testFieldTypeTablesMatch()414 public void testFieldTypeTablesMatch() throws Exception { 415 FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values(); 416 WireFormat.FieldType[] values2 = WireFormat.FieldType.values(); 417 418 assertEquals(values1.length, values2.length); 419 420 for (int i = 0; i < values1.length; i++) { 421 assertEquals(values1[i].toString(), values2[i].toString()); 422 } 423 } 424 425 /** 426 * Test that the FieldDescriptor.JavaType enum is the same as the 427 * WireFormat.JavaType enum. 428 */ testJavaTypeTablesMatch()429 public void testJavaTypeTablesMatch() throws Exception { 430 FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values(); 431 WireFormat.JavaType[] values2 = WireFormat.JavaType.values(); 432 433 assertEquals(values1.length, values2.length); 434 435 for (int i = 0; i < values1.length; i++) { 436 assertEquals(values1[i].toString(), values2[i].toString()); 437 } 438 } 439 testEnormousDescriptor()440 public void testEnormousDescriptor() throws Exception { 441 // The descriptor for this file is larger than 64k, yet it did not cause 442 // a compiler error due to an over-long string literal. 443 assertTrue( 444 UnittestEnormousDescriptor.getDescriptor() 445 .toProto().getSerializedSize() > 65536); 446 } 447 448 /** 449 * Tests that the DescriptorValidationException works as intended. 450 */ testDescriptorValidatorException()451 public void testDescriptorValidatorException() throws Exception { 452 FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder() 453 .setName("foo.proto") 454 .addMessageType(DescriptorProto.newBuilder() 455 .setName("Foo") 456 .addField(FieldDescriptorProto.newBuilder() 457 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 458 .setType(FieldDescriptorProto.Type.TYPE_INT32) 459 .setName("foo") 460 .setNumber(1) 461 .setDefaultValue("invalid") 462 .build()) 463 .build()) 464 .build(); 465 try { 466 Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, 467 new FileDescriptor[0]); 468 fail("DescriptorValidationException expected"); 469 } catch (DescriptorValidationException e) { 470 // Expected; check that the error message contains some useful hints 471 assertTrue(e.getMessage().indexOf("foo") != -1); 472 assertTrue(e.getMessage().indexOf("Foo") != -1); 473 assertTrue(e.getMessage().indexOf("invalid") != -1); 474 assertTrue(e.getCause() instanceof NumberFormatException); 475 assertTrue(e.getCause().getMessage().indexOf("invalid") != -1); 476 } 477 } 478 479 /** 480 * Tests the translate/crosslink for an example where a message field's name 481 * and type name are the same. 482 */ testDescriptorComplexCrosslink()483 public void testDescriptorComplexCrosslink() throws Exception { 484 FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder() 485 .setName("foo.proto") 486 .addMessageType(DescriptorProto.newBuilder() 487 .setName("Foo") 488 .addField(FieldDescriptorProto.newBuilder() 489 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 490 .setType(FieldDescriptorProto.Type.TYPE_INT32) 491 .setName("foo") 492 .setNumber(1) 493 .build()) 494 .build()) 495 .addMessageType(DescriptorProto.newBuilder() 496 .setName("Bar") 497 .addField(FieldDescriptorProto.newBuilder() 498 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 499 .setTypeName("Foo") 500 .setName("Foo") 501 .setNumber(1) 502 .build()) 503 .build()) 504 .build(); 505 // translate and crosslink 506 FileDescriptor file = 507 Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, 508 new FileDescriptor[0]); 509 // verify resulting descriptors 510 assertNotNull(file); 511 List<Descriptor> msglist = file.getMessageTypes(); 512 assertNotNull(msglist); 513 assertTrue(msglist.size() == 2); 514 boolean barFound = false; 515 for (Descriptor desc : msglist) { 516 if (desc.getName().equals("Bar")) { 517 barFound = true; 518 assertNotNull(desc.getFields()); 519 List<FieldDescriptor> fieldlist = desc.getFields(); 520 assertNotNull(fieldlist); 521 assertTrue(fieldlist.size() == 1); 522 assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE); 523 assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo")); 524 } 525 } 526 assertTrue(barFound); 527 } 528 testDependencyOrder()529 public void testDependencyOrder() throws Exception { 530 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() 531 .setName("foo.proto").build(); 532 FileDescriptorProto barProto = FileDescriptorProto.newBuilder() 533 .setName("bar.proto") 534 .addDependency("foo.proto") 535 .build(); 536 FileDescriptorProto bazProto = FileDescriptorProto.newBuilder() 537 .setName("baz.proto") 538 .addDependency("foo.proto") 539 .addDependency("bar.proto") 540 .addPublicDependency(0) 541 .addPublicDependency(1) 542 .build(); 543 FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, 544 new FileDescriptor[0]); 545 FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, 546 new FileDescriptor[] {fooFile}); 547 548 // Items in the FileDescriptor array can be in any order. 549 Descriptors.FileDescriptor.buildFrom(bazProto, 550 new FileDescriptor[] {fooFile, barFile}); 551 Descriptors.FileDescriptor.buildFrom(bazProto, 552 new FileDescriptor[] {barFile, fooFile}); 553 } 554 testInvalidPublicDependency()555 public void testInvalidPublicDependency() throws Exception { 556 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() 557 .setName("foo.proto").build(); 558 FileDescriptorProto barProto = FileDescriptorProto.newBuilder() 559 .setName("boo.proto") 560 .addDependency("foo.proto") 561 .addPublicDependency(1) // Error, should be 0. 562 .build(); 563 FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, 564 new FileDescriptor[0]); 565 try { 566 Descriptors.FileDescriptor.buildFrom(barProto, 567 new FileDescriptor[] {fooFile}); 568 fail("DescriptorValidationException expected"); 569 } catch (DescriptorValidationException e) { 570 assertTrue( 571 e.getMessage().indexOf("Invalid public dependency index.") != -1); 572 } 573 } 574 testUnknownFieldsDenied()575 public void testUnknownFieldsDenied() throws Exception { 576 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() 577 .setName("foo.proto") 578 .addMessageType(DescriptorProto.newBuilder() 579 .setName("Foo") 580 .addField(FieldDescriptorProto.newBuilder() 581 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 582 .setTypeName("Bar") 583 .setName("bar") 584 .setNumber(1))) 585 .build(); 586 587 try { 588 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); 589 fail("DescriptorValidationException expected"); 590 } catch (DescriptorValidationException e) { 591 assertTrue(e.getMessage().indexOf("Bar") != -1); 592 assertTrue(e.getMessage().indexOf("is not defined") != -1); 593 } 594 } 595 testUnknownFieldsAllowed()596 public void testUnknownFieldsAllowed() throws Exception { 597 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() 598 .setName("foo.proto") 599 .addDependency("bar.proto") 600 .addMessageType(DescriptorProto.newBuilder() 601 .setName("Foo") 602 .addField(FieldDescriptorProto.newBuilder() 603 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 604 .setTypeName("Bar") 605 .setName("bar") 606 .setNumber(1))) 607 .build(); 608 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true); 609 } 610 testHiddenDependency()611 public void testHiddenDependency() throws Exception { 612 FileDescriptorProto barProto = FileDescriptorProto.newBuilder() 613 .setName("bar.proto") 614 .addMessageType(DescriptorProto.newBuilder().setName("Bar")) 615 .build(); 616 FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder() 617 .setName("forward.proto") 618 .addDependency("bar.proto") 619 .build(); 620 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() 621 .setName("foo.proto") 622 .addDependency("forward.proto") 623 .addMessageType(DescriptorProto.newBuilder() 624 .setName("Foo") 625 .addField(FieldDescriptorProto.newBuilder() 626 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 627 .setTypeName("Bar") 628 .setName("bar") 629 .setNumber(1))) 630 .build(); 631 FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( 632 barProto, new FileDescriptor[0]); 633 FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom( 634 forwardProto, new FileDescriptor[] {barFile}); 635 636 try { 637 Descriptors.FileDescriptor.buildFrom( 638 fooProto, new FileDescriptor[] {forwardFile}); 639 fail("DescriptorValidationException expected"); 640 } catch (DescriptorValidationException e) { 641 assertTrue(e.getMessage().indexOf("Bar") != -1); 642 assertTrue(e.getMessage().indexOf("is not defined") != -1); 643 } 644 } 645 testPublicDependency()646 public void testPublicDependency() throws Exception { 647 FileDescriptorProto barProto = FileDescriptorProto.newBuilder() 648 .setName("bar.proto") 649 .addMessageType(DescriptorProto.newBuilder().setName("Bar")) 650 .build(); 651 FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder() 652 .setName("forward.proto") 653 .addDependency("bar.proto") 654 .addPublicDependency(0) 655 .build(); 656 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() 657 .setName("foo.proto") 658 .addDependency("forward.proto") 659 .addMessageType(DescriptorProto.newBuilder() 660 .setName("Foo") 661 .addField(FieldDescriptorProto.newBuilder() 662 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 663 .setTypeName("Bar") 664 .setName("bar") 665 .setNumber(1))) 666 .build(); 667 FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( 668 barProto, new FileDescriptor[0]); 669 FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom( 670 forwardProto, new FileDescriptor[]{barFile}); 671 Descriptors.FileDescriptor.buildFrom( 672 fooProto, new FileDescriptor[] {forwardFile}); 673 } 674 675 /** 676 * Tests the translate/crosslink for an example with a more complex namespace 677 * referencing. 678 */ testComplexNamespacePublicDependency()679 public void testComplexNamespacePublicDependency() throws Exception { 680 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder() 681 .setName("bar.proto") 682 .setPackage("a.b.c.d.bar.shared") 683 .addEnumType(EnumDescriptorProto.newBuilder() 684 .setName("MyEnum") 685 .addValue(EnumValueDescriptorProto.newBuilder() 686 .setName("BLAH") 687 .setNumber(1))) 688 .build(); 689 FileDescriptorProto barProto = FileDescriptorProto.newBuilder() 690 .setName("foo.proto") 691 .addDependency("bar.proto") 692 .setPackage("a.b.c.d.foo.shared") 693 .addMessageType(DescriptorProto.newBuilder() 694 .setName("MyMessage") 695 .addField(FieldDescriptorProto.newBuilder() 696 .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) 697 .setTypeName("bar.shared.MyEnum") 698 .setName("MyField") 699 .setNumber(1))) 700 .build(); 701 // translate and crosslink 702 FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom( 703 fooProto, new FileDescriptor[0]); 704 FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom( 705 barProto, new FileDescriptor[]{fooFile}); 706 // verify resulting descriptors 707 assertNotNull(barFile); 708 List<Descriptor> msglist = barFile.getMessageTypes(); 709 assertNotNull(msglist); 710 assertTrue(msglist.size() == 1); 711 Descriptor desc = msglist.get(0); 712 if (desc.getName().equals("MyMessage")) { 713 assertNotNull(desc.getFields()); 714 List<FieldDescriptor> fieldlist = desc.getFields(); 715 assertNotNull(fieldlist); 716 assertTrue(fieldlist.size() == 1); 717 FieldDescriptor field = fieldlist.get(0); 718 assertTrue(field.getType() == FieldDescriptor.Type.ENUM); 719 assertTrue(field.getEnumType().getName().equals("MyEnum")); 720 assertTrue(field.getEnumType().getFile().getName().equals("bar.proto")); 721 assertTrue(field.getEnumType().getFile().getPackage().equals( 722 "a.b.c.d.bar.shared")); 723 } 724 } 725 testOneofDescriptor()726 public void testOneofDescriptor() throws Exception { 727 Descriptor messageType = TestAllTypes.getDescriptor(); 728 FieldDescriptor field = 729 messageType.findFieldByName("oneof_nested_message"); 730 OneofDescriptor oneofDescriptor = field.getContainingOneof(); 731 assertNotNull(oneofDescriptor); 732 assertSame(oneofDescriptor, messageType.getOneofs().get(0)); 733 assertEquals("oneof_field", oneofDescriptor.getName()); 734 735 assertEquals(4, oneofDescriptor.getFieldCount()); 736 assertSame(oneofDescriptor.getField(1), field); 737 738 assertEquals(4, oneofDescriptor.getFields().size()); 739 assertEquals(oneofDescriptor.getFields().get(1), field); 740 } 741 testMessageDescriptorExtensions()742 public void testMessageDescriptorExtensions() throws Exception { 743 assertFalse(TestAllTypes.getDescriptor().isExtendable()); 744 assertTrue(TestAllExtensions.getDescriptor().isExtendable()); 745 assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtendable()); 746 747 assertFalse(TestAllTypes.getDescriptor().isExtensionNumber(3)); 748 assertTrue(TestAllExtensions.getDescriptor().isExtensionNumber(3)); 749 assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42)); 750 assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43)); 751 assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142)); 752 assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143)); 753 } 754 testReservedFields()755 public void testReservedFields() { 756 Descriptor d = TestReservedFields.getDescriptor(); 757 assertTrue(d.isReservedNumber(2)); 758 assertFalse(d.isReservedNumber(8)); 759 assertTrue(d.isReservedNumber(9)); 760 assertTrue(d.isReservedNumber(10)); 761 assertTrue(d.isReservedNumber(11)); 762 assertFalse(d.isReservedNumber(12)); 763 assertFalse(d.isReservedName("foo")); 764 assertTrue(d.isReservedName("bar")); 765 assertTrue(d.isReservedName("baz")); 766 } 767 testToString()768 public void testToString() { 769 assertEquals("protobuf_unittest.TestAllTypes.optional_uint64", 770 UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber( 771 UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER).toString()); 772 } 773 testPackedEnumField()774 public void testPackedEnumField() throws Exception { 775 FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder() 776 .setName("foo.proto") 777 .addEnumType(EnumDescriptorProto.newBuilder() 778 .setName("Enum") 779 .addValue(EnumValueDescriptorProto.newBuilder() 780 .setName("FOO") 781 .setNumber(1) 782 .build()) 783 .build()) 784 .addMessageType(DescriptorProto.newBuilder() 785 .setName("Message") 786 .addField(FieldDescriptorProto.newBuilder() 787 .setName("foo") 788 .setTypeName("Enum") 789 .setNumber(1) 790 .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) 791 .setOptions(DescriptorProtos.FieldOptions.newBuilder() 792 .setPacked(true) 793 .build()) 794 .build()) 795 .build()) 796 .build(); 797 Descriptors.FileDescriptor.buildFrom( 798 fileDescriptorProto, new FileDescriptor[0]); 799 } 800 } 801