1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.common.truth.Truth.assertThat; 11 import static com.google.common.truth.Truth.assertWithMessage; 12 import static org.junit.Assert.assertThrows; 13 14 import com.google.protobuf.DescriptorProtos.DescriptorProto; 15 import com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange; 16 import com.google.protobuf.DescriptorProtos.Edition; 17 import com.google.protobuf.DescriptorProtos.EnumDescriptorProto; 18 import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto; 19 import com.google.protobuf.DescriptorProtos.FeatureSetDefaults; 20 import com.google.protobuf.DescriptorProtos.FeatureSetDefaults.FeatureSetEditionDefault; 21 import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; 22 import com.google.protobuf.DescriptorProtos.FieldOptions; 23 import com.google.protobuf.DescriptorProtos.FileDescriptorProto; 24 import com.google.protobuf.DescriptorProtos.FileOptions; 25 import com.google.protobuf.DescriptorProtos.MethodDescriptorProto; 26 import com.google.protobuf.DescriptorProtos.OneofDescriptorProto; 27 import com.google.protobuf.DescriptorProtos.ServiceDescriptorProto; 28 import com.google.protobuf.Descriptors.Descriptor; 29 import com.google.protobuf.Descriptors.DescriptorValidationException; 30 import com.google.protobuf.Descriptors.EnumDescriptor; 31 import com.google.protobuf.Descriptors.EnumValueDescriptor; 32 import com.google.protobuf.Descriptors.FieldDescriptor; 33 import com.google.protobuf.Descriptors.FileDescriptor; 34 import com.google.protobuf.Descriptors.MethodDescriptor; 35 import com.google.protobuf.Descriptors.OneofDescriptor; 36 import com.google.protobuf.Descriptors.ServiceDescriptor; 37 import com.google.protobuf.test.UnittestImport; 38 import com.google.protobuf.test.UnittestImport.ImportEnum; 39 import com.google.protobuf.test.UnittestImport.ImportEnumForMap; 40 import legacy_features_unittest.UnittestLegacyFeatures; 41 import pb.UnittestFeatures; 42 import protobuf_unittest.TestCustomOptions; 43 import protobuf_unittest.UnittestCustomOptions; 44 import protobuf_unittest.UnittestProto; 45 import protobuf_unittest.UnittestProto.ForeignEnum; 46 import protobuf_unittest.UnittestProto.ForeignMessage; 47 import protobuf_unittest.UnittestProto.TestAllExtensions; 48 import protobuf_unittest.UnittestProto.TestAllTypes; 49 import protobuf_unittest.UnittestProto.TestExtremeDefaultValues; 50 import protobuf_unittest.UnittestProto.TestJsonName; 51 import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges; 52 import protobuf_unittest.UnittestProto.TestRequired; 53 import protobuf_unittest.UnittestProto.TestReservedEnumFields; 54 import protobuf_unittest.UnittestProto.TestReservedFields; 55 import protobuf_unittest.UnittestProto.TestService; 56 import protobuf_unittest.UnittestRetention; 57 import protobuf_unittest.UnittestProto3Extensions.Proto3FileExtensions; 58 import java.util.Collections; 59 import java.util.List; 60 import org.junit.Before; 61 import org.junit.Test; 62 import org.junit.experimental.runners.Enclosed; 63 import org.junit.runner.RunWith; 64 65 import protobuf_unittest.NestedExtension; 66 import protobuf_unittest.NonNestedExtension; 67 68 /** Unit test for {@link Descriptors}. */ 69 @RunWith(Enclosed.class) 70 public class DescriptorsTest { 71 72 public static class GeneralDescriptorsTest { 73 // Regression test for bug where referencing a FieldDescriptor.Type value 74 // before a FieldDescriptorProto.Type value would yield a 75 // ExceptionInInitializerError. 76 @SuppressWarnings("unused") 77 private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL; 78 79 @Test testFieldTypeEnumMapping()80 public void testFieldTypeEnumMapping() throws Exception { 81 assertThat(FieldDescriptor.Type.values()) 82 .hasLength(FieldDescriptorProto.Type.values().length); 83 for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) { 84 FieldDescriptorProto.Type protoType = type.toProto(); 85 assertThat(protoType.name()).isEqualTo("TYPE_" + type.name()); 86 assertThat(FieldDescriptor.Type.valueOf(protoType)).isEqualTo(type); 87 } 88 } 89 90 @Test testFileDescriptor()91 public void testFileDescriptor() throws Exception { 92 FileDescriptor file = UnittestProto.getDescriptor(); 93 94 assertThat(file.getName()).isEqualTo("google/protobuf/unittest.proto"); 95 assertThat(file.getPackage()).isEqualTo("protobuf_unittest"); 96 assertThat(file.getOptions().getJavaOuterClassname()).isEqualTo("UnittestProto"); 97 assertThat(file.toProto().getName()).isEqualTo("google/protobuf/unittest.proto"); 98 99 assertThat(file.getDependencies()).containsExactly(UnittestImport.getDescriptor()); 100 101 Descriptor messageType = TestAllTypes.getDescriptor(); 102 assertThat(file.getMessageTypes().get(0)).isEqualTo(messageType); 103 assertThat(file.findMessageTypeByName("TestAllTypes")).isEqualTo(messageType); 104 assertThat(file.findMessageTypeByName("NoSuchType")).isNull(); 105 assertThat(file.findMessageTypeByName("protobuf_unittest.TestAllTypes")).isNull(); 106 for (int i = 0; i < file.getMessageTypes().size(); i++) { 107 assertThat(file.getMessageTypes().get(i).getIndex()).isEqualTo(i); 108 } 109 110 EnumDescriptor enumType = ForeignEnum.getDescriptor(); 111 assertThat(file.getEnumTypes().get(0)).isEqualTo(enumType); 112 assertThat(file.findEnumTypeByName("ForeignEnum")).isEqualTo(enumType); 113 assertThat(file.findEnumTypeByName("NoSuchType")).isNull(); 114 assertThat(file.findEnumTypeByName("protobuf_unittest.ForeignEnum")).isNull(); 115 assertThat(UnittestImport.getDescriptor().getEnumTypes()) 116 .containsExactly(ImportEnum.getDescriptor(), ImportEnumForMap.getDescriptor()) 117 .inOrder(); 118 for (int i = 0; i < file.getEnumTypes().size(); i++) { 119 assertThat(file.getEnumTypes().get(i).getIndex()).isEqualTo(i); 120 } 121 122 ServiceDescriptor service = TestService.getDescriptor(); 123 assertThat(file.getServices().get(0)).isEqualTo(service); 124 assertThat(file.findServiceByName("TestService")).isEqualTo(service); 125 assertThat(file.findServiceByName("NoSuchType")).isNull(); 126 assertThat(file.findServiceByName("protobuf_unittest.TestService")).isNull(); 127 assertThat(UnittestImport.getDescriptor().getServices()).isEqualTo(Collections.emptyList()); 128 for (int i = 0; i < file.getServices().size(); i++) { 129 assertThat(file.getServices().get(i).getIndex()).isEqualTo(i); 130 } 131 132 FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor(); 133 assertThat(file.getExtensions().get(0)).isEqualTo(extension); 134 assertThat(file.findExtensionByName("optional_int32_extension")).isEqualTo(extension); 135 assertThat(file.findExtensionByName("no_such_ext")).isNull(); 136 assertThat(file.findExtensionByName("protobuf_unittest.optional_int32_extension")).isNull(); 137 assertThat(UnittestImport.getDescriptor().getExtensions()).isEqualTo(Collections.emptyList()); 138 for (int i = 0; i < file.getExtensions().size(); i++) { 139 assertThat(file.getExtensions().get(i).getIndex()).isEqualTo(i); 140 } 141 } 142 143 @Test testFileDescriptorGetEdition()144 public void testFileDescriptorGetEdition() throws Exception { 145 FileDescriptorProto proto2 = FileDescriptorProto.newBuilder().setSyntax("proto2").build(); 146 FileDescriptor file2 = Descriptors.FileDescriptor.buildFrom(proto2, new FileDescriptor[0]); 147 assertThat(file2.getEdition()).isEqualTo(Edition.EDITION_PROTO2); 148 149 FileDescriptorProto proto3 = FileDescriptorProto.newBuilder().setSyntax("proto3").build(); 150 FileDescriptor file3 = Descriptors.FileDescriptor.buildFrom(proto3, new FileDescriptor[0]); 151 assertThat(file3.getEdition()).isEqualTo(Edition.EDITION_PROTO3); 152 153 FileDescriptorProto protoEdition = 154 FileDescriptorProto.newBuilder() 155 .setSyntax("editions") 156 .setEdition(Edition.EDITION_2023) 157 .build(); 158 FileDescriptor fileEdition = 159 Descriptors.FileDescriptor.buildFrom(protoEdition, new FileDescriptor[0]); 160 assertThat(fileEdition.getEdition()).isEqualTo(Edition.EDITION_2023); 161 162 FileDescriptorProto protoMissingEdition = 163 FileDescriptorProto.newBuilder().setSyntax("editions").build(); 164 IllegalArgumentException exception = 165 assertThrows( 166 IllegalArgumentException.class, 167 () -> 168 Descriptors.FileDescriptor.buildFrom(protoMissingEdition, new FileDescriptor[0])); 169 assertThat(exception) 170 .hasMessageThat() 171 .contains("Edition EDITION_UNKNOWN is lower than the minimum supported edition"); 172 } 173 174 @Test testFileDescriptorCopyHeadingTo()175 public void testFileDescriptorCopyHeadingTo() throws Exception { 176 FileDescriptorProto.Builder protoBuilder = 177 FileDescriptorProto.newBuilder() 178 .setName("foo.proto") 179 .setPackage("foo.bar.baz") 180 .setSyntax("proto2") 181 .setOptions(FileOptions.newBuilder().setJavaPackage("foo.bar.baz").build()) 182 // Won't be copied. 183 .addMessageType(DescriptorProto.newBuilder().setName("Foo").build()); 184 FileDescriptor file2 = 185 Descriptors.FileDescriptor.buildFrom(protoBuilder.build(), new FileDescriptor[0]); 186 FileDescriptorProto.Builder protoBuilder2 = FileDescriptorProto.newBuilder(); 187 file2.copyHeadingTo(protoBuilder2); 188 FileDescriptorProto toProto2 = protoBuilder2.build(); 189 assertThat(toProto2.getName()).isEqualTo("foo.proto"); 190 assertThat(toProto2.getPackage()).isEqualTo("foo.bar.baz"); 191 assertThat(toProto2.getSyntax()).isEqualTo("proto2"); 192 assertThat(toProto2.getOptions().getJavaPackage()).isEqualTo("foo.bar.baz"); 193 assertThat(toProto2.getMessageTypeList()).isEmpty(); 194 195 protoBuilder.setSyntax("proto3"); 196 FileDescriptor file3 = 197 Descriptors.FileDescriptor.buildFrom(protoBuilder.build(), new FileDescriptor[0]); 198 FileDescriptorProto.Builder protoBuilder3 = FileDescriptorProto.newBuilder(); 199 file3.copyHeadingTo(protoBuilder3); 200 FileDescriptorProto toProto3 = protoBuilder3.build(); 201 assertThat(toProto3.getName()).isEqualTo("foo.proto"); 202 assertThat(toProto3.getPackage()).isEqualTo("foo.bar.baz"); 203 assertThat(toProto3.getSyntax()).isEqualTo("proto3"); 204 assertThat(toProto2.getOptions().getJavaPackage()).isEqualTo("foo.bar.baz"); 205 assertThat(toProto3.getMessageTypeList()).isEmpty(); 206 } 207 208 @Test testDescriptor()209 public void testDescriptor() throws Exception { 210 Descriptor messageType = TestAllTypes.getDescriptor(); 211 Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor(); 212 213 assertThat(messageType.getName()).isEqualTo("TestAllTypes"); 214 assertThat(messageType.getFullName()).isEqualTo("protobuf_unittest.TestAllTypes"); 215 assertThat(messageType.getFile()).isEqualTo(UnittestProto.getDescriptor()); 216 assertThat(messageType.getContainingType()).isNull(); 217 assertThat(messageType.getOptions()) 218 .isEqualTo(DescriptorProtos.MessageOptions.getDefaultInstance()); 219 assertThat(messageType.toProto().getName()).isEqualTo("TestAllTypes"); 220 221 assertThat(nestedType.getName()).isEqualTo("NestedMessage"); 222 assertThat(nestedType.getFullName()).isEqualTo("protobuf_unittest.TestAllTypes.NestedMessage"); 223 assertThat(nestedType.getFile()).isEqualTo(UnittestProto.getDescriptor()); 224 assertThat(nestedType.getContainingType()).isEqualTo(messageType); 225 226 FieldDescriptor field = messageType.getFields().get(0); 227 assertThat(field.getName()).isEqualTo("optional_int32"); 228 assertThat(messageType.findFieldByName("optional_int32")).isEqualTo(field); 229 assertThat(messageType.findFieldByName("no_such_field")).isNull(); 230 assertThat(messageType.findFieldByNumber(1)).isEqualTo(field); 231 assertThat(messageType.findFieldByNumber(571283)).isNull(); 232 for (int i = 0; i < messageType.getFields().size(); i++) { 233 assertThat(messageType.getFields().get(i).getIndex()).isEqualTo(i); 234 } 235 236 assertThat(messageType.getNestedTypes().get(0)).isEqualTo(nestedType); 237 assertThat(messageType.findNestedTypeByName("NestedMessage")).isEqualTo(nestedType); 238 assertThat(messageType.findNestedTypeByName("NoSuchType")).isNull(); 239 for (int i = 0; i < messageType.getNestedTypes().size(); i++) { 240 assertThat(messageType.getNestedTypes().get(i).getIndex()).isEqualTo(i); 241 } 242 243 EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor(); 244 assertThat(messageType.getEnumTypes().get(0)).isEqualTo(enumType); 245 assertThat(messageType.findEnumTypeByName("NestedEnum")).isEqualTo(enumType); 246 assertThat(messageType.findEnumTypeByName("NoSuchType")).isNull(); 247 for (int i = 0; i < messageType.getEnumTypes().size(); i++) { 248 assertThat(messageType.getEnumTypes().get(i).getIndex()).isEqualTo(i); 249 } 250 } 251 252 @Test testFieldDescriptor()253 public void testFieldDescriptor() throws Exception { 254 Descriptor messageType = TestAllTypes.getDescriptor(); 255 FieldDescriptor primitiveField = messageType.findFieldByName("optional_int32"); 256 FieldDescriptor enumField = messageType.findFieldByName("optional_nested_enum"); 257 FieldDescriptor messageField = messageType.findFieldByName("optional_foreign_message"); 258 FieldDescriptor cordField = messageType.findFieldByName("optional_cord"); 259 FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor(); 260 FieldDescriptor nestedExtension = TestRequired.single.getDescriptor(); 261 262 assertThat(primitiveField.getName()).isEqualTo("optional_int32"); 263 assertThat(primitiveField.getFullName()) 264 .isEqualTo("protobuf_unittest.TestAllTypes.optional_int32"); 265 assertThat(primitiveField.getNumber()).isEqualTo(1); 266 assertThat(primitiveField.getContainingType()).isEqualTo(messageType); 267 assertThat(primitiveField.getFile()).isEqualTo(UnittestProto.getDescriptor()); 268 assertThat(primitiveField.getType()).isEqualTo(FieldDescriptor.Type.INT32); 269 assertThat(primitiveField.getJavaType()).isEqualTo(FieldDescriptor.JavaType.INT); 270 assertThat(primitiveField.getOptions()) 271 .isEqualTo(DescriptorProtos.FieldOptions.getDefaultInstance()); 272 assertThat(primitiveField.isExtension()).isFalse(); 273 assertThat(primitiveField.toProto().getName()).isEqualTo("optional_int32"); 274 275 assertThat(enumField.getName()).isEqualTo("optional_nested_enum"); 276 assertThat(enumField.getType()).isEqualTo(FieldDescriptor.Type.ENUM); 277 assertThat(enumField.getJavaType()).isEqualTo(FieldDescriptor.JavaType.ENUM); 278 assertThat(enumField.getEnumType()).isEqualTo(TestAllTypes.NestedEnum.getDescriptor()); 279 280 assertThat(messageField.getName()).isEqualTo("optional_foreign_message"); 281 assertThat(messageField.getType()).isEqualTo(FieldDescriptor.Type.MESSAGE); 282 assertThat(messageField.getJavaType()).isEqualTo(FieldDescriptor.JavaType.MESSAGE); 283 assertThat(messageField.getMessageType()).isEqualTo(ForeignMessage.getDescriptor()); 284 285 assertThat(cordField.getName()).isEqualTo("optional_cord"); 286 assertThat(cordField.getType()).isEqualTo(FieldDescriptor.Type.STRING); 287 assertThat(cordField.getJavaType()).isEqualTo(FieldDescriptor.JavaType.STRING); 288 assertThat(cordField.getOptions().getCtype()) 289 .isEqualTo(DescriptorProtos.FieldOptions.CType.CORD); 290 291 assertThat(extension.getName()).isEqualTo("optional_int32_extension"); 292 assertThat(extension.getFullName()).isEqualTo("protobuf_unittest.optional_int32_extension"); 293 assertThat(extension.getNumber()).isEqualTo(1); 294 assertThat(extension.getContainingType()).isEqualTo(TestAllExtensions.getDescriptor()); 295 assertThat(extension.getFile()).isEqualTo(UnittestProto.getDescriptor()); 296 assertThat(extension.getType()).isEqualTo(FieldDescriptor.Type.INT32); 297 assertThat(extension.getJavaType()).isEqualTo(FieldDescriptor.JavaType.INT); 298 assertThat(extension.getOptions()) 299 .isEqualTo(DescriptorProtos.FieldOptions.getDefaultInstance()); 300 assertThat(extension.isExtension()).isTrue(); 301 assertThat(extension.getExtensionScope()).isNull(); 302 assertThat(extension.toProto().getName()).isEqualTo("optional_int32_extension"); 303 304 assertThat(nestedExtension.getName()).isEqualTo("single"); 305 assertThat(nestedExtension.getFullName()).isEqualTo("protobuf_unittest.TestRequired.single"); 306 assertThat(nestedExtension.getExtensionScope()).isEqualTo(TestRequired.getDescriptor()); 307 } 308 309 @Test testFieldDescriptorLabel()310 public void testFieldDescriptorLabel() throws Exception { 311 FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a"); 312 FieldDescriptor optionalField = 313 TestAllTypes.getDescriptor().findFieldByName("optional_int32"); 314 FieldDescriptor repeatedField = 315 TestAllTypes.getDescriptor().findFieldByName("repeated_int32"); 316 317 assertThat(requiredField.isRequired()).isTrue(); 318 assertThat(requiredField.isRepeated()).isFalse(); 319 assertThat(optionalField.isRequired()).isFalse(); 320 assertThat(optionalField.isRepeated()).isFalse(); 321 assertThat(repeatedField.isRequired()).isFalse(); 322 assertThat(repeatedField.isRepeated()).isTrue(); 323 } 324 325 @Test testFieldDescriptorJsonName()326 public void testFieldDescriptorJsonName() throws Exception { 327 FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a"); 328 FieldDescriptor optionalField = 329 TestAllTypes.getDescriptor().findFieldByName("optional_int32"); 330 FieldDescriptor repeatedField = 331 TestAllTypes.getDescriptor().findFieldByName("repeated_int32"); 332 assertThat(requiredField.getJsonName()).isEqualTo("a"); 333 assertThat(optionalField.getJsonName()).isEqualTo("optionalInt32"); 334 assertThat(repeatedField.getJsonName()).isEqualTo("repeatedInt32"); 335 } 336 337 @Test testFieldDescriptorDefault()338 public void testFieldDescriptorDefault() throws Exception { 339 Descriptor d = TestAllTypes.getDescriptor(); 340 assertThat(d.findFieldByName("optional_int32").hasDefaultValue()).isFalse(); 341 assertThat(d.findFieldByName("optional_int32").getDefaultValue()).isEqualTo(0); 342 assertThat(d.findFieldByName("default_int32").hasDefaultValue()).isTrue(); 343 assertThat(d.findFieldByName("default_int32").getDefaultValue()).isEqualTo(41); 344 345 d = TestExtremeDefaultValues.getDescriptor(); 346 assertThat(d.findFieldByName("escaped_bytes").getDefaultValue()) 347 .isEqualTo( 348 ByteString.copyFrom( 349 "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1))); 350 assertThat(d.findFieldByName("large_uint32").getDefaultValue()).isEqualTo(-1); 351 assertThat(d.findFieldByName("large_uint64").getDefaultValue()).isEqualTo(-1L); 352 } 353 354 @Test testFieldDescriptorLegacyEnumFieldTreatedAsOpen()355 public void testFieldDescriptorLegacyEnumFieldTreatedAsOpen() throws Exception { 356 // Make an open enum definition and message that treats enum fields as open. 357 358 FileDescriptorProto openEnumFile = 359 FileDescriptorProto.newBuilder() 360 .setName("open_enum.proto") 361 .setSyntax("proto3") 362 .addEnumType( 363 EnumDescriptorProto.newBuilder() 364 .setName("TestEnumOpen") 365 .addValue( 366 EnumValueDescriptorProto.newBuilder() 367 .setName("TestEnumOpen_VALUE0") 368 .setNumber(0) 369 .build()) 370 .build()) 371 .addMessageType( 372 DescriptorProto.newBuilder() 373 .setName("TestOpenEnumField") 374 .addField( 375 FieldDescriptorProto.newBuilder() 376 .setName("int_field") 377 .setNumber(1) 378 .setType(FieldDescriptorProto.Type.TYPE_INT32) 379 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 380 .build()) 381 .addField( 382 FieldDescriptorProto.newBuilder() 383 .setName("open_enum") 384 .setNumber(2) 385 .setType(FieldDescriptorProto.Type.TYPE_ENUM) 386 .setTypeName("TestEnumOpen") 387 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 388 .build()) 389 .build()) 390 .build(); 391 FileDescriptor openEnumFileDescriptor = 392 Descriptors.FileDescriptor.buildFrom(openEnumFile, new FileDescriptor[0]); 393 Descriptor openMessage = openEnumFileDescriptor.getMessageTypes().get(0); 394 EnumDescriptor openEnum = openEnumFileDescriptor.findEnumTypeByName("TestEnumOpen"); 395 assertThat(openEnum.isClosed()).isFalse(); 396 assertThat(openMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) 397 .isFalse(); 398 assertThat(openMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) 399 .isFalse(); 400 } 401 402 @Test testEditionFieldDescriptorLegacyEnumFieldTreatedAsClosedUnknown()403 public void testEditionFieldDescriptorLegacyEnumFieldTreatedAsClosedUnknown() throws Exception { 404 // Make an open enum definition. 405 FileDescriptorProto openEnumFile = 406 FileDescriptorProto.newBuilder() 407 .setName("open_enum.proto") 408 .setSyntax("editions") 409 .setEdition(Edition.EDITION_2023) 410 .addEnumType( 411 EnumDescriptorProto.newBuilder() 412 .setName("TestEnumOpen") 413 .addValue( 414 EnumValueDescriptorProto.newBuilder() 415 .setName("TestEnumOpen_VALUE0") 416 .setNumber(0) 417 .build()) 418 .build()) 419 .build(); 420 FileDescriptor openFileDescriptor = 421 Descriptors.FileDescriptor.buildFrom(openEnumFile, new FileDescriptor[0]); 422 EnumDescriptor openEnum = openFileDescriptor.getEnumTypes().get(0); 423 assertThat(openEnum.isClosed()).isFalse(); 424 425 // Create a message that treats enum fields as closed. 426 FileDescriptorProto editionsClosedEnumFile = 427 FileDescriptorProto.newBuilder() 428 .setName("editions_closed_enum_field.proto") 429 .addDependency("open_enum.proto") 430 .setSyntax("editions") 431 .setEdition(Edition.EDITION_2023) 432 .setOptions( 433 FileOptions.newBuilder() 434 .setFeatures( 435 DescriptorProtos.FeatureSet.newBuilder() 436 .setEnumType(DescriptorProtos.FeatureSet.EnumType.CLOSED) 437 .build()) 438 .build()) 439 .addEnumType( 440 EnumDescriptorProto.newBuilder() 441 .setName("TestEnum") 442 .addValue( 443 EnumValueDescriptorProto.newBuilder() 444 .setName("TestEnum_VALUE0") 445 .setNumber(0) 446 .build()) 447 .build()) 448 .addMessageType( 449 DescriptorProto.newBuilder() 450 .setName("TestClosedEnumField") 451 .addField( 452 FieldDescriptorProto.newBuilder() 453 .setName("int_field") 454 .setNumber(1) 455 .setType(FieldDescriptorProto.Type.TYPE_INT32) 456 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 457 .build()) 458 .addField( 459 FieldDescriptorProto.newBuilder() 460 .setName("open_enum") 461 .setNumber(2) 462 .setType(FieldDescriptorProto.Type.TYPE_ENUM) 463 .setTypeName("TestEnumOpen") 464 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 465 .setOptions( 466 DescriptorProtos.FieldOptions.newBuilder() 467 .setFeatures( 468 DescriptorProtos.FeatureSet.newBuilder() 469 .setExtension( 470 JavaFeaturesProto.java_, 471 JavaFeaturesProto.JavaFeatures.newBuilder() 472 .setLegacyClosedEnum(true) 473 .build()) 474 .build()) 475 .build()) 476 .build()) 477 .addField( 478 FieldDescriptorProto.newBuilder() 479 .setName("closed_enum") 480 .setNumber(3) 481 .setType(FieldDescriptorProto.Type.TYPE_ENUM) 482 .setTypeName("TestEnum") 483 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 484 .build()) 485 .build()) 486 .build(); 487 // Ensure Java features are in unknown fields. 488 editionsClosedEnumFile = 489 FileDescriptorProto.parseFrom( 490 editionsClosedEnumFile.toByteString(), ExtensionRegistry.getEmptyRegistry()); 491 Descriptor editionsClosedMessage = 492 Descriptors.FileDescriptor.buildFrom( 493 editionsClosedEnumFile, new FileDescriptor[] {openFileDescriptor}) 494 .getMessageTypes() 495 .get(0); 496 assertThat( 497 editionsClosedMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) 498 .isFalse(); 499 assertThat( 500 editionsClosedMessage.findFieldByName("closed_enum").legacyEnumFieldTreatedAsClosed()) 501 .isTrue(); 502 assertThat( 503 editionsClosedMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) 504 .isTrue(); 505 } 506 507 @Test testEditionFieldDescriptorLegacyEnumFieldTreatedAsClosedCustomPool()508 public void testEditionFieldDescriptorLegacyEnumFieldTreatedAsClosedCustomPool() 509 throws Exception { 510 511 FileDescriptor javaFeaturesDescriptor = 512 Descriptors.FileDescriptor.buildFrom( 513 JavaFeaturesProto.getDescriptor().toProto(), 514 new FileDescriptor[] {DescriptorProtos.getDescriptor()}); 515 // Make an open enum definition. 516 FileDescriptorProto openEnumFile = 517 FileDescriptorProto.newBuilder() 518 .setName("open_enum.proto") 519 .setSyntax("editions") 520 .setEdition(Edition.EDITION_2023) 521 .addEnumType( 522 EnumDescriptorProto.newBuilder() 523 .setName("TestEnumOpen") 524 .addValue( 525 EnumValueDescriptorProto.newBuilder() 526 .setName("TestEnumOpen_VALUE0") 527 .setNumber(0) 528 .build()) 529 .build()) 530 .build(); 531 FileDescriptor openFileDescriptor = 532 Descriptors.FileDescriptor.buildFrom(openEnumFile, new FileDescriptor[0]); 533 EnumDescriptor openEnum = openFileDescriptor.getEnumTypes().get(0); 534 assertThat(openEnum.isClosed()).isFalse(); 535 536 // Create a message that treats enum fields as closed. 537 FileDescriptorProto editionsClosedEnumFile = 538 FileDescriptorProto.newBuilder() 539 .setName("editions_closed_enum_field.proto") 540 .addDependency("open_enum.proto") 541 .setSyntax("editions") 542 .setEdition(Edition.EDITION_2023) 543 .setOptions( 544 FileOptions.newBuilder() 545 .setFeatures( 546 DescriptorProtos.FeatureSet.newBuilder() 547 .setEnumType(DescriptorProtos.FeatureSet.EnumType.CLOSED) 548 .build()) 549 .build()) 550 .addEnumType( 551 EnumDescriptorProto.newBuilder() 552 .setName("TestEnum") 553 .addValue( 554 EnumValueDescriptorProto.newBuilder() 555 .setName("TestEnum_VALUE0") 556 .setNumber(0) 557 .build()) 558 .build()) 559 .addMessageType( 560 DescriptorProto.newBuilder() 561 .setName("TestClosedEnumField") 562 .addField( 563 FieldDescriptorProto.newBuilder() 564 .setName("int_field") 565 .setNumber(1) 566 .setType(FieldDescriptorProto.Type.TYPE_INT32) 567 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 568 .build()) 569 .addField( 570 FieldDescriptorProto.newBuilder() 571 .setName("open_enum") 572 .setNumber(2) 573 .setType(FieldDescriptorProto.Type.TYPE_ENUM) 574 .setTypeName("TestEnumOpen") 575 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 576 .setOptions( 577 DescriptorProtos.FieldOptions.newBuilder() 578 .setFeatures( 579 DescriptorProtos.FeatureSet.newBuilder() 580 .setField( 581 // Set extension using custom descriptor 582 javaFeaturesDescriptor.findExtensionByName( 583 JavaFeaturesProto.java_ 584 .getDescriptor() 585 .getName()), 586 JavaFeaturesProto.JavaFeatures.newBuilder() 587 .setLegacyClosedEnum(true) 588 .build()) 589 .build()) 590 .build()) 591 .build()) 592 .addField( 593 FieldDescriptorProto.newBuilder() 594 .setName("closed_enum") 595 .setNumber(3) 596 .setType(FieldDescriptorProto.Type.TYPE_ENUM) 597 .setTypeName("TestEnum") 598 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 599 .build()) 600 .build()) 601 .build(); 602 Descriptor editionsClosedMessage = 603 Descriptors.FileDescriptor.buildFrom( 604 editionsClosedEnumFile, 605 new FileDescriptor[] {openFileDescriptor, javaFeaturesDescriptor}) 606 .getMessageTypes() 607 .get(0); 608 assertThat( 609 editionsClosedMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) 610 .isFalse(); 611 assertThat( 612 editionsClosedMessage.findFieldByName("closed_enum").legacyEnumFieldTreatedAsClosed()) 613 .isTrue(); 614 assertThat( 615 editionsClosedMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) 616 .isTrue(); 617 } 618 619 @Test testEnumDescriptor()620 public void testEnumDescriptor() throws Exception { 621 EnumDescriptor enumType = ForeignEnum.getDescriptor(); 622 EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor(); 623 624 assertThat(enumType.getName()).isEqualTo("ForeignEnum"); 625 assertThat(enumType.getFullName()).isEqualTo("protobuf_unittest.ForeignEnum"); 626 assertThat(enumType.getFile()).isEqualTo(UnittestProto.getDescriptor()); 627 assertThat(enumType.isClosed()).isTrue(); 628 assertThat(enumType.getContainingType()).isNull(); 629 assertThat(enumType.getOptions()) 630 .isEqualTo(DescriptorProtos.EnumOptions.getDefaultInstance()); 631 632 assertThat(nestedType.getName()).isEqualTo("NestedEnum"); 633 assertThat(nestedType.getFullName()).isEqualTo("protobuf_unittest.TestAllTypes.NestedEnum"); 634 assertThat(nestedType.getFile()).isEqualTo(UnittestProto.getDescriptor()); 635 assertThat(nestedType.getContainingType()).isEqualTo(TestAllTypes.getDescriptor()); 636 637 EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor(); 638 assertThat(enumType.getValues().get(0)).isEqualTo(value); 639 assertThat(value.getName()).isEqualTo("FOREIGN_FOO"); 640 assertThat(value.toString()).isEqualTo("FOREIGN_FOO"); 641 assertThat(value.getNumber()).isEqualTo(4); 642 assertThat(enumType.findValueByName("FOREIGN_FOO")).isEqualTo(value); 643 assertThat(enumType.findValueByNumber(4)).isEqualTo(value); 644 assertThat(enumType.findValueByName("NO_SUCH_VALUE")).isNull(); 645 for (int i = 0; i < enumType.getValues().size(); i++) { 646 assertThat(enumType.getValues().get(i).getIndex()).isEqualTo(i); 647 } 648 } 649 650 @Test testServiceDescriptor()651 public void testServiceDescriptor() throws Exception { 652 ServiceDescriptor service = TestService.getDescriptor(); 653 654 assertThat(service.getName()).isEqualTo("TestService"); 655 assertThat(service.getFullName()).isEqualTo("protobuf_unittest.TestService"); 656 assertThat(service.getFile()).isEqualTo(UnittestProto.getDescriptor()); 657 658 MethodDescriptor fooMethod = service.getMethods().get(0); 659 assertThat(fooMethod.getName()).isEqualTo("Foo"); 660 assertThat(fooMethod.getInputType()).isEqualTo(UnittestProto.FooRequest.getDescriptor()); 661 assertThat(fooMethod.getOutputType()).isEqualTo(UnittestProto.FooResponse.getDescriptor()); 662 assertThat(service.findMethodByName("Foo")).isEqualTo(fooMethod); 663 664 MethodDescriptor barMethod = service.getMethods().get(1); 665 assertThat(barMethod.getName()).isEqualTo("Bar"); 666 assertThat(barMethod.getInputType()).isEqualTo(UnittestProto.BarRequest.getDescriptor()); 667 assertThat(barMethod.getOutputType()).isEqualTo(UnittestProto.BarResponse.getDescriptor()); 668 assertThat(service.findMethodByName("Bar")).isEqualTo(barMethod); 669 670 assertThat(service.findMethodByName("NoSuchMethod")).isNull(); 671 672 for (int i = 0; i < service.getMethods().size(); i++) { 673 assertThat(service.getMethods().get(i).getIndex()).isEqualTo(i); 674 } 675 } 676 677 @Test testCustomOptions()678 public void testCustomOptions() throws Exception { 679 // Get the descriptor indirectly from a dependent proto class. This is to 680 // ensure that when a proto class is loaded, custom options defined in its 681 // dependencies are also properly initialized. 682 Descriptor descriptor = 683 TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor() 684 .findFieldByName("field") 685 .getMessageType(); 686 687 assertThat(descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1)).isTrue(); 688 assertThat(descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1)) 689 .isEqualTo(Integer.valueOf(-56)); 690 691 FieldDescriptor field = descriptor.findFieldByName("field1"); 692 assertThat(field).isNotNull(); 693 694 assertThat(field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1)).isTrue(); 695 assertThat(field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1)) 696 .isEqualTo(Long.valueOf(8765432109L)); 697 698 OneofDescriptor oneof = descriptor.getOneofs().get(0); 699 assertThat(oneof).isNotNull(); 700 701 assertThat(oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1)).isTrue(); 702 assertThat(oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1)) 703 .isEqualTo(Integer.valueOf(-99)); 704 705 EnumDescriptor enumType = 706 UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor(); 707 708 assertThat(enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1)).isTrue(); 709 assertThat(enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1)) 710 .isEqualTo(Integer.valueOf(-789)); 711 712 ServiceDescriptor service = 713 UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor(); 714 715 assertThat(service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1)).isTrue(); 716 assertThat(service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1)) 717 .isEqualTo(Long.valueOf(-9876543210L)); 718 719 MethodDescriptor method = service.findMethodByName("Foo"); 720 assertThat(method).isNotNull(); 721 722 assertThat(method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1)).isTrue(); 723 assertThat(method.getOptions().getExtension(UnittestCustomOptions.methodOpt1)) 724 .isEqualTo(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2); 725 } 726 727 @Test testOptionRetention()728 public void testOptionRetention() throws Exception { 729 // Verify that options with RETENTION_SOURCE are stripped from the 730 // generated descriptors. 731 FileOptions options = UnittestRetention.getDescriptor().getOptions(); 732 assertThat(options.hasExtension(UnittestRetention.plainOption)).isTrue(); 733 assertThat(options.hasExtension(UnittestRetention.runtimeRetentionOption)).isTrue(); 734 assertThat(options.hasExtension(UnittestRetention.sourceRetentionOption)).isFalse(); 735 } 736 737 /** Test that the FieldDescriptor.Type enum is the same as the WireFormat.FieldType enum. */ 738 @Test testFieldTypeTablesMatch()739 public void testFieldTypeTablesMatch() throws Exception { 740 FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values(); 741 WireFormat.FieldType[] values2 = WireFormat.FieldType.values(); 742 743 assertThat(values1).hasLength(values2.length); 744 745 for (int i = 0; i < values1.length; i++) { 746 assertThat(values1[i].toString()).isEqualTo(values2[i].toString()); 747 } 748 } 749 750 /** Test that the FieldDescriptor.JavaType enum is the same as the WireFormat.JavaType enum. */ 751 @Test testJavaTypeTablesMatch()752 public void testJavaTypeTablesMatch() throws Exception { 753 FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values(); 754 WireFormat.JavaType[] values2 = WireFormat.JavaType.values(); 755 756 assertThat(values1).hasLength(values2.length); 757 758 for (int i = 0; i < values1.length; i++) { 759 assertThat(values1[i].toString()).isEqualTo(values2[i].toString()); 760 } 761 } 762 763 @Test testEnormousDescriptor()764 public void testEnormousDescriptor() throws Exception { 765 // The descriptor for this file is larger than 64k, yet it did not cause 766 // a compiler error due to an over-long string literal. 767 assertThat(UnittestEnormousDescriptor.getDescriptor().toProto().getSerializedSize()) 768 .isGreaterThan(65536); 769 } 770 771 /** Tests that the DescriptorValidationException works as intended. */ 772 @Test testDescriptorValidatorException()773 public void testDescriptorValidatorException() throws Exception { 774 FileDescriptorProto fileDescriptorProto = 775 FileDescriptorProto.newBuilder() 776 .setName("foo.proto") 777 .addMessageType( 778 DescriptorProto.newBuilder() 779 .setName("Foo") 780 .addField( 781 FieldDescriptorProto.newBuilder() 782 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 783 .setType(FieldDescriptorProto.Type.TYPE_INT32) 784 .setName("foo") 785 .setNumber(1) 786 .setDefaultValue("invalid") 787 .build()) 788 .build()) 789 .build(); 790 try { 791 Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); 792 assertWithMessage("DescriptorValidationException expected").fail(); 793 } catch (DescriptorValidationException e) { 794 // Expected; check that the error message contains some useful hints 795 assertThat(e).hasMessageThat().contains("foo"); 796 assertThat(e).hasMessageThat().contains("Foo"); 797 assertThat(e).hasMessageThat().contains("invalid"); 798 assertThat(e).hasCauseThat().isInstanceOf(NumberFormatException.class); 799 assertThat(e).hasCauseThat().hasMessageThat().contains("invalid"); 800 } 801 } 802 803 /** Tests that parsing an unknown enum throws an exception */ 804 @Test testParseUnknownEnum()805 public void testParseUnknownEnum() { 806 FieldDescriptorProto.Builder field = 807 FieldDescriptorProto.newBuilder() 808 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 809 .setTypeName("UnknownEnum") 810 .setType(FieldDescriptorProto.Type.TYPE_ENUM) 811 .setName("bar") 812 .setNumber(1); 813 DescriptorProto.Builder messageType = 814 DescriptorProto.newBuilder().setName("Foo").addField(field); 815 FileDescriptorProto fooProto = 816 FileDescriptorProto.newBuilder() 817 .setName("foo.proto") 818 .addDependency("bar.proto") 819 .addMessageType(messageType) 820 .build(); 821 try { 822 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true); 823 assertWithMessage("DescriptorValidationException expected").fail(); 824 } catch (DescriptorValidationException expected) { 825 assertThat(expected.getMessage()).contains("\"UnknownEnum\" is not an enum type."); 826 } 827 } 828 829 /** 830 * Tests the translate/crosslink for an example where a message field's name and type name are 831 * the same. 832 */ 833 @Test testDescriptorComplexCrosslink()834 public void testDescriptorComplexCrosslink() throws Exception { 835 FileDescriptorProto fileDescriptorProto = 836 FileDescriptorProto.newBuilder() 837 .setName("foo.proto") 838 .addMessageType( 839 DescriptorProto.newBuilder() 840 .setName("Foo") 841 .addField( 842 FieldDescriptorProto.newBuilder() 843 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 844 .setType(FieldDescriptorProto.Type.TYPE_INT32) 845 .setName("foo") 846 .setNumber(1) 847 .build()) 848 .build()) 849 .addMessageType( 850 DescriptorProto.newBuilder() 851 .setName("Bar") 852 .addField( 853 FieldDescriptorProto.newBuilder() 854 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 855 .setTypeName("Foo") 856 .setName("Foo") 857 .setNumber(1) 858 .build()) 859 .build()) 860 .build(); 861 // translate and crosslink 862 FileDescriptor file = 863 Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); 864 // verify resulting descriptors 865 assertThat(file).isNotNull(); 866 List<Descriptor> msglist = file.getMessageTypes(); 867 assertThat(msglist).isNotNull(); 868 assertThat(msglist).hasSize(2); 869 boolean barFound = false; 870 for (Descriptor desc : msglist) { 871 if (desc.getName().equals("Bar")) { 872 barFound = true; 873 assertThat(desc.getFields()).isNotNull(); 874 List<FieldDescriptor> fieldlist = desc.getFields(); 875 assertThat(fieldlist).isNotNull(); 876 assertThat(fieldlist).hasSize(1); 877 assertThat(fieldlist.get(0).getType()).isSameInstanceAs(FieldDescriptor.Type.MESSAGE); 878 assertThat(fieldlist.get(0).getMessageType().getName().equals("Foo")).isTrue(); 879 } 880 } 881 assertThat(barFound).isTrue(); 882 } 883 884 @Test testDependencyOrder()885 public void testDependencyOrder() throws Exception { 886 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build(); 887 FileDescriptorProto barProto = 888 FileDescriptorProto.newBuilder().setName("bar.proto").addDependency("foo.proto").build(); 889 FileDescriptorProto bazProto = 890 FileDescriptorProto.newBuilder() 891 .setName("baz.proto") 892 .addDependency("foo.proto") 893 .addDependency("bar.proto") 894 .addPublicDependency(0) 895 .addPublicDependency(1) 896 .build(); 897 FileDescriptor fooFile = 898 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); 899 FileDescriptor barFile = 900 Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile}); 901 902 // Items in the FileDescriptor array can be in any order. 903 FileDescriptor unused1 = 904 Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {fooFile, barFile}); 905 FileDescriptor unused2 = 906 Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {barFile, fooFile}); 907 } 908 909 @Test testInvalidPublicDependency()910 public void testInvalidPublicDependency() throws Exception { 911 FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build(); 912 FileDescriptorProto barProto = 913 FileDescriptorProto.newBuilder() 914 .setName("boo.proto") 915 .addDependency("foo.proto") 916 .addPublicDependency(1) // Error, should be 0. 917 .build(); 918 FileDescriptor fooFile = 919 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); 920 try { 921 Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile}); 922 assertWithMessage("DescriptorValidationException expected").fail(); 923 } catch (DescriptorValidationException e) { 924 assertThat(e).hasMessageThat().contains("Invalid public dependency index."); 925 } 926 } 927 928 @Test testUnknownFieldsDenied()929 public void testUnknownFieldsDenied() throws Exception { 930 FileDescriptorProto fooProto = 931 FileDescriptorProto.newBuilder() 932 .setName("foo.proto") 933 .addMessageType( 934 DescriptorProto.newBuilder() 935 .setName("Foo") 936 .addField( 937 FieldDescriptorProto.newBuilder() 938 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 939 .setTypeName("Bar") 940 .setName("bar") 941 .setNumber(1))) 942 .build(); 943 944 try { 945 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); 946 assertWithMessage("DescriptorValidationException expected").fail(); 947 } catch (DescriptorValidationException e) { 948 assertThat(e).hasMessageThat().contains("Bar"); 949 assertThat(e).hasMessageThat().contains("is not defined"); 950 } 951 } 952 953 @Test testUnknownFieldsAllowed()954 public void testUnknownFieldsAllowed() throws Exception { 955 FileDescriptorProto fooProto = 956 FileDescriptorProto.newBuilder() 957 .setName("foo.proto") 958 .addDependency("bar.proto") 959 .addMessageType( 960 DescriptorProto.newBuilder() 961 .setName("Foo") 962 .addField( 963 FieldDescriptorProto.newBuilder() 964 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 965 .setTypeName("Bar") 966 .setName("bar") 967 .setNumber(1))) 968 .build(); 969 FileDescriptor unused = 970 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true); 971 } 972 973 @Test testHiddenDependency()974 public void testHiddenDependency() throws Exception { 975 FileDescriptorProto barProto = 976 FileDescriptorProto.newBuilder() 977 .setName("bar.proto") 978 .addMessageType(DescriptorProto.newBuilder().setName("Bar")) 979 .build(); 980 FileDescriptorProto forwardProto = 981 FileDescriptorProto.newBuilder() 982 .setName("forward.proto") 983 .addDependency("bar.proto") 984 .build(); 985 FileDescriptorProto fooProto = 986 FileDescriptorProto.newBuilder() 987 .setName("foo.proto") 988 .addDependency("forward.proto") 989 .addMessageType( 990 DescriptorProto.newBuilder() 991 .setName("Foo") 992 .addField( 993 FieldDescriptorProto.newBuilder() 994 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 995 .setTypeName("Bar") 996 .setName("bar") 997 .setNumber(1))) 998 .build(); 999 FileDescriptor barFile = 1000 Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]); 1001 FileDescriptor forwardFile = 1002 Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile}); 1003 1004 try { 1005 FileDescriptor unused = 1006 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile}); 1007 assertWithMessage("DescriptorValidationException expected").fail(); 1008 } catch (DescriptorValidationException e) { 1009 assertThat(e).hasMessageThat().contains("Bar"); 1010 assertThat(e).hasMessageThat().contains("is not defined"); 1011 } 1012 } 1013 1014 @Test testPublicDependency()1015 public void testPublicDependency() throws Exception { 1016 FileDescriptorProto barProto = 1017 FileDescriptorProto.newBuilder() 1018 .setName("bar.proto") 1019 .addMessageType(DescriptorProto.newBuilder().setName("Bar")) 1020 .build(); 1021 FileDescriptorProto forwardProto = 1022 FileDescriptorProto.newBuilder() 1023 .setName("forward.proto") 1024 .addDependency("bar.proto") 1025 .addPublicDependency(0) 1026 .build(); 1027 FileDescriptorProto fooProto = 1028 FileDescriptorProto.newBuilder() 1029 .setName("foo.proto") 1030 .addDependency("forward.proto") 1031 .addMessageType( 1032 DescriptorProto.newBuilder() 1033 .setName("Foo") 1034 .addField( 1035 FieldDescriptorProto.newBuilder() 1036 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 1037 .setTypeName("Bar") 1038 .setName("bar") 1039 .setNumber(1))) 1040 .build(); 1041 FileDescriptor barFile = 1042 Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]); 1043 FileDescriptor forwardFile = 1044 Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile}); 1045 FileDescriptor unused = 1046 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile}); 1047 } 1048 1049 /** Tests the translate/crosslink for an example with a more complex namespace referencing. */ 1050 @Test testComplexNamespacePublicDependency()1051 public void testComplexNamespacePublicDependency() throws Exception { 1052 FileDescriptorProto fooProto = 1053 FileDescriptorProto.newBuilder() 1054 .setName("bar.proto") 1055 .setPackage("a.b.c.d.bar.shared") 1056 .addEnumType( 1057 EnumDescriptorProto.newBuilder() 1058 .setName("MyEnum") 1059 .addValue(EnumValueDescriptorProto.newBuilder().setName("BLAH").setNumber(1))) 1060 .build(); 1061 FileDescriptorProto barProto = 1062 FileDescriptorProto.newBuilder() 1063 .setName("foo.proto") 1064 .addDependency("bar.proto") 1065 .setPackage("a.b.c.d.foo.shared") 1066 .addMessageType( 1067 DescriptorProto.newBuilder() 1068 .setName("MyMessage") 1069 .addField( 1070 FieldDescriptorProto.newBuilder() 1071 .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) 1072 .setTypeName("bar.shared.MyEnum") 1073 .setName("MyField") 1074 .setNumber(1))) 1075 .build(); 1076 // translate and crosslink 1077 FileDescriptor fooFile = 1078 Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]); 1079 FileDescriptor barFile = 1080 Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile}); 1081 // verify resulting descriptors 1082 assertThat(barFile).isNotNull(); 1083 List<Descriptor> msglist = barFile.getMessageTypes(); 1084 assertThat(msglist).isNotNull(); 1085 assertThat(msglist).hasSize(1); 1086 Descriptor desc = msglist.get(0); 1087 if (desc.getName().equals("MyMessage")) { 1088 assertThat(desc.getFields()).isNotNull(); 1089 List<FieldDescriptor> fieldlist = desc.getFields(); 1090 assertThat(fieldlist).isNotNull(); 1091 assertThat(fieldlist).hasSize(1); 1092 FieldDescriptor field = fieldlist.get(0); 1093 assertThat(field.getType()).isSameInstanceAs(FieldDescriptor.Type.ENUM); 1094 assertThat(field.getEnumType().getName().equals("MyEnum")).isTrue(); 1095 assertThat(field.getEnumType().getFile().getName().equals("bar.proto")).isTrue(); 1096 assertThat(field.getEnumType().getFile().getPackage().equals("a.b.c.d.bar.shared")) 1097 .isTrue(); 1098 } 1099 } 1100 1101 @Test testOneofDescriptor()1102 public void testOneofDescriptor() throws Exception { 1103 Descriptor messageType = TestAllTypes.getDescriptor(); 1104 FieldDescriptor field = messageType.findFieldByName("oneof_nested_message"); 1105 OneofDescriptor oneofDescriptor = field.getContainingOneof(); 1106 assertThat(oneofDescriptor).isNotNull(); 1107 assertThat(messageType.getOneofs().get(0)).isSameInstanceAs(oneofDescriptor); 1108 assertThat(oneofDescriptor.getName()).isEqualTo("oneof_field"); 1109 1110 assertThat(oneofDescriptor.getFieldCount()).isEqualTo(7); 1111 assertThat(field).isSameInstanceAs(oneofDescriptor.getField(1)); 1112 1113 assertThat(oneofDescriptor.getFields()).hasSize(7); 1114 assertThat(field).isEqualTo(oneofDescriptor.getFields().get(1)); 1115 } 1116 1117 @Test testMessageDescriptorExtensions()1118 public void testMessageDescriptorExtensions() throws Exception { 1119 assertThat(TestAllTypes.getDescriptor().isExtendable()).isFalse(); 1120 assertThat(TestAllExtensions.getDescriptor().isExtendable()).isTrue(); 1121 assertThat(TestMultipleExtensionRanges.getDescriptor().isExtendable()).isTrue(); 1122 1123 assertThat(TestAllTypes.getDescriptor().isExtensionNumber(3)).isFalse(); 1124 assertThat(TestAllExtensions.getDescriptor().isExtensionNumber(3)).isTrue(); 1125 assertThat(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42)).isTrue(); 1126 assertThat(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43)).isFalse(); 1127 assertThat(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142)).isFalse(); 1128 assertThat(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143)).isTrue(); 1129 } 1130 1131 @Test testReservedFields()1132 public void testReservedFields() { 1133 Descriptor d = TestReservedFields.getDescriptor(); 1134 assertThat(d.isReservedNumber(2)).isTrue(); 1135 assertThat(d.isReservedNumber(8)).isFalse(); 1136 assertThat(d.isReservedNumber(9)).isTrue(); 1137 assertThat(d.isReservedNumber(10)).isTrue(); 1138 assertThat(d.isReservedNumber(11)).isTrue(); 1139 assertThat(d.isReservedNumber(12)).isFalse(); 1140 assertThat(d.isReservedName("foo")).isFalse(); 1141 assertThat(d.isReservedName("bar")).isTrue(); 1142 assertThat(d.isReservedName("baz")).isTrue(); 1143 } 1144 1145 @Test testReservedEnumFields()1146 public void testReservedEnumFields() { 1147 EnumDescriptor d = TestReservedEnumFields.getDescriptor(); 1148 assertThat(d.isReservedNumber(2)).isTrue(); 1149 assertThat(d.isReservedNumber(8)).isFalse(); 1150 assertThat(d.isReservedNumber(9)).isTrue(); 1151 assertThat(d.isReservedNumber(10)).isTrue(); 1152 assertThat(d.isReservedNumber(11)).isTrue(); 1153 assertThat(d.isReservedNumber(12)).isFalse(); 1154 assertThat(d.isReservedName("foo")).isFalse(); 1155 assertThat(d.isReservedName("bar")).isTrue(); 1156 assertThat(d.isReservedName("baz")).isTrue(); 1157 } 1158 1159 @Test testToString()1160 public void testToString() { 1161 assertThat( 1162 UnittestProto.TestAllTypes.getDescriptor() 1163 .findFieldByNumber(UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER) 1164 .toString()) 1165 .isEqualTo("protobuf_unittest.TestAllTypes.optional_uint64"); 1166 } 1167 1168 @Test testPackedEnumField()1169 public void testPackedEnumField() throws Exception { 1170 FileDescriptorProto fileDescriptorProto = 1171 FileDescriptorProto.newBuilder() 1172 .setName("foo.proto") 1173 .addEnumType( 1174 EnumDescriptorProto.newBuilder() 1175 .setName("Enum") 1176 .addValue( 1177 EnumValueDescriptorProto.newBuilder().setName("FOO").setNumber(1).build()) 1178 .build()) 1179 .addMessageType( 1180 DescriptorProto.newBuilder() 1181 .setName("Message") 1182 .addField( 1183 FieldDescriptorProto.newBuilder() 1184 .setName("foo") 1185 .setTypeName("Enum") 1186 .setNumber(1) 1187 .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) 1188 .setOptions( 1189 DescriptorProtos.FieldOptions.newBuilder() 1190 .setPacked(true) 1191 .build()) 1192 .build()) 1193 .build()) 1194 .build(); 1195 FileDescriptor unused = 1196 Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]); 1197 } 1198 1199 @Test testFieldJsonName()1200 public void testFieldJsonName() throws Exception { 1201 Descriptor d = TestJsonName.getDescriptor(); 1202 assertThat(d.getFields()).hasSize(7); 1203 assertThat(d.getFields().get(0).getJsonName()).isEqualTo("fieldName1"); 1204 assertThat(d.getFields().get(1).getJsonName()).isEqualTo("fieldName2"); 1205 assertThat(d.getFields().get(2).getJsonName()).isEqualTo("FieldName3"); 1206 assertThat(d.getFields().get(3).getJsonName()).isEqualTo("FieldName4"); 1207 assertThat(d.getFields().get(4).getJsonName()).isEqualTo("FIELDNAME5"); 1208 assertThat(d.getFields().get(5).getJsonName()).isEqualTo("@type"); 1209 assertThat(d.getFields().get(6).getJsonName()).isEqualTo("fieldname7"); 1210 } 1211 1212 @Test testExtensionRenamesKeywords()1213 public void testExtensionRenamesKeywords() { 1214 assertThat(NonNestedExtension.if_).isInstanceOf(GeneratedMessage.GeneratedExtension.class); 1215 assertThat(NestedExtension.MyNestedExtension.default_) 1216 .isInstanceOf(GeneratedMessage.GeneratedExtension.class); 1217 1218 NonNestedExtension.MessageToBeExtended msg = 1219 NonNestedExtension.MessageToBeExtended.newBuilder() 1220 .setExtension(NonNestedExtension.if_, "!fi") 1221 .build(); 1222 assertThat(msg.getExtension(NonNestedExtension.if_)).isEqualTo("!fi"); 1223 1224 msg = 1225 NonNestedExtension.MessageToBeExtended.newBuilder() 1226 .setExtension(NestedExtension.MyNestedExtension.default_, 8) 1227 .build(); 1228 assertThat(msg.getExtension(NestedExtension.MyNestedExtension.default_).intValue()) 1229 .isEqualTo(8); 1230 } 1231 1232 @Test testDefaultDescriptorExtensionRange()1233 public void testDefaultDescriptorExtensionRange() throws Exception { 1234 assertThat(new Descriptor("default").isExtensionNumber(1)).isTrue(); 1235 } 1236 1237 @Test testGetOptionsStripsFeatures()1238 public void testGetOptionsStripsFeatures() { 1239 FieldDescriptor field = 1240 UnittestLegacyFeatures.TestEditionsMessage.getDescriptor() 1241 .findFieldByName("required_field"); 1242 assertThat(field.getOptions().hasFeatures()).isFalse(); 1243 } 1244 1245 @Test testLegacyRequiredTransform()1246 public void testLegacyRequiredTransform() { 1247 Descriptor descriptor = UnittestLegacyFeatures.TestEditionsMessage.getDescriptor(); 1248 assertThat(descriptor.findFieldByName("required_field").isRequired()).isTrue(); 1249 } 1250 1251 @Test testLegacyGroupTransform()1252 public void testLegacyGroupTransform() { 1253 Descriptor descriptor = UnittestLegacyFeatures.TestEditionsMessage.getDescriptor(); 1254 assertThat(descriptor.findFieldByName("delimited_field").getType()) 1255 .isEqualTo(FieldDescriptor.Type.GROUP); 1256 } 1257 1258 @Test testLegacyInferRequired()1259 public void testLegacyInferRequired() throws Exception { 1260 FileDescriptor file = 1261 FileDescriptor.buildFrom( 1262 FileDescriptorProto.newBuilder() 1263 .setName("some/filename/some.proto") 1264 .setSyntax("proto2") 1265 .addMessageType( 1266 DescriptorProto.newBuilder() 1267 .setName("Foo") 1268 .addField( 1269 FieldDescriptorProto.newBuilder() 1270 .setName("a") 1271 .setNumber(1) 1272 .setType(FieldDescriptorProto.Type.TYPE_INT32) 1273 .setLabel(FieldDescriptorProto.Label.LABEL_REQUIRED) 1274 .build()) 1275 .build()) 1276 .build(), 1277 new FileDescriptor[0]); 1278 FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("a"); 1279 assertThat(field.features.getFieldPresence()) 1280 .isEqualTo(DescriptorProtos.FeatureSet.FieldPresence.LEGACY_REQUIRED); 1281 } 1282 1283 @Test testLegacyInferGroup()1284 public void testLegacyInferGroup() throws Exception { 1285 FileDescriptor file = 1286 FileDescriptor.buildFrom( 1287 FileDescriptorProto.newBuilder() 1288 .setName("some/filename/some.proto") 1289 .setSyntax("proto2") 1290 .addMessageType( 1291 DescriptorProto.newBuilder() 1292 .setName("Foo") 1293 .addNestedType( 1294 DescriptorProto.newBuilder().setName("OptionalGroup").build()) 1295 .addField( 1296 FieldDescriptorProto.newBuilder() 1297 .setName("optionalgroup") 1298 .setNumber(1) 1299 .setType(FieldDescriptorProto.Type.TYPE_GROUP) 1300 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 1301 .setTypeName("Foo.OptionalGroup") 1302 .build()) 1303 .build()) 1304 .build(), 1305 new FileDescriptor[0]); 1306 FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("optionalgroup"); 1307 assertThat(field.features.getMessageEncoding()) 1308 .isEqualTo(DescriptorProtos.FeatureSet.MessageEncoding.DELIMITED); 1309 } 1310 1311 @Test testLegacyInferProto2Packed()1312 public void testLegacyInferProto2Packed() throws Exception { 1313 FileDescriptor file = 1314 FileDescriptor.buildFrom( 1315 FileDescriptorProto.newBuilder() 1316 .setName("some/filename/some.proto") 1317 .setSyntax("proto2") 1318 .addMessageType( 1319 DescriptorProto.newBuilder() 1320 .setName("Foo") 1321 .addField( 1322 FieldDescriptorProto.newBuilder() 1323 .setName("a") 1324 .setNumber(1) 1325 .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) 1326 .setType(FieldDescriptorProto.Type.TYPE_INT32) 1327 .setOptions(FieldOptions.newBuilder().setPacked(true).build()) 1328 .build()) 1329 .build()) 1330 .build(), 1331 new FileDescriptor[0]); 1332 FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("a"); 1333 assertThat(field.features.getRepeatedFieldEncoding()) 1334 .isEqualTo(DescriptorProtos.FeatureSet.RepeatedFieldEncoding.PACKED); 1335 } 1336 1337 @Test testLegacyInferProto3Expanded()1338 public void testLegacyInferProto3Expanded() throws Exception { 1339 FileDescriptor file = 1340 FileDescriptor.buildFrom( 1341 FileDescriptorProto.newBuilder() 1342 .setName("some/filename/some.proto") 1343 .setSyntax("proto3") 1344 .addMessageType( 1345 DescriptorProto.newBuilder() 1346 .setName("Foo") 1347 .addField( 1348 FieldDescriptorProto.newBuilder() 1349 .setName("a") 1350 .setNumber(1) 1351 .setType(FieldDescriptorProto.Type.TYPE_INT32) 1352 .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) 1353 .setOptions(FieldOptions.newBuilder().setPacked(false).build()) 1354 .build()) 1355 .build()) 1356 .build(), 1357 new FileDescriptor[0]); 1358 FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("a"); 1359 assertThat(field.features.getRepeatedFieldEncoding()) 1360 .isEqualTo(DescriptorProtos.FeatureSet.RepeatedFieldEncoding.EXPANDED); 1361 } 1362 1363 @Test testLegacyInferProto2Utf8Validation()1364 public void testLegacyInferProto2Utf8Validation() throws Exception { 1365 FileDescriptor file = 1366 FileDescriptor.buildFrom( 1367 FileDescriptorProto.newBuilder() 1368 .setName("some/filename/some.proto") 1369 .setPackage("protobuf_unittest") 1370 .setSyntax("proto2") 1371 .setOptions(FileOptions.newBuilder().setJavaStringCheckUtf8(true)) 1372 .build(), 1373 new FileDescriptor[0]); 1374 assertThat(file.features.getExtension(JavaFeaturesProto.java_).getUtf8Validation()) 1375 .isEqualTo(JavaFeaturesProto.JavaFeatures.Utf8Validation.VERIFY); 1376 } 1377 1378 @Test testProto2Defaults()1379 public void testProto2Defaults() throws Exception { 1380 FileDescriptor proto2File = 1381 FileDescriptor.buildFrom( 1382 FileDescriptorProto.newBuilder() 1383 .setName("some/filename/some.proto") 1384 .setPackage("protobuf_unittest") 1385 .setSyntax("proto2") 1386 .build(), 1387 new FileDescriptor[0]); 1388 DescriptorProtos.FeatureSet features = proto2File.features; 1389 assertThat(features.getFieldPresence()) 1390 .isEqualTo(DescriptorProtos.FeatureSet.FieldPresence.EXPLICIT); 1391 assertThat(features.getEnumType()).isEqualTo(DescriptorProtos.FeatureSet.EnumType.CLOSED); 1392 assertThat(features.getRepeatedFieldEncoding()) 1393 .isEqualTo(DescriptorProtos.FeatureSet.RepeatedFieldEncoding.EXPANDED); 1394 assertThat(features.getUtf8Validation()) 1395 .isEqualTo(DescriptorProtos.FeatureSet.Utf8Validation.NONE); 1396 assertThat(features.getMessageEncoding()) 1397 .isEqualTo(DescriptorProtos.FeatureSet.MessageEncoding.LENGTH_PREFIXED); 1398 assertThat(features.getJsonFormat()) 1399 .isEqualTo(DescriptorProtos.FeatureSet.JsonFormat.LEGACY_BEST_EFFORT); 1400 1401 assertThat(features.getExtension(JavaFeaturesProto.java_).getLegacyClosedEnum()).isTrue(); 1402 assertThat(features.getExtension(JavaFeaturesProto.java_).getUtf8Validation()) 1403 .isEqualTo(JavaFeaturesProto.JavaFeatures.Utf8Validation.DEFAULT); 1404 } 1405 1406 @Test testProto3Defaults()1407 public void testProto3Defaults() throws Exception { 1408 FileDescriptor proto3File = 1409 FileDescriptor.buildFrom( 1410 FileDescriptorProto.newBuilder() 1411 .setName("some/filename/some.proto") 1412 .setPackage("proto3_unittest") 1413 .setSyntax("proto3") 1414 .build(), 1415 new FileDescriptor[0]); 1416 DescriptorProtos.FeatureSet features = proto3File.features; 1417 assertThat(features.getFieldPresence()) 1418 .isEqualTo(DescriptorProtos.FeatureSet.FieldPresence.IMPLICIT); 1419 assertThat(features.getEnumType()).isEqualTo(DescriptorProtos.FeatureSet.EnumType.OPEN); 1420 assertThat(features.getRepeatedFieldEncoding()) 1421 .isEqualTo(DescriptorProtos.FeatureSet.RepeatedFieldEncoding.PACKED); 1422 assertThat(features.getUtf8Validation()) 1423 .isEqualTo(DescriptorProtos.FeatureSet.Utf8Validation.VERIFY); 1424 assertThat(features.getMessageEncoding()) 1425 .isEqualTo(DescriptorProtos.FeatureSet.MessageEncoding.LENGTH_PREFIXED); 1426 1427 assertThat(features.getExtension(JavaFeaturesProto.java_).getLegacyClosedEnum()).isFalse(); 1428 assertThat(features.getExtension(JavaFeaturesProto.java_).getUtf8Validation()) 1429 .isEqualTo(JavaFeaturesProto.JavaFeatures.Utf8Validation.DEFAULT); 1430 } 1431 1432 @Test testProto3ExtensionPresence()1433 public void testProto3ExtensionPresence() { 1434 FileDescriptorProto.Builder file = FileDescriptorProto.newBuilder(); 1435 1436 assertThat(file.getOptions().hasExtension(Proto3FileExtensions.singularInt)).isFalse(); 1437 assertThat(file.getOptions().getExtension(Proto3FileExtensions.singularInt)).isEqualTo(0); 1438 1439 file.getOptionsBuilder().setExtension(Proto3FileExtensions.singularInt, 1); 1440 1441 assertThat(file.getOptions().hasExtension(Proto3FileExtensions.singularInt)).isTrue(); 1442 assertThat(file.getOptions().getExtension(Proto3FileExtensions.singularInt)).isEqualTo(1); 1443 } 1444 1445 @Test testProto3ExtensionHasPresence()1446 public void testProto3ExtensionHasPresence() { 1447 assertThat(Proto3FileExtensions.singularInt.getDescriptor().hasPresence()).isTrue(); 1448 assertThat(Proto3FileExtensions.repeatedInt.getDescriptor().hasPresence()).isFalse(); 1449 } 1450 } 1451 1452 public static class FeatureInheritanceTest { 1453 FileDescriptorProto.Builder fileProto; 1454 FieldDescriptorProto.Builder topExtensionProto; 1455 EnumDescriptorProto.Builder topEnumProto; 1456 EnumValueDescriptorProto.Builder enumValueProto; 1457 DescriptorProto.Builder topMessageProto; 1458 FieldDescriptorProto.Builder fieldProto; 1459 FieldDescriptorProto.Builder nestedExtensionProto; 1460 DescriptorProto.Builder nestedMessageProto; 1461 EnumDescriptorProto.Builder nestedEnumProto; 1462 OneofDescriptorProto.Builder oneofProto; 1463 FieldDescriptorProto.Builder oneofFieldProto; 1464 ServiceDescriptorProto.Builder serviceProto; 1465 MethodDescriptorProto.Builder methodProto; 1466 1467 @Before setUp()1468 public void setUp() { 1469 FeatureSetDefaults.Builder defaults = Descriptors.getJavaEditionDefaults().toBuilder(); 1470 for (FeatureSetEditionDefault.Builder editionDefaults : defaults.getDefaultsBuilderList()) { 1471 setTestFeature(editionDefaults.getOverridableFeaturesBuilder(), 1); 1472 } 1473 Descriptors.setTestJavaEditionDefaults(defaults.build()); 1474 1475 this.fileProto = 1476 DescriptorProtos.FileDescriptorProto.newBuilder() 1477 .setName("some/filename/some.proto") 1478 .setPackage("protobuf_unittest") 1479 .setEdition(DescriptorProtos.Edition.EDITION_2023) 1480 .setSyntax("editions"); 1481 1482 this.topExtensionProto = 1483 this.fileProto 1484 .addExtensionBuilder() 1485 .setName("top_extension") 1486 .setNumber(10) 1487 .setType(FieldDescriptorProto.Type.TYPE_INT32) 1488 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 1489 .setExtendee(".protobuf_unittest.TopMessage"); 1490 1491 this.topEnumProto = this.fileProto.addEnumTypeBuilder().setName("TopEnum"); 1492 this.enumValueProto = this.topEnumProto.addValueBuilder().setName("TOP_VALUE").setNumber(0); 1493 1494 this.topMessageProto = 1495 this.fileProto 1496 .addMessageTypeBuilder() 1497 .setName("TopMessage") 1498 .addExtensionRange(ExtensionRange.newBuilder().setStart(10).setEnd(20).build()); 1499 1500 this.fieldProto = 1501 this.topMessageProto 1502 .addFieldBuilder() 1503 .setName("field") 1504 .setNumber(1) 1505 .setType(FieldDescriptorProto.Type.TYPE_INT32) 1506 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL); 1507 this.nestedExtensionProto = 1508 this.topMessageProto 1509 .addExtensionBuilder() 1510 .setName("nested_extension") 1511 .setNumber(11) 1512 .setType(FieldDescriptorProto.Type.TYPE_INT32) 1513 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 1514 .setExtendee(".protobuf_unittest.TopMessage"); 1515 this.nestedMessageProto = 1516 this.topMessageProto.addNestedTypeBuilder().setName("NestedMessage"); 1517 this.nestedEnumProto = 1518 this.topMessageProto 1519 .addEnumTypeBuilder() 1520 .setName("NestedEnum") 1521 .addValue(EnumValueDescriptorProto.newBuilder().setName("NESTED_VALUE").setNumber(0)); 1522 this.oneofProto = this.topMessageProto.addOneofDeclBuilder().setName("Oneof"); 1523 this.oneofFieldProto = 1524 this.topMessageProto 1525 .addFieldBuilder() 1526 .setName("oneof_field") 1527 .setNumber(2) 1528 .setType(FieldDescriptorProto.Type.TYPE_INT32) 1529 .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) 1530 .setOneofIndex(0); 1531 this.serviceProto = this.fileProto.addServiceBuilder().setName("TestService"); 1532 this.methodProto = 1533 this.serviceProto 1534 .addMethodBuilder() 1535 .setName("CallMethod") 1536 .setInputType(".protobuf_unittest.TopMessage") 1537 .setOutputType(".protobuf_unittest.TopMessage"); 1538 } 1539 setTestFeature(DescriptorProtos.FeatureSet.Builder features, int value)1540 void setTestFeature(DescriptorProtos.FeatureSet.Builder features, int value) { 1541 features.setExtension( 1542 UnittestFeatures.test, 1543 features.getExtension(UnittestFeatures.test).toBuilder() 1544 .setMultipleFeature(UnittestFeatures.EnumFeature.forNumber(value)) 1545 .build()); 1546 } 1547 getTestFeature(DescriptorProtos.FeatureSet features)1548 int getTestFeature(DescriptorProtos.FeatureSet features) { 1549 return features.getExtension(UnittestFeatures.test).getMultipleFeature().getNumber(); 1550 } 1551 buildFrom(FileDescriptorProto fileProto)1552 FileDescriptor buildFrom(FileDescriptorProto fileProto) throws Exception { 1553 return FileDescriptor.buildFrom(fileProto, new FileDescriptor[0]); 1554 } 1555 1556 @Test testFileDefaults()1557 public void testFileDefaults() throws Exception { 1558 FileDescriptor descriptor = buildFrom(fileProto.build()); 1559 assertThat(getTestFeature(descriptor.features)).isEqualTo(1); 1560 } 1561 1562 @Test testFileOverrides()1563 public void testFileOverrides() throws Exception { 1564 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1565 FileDescriptor descriptor = buildFrom(fileProto.build()); 1566 assertThat(getTestFeature(descriptor.features)).isEqualTo(3); 1567 } 1568 1569 @Test testFileMessageInherit()1570 public void testFileMessageInherit() throws Exception { 1571 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1572 FileDescriptor descriptor = buildFrom(fileProto.build()); 1573 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).features)).isEqualTo(3); 1574 } 1575 1576 @Test testFileMessageOverride()1577 public void testFileMessageOverride() throws Exception { 1578 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1579 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1580 FileDescriptor descriptor = buildFrom(fileProto.build()); 1581 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).features)).isEqualTo(5); 1582 } 1583 1584 @Test testFileEnumInherit()1585 public void testFileEnumInherit() throws Exception { 1586 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1587 FileDescriptor descriptor = buildFrom(fileProto.build()); 1588 assertThat(getTestFeature(descriptor.getEnumTypes().get(0).features)).isEqualTo(3); 1589 } 1590 1591 @Test testFileEnumOverride()1592 public void testFileEnumOverride() throws Exception { 1593 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1594 setTestFeature(topEnumProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1595 FileDescriptor descriptor = buildFrom(fileProto.build()); 1596 assertThat(getTestFeature(descriptor.getEnumTypes().get(0).features)).isEqualTo(5); 1597 } 1598 1599 @Test testFileExtensionInherit()1600 public void testFileExtensionInherit() throws Exception { 1601 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1602 FileDescriptor descriptor = buildFrom(fileProto.build()); 1603 assertThat(getTestFeature(descriptor.getExtensions().get(0).features)).isEqualTo(3); 1604 } 1605 1606 @Test testFileExtensionOverride()1607 public void testFileExtensionOverride() throws Exception { 1608 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1609 setTestFeature(topExtensionProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1610 FileDescriptor descriptor = buildFrom(fileProto.build()); 1611 assertThat(getTestFeature(descriptor.getExtensions().get(0).features)).isEqualTo(5); 1612 } 1613 1614 @Test testFileServiceInherit()1615 public void testFileServiceInherit() throws Exception { 1616 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1617 FileDescriptor descriptor = buildFrom(fileProto.build()); 1618 assertThat(getTestFeature(descriptor.getServices().get(0).features)).isEqualTo(3); 1619 } 1620 1621 @Test testFileServiceOverride()1622 public void testFileServiceOverride() throws Exception { 1623 setTestFeature(fileProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1624 setTestFeature(serviceProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1625 FileDescriptor descriptor = buildFrom(fileProto.build()); 1626 assertThat(getTestFeature(descriptor.getServices().get(0).features)).isEqualTo(5); 1627 } 1628 1629 @Test testMessageFieldInherit()1630 public void testMessageFieldInherit() throws Exception { 1631 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1632 FileDescriptor descriptor = buildFrom(fileProto.build()); 1633 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).getFields().get(0).features)) 1634 .isEqualTo(3); 1635 } 1636 1637 @Test testMessageFieldOverride()1638 public void testMessageFieldOverride() throws Exception { 1639 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1640 setTestFeature(fieldProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1641 FileDescriptor descriptor = buildFrom(fileProto.build()); 1642 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).getFields().get(0).features)) 1643 .isEqualTo(5); 1644 } 1645 1646 @Test testMessageEnumInherit()1647 public void testMessageEnumInherit() throws Exception { 1648 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1649 FileDescriptor descriptor = buildFrom(fileProto.build()); 1650 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).getEnumTypes().get(0).features)) 1651 .isEqualTo(3); 1652 } 1653 1654 @Test testMessageEnumOverride()1655 public void testMessageEnumOverride() throws Exception { 1656 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1657 setTestFeature(nestedEnumProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1658 FileDescriptor descriptor = buildFrom(fileProto.build()); 1659 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).getEnumTypes().get(0).features)) 1660 .isEqualTo(5); 1661 } 1662 1663 @Test testMessageMessageInherit()1664 public void testMessageMessageInherit() throws Exception { 1665 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1666 FileDescriptor descriptor = buildFrom(fileProto.build()); 1667 assertThat( 1668 getTestFeature(descriptor.getMessageTypes().get(0).getNestedTypes().get(0).features)) 1669 .isEqualTo(3); 1670 } 1671 1672 @Test testMessageMessageOverride()1673 public void testMessageMessageOverride() throws Exception { 1674 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1675 setTestFeature(nestedMessageProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1676 FileDescriptor descriptor = buildFrom(fileProto.build()); 1677 assertThat( 1678 getTestFeature(descriptor.getMessageTypes().get(0).getNestedTypes().get(0).features)) 1679 .isEqualTo(5); 1680 } 1681 1682 @Test testMessageExtensionInherit()1683 public void testMessageExtensionInherit() throws Exception { 1684 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1685 FileDescriptor descriptor = buildFrom(fileProto.build()); 1686 assertThat( 1687 getTestFeature(descriptor.getMessageTypes().get(0).getExtensions().get(0).features)) 1688 .isEqualTo(3); 1689 } 1690 1691 @Test testMessageExtensionOverride()1692 public void testMessageExtensionOverride() throws Exception { 1693 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1694 setTestFeature(nestedExtensionProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1695 FileDescriptor descriptor = buildFrom(fileProto.build()); 1696 assertThat( 1697 getTestFeature(descriptor.getMessageTypes().get(0).getExtensions().get(0).features)) 1698 .isEqualTo(5); 1699 } 1700 1701 @Test testMessageOneofInherit()1702 public void testMessageOneofInherit() throws Exception { 1703 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1704 FileDescriptor descriptor = buildFrom(fileProto.build()); 1705 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).getOneofs().get(0).features)) 1706 .isEqualTo(3); 1707 } 1708 1709 @Test testMessageOneofOverride()1710 public void testMessageOneofOverride() throws Exception { 1711 setTestFeature(topMessageProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1712 setTestFeature(oneofProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1713 FileDescriptor descriptor = buildFrom(fileProto.build()); 1714 assertThat(getTestFeature(descriptor.getMessageTypes().get(0).getOneofs().get(0).features)) 1715 .isEqualTo(5); 1716 } 1717 1718 @Test testOneofFieldInherit()1719 public void testOneofFieldInherit() throws Exception { 1720 setTestFeature(oneofProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1721 FileDescriptor descriptor = buildFrom(fileProto.build()); 1722 assertThat( 1723 getTestFeature( 1724 descriptor 1725 .getMessageTypes() 1726 .get(0) 1727 .getOneofs() 1728 .get(0) 1729 .getFields() 1730 .get(0) 1731 .features)) 1732 .isEqualTo(3); 1733 } 1734 1735 @Test testOneofFieldOverride()1736 public void testOneofFieldOverride() throws Exception { 1737 setTestFeature(oneofProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1738 setTestFeature(oneofFieldProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1739 FileDescriptor descriptor = buildFrom(fileProto.build()); 1740 assertThat( 1741 getTestFeature( 1742 descriptor 1743 .getMessageTypes() 1744 .get(0) 1745 .getOneofs() 1746 .get(0) 1747 .getFields() 1748 .get(0) 1749 .features)) 1750 .isEqualTo(5); 1751 } 1752 1753 @Test testEnumValueInherit()1754 public void testEnumValueInherit() throws Exception { 1755 setTestFeature(topEnumProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1756 FileDescriptor descriptor = buildFrom(fileProto.build()); 1757 assertThat(getTestFeature(descriptor.getEnumTypes().get(0).getValues().get(0).features)) 1758 .isEqualTo(3); 1759 } 1760 1761 @Test testEnumValueOverride()1762 public void testEnumValueOverride() throws Exception { 1763 setTestFeature(topEnumProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1764 setTestFeature(enumValueProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1765 FileDescriptor descriptor = buildFrom(fileProto.build()); 1766 assertThat(getTestFeature(descriptor.getEnumTypes().get(0).getValues().get(0).features)) 1767 .isEqualTo(5); 1768 } 1769 1770 @Test testServiceMethodInherit()1771 public void testServiceMethodInherit() throws Exception { 1772 setTestFeature(serviceProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1773 FileDescriptor descriptor = buildFrom(fileProto.build()); 1774 assertThat(getTestFeature(descriptor.getServices().get(0).getMethods().get(0).features)) 1775 .isEqualTo(3); 1776 } 1777 1778 @Test testServiceMethodOverride()1779 public void testServiceMethodOverride() throws Exception { 1780 setTestFeature(serviceProto.getOptionsBuilder().getFeaturesBuilder(), 3); 1781 setTestFeature(methodProto.getOptionsBuilder().getFeaturesBuilder(), 5); 1782 FileDescriptor descriptor = buildFrom(fileProto.build()); 1783 assertThat(getTestFeature(descriptor.getServices().get(0).getMethods().get(0).features)) 1784 .isEqualTo(5); 1785 } 1786 } 1787 } 1788