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