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"""Unittest for google.protobuf.internal.descriptor.""" 9 10__author__ = 'robinson@google.com (Will Robinson)' 11 12import unittest 13import warnings 14 15from google.protobuf import descriptor 16from google.protobuf import descriptor_pb2 17from google.protobuf import descriptor_pool 18from google.protobuf import symbol_database 19from google.protobuf import text_format 20from google.protobuf.internal import api_implementation 21from google.protobuf.internal import test_proto2_pb2 22from google.protobuf.internal import test_util 23from google.protobuf.internal import testing_refleaks 24 25from google.protobuf.internal import _parameterized 26from google.protobuf import unittest_custom_options_pb2 27from google.protobuf import unittest_features_pb2 28from google.protobuf import unittest_import_pb2 29from google.protobuf import unittest_legacy_features_pb2 30from google.protobuf import unittest_pb2 31from google.protobuf import unittest_proto3_extensions_pb2 32from google.protobuf import unittest_proto3_pb2 33 34 35TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """ 36name: 'TestEmptyMessage' 37""" 38 39TEST_FILE_DESCRIPTOR_DEBUG = """syntax = "proto2"; 40 41package protobuf_unittest; 42 43message NestedMessage { 44 enum ForeignEnum { 45 FOREIGN_FOO = 4; 46 FOREIGN_BAR = 5; 47 FOREIGN_BAZ = 6; 48 FOREIGN_BAX = 32; 49 } 50 optional int32 bb = 1; 51} 52 53message ResponseMessage { 54} 55 56service DescriptorTestService { 57 rpc CallMethod(.protobuf_unittest.NestedMessage) returns (.protobuf_unittest.ResponseMessage); 58} 59 60""" 61 62 63warnings.simplefilter('error', DeprecationWarning) 64 65 66@testing_refleaks.TestCase 67class DescriptorTest(unittest.TestCase): 68 69 def setUp(self): 70 file_proto = descriptor_pb2.FileDescriptorProto( 71 name='some/filename/some.proto', 72 package='protobuf_unittest') 73 message_proto = file_proto.message_type.add( 74 name='NestedMessage') 75 message_proto.field.add( 76 name='bb', 77 number=1, 78 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 79 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) 80 enum_proto = message_proto.enum_type.add( 81 name='ForeignEnum') 82 enum_proto.value.add(name='FOREIGN_FOO', number=4) 83 enum_proto.value.add(name='FOREIGN_BAR', number=5) 84 enum_proto.value.add(name='FOREIGN_BAZ', number=6) 85 enum_proto.value.add(name='FOREIGN_BAX', number=32) 86 87 file_proto.message_type.add(name='ResponseMessage') 88 service_proto = file_proto.service.add(name='DescriptorTestService') 89 method_proto = service_proto.method.add( 90 name='CallMethod', 91 input_type='.protobuf_unittest.NestedMessage', 92 output_type='.protobuf_unittest.ResponseMessage') 93 94 # Note: Calling DescriptorPool.Add() multiple times with the same file only 95 # works if the input is canonical; in particular, all type names must be 96 # fully qualified. 97 self.pool = self.GetDescriptorPool() 98 self.pool.Add(file_proto) 99 self.my_file = self.pool.FindFileByName(file_proto.name) 100 self.my_message = self.my_file.message_types_by_name[message_proto.name] 101 self.my_enum = self.my_message.enum_types_by_name[enum_proto.name] 102 self.my_service = self.my_file.services_by_name[service_proto.name] 103 self.my_method = self.my_service.methods_by_name[method_proto.name] 104 105 def GetDescriptorPool(self): 106 return symbol_database.Default().pool 107 108 def testMissingPackage(self): 109 file_proto = descriptor_pb2.FileDescriptorProto( 110 name='some/filename/some.proto') 111 serialized = file_proto.SerializeToString() 112 pool = descriptor_pool.DescriptorPool() 113 file_descriptor = pool.AddSerializedFile(serialized) 114 self.assertEqual('', file_descriptor.package) 115 116 def testEmptyPackage(self): 117 file_proto = descriptor_pb2.FileDescriptorProto( 118 name='some/filename/some.proto', package='') 119 serialized = file_proto.SerializeToString() 120 pool = descriptor_pool.DescriptorPool() 121 file_descriptor = pool.AddSerializedFile(serialized) 122 self.assertEqual('', file_descriptor.package) 123 124 def testReservedName(self): 125 text = """ 126 name: "foo.proto" 127 message_type { 128 name: "BrokenMessageFoo" 129 reserved_name: "is_deprecated" 130 } 131 """ 132 133 fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto()) 134 serialized = fdp.SerializeToString() 135 # AddSerializedFile() will allow duplicate adds but only if the descriptors 136 # are identical and can round-trip through a FileDescriptor losslessly. 137 desc1 = descriptor_pool.Default().AddSerializedFile(serialized) 138 desc2 = descriptor_pool.Default().AddSerializedFile(serialized) 139 self.assertEqual(desc1, desc2) 140 141 def testReservedRange(self): 142 text = """ 143 name: "bar.proto" 144 message_type { 145 name: "BrokenMessageBar" 146 reserved_range { 147 start: 101 148 end: 102 149 } 150 } 151 """ 152 153 fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto()) 154 serialized = fdp.SerializeToString() 155 # AddSerializedFile() will allow duplicate adds but only if the descriptors 156 # are identical and can round-trip through a FileDescriptor losslessly. 157 desc1 = descriptor_pool.Default().AddSerializedFile(serialized) 158 desc2 = descriptor_pool.Default().AddSerializedFile(serialized) 159 self.assertEqual(desc1, desc2) 160 161 def testReservedNameEnum(self): 162 text = """ 163 name: "baz.proto" 164 enum_type { 165 name: "BrokenMessageBaz" 166 value: < 167 name: 'ENUM_BAZ' 168 number: 114 169 > 170 reserved_name: "is_deprecated" 171 } 172 """ 173 174 fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto()) 175 serialized = fdp.SerializeToString() 176 # AddSerializedFile() will allow duplicate adds but only if the descriptors 177 # are identical and can round-trip through a FileDescriptor losslessly. 178 desc1 = descriptor_pool.Default().AddSerializedFile(serialized) 179 desc2 = descriptor_pool.Default().AddSerializedFile(serialized) 180 self.assertEqual(desc1, desc2) 181 182 def testReservedRangeEnum(self): 183 text = """ 184 name: "bat.proto" 185 enum_type { 186 name: "BrokenMessageBat" 187 value: < 188 name: 'ENUM_BAT' 189 number: 115 190 > 191 reserved_range { 192 start: 1001 193 end: 1002 194 } 195 } 196 """ 197 198 fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto()) 199 serialized = fdp.SerializeToString() 200 # AddSerializedFile() will allow duplicate adds but only if the descriptors 201 # are identical and can round-trip through a FileDescriptor losslessly. 202 desc1 = descriptor_pool.Default().AddSerializedFile(serialized) 203 desc2 = descriptor_pool.Default().AddSerializedFile(serialized) 204 self.assertEqual(desc1, desc2) 205 206 def testFindMethodByName(self): 207 service_descriptor = (unittest_custom_options_pb2. 208 TestServiceWithCustomOptions.DESCRIPTOR) 209 method_descriptor = service_descriptor.FindMethodByName('Foo') 210 self.assertEqual(method_descriptor.name, 'Foo') 211 with self.assertRaises(KeyError): 212 service_descriptor.FindMethodByName('MethodDoesNotExist') 213 214 def testEnumValueName(self): 215 self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), 216 'FOREIGN_FOO') 217 218 self.assertEqual( 219 self.my_message.enum_types_by_name[ 220 'ForeignEnum'].values_by_number[4].name, 221 self.my_message.EnumValueName('ForeignEnum', 4)) 222 with self.assertRaises(KeyError): 223 self.my_message.EnumValueName('ForeignEnum', 999) 224 with self.assertRaises(KeyError): 225 self.my_message.EnumValueName('NoneEnum', 999) 226 with self.assertRaises(TypeError): 227 self.my_message.EnumValueName() 228 229 def testEnumFixups(self): 230 self.assertEqual(self.my_enum, self.my_enum.values[0].type) 231 232 def testContainingTypeFixups(self): 233 self.assertEqual(self.my_message, self.my_message.fields[0].containing_type) 234 self.assertEqual(self.my_message, self.my_enum.containing_type) 235 236 def testContainingServiceFixups(self): 237 self.assertEqual(self.my_service, self.my_method.containing_service) 238 239 @unittest.skipIf( 240 api_implementation.Type() == 'python', 241 'GetDebugString is only available with the cpp implementation', 242 ) 243 def testGetDebugString(self): 244 self.assertEqual(self.my_file.GetDebugString(), TEST_FILE_DESCRIPTOR_DEBUG) 245 246 def testGetOptions(self): 247 self.assertEqual(self.my_enum.GetOptions(), 248 descriptor_pb2.EnumOptions()) 249 self.assertEqual(self.my_enum.values[0].GetOptions(), 250 descriptor_pb2.EnumValueOptions()) 251 self.assertEqual(self.my_message.GetOptions(), 252 descriptor_pb2.MessageOptions()) 253 self.assertEqual(self.my_message.fields[0].GetOptions(), 254 descriptor_pb2.FieldOptions()) 255 self.assertEqual(self.my_method.GetOptions(), 256 descriptor_pb2.MethodOptions()) 257 self.assertEqual(self.my_service.GetOptions(), 258 descriptor_pb2.ServiceOptions()) 259 260 def testSimpleCustomOptions(self): 261 file_descriptor = unittest_custom_options_pb2.DESCRIPTOR 262 message_descriptor = (unittest_custom_options_pb2. 263 TestMessageWithCustomOptions.DESCRIPTOR) 264 field_descriptor = message_descriptor.fields_by_name['field1'] 265 oneof_descriptor = message_descriptor.oneofs_by_name['AnOneof'] 266 enum_descriptor = message_descriptor.enum_types_by_name['AnEnum'] 267 enum_value_descriptor = (message_descriptor. 268 enum_values_by_name['ANENUM_VAL2']) 269 other_enum_value_descriptor = (message_descriptor. 270 enum_values_by_name['ANENUM_VAL1']) 271 service_descriptor = (unittest_custom_options_pb2. 272 TestServiceWithCustomOptions.DESCRIPTOR) 273 method_descriptor = service_descriptor.FindMethodByName('Foo') 274 275 file_options = file_descriptor.GetOptions() 276 file_opt1 = unittest_custom_options_pb2.file_opt1 277 self.assertEqual(9876543210, file_options.Extensions[file_opt1]) 278 message_options = message_descriptor.GetOptions() 279 message_opt1 = unittest_custom_options_pb2.message_opt1 280 self.assertEqual(-56, message_options.Extensions[message_opt1]) 281 field_options = field_descriptor.GetOptions() 282 field_opt1 = unittest_custom_options_pb2.field_opt1 283 self.assertEqual(8765432109, field_options.Extensions[field_opt1]) 284 field_opt2 = unittest_custom_options_pb2.field_opt2 285 self.assertEqual(42, field_options.Extensions[field_opt2]) 286 oneof_options = oneof_descriptor.GetOptions() 287 oneof_opt1 = unittest_custom_options_pb2.oneof_opt1 288 self.assertEqual(-99, oneof_options.Extensions[oneof_opt1]) 289 enum_options = enum_descriptor.GetOptions() 290 enum_opt1 = unittest_custom_options_pb2.enum_opt1 291 self.assertEqual(-789, enum_options.Extensions[enum_opt1]) 292 enum_value_options = enum_value_descriptor.GetOptions() 293 enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1 294 self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1]) 295 296 service_options = service_descriptor.GetOptions() 297 service_opt1 = unittest_custom_options_pb2.service_opt1 298 self.assertEqual(-9876543210, service_options.Extensions[service_opt1]) 299 method_options = method_descriptor.GetOptions() 300 method_opt1 = unittest_custom_options_pb2.method_opt1 301 self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, 302 method_options.Extensions[method_opt1]) 303 304 message_descriptor = ( 305 unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR) 306 self.assertTrue(file_descriptor.has_options) 307 self.assertFalse(message_descriptor.has_options) 308 self.assertTrue(field_descriptor.has_options) 309 self.assertTrue(oneof_descriptor.has_options) 310 self.assertTrue(enum_descriptor.has_options) 311 self.assertTrue(enum_value_descriptor.has_options) 312 self.assertFalse(other_enum_value_descriptor.has_options) 313 314 def testCustomOptionsCopyTo(self): 315 message_descriptor = (unittest_custom_options_pb2. 316 TestMessageWithCustomOptions.DESCRIPTOR) 317 message_proto = descriptor_pb2.DescriptorProto() 318 message_descriptor.CopyToProto(message_proto) 319 self.assertEqual(len(message_proto.options.ListFields()), 320 2) 321 322 def testDifferentCustomOptionTypes(self): 323 kint32min = -2**31 324 kint64min = -2**63 325 kint32max = 2**31 - 1 326 kint64max = 2**63 - 1 327 kuint32max = 2**32 - 1 328 kuint64max = 2**64 - 1 329 330 message_descriptor =\ 331 unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR 332 message_options = message_descriptor.GetOptions() 333 self.assertEqual(False, message_options.Extensions[ 334 unittest_custom_options_pb2.bool_opt]) 335 self.assertEqual(kint32min, message_options.Extensions[ 336 unittest_custom_options_pb2.int32_opt]) 337 self.assertEqual(kint64min, message_options.Extensions[ 338 unittest_custom_options_pb2.int64_opt]) 339 self.assertEqual(0, message_options.Extensions[ 340 unittest_custom_options_pb2.uint32_opt]) 341 self.assertEqual(0, message_options.Extensions[ 342 unittest_custom_options_pb2.uint64_opt]) 343 self.assertEqual(kint32min, message_options.Extensions[ 344 unittest_custom_options_pb2.sint32_opt]) 345 self.assertEqual(kint64min, message_options.Extensions[ 346 unittest_custom_options_pb2.sint64_opt]) 347 self.assertEqual(0, message_options.Extensions[ 348 unittest_custom_options_pb2.fixed32_opt]) 349 self.assertEqual(0, message_options.Extensions[ 350 unittest_custom_options_pb2.fixed64_opt]) 351 self.assertEqual(kint32min, message_options.Extensions[ 352 unittest_custom_options_pb2.sfixed32_opt]) 353 self.assertEqual(kint64min, message_options.Extensions[ 354 unittest_custom_options_pb2.sfixed64_opt]) 355 356 message_descriptor =\ 357 unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR 358 message_options = message_descriptor.GetOptions() 359 self.assertEqual(True, message_options.Extensions[ 360 unittest_custom_options_pb2.bool_opt]) 361 self.assertEqual(kint32max, message_options.Extensions[ 362 unittest_custom_options_pb2.int32_opt]) 363 self.assertEqual(kint64max, message_options.Extensions[ 364 unittest_custom_options_pb2.int64_opt]) 365 self.assertEqual(kuint32max, message_options.Extensions[ 366 unittest_custom_options_pb2.uint32_opt]) 367 self.assertEqual(kuint64max, message_options.Extensions[ 368 unittest_custom_options_pb2.uint64_opt]) 369 self.assertEqual(kint32max, message_options.Extensions[ 370 unittest_custom_options_pb2.sint32_opt]) 371 self.assertEqual(kint64max, message_options.Extensions[ 372 unittest_custom_options_pb2.sint64_opt]) 373 self.assertEqual(kuint32max, message_options.Extensions[ 374 unittest_custom_options_pb2.fixed32_opt]) 375 self.assertEqual(kuint64max, message_options.Extensions[ 376 unittest_custom_options_pb2.fixed64_opt]) 377 self.assertEqual(kint32max, message_options.Extensions[ 378 unittest_custom_options_pb2.sfixed32_opt]) 379 self.assertEqual(kint64max, message_options.Extensions[ 380 unittest_custom_options_pb2.sfixed64_opt]) 381 382 message_descriptor =\ 383 unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR 384 message_options = message_descriptor.GetOptions() 385 self.assertEqual(-100, message_options.Extensions[ 386 unittest_custom_options_pb2.int32_opt]) 387 self.assertAlmostEqual(12.3456789, message_options.Extensions[ 388 unittest_custom_options_pb2.float_opt], 6) 389 self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[ 390 unittest_custom_options_pb2.double_opt]) 391 self.assertEqual("Hello, \"World\"", message_options.Extensions[ 392 unittest_custom_options_pb2.string_opt]) 393 self.assertEqual(b"Hello\0World", message_options.Extensions[ 394 unittest_custom_options_pb2.bytes_opt]) 395 dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum 396 self.assertEqual( 397 dummy_enum.TEST_OPTION_ENUM_TYPE2, 398 message_options.Extensions[unittest_custom_options_pb2.enum_opt]) 399 400 message_descriptor =\ 401 unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR 402 message_options = message_descriptor.GetOptions() 403 self.assertAlmostEqual(12, message_options.Extensions[ 404 unittest_custom_options_pb2.float_opt], 6) 405 self.assertAlmostEqual(154, message_options.Extensions[ 406 unittest_custom_options_pb2.double_opt]) 407 408 message_descriptor =\ 409 unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR 410 message_options = message_descriptor.GetOptions() 411 self.assertAlmostEqual(-12, message_options.Extensions[ 412 unittest_custom_options_pb2.float_opt], 6) 413 self.assertAlmostEqual(-154, message_options.Extensions[ 414 unittest_custom_options_pb2.double_opt]) 415 416 def testComplexExtensionOptions(self): 417 descriptor =\ 418 unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR 419 options = descriptor.GetOptions() 420 self.assertEqual(42, options.Extensions[ 421 unittest_custom_options_pb2.complex_opt1].foo) 422 self.assertEqual(324, options.Extensions[ 423 unittest_custom_options_pb2.complex_opt1].Extensions[ 424 unittest_custom_options_pb2.mooo]) 425 self.assertEqual(876, options.Extensions[ 426 unittest_custom_options_pb2.complex_opt1].Extensions[ 427 unittest_custom_options_pb2.corge].moo) 428 self.assertEqual(987, options.Extensions[ 429 unittest_custom_options_pb2.complex_opt2].baz) 430 self.assertEqual(654, options.Extensions[ 431 unittest_custom_options_pb2.complex_opt2].Extensions[ 432 unittest_custom_options_pb2.grault]) 433 self.assertEqual(743, options.Extensions[ 434 unittest_custom_options_pb2.complex_opt2].bar.foo) 435 self.assertEqual(1999, options.Extensions[ 436 unittest_custom_options_pb2.complex_opt2].bar.Extensions[ 437 unittest_custom_options_pb2.mooo]) 438 self.assertEqual(2008, options.Extensions[ 439 unittest_custom_options_pb2.complex_opt2].bar.Extensions[ 440 unittest_custom_options_pb2.corge].moo) 441 self.assertEqual(741, options.Extensions[ 442 unittest_custom_options_pb2.complex_opt2].Extensions[ 443 unittest_custom_options_pb2.garply].foo) 444 self.assertEqual(1998, options.Extensions[ 445 unittest_custom_options_pb2.complex_opt2].Extensions[ 446 unittest_custom_options_pb2.garply].Extensions[ 447 unittest_custom_options_pb2.mooo]) 448 self.assertEqual(2121, options.Extensions[ 449 unittest_custom_options_pb2.complex_opt2].Extensions[ 450 unittest_custom_options_pb2.garply].Extensions[ 451 unittest_custom_options_pb2.corge].moo) 452 self.assertEqual(1971, options.Extensions[ 453 unittest_custom_options_pb2.ComplexOptionType2 454 .ComplexOptionType4.complex_opt4].waldo) 455 self.assertEqual(321, options.Extensions[ 456 unittest_custom_options_pb2.complex_opt2].fred.waldo) 457 self.assertEqual(9, options.Extensions[ 458 unittest_custom_options_pb2.complex_opt3].moo) 459 self.assertEqual(22, options.Extensions[ 460 unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh) 461 self.assertEqual(24, options.Extensions[ 462 unittest_custom_options_pb2.complexopt6].xyzzy) 463 464 # Check that aggregate options were parsed and saved correctly in 465 # the appropriate descriptors. 466 def testAggregateOptions(self): 467 file_descriptor = unittest_custom_options_pb2.DESCRIPTOR 468 message_descriptor =\ 469 unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR 470 field_descriptor = message_descriptor.fields_by_name["fieldname"] 471 enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR 472 enum_value_descriptor = enum_descriptor.values_by_name["VALUE"] 473 service_descriptor =\ 474 unittest_custom_options_pb2.AggregateService.DESCRIPTOR 475 method_descriptor = service_descriptor.FindMethodByName("Method") 476 477 # Tests for the different types of data embedded in fileopt 478 file_options = file_descriptor.GetOptions().Extensions[ 479 unittest_custom_options_pb2.fileopt] 480 self.assertEqual(100, file_options.i) 481 self.assertEqual("FileAnnotation", file_options.s) 482 self.assertEqual("NestedFileAnnotation", file_options.sub.s) 483 self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[ 484 unittest_custom_options_pb2.fileopt].s) 485 self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[ 486 unittest_custom_options_pb2.AggregateMessageSetElement 487 .message_set_extension].s) 488 489 # Simple tests for all the other types of annotations 490 self.assertEqual( 491 "MessageAnnotation", 492 message_descriptor.GetOptions().Extensions[ 493 unittest_custom_options_pb2.msgopt].s) 494 self.assertEqual( 495 "FieldAnnotation", 496 field_descriptor.GetOptions().Extensions[ 497 unittest_custom_options_pb2.fieldopt].s) 498 self.assertEqual( 499 "EnumAnnotation", 500 enum_descriptor.GetOptions().Extensions[ 501 unittest_custom_options_pb2.enumopt].s) 502 self.assertEqual( 503 "EnumValueAnnotation", 504 enum_value_descriptor.GetOptions().Extensions[ 505 unittest_custom_options_pb2.enumvalopt].s) 506 self.assertEqual( 507 "ServiceAnnotation", 508 service_descriptor.GetOptions().Extensions[ 509 unittest_custom_options_pb2.serviceopt].s) 510 self.assertEqual( 511 "MethodAnnotation", 512 method_descriptor.GetOptions().Extensions[ 513 unittest_custom_options_pb2.methodopt].s) 514 515 def testNestedOptions(self): 516 nested_message =\ 517 unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR 518 self.assertEqual(1001, nested_message.GetOptions().Extensions[ 519 unittest_custom_options_pb2.message_opt1]) 520 nested_field = nested_message.fields_by_name["nested_field"] 521 self.assertEqual(1002, nested_field.GetOptions().Extensions[ 522 unittest_custom_options_pb2.field_opt1]) 523 outer_message =\ 524 unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR 525 nested_enum = outer_message.enum_types_by_name["NestedEnum"] 526 self.assertEqual(1003, nested_enum.GetOptions().Extensions[ 527 unittest_custom_options_pb2.enum_opt1]) 528 nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"] 529 self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[ 530 unittest_custom_options_pb2.enum_value_opt1]) 531 nested_extension = outer_message.extensions_by_name["nested_extension"] 532 self.assertEqual(1005, nested_extension.GetOptions().Extensions[ 533 unittest_custom_options_pb2.field_opt2]) 534 535 def testFileDescriptorReferences(self): 536 self.assertEqual(self.my_enum.file, self.my_file) 537 self.assertEqual(self.my_message.file, self.my_file) 538 539 def testFileDescriptor(self): 540 self.assertEqual(self.my_file.name, 'some/filename/some.proto') 541 self.assertEqual(self.my_file.package, 'protobuf_unittest') 542 self.assertEqual(self.my_file.pool, self.pool) 543 self.assertFalse(self.my_file.has_options) 544 file_proto = descriptor_pb2.FileDescriptorProto() 545 self.my_file.CopyToProto(file_proto) 546 self.assertEqual(self.my_file.serialized_pb, 547 file_proto.SerializeToString()) 548 # Generated modules also belong to the default pool. 549 self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default()) 550 551 @unittest.skipIf( 552 api_implementation.Type() == 'python', 553 'Immutability of descriptors is only enforced in v2 implementation') 554 def testImmutableCppDescriptor(self): 555 file_descriptor = unittest_pb2.DESCRIPTOR 556 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 557 field_descriptor = message_descriptor.fields_by_name['optional_int32'] 558 enum_descriptor = message_descriptor.enum_types_by_name['NestedEnum'] 559 oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] 560 with self.assertRaises(AttributeError): 561 message_descriptor.fields_by_name = None 562 with self.assertRaises(TypeError): 563 message_descriptor.fields_by_name['Another'] = None 564 with self.assertRaises(TypeError): 565 message_descriptor.fields.append(None) 566 with self.assertRaises(AttributeError): 567 field_descriptor.containing_type = message_descriptor 568 with self.assertRaises(AttributeError): 569 file_descriptor.has_options = False 570 with self.assertRaises(AttributeError): 571 field_descriptor.has_options = False 572 with self.assertRaises(AttributeError): 573 oneof_descriptor.has_options = False 574 with self.assertRaises(AttributeError): 575 enum_descriptor.has_options = False 576 with self.assertRaises(AttributeError) as e: 577 message_descriptor.has_options = True 578 self.assertEqual('attribute is not writable: has_options', 579 str(e.exception)) 580 581 def testDefault(self): 582 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 583 field = message_descriptor.fields_by_name['repeated_int32'] 584 self.assertEqual(field.default_value, []) 585 field = message_descriptor.fields_by_name['repeated_nested_message'] 586 self.assertEqual(field.default_value, []) 587 field = message_descriptor.fields_by_name['optionalgroup'] 588 self.assertEqual(field.default_value, None) 589 field = message_descriptor.fields_by_name['optional_nested_message'] 590 self.assertEqual(field.default_value, None) 591 592 593class NewDescriptorTest(DescriptorTest): 594 """Redo the same tests as above, but with a separate DescriptorPool.""" 595 596 def GetDescriptorPool(self): 597 return descriptor_pool.DescriptorPool() 598 599 600class GeneratedDescriptorTest(unittest.TestCase): 601 """Tests for the properties of descriptors in generated code.""" 602 603 def CheckMessageDescriptor(self, message_descriptor): 604 # Basic properties 605 self.assertEqual(message_descriptor.name, 'TestAllTypes') 606 self.assertEqual(message_descriptor.full_name, 607 'protobuf_unittest.TestAllTypes') 608 # Test equality and hashability 609 self.assertEqual(message_descriptor, message_descriptor) 610 self.assertEqual(message_descriptor.fields[0].containing_type, 611 message_descriptor) 612 self.assertIn(message_descriptor, [message_descriptor]) 613 self.assertIn(message_descriptor, {message_descriptor: None}) 614 # Test field containers 615 self.CheckDescriptorSequence(message_descriptor.fields) 616 self.CheckDescriptorMapping(message_descriptor.fields_by_name) 617 self.CheckDescriptorMapping(message_descriptor.fields_by_number) 618 self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name) 619 self.CheckDescriptorMapping(message_descriptor.enum_types_by_name) 620 self.CheckDescriptorMapping(message_descriptor.enum_values_by_name) 621 self.CheckDescriptorMapping(message_descriptor.oneofs_by_name) 622 self.CheckDescriptorMapping(message_descriptor.enum_types[0].values_by_name) 623 # Test extension range 624 self.assertEqual(message_descriptor.extension_ranges, []) 625 626 def CheckFieldDescriptor(self, field_descriptor): 627 # Basic properties 628 self.assertEqual(field_descriptor.name, 'optional_int32') 629 self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32') 630 self.assertEqual(field_descriptor.full_name, 631 'protobuf_unittest.TestAllTypes.optional_int32') 632 self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes') 633 self.assertEqual(field_descriptor.file, unittest_pb2.DESCRIPTOR) 634 # Test equality and hashability 635 self.assertEqual(field_descriptor, field_descriptor) 636 self.assertEqual( 637 field_descriptor.containing_type.fields_by_name['optional_int32'], 638 field_descriptor) 639 self.assertEqual( 640 field_descriptor.containing_type.fields_by_camelcase_name[ 641 'optionalInt32'], 642 field_descriptor) 643 self.assertIn(field_descriptor, [field_descriptor]) 644 self.assertIn(field_descriptor, {field_descriptor: None}) 645 self.assertEqual(None, field_descriptor.extension_scope) 646 self.assertEqual(None, field_descriptor.enum_type) 647 self.assertTrue(field_descriptor.has_presence) 648 if api_implementation.Type() == 'cpp': 649 # For test coverage only 650 self.assertEqual(field_descriptor.id, field_descriptor.id) 651 652 def CheckDescriptorSequence(self, sequence): 653 # Verifies that a property like 'messageDescriptor.fields' has all the 654 # properties of an immutable abc.Sequence. 655 self.assertNotEqual(sequence, 656 unittest_pb2.TestAllExtensions.DESCRIPTOR.fields) 657 self.assertNotEqual(sequence, []) 658 self.assertNotEqual(sequence, 1) 659 self.assertFalse(sequence == 1) # Only for cpp test coverage 660 self.assertEqual(sequence, sequence) 661 expected_list = list(sequence) 662 self.assertEqual(expected_list, sequence) 663 self.assertGreater(len(sequence), 0) # Sized 664 self.assertEqual(len(sequence), len(expected_list)) # Iterable 665 self.assertEqual(sequence[len(sequence) -1], sequence[-1]) 666 item = sequence[0] 667 self.assertEqual(item, sequence[0]) 668 self.assertIn(item, sequence) # Container 669 self.assertEqual(sequence.index(item), 0) 670 self.assertEqual(sequence.count(item), 1) 671 other_item = unittest_pb2.NestedTestAllTypes.DESCRIPTOR.fields[0] 672 self.assertNotIn(other_item, sequence) 673 self.assertEqual(sequence.count(other_item), 0) 674 self.assertRaises(ValueError, sequence.index, other_item) 675 self.assertRaises(ValueError, sequence.index, []) 676 reversed_iterator = reversed(sequence) 677 self.assertEqual(list(reversed_iterator), list(sequence)[::-1]) 678 self.assertRaises(StopIteration, next, reversed_iterator) 679 expected_list[0] = 'change value' 680 self.assertNotEqual(expected_list, sequence) 681 # TODO: Change __repr__ support for DescriptorSequence. 682 if api_implementation.Type() == 'python': 683 self.assertEqual(str(list(sequence)), str(sequence)) 684 else: 685 self.assertEqual(str(sequence)[0], '<') 686 687 def CheckDescriptorMapping(self, mapping): 688 # Verifies that a property like 'messageDescriptor.fields' has all the 689 # properties of an immutable abc.Mapping. 690 iterated_keys = [] 691 for key in mapping: 692 iterated_keys.append(key) 693 self.assertEqual(len(iterated_keys), len(mapping)) 694 self.assertEqual(set(iterated_keys), set(mapping.keys())) 695 696 self.assertNotEqual( 697 mapping, unittest_pb2.TestAllExtensions.DESCRIPTOR.fields_by_name) 698 self.assertNotEqual(mapping, {}) 699 self.assertNotEqual(mapping, 1) 700 self.assertFalse(mapping == 1) # Only for cpp test coverage 701 excepted_dict = dict(mapping.items()) 702 self.assertEqual(mapping, excepted_dict) 703 self.assertEqual(mapping, mapping) 704 self.assertGreater(len(mapping), 0) # Sized 705 self.assertEqual(len(mapping), len(excepted_dict)) # Iterable 706 key, item = next(iter(mapping.items())) 707 self.assertIn(key, mapping) # Container 708 self.assertEqual(mapping.get(key), item) 709 with self.assertRaises(TypeError): 710 mapping.get() 711 # TODO: Fix python and cpp extension diff. 712 if api_implementation.Type() == 'cpp': 713 self.assertEqual(None, mapping.get([])) 714 else: 715 self.assertRaises(TypeError, mapping.get, []) 716 with self.assertRaises(TypeError): 717 if [] in mapping: 718 pass 719 with self.assertRaises(TypeError): 720 _ = mapping[[]] 721 # keys(), iterkeys() &co 722 item = (next(iter(mapping.keys())), next(iter(mapping.values()))) 723 self.assertEqual(item, next(iter(mapping.items()))) 724 excepted_dict[key] = 'change value' 725 self.assertNotEqual(mapping, excepted_dict) 726 del excepted_dict[key] 727 excepted_dict['new_key'] = 'new' 728 self.assertNotEqual(mapping, excepted_dict) 729 self.assertRaises(KeyError, mapping.__getitem__, 'key_error') 730 self.assertRaises(KeyError, mapping.__getitem__, len(mapping) * 2) 731 # TODO: Add __repr__ support for DescriptorMapping. 732 if api_implementation.Type() == 'cpp': 733 self.assertEqual(str(mapping)[0], '<') 734 else: 735 print(str(dict(mapping.items()))[:100]) 736 print(str(mapping)[:100]) 737 self.assertEqual(len(str(dict(mapping.items()))), len(str(mapping))) 738 739 def testDescriptor(self): 740 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 741 self.CheckMessageDescriptor(message_descriptor) 742 field_descriptor = message_descriptor.fields_by_name['optional_int32'] 743 self.CheckFieldDescriptor(field_descriptor) 744 field_descriptor = message_descriptor.fields_by_camelcase_name[ 745 'optionalInt32'] 746 self.CheckFieldDescriptor(field_descriptor) 747 enum_descriptor = unittest_pb2.DESCRIPTOR.enum_types_by_name[ 748 'ForeignEnum'] 749 self.assertEqual(None, enum_descriptor.containing_type) 750 # Test extension range 751 self.assertEqual( 752 unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, 753 [(1, 536870912)]) 754 self.assertEqual( 755 unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, 756 [(42, 43), (4143, 4244), (65536, 536870912)]) 757 758 def testCppDescriptorContainer(self): 759 containing_file = unittest_pb2.DESCRIPTOR 760 self.CheckDescriptorSequence(containing_file.dependencies) 761 self.CheckDescriptorMapping(containing_file.message_types_by_name) 762 self.CheckDescriptorMapping(containing_file.enum_types_by_name) 763 self.CheckDescriptorMapping(containing_file.services_by_name) 764 self.CheckDescriptorMapping(containing_file.extensions_by_name) 765 self.CheckDescriptorMapping( 766 unittest_pb2.TestNestedExtension.DESCRIPTOR.extensions_by_name) 767 768 def testCppDescriptorContainer_Iterator(self): 769 # Same test with the iterator 770 enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] 771 values_iter = iter(enum.values) 772 del enum 773 self.assertEqual('FOO', next(values_iter).name) 774 775 def testDescriptorNestedTypesContainer(self): 776 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 777 nested_message_descriptor = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR 778 self.assertEqual(len(message_descriptor.nested_types), 3) 779 self.assertFalse(None in message_descriptor.nested_types) 780 self.assertTrue( 781 nested_message_descriptor in message_descriptor.nested_types) 782 783 def testServiceDescriptor(self): 784 service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService'] 785 self.assertEqual(service_descriptor.name, 'TestService') 786 self.assertEqual(service_descriptor.methods[0].name, 'Foo') 787 self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR) 788 self.assertEqual(service_descriptor.index, 0) 789 self.CheckDescriptorMapping(service_descriptor.methods_by_name) 790 791 def testOneofDescriptor(self): 792 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 793 oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] 794 self.assertFalse(oneof_descriptor.has_options) 795 self.assertEqual(message_descriptor, oneof_descriptor.containing_type) 796 self.assertEqual('oneof_field', oneof_descriptor.name) 797 self.assertEqual('protobuf_unittest.TestAllTypes.oneof_field', 798 oneof_descriptor.full_name) 799 self.assertEqual(0, oneof_descriptor.index) 800 801 def testDescriptorSlice(self): 802 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 803 nested = message_descriptor.nested_types[:] 804 self.assertEqual(message_descriptor.nested_types, nested) 805 fields = message_descriptor.fields 806 fields_list = list(fields) 807 self.assertEqual(fields_list[:], fields[:]) 808 self.assertEqual(fields_list[2::2], fields[2::2]) 809 self.assertEqual(fields_list[3:19:3], fields[3:19:3]) 810 811class DescriptorCopyToProtoTest(unittest.TestCase): 812 """Tests for CopyTo functions of Descriptor.""" 813 814 def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii): 815 expected_proto = expected_class() 816 text_format.Merge(expected_ascii, expected_proto) 817 818 self.assertEqual( 819 actual_proto, expected_proto, 820 'Not equal,\nActual:\n%s\nExpected:\n%s\n' 821 % (str(actual_proto), str(expected_proto))) 822 823 def _InternalTestCopyToProto(self, desc, expected_proto_class, 824 expected_proto_ascii): 825 actual = expected_proto_class() 826 desc.CopyToProto(actual) 827 self._AssertProtoEqual( 828 actual, expected_proto_class, expected_proto_ascii) 829 830 def testCopyToProto_EmptyMessage(self): 831 self._InternalTestCopyToProto( 832 unittest_pb2.TestEmptyMessage.DESCRIPTOR, 833 descriptor_pb2.DescriptorProto, 834 TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII) 835 836 def testCopyToProto_NestedMessage(self): 837 TEST_NESTED_MESSAGE_ASCII = """ 838 name: 'NestedMessage' 839 field: < 840 name: 'bb' 841 number: 1 842 label: 1 # Optional 843 type: 5 # TYPE_INT32 844 > 845 """ 846 847 self._InternalTestCopyToProto( 848 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, 849 descriptor_pb2.DescriptorProto, 850 TEST_NESTED_MESSAGE_ASCII) 851 852 def testCopyToProto_ForeignNestedMessage(self): 853 TEST_FOREIGN_NESTED_ASCII = """ 854 name: 'TestForeignNested' 855 field: < 856 name: 'foreign_nested' 857 number: 1 858 label: 1 # Optional 859 type: 11 # TYPE_MESSAGE 860 type_name: '.protobuf_unittest.TestAllTypes.NestedMessage' 861 > 862 """ 863 864 self._InternalTestCopyToProto( 865 unittest_pb2.TestForeignNested.DESCRIPTOR, 866 descriptor_pb2.DescriptorProto, 867 TEST_FOREIGN_NESTED_ASCII) 868 869 def testCopyToProto_ForeignEnum(self): 870 TEST_FOREIGN_ENUM_ASCII = """ 871 name: 'ForeignEnum' 872 value: < 873 name: 'FOREIGN_FOO' 874 number: 4 875 > 876 value: < 877 name: 'FOREIGN_BAR' 878 number: 5 879 > 880 value: < 881 name: 'FOREIGN_BAZ' 882 number: 6 883 > 884 value: < 885 name: 'FOREIGN_BAX' 886 number: 32 887 > 888 value: < 889 name: 'FOREIGN_LARGE' 890 number: 123456 891 > 892 """ 893 894 self._InternalTestCopyToProto( 895 unittest_pb2.ForeignEnum.DESCRIPTOR, 896 descriptor_pb2.EnumDescriptorProto, 897 TEST_FOREIGN_ENUM_ASCII) 898 899 def testCopyToProto_Options(self): 900 TEST_DEPRECATED_FIELDS_ASCII = """ 901 name: 'TestDeprecatedFields' 902 field: < 903 name: 'deprecated_int32' 904 number: 1 905 label: 1 # Optional 906 type: 5 # TYPE_INT32 907 options: < 908 deprecated: true 909 > 910 > 911 field: { 912 name: 'deprecated_repeated_string' 913 number: 4 914 label: LABEL_REPEATED 915 type: TYPE_STRING 916 options: { 917 deprecated: true 918 } 919 } 920 field { 921 name: "deprecated_message" 922 number: 3 923 label: LABEL_OPTIONAL 924 type: TYPE_MESSAGE 925 type_name: ".protobuf_unittest.TestAllTypes.NestedMessage" 926 options { 927 deprecated: true 928 } 929 } 930 field { 931 name: "deprecated_int32_in_oneof" 932 number: 2 933 label: LABEL_OPTIONAL 934 type: TYPE_INT32 935 options { 936 deprecated: true 937 } 938 oneof_index: 0 939 } 940 field { 941 name: "nested" 942 number: 5 943 label: LABEL_OPTIONAL 944 type: TYPE_MESSAGE 945 type_name: ".protobuf_unittest.TestDeprecatedFields" 946 } 947 oneof_decl { 948 name: "oneof_fields" 949 } 950 """ 951 952 self._InternalTestCopyToProto( 953 unittest_pb2.TestDeprecatedFields.DESCRIPTOR, 954 descriptor_pb2.DescriptorProto, 955 TEST_DEPRECATED_FIELDS_ASCII) 956 957 def testCopyToProto_AllExtensions(self): 958 TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """ 959 name: 'TestEmptyMessageWithExtensions' 960 extension_range: < 961 start: 1 962 end: 536870912 963 > 964 """ 965 966 self._InternalTestCopyToProto( 967 unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR, 968 descriptor_pb2.DescriptorProto, 969 TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII) 970 971 def testCopyToProto_SeveralExtensions(self): 972 TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """ 973 name: 'TestMultipleExtensionRanges' 974 extension_range: < 975 start: 42 976 end: 43 977 > 978 extension_range: < 979 start: 4143 980 end: 4244 981 > 982 extension_range: < 983 start: 65536 984 end: 536870912 985 > 986 """ 987 988 self._InternalTestCopyToProto( 989 unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR, 990 descriptor_pb2.DescriptorProto, 991 TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) 992 993 def testCopyToProto_FileDescriptor(self): 994 UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" 995 name: 'google/protobuf/unittest_import.proto' 996 package: 'protobuf_unittest_import' 997 dependency: 'google/protobuf/unittest_import_public.proto' 998 message_type: < 999 name: 'ImportMessage' 1000 field: < 1001 name: 'd' 1002 number: 1 1003 label: 1 # Optional 1004 type: 5 # TYPE_INT32 1005 > 1006 > 1007 """ + 1008 """enum_type: < 1009 name: 'ImportEnum' 1010 value: < 1011 name: 'IMPORT_FOO' 1012 number: 7 1013 > 1014 value: < 1015 name: 'IMPORT_BAR' 1016 number: 8 1017 > 1018 value: < 1019 name: 'IMPORT_BAZ' 1020 number: 9 1021 > 1022 > 1023 enum_type: < 1024 name: 'ImportEnumForMap' 1025 value: < 1026 name: 'UNKNOWN' 1027 number: 0 1028 > 1029 value: < 1030 name: 'FOO' 1031 number: 1 1032 > 1033 value: < 1034 name: 'BAR' 1035 number: 2 1036 > 1037 > 1038 options: < 1039 java_package: 'com.google.protobuf.test' 1040 optimize_for: 1 # SPEED 1041 """ + 1042 """ 1043 cc_enable_arenas: true 1044 > 1045 public_dependency: 0 1046 """) 1047 self._InternalTestCopyToProto( 1048 unittest_import_pb2.DESCRIPTOR, 1049 descriptor_pb2.FileDescriptorProto, 1050 UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) 1051 1052 def testCopyToProto_ServiceDescriptor(self): 1053 TEST_SERVICE_ASCII = """ 1054 name: 'TestService' 1055 method: < 1056 name: 'Foo' 1057 input_type: '.protobuf_unittest.FooRequest' 1058 output_type: '.protobuf_unittest.FooResponse' 1059 > 1060 method: < 1061 name: 'Bar' 1062 input_type: '.protobuf_unittest.BarRequest' 1063 output_type: '.protobuf_unittest.BarResponse' 1064 > 1065 """ 1066 self._InternalTestCopyToProto( 1067 unittest_pb2.TestService.DESCRIPTOR, 1068 descriptor_pb2.ServiceDescriptorProto, 1069 TEST_SERVICE_ASCII) 1070 1071 def testCopyToProto_MethodDescriptor(self): 1072 expected_ascii = """ 1073 name: 'Foo' 1074 input_type: '.protobuf_unittest.FooRequest' 1075 output_type: '.protobuf_unittest.FooResponse' 1076 """ 1077 method_descriptor = unittest_pb2.TestService.DESCRIPTOR.FindMethodByName( 1078 'Foo') 1079 self._InternalTestCopyToProto( 1080 method_descriptor, 1081 descriptor_pb2.MethodDescriptorProto, 1082 expected_ascii) 1083 1084 @unittest.skipIf( 1085 api_implementation.Type() == 'python', 1086 'Pure python does not raise error.') 1087 # TODO: Fix pure python to check with the proto type. 1088 def testCopyToProto_TypeError(self): 1089 file_proto = descriptor_pb2.FileDescriptorProto() 1090 self.assertRaises(TypeError, 1091 unittest_pb2.TestEmptyMessage.DESCRIPTOR.CopyToProto, 1092 file_proto) 1093 self.assertRaises(TypeError, 1094 unittest_pb2.ForeignEnum.DESCRIPTOR.CopyToProto, 1095 file_proto) 1096 self.assertRaises(TypeError, 1097 unittest_pb2.TestService.DESCRIPTOR.CopyToProto, 1098 file_proto) 1099 proto = descriptor_pb2.DescriptorProto() 1100 self.assertRaises(TypeError, 1101 unittest_import_pb2.DESCRIPTOR.CopyToProto, 1102 proto) 1103 1104 1105class MakeDescriptorTest(unittest.TestCase): 1106 1107 def testMakeDescriptorWithNestedFields(self): 1108 file_descriptor_proto = descriptor_pb2.FileDescriptorProto() 1109 file_descriptor_proto.name = 'Foo2' 1110 message_type = file_descriptor_proto.message_type.add() 1111 message_type.name = file_descriptor_proto.name 1112 nested_type = message_type.nested_type.add() 1113 nested_type.name = 'Sub' 1114 enum_type = nested_type.enum_type.add() 1115 enum_type.name = 'FOO' 1116 enum_type_val = enum_type.value.add() 1117 enum_type_val.name = 'BAR' 1118 enum_type_val.number = 3 1119 field = message_type.field.add() 1120 field.number = 1 1121 field.name = 'uint64_field' 1122 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 1123 field.type = descriptor.FieldDescriptor.TYPE_UINT64 1124 field = message_type.field.add() 1125 field.number = 2 1126 field.name = 'nested_message_field' 1127 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 1128 field.type = descriptor.FieldDescriptor.TYPE_MESSAGE 1129 field.type_name = 'Sub' 1130 enum_field = nested_type.field.add() 1131 enum_field.number = 2 1132 enum_field.name = 'bar_field' 1133 enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 1134 enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM 1135 enum_field.type_name = 'Foo2.Sub.FOO' 1136 1137 result = descriptor.MakeDescriptor(message_type) 1138 self.assertEqual(result.fields[0].cpp_type, 1139 descriptor.FieldDescriptor.CPPTYPE_UINT64) 1140 self.assertEqual(result.fields[0].cpp_type, 1141 result.fields[0].CPPTYPE_UINT64) 1142 self.assertEqual(result.fields[1].cpp_type, 1143 descriptor.FieldDescriptor.CPPTYPE_MESSAGE) 1144 self.assertEqual(result.fields[1].cpp_type, 1145 result.fields[1].CPPTYPE_MESSAGE) 1146 self.assertEqual(result.fields[1].message_type.containing_type, 1147 result) 1148 self.assertEqual(result.nested_types[0].fields[0].full_name, 1149 'Foo2.Sub.bar_field') 1150 self.assertEqual(result.nested_types[0].fields[0].enum_type, 1151 result.nested_types[0].enum_types[0]) 1152 self.assertFalse(result.has_options) 1153 self.assertFalse(result.fields[0].has_options) 1154 if api_implementation.Type() == 'cpp': 1155 with self.assertRaises(AttributeError): 1156 result.fields[0].has_options = False 1157 1158 def testMakeDescriptorWithUnsignedIntField(self): 1159 file_descriptor_proto = descriptor_pb2.FileDescriptorProto() 1160 file_descriptor_proto.name = 'Foo' 1161 message_type = file_descriptor_proto.message_type.add() 1162 message_type.name = file_descriptor_proto.name 1163 enum_type = message_type.enum_type.add() 1164 enum_type.name = 'FOO' 1165 enum_type_val = enum_type.value.add() 1166 enum_type_val.name = 'BAR' 1167 enum_type_val.number = 3 1168 field = message_type.field.add() 1169 field.number = 1 1170 field.name = 'uint64_field' 1171 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 1172 field.type = descriptor.FieldDescriptor.TYPE_UINT64 1173 enum_field = message_type.field.add() 1174 enum_field.number = 2 1175 enum_field.name = 'bar_field' 1176 enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 1177 enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM 1178 enum_field.type_name = 'Foo.FOO' 1179 1180 result = descriptor.MakeDescriptor(message_type) 1181 self.assertEqual(result.fields[0].cpp_type, 1182 descriptor.FieldDescriptor.CPPTYPE_UINT64) 1183 1184 def testMakeDescriptorWithOptions(self): 1185 descriptor_proto = descriptor_pb2.DescriptorProto() 1186 aggregate_message = unittest_custom_options_pb2.AggregateMessage 1187 aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto) 1188 reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto) 1189 1190 options = reformed_descriptor.GetOptions() 1191 self.assertEqual(101, 1192 options.Extensions[unittest_custom_options_pb2.msgopt].i) 1193 1194 def testCamelcaseName(self): 1195 descriptor_proto = descriptor_pb2.DescriptorProto() 1196 descriptor_proto.options.deprecated_legacy_json_field_conflicts = True 1197 descriptor_proto.name = 'Bar' 1198 names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar'] 1199 camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar'] 1200 for index in range(len(names)): 1201 field = descriptor_proto.field.add() 1202 field.number = index + 1 1203 field.name = names[index] 1204 result = descriptor.MakeDescriptor(descriptor_proto) 1205 for index in range(len(camelcase_names)): 1206 self.assertEqual(result.fields[index].camelcase_name, 1207 camelcase_names[index]) 1208 1209 def testJsonName(self): 1210 descriptor_proto = descriptor_pb2.DescriptorProto() 1211 descriptor_proto.options.deprecated_legacy_json_field_conflicts = True 1212 descriptor_proto.name = 'TestJsonName' 1213 names = ['field_name', 'fieldName', 'FieldName', 1214 '_field_name', 'FIELD_NAME', 'json_name'] 1215 json_names = ['fieldName', 'fieldName', 'FieldName', 1216 'FieldName', 'FIELDNAME', '@type'] 1217 for index in range(len(names)): 1218 field = descriptor_proto.field.add() 1219 field.number = index + 1 1220 field.name = names[index] 1221 field.json_name = '@type' 1222 result = descriptor.MakeDescriptor(descriptor_proto) 1223 for index in range(len(json_names)): 1224 self.assertEqual(result.fields[index].json_name, 1225 json_names[index]) 1226 1227 1228@testing_refleaks.TestCase 1229class FeaturesTest(_parameterized.TestCase): 1230 1231 @_parameterized.named_parameters([ 1232 ('File', lambda: descriptor_pb2.DESCRIPTOR), 1233 ('Message', lambda: descriptor_pb2.FeatureSet.DESCRIPTOR), 1234 ( 1235 'Enum', 1236 lambda: descriptor_pb2.FeatureSet.FieldPresence.DESCRIPTOR, 1237 ), 1238 ( 1239 'Field', 1240 lambda: descriptor_pb2.FeatureSet.DESCRIPTOR.fields_by_name[ 1241 'enum_type' 1242 ], 1243 ), 1244 ]) 1245 def testDescriptorProtoDefaultFeatures(self, desc): 1246 self.assertEqual( 1247 desc()._GetFeatures().field_presence, 1248 descriptor_pb2.FeatureSet.FieldPresence.EXPLICIT, 1249 ) 1250 self.assertEqual( 1251 desc()._GetFeatures().enum_type, 1252 descriptor_pb2.FeatureSet.EnumType.CLOSED, 1253 ) 1254 self.assertEqual( 1255 desc()._GetFeatures().repeated_field_encoding, 1256 descriptor_pb2.FeatureSet.RepeatedFieldEncoding.EXPANDED, 1257 ) 1258 1259 def testDescriptorProtoOverrideFeatures(self): 1260 desc = descriptor_pb2.SourceCodeInfo.Location.DESCRIPTOR.fields_by_name[ 1261 'path' 1262 ] 1263 self.assertEqual( 1264 desc._GetFeatures().field_presence, 1265 descriptor_pb2.FeatureSet.FieldPresence.EXPLICIT, 1266 ) 1267 self.assertEqual( 1268 desc._GetFeatures().enum_type, 1269 descriptor_pb2.FeatureSet.EnumType.CLOSED, 1270 ) 1271 self.assertEqual( 1272 desc._GetFeatures().repeated_field_encoding, 1273 descriptor_pb2.FeatureSet.RepeatedFieldEncoding.PACKED, 1274 ) 1275 1276 def testFeaturesStripped(self): 1277 desc = unittest_legacy_features_pb2.TestEditionsMessage.DESCRIPTOR.fields_by_name[ 1278 'required_field' 1279 ] 1280 self.assertFalse(desc.GetOptions().HasField('features')) 1281 1282 def testLegacyRequiredTransform(self): 1283 desc = unittest_legacy_features_pb2.TestEditionsMessage.DESCRIPTOR 1284 self.assertEqual( 1285 desc.fields_by_name['required_field'].label, 1286 descriptor.FieldDescriptor.LABEL_REQUIRED, 1287 ) 1288 1289 def testLegacyGroupTransform(self): 1290 desc = unittest_legacy_features_pb2.TestEditionsMessage.DESCRIPTOR 1291 self.assertEqual( 1292 desc.fields_by_name['delimited_field'].type, 1293 descriptor.FieldDescriptor.TYPE_GROUP, 1294 ) 1295 1296 def testLegacyInferRequired(self): 1297 desc = unittest_pb2.TestRequired.DESCRIPTOR.fields_by_name['a'] 1298 self.assertEqual( 1299 desc._GetFeatures().field_presence, 1300 descriptor_pb2.FeatureSet.FieldPresence.LEGACY_REQUIRED, 1301 ) 1302 1303 def testLegacyInferGroup(self): 1304 desc = unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optionalgroup'] 1305 self.assertEqual( 1306 desc._GetFeatures().message_encoding, 1307 descriptor_pb2.FeatureSet.MessageEncoding.DELIMITED, 1308 ) 1309 1310 def testLegacyInferProto2Packed(self): 1311 desc = unittest_pb2.TestPackedTypes.DESCRIPTOR.fields_by_name[ 1312 'packed_int32' 1313 ] 1314 self.assertEqual( 1315 desc._GetFeatures().repeated_field_encoding, 1316 descriptor_pb2.FeatureSet.RepeatedFieldEncoding.PACKED, 1317 ) 1318 1319 def testLegacyInferProto3Expanded(self): 1320 desc = unittest_proto3_pb2.TestUnpackedTypes.DESCRIPTOR.fields_by_name[ 1321 'repeated_int32' 1322 ] 1323 self.assertEqual( 1324 desc._GetFeatures().repeated_field_encoding, 1325 descriptor_pb2.FeatureSet.RepeatedFieldEncoding.EXPANDED, 1326 ) 1327 1328 def testProto2Defaults(self): 1329 features = test_proto2_pb2.TestProto2.DESCRIPTOR.fields_by_name[ 1330 'optional_int32' 1331 ]._GetFeatures() 1332 fs = descriptor_pb2.FeatureSet 1333 self.assertEqual(features.field_presence, fs.FieldPresence.EXPLICIT) 1334 self.assertEqual(features.enum_type, fs.EnumType.CLOSED) 1335 self.assertEqual( 1336 features.repeated_field_encoding, fs.RepeatedFieldEncoding.EXPANDED 1337 ) 1338 self.assertEqual(features.utf8_validation, fs.Utf8Validation.NONE) 1339 self.assertEqual( 1340 features.message_encoding, fs.MessageEncoding.LENGTH_PREFIXED 1341 ) 1342 self.assertEqual(features.json_format, fs.JsonFormat.LEGACY_BEST_EFFORT) 1343 1344 def testProto3Defaults(self): 1345 features = unittest_proto3_pb2.TestAllTypes.DESCRIPTOR.fields_by_name[ 1346 'optional_int32' 1347 ]._GetFeatures() 1348 fs = descriptor_pb2.FeatureSet 1349 self.assertEqual(features.field_presence, fs.FieldPresence.IMPLICIT) 1350 self.assertEqual(features.enum_type, fs.EnumType.OPEN) 1351 self.assertEqual( 1352 features.repeated_field_encoding, fs.RepeatedFieldEncoding.PACKED 1353 ) 1354 self.assertEqual(features.utf8_validation, fs.Utf8Validation.VERIFY) 1355 self.assertEqual( 1356 features.message_encoding, fs.MessageEncoding.LENGTH_PREFIXED 1357 ) 1358 self.assertEqual(features.json_format, fs.JsonFormat.ALLOW) 1359 1360 def testProto3ExtensionPresence(self): 1361 ext = unittest_proto3_extensions_pb2.Proto3FileExtensions.singular_int 1362 file = descriptor_pb2.FileDescriptorProto() 1363 1364 self.assertFalse(file.options.HasExtension(ext)) 1365 1366 file.options.Extensions[ext] = 1 1367 1368 self.assertTrue(file.options.HasExtension(ext)) 1369 1370 def testProto3ExtensionHasPresence(self): 1371 exts = unittest_proto3_extensions_pb2.Proto3FileExtensions 1372 self.assertTrue(exts.singular_int.has_presence) 1373 self.assertFalse(exts.repeated_int.has_presence) 1374 1375 1376def GetTestFeature(desc): 1377 return ( 1378 desc._GetFeatures() 1379 .Extensions[unittest_features_pb2.test] 1380 .multiple_feature 1381 ) 1382 1383 1384def SetTestFeature(proto, value): 1385 proto.options.features.Extensions[ 1386 unittest_features_pb2.test 1387 ].multiple_feature = value 1388 1389 1390@testing_refleaks.TestCase 1391class FeatureInheritanceTest(unittest.TestCase): 1392 1393 def setUp(self): 1394 super(FeatureInheritanceTest, self).setUp() 1395 self.file_proto = descriptor_pb2.FileDescriptorProto( 1396 name='some/filename/some.proto', 1397 package='protobuf_unittest', 1398 edition=descriptor_pb2.Edition.EDITION_2023, 1399 syntax='editions', 1400 ) 1401 self.top_extension_proto = self.file_proto.extension.add( 1402 name='top_extension', 1403 number=10, 1404 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 1405 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL, 1406 extendee='.protobuf_unittest.TopMessage', 1407 ) 1408 self.top_enum_proto = self.file_proto.enum_type.add(name='TopEnum') 1409 self.enum_value_proto = self.top_enum_proto.value.add( 1410 name='TOP_VALUE', number=0 1411 ) 1412 self.top_message_proto = self.file_proto.message_type.add(name='TopMessage') 1413 self.field_proto = self.top_message_proto.field.add( 1414 name='field', 1415 number=1, 1416 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 1417 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL, 1418 ) 1419 self.top_message_proto.extension_range.add(start=10, end=20) 1420 self.nested_extension_proto = self.top_message_proto.extension.add( 1421 name='nested_extension', 1422 number=11, 1423 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 1424 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL, 1425 extendee='.protobuf_unittest.TopMessage', 1426 ) 1427 self.nested_message_proto = self.top_message_proto.nested_type.add( 1428 name='NestedMessage' 1429 ) 1430 self.nested_enum_proto = self.top_message_proto.enum_type.add( 1431 name='NestedEnum' 1432 ) 1433 self.nested_enum_proto.value.add(name='NESTED_VALUE', number=0) 1434 self.oneof_proto = self.top_message_proto.oneof_decl.add(name='Oneof') 1435 self.oneof_field_proto = self.top_message_proto.field.add( 1436 name='oneof_field', 1437 number=2, 1438 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 1439 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL, 1440 oneof_index=0, 1441 ) 1442 1443 self.service_proto = self.file_proto.service.add(name='TestService') 1444 self.method_proto = self.service_proto.method.add( 1445 name='CallMethod', 1446 input_type='.protobuf_unittest.TopMessage', 1447 output_type='.protobuf_unittest.TopMessage', 1448 ) 1449 1450 def BuildPool(self): 1451 1452 # These can't be put onto the fixture without breaking the refleak checks. 1453 class ReturnObject: 1454 pass 1455 1456 ret = ReturnObject() 1457 ret.pool = descriptor_pool.DescriptorPool() 1458 1459 defaults = descriptor_pb2.FeatureSetDefaults( 1460 defaults=[ 1461 descriptor_pb2.FeatureSetDefaults.FeatureSetEditionDefault( 1462 edition=descriptor_pb2.Edition.EDITION_PROTO2, 1463 overridable_features=unittest_pb2.TestAllTypes.DESCRIPTOR._GetFeatures(), 1464 ) 1465 ], 1466 minimum_edition=descriptor_pb2.Edition.EDITION_PROTO2, 1467 maximum_edition=descriptor_pb2.Edition.EDITION_2023, 1468 ) 1469 defaults.defaults[0].overridable_features.Extensions[ 1470 unittest_features_pb2.test 1471 ].multiple_feature = 1 1472 ret.pool.SetFeatureSetDefaults(defaults) 1473 1474 # Add dependencies 1475 file = descriptor_pb2.FileDescriptorProto() 1476 descriptor_pb2.DESCRIPTOR.CopyToProto(file) 1477 ret.pool.Add(file) 1478 file.Clear() 1479 unittest_features_pb2.DESCRIPTOR.CopyToProto(file) 1480 ret.pool.Add(file) 1481 1482 ret.file = ret.pool.AddSerializedFile(self.file_proto.SerializeToString()) 1483 ret.top_message = ret.pool.FindMessageTypeByName( 1484 'protobuf_unittest.TopMessage' 1485 ) 1486 ret.top_enum = ret.pool.FindEnumTypeByName('protobuf_unittest.TopEnum') 1487 ret.top_extension = ret.pool.FindExtensionByName( 1488 'protobuf_unittest.top_extension' 1489 ) 1490 ret.nested_message = ret.top_message.nested_types_by_name['NestedMessage'] 1491 ret.nested_enum = ret.top_message.enum_types_by_name['NestedEnum'] 1492 ret.nested_extension = ret.top_message.extensions_by_name[ 1493 'nested_extension' 1494 ] 1495 ret.field = ret.top_message.fields_by_name['field'] 1496 ret.oneof = ret.top_message.oneofs_by_name['Oneof'] 1497 ret.oneof_field = ret.top_message.fields_by_name['oneof_field'] 1498 ret.enum_value = ret.top_enum.values_by_name['TOP_VALUE'] 1499 ret.service = ret.pool.FindServiceByName('protobuf_unittest.TestService') 1500 ret.method = ret.service.methods_by_name['CallMethod'] 1501 return ret 1502 1503 def testFileDefaults(self): 1504 pool = self.BuildPool() 1505 self.assertEqual(GetTestFeature(pool.file), 1) 1506 1507 def testFileOverride(self): 1508 SetTestFeature(self.file_proto, 3) 1509 pool = self.BuildPool() 1510 self.assertEqual(GetTestFeature(pool.file), 3) 1511 1512 def testFileMessageInherit(self): 1513 SetTestFeature(self.file_proto, 3) 1514 pool = self.BuildPool() 1515 self.assertEqual(GetTestFeature(pool.top_message), 3) 1516 1517 def testFileMessageOverride(self): 1518 SetTestFeature(self.file_proto, 3) 1519 SetTestFeature(self.top_message_proto, 5) 1520 pool = self.BuildPool() 1521 self.assertEqual(GetTestFeature(pool.top_message), 5) 1522 1523 def testFileEnumInherit(self): 1524 SetTestFeature(self.file_proto, 3) 1525 pool = self.BuildPool() 1526 self.assertEqual(GetTestFeature(pool.top_enum), 3) 1527 1528 def testFileEnumOverride(self): 1529 SetTestFeature(self.file_proto, 3) 1530 SetTestFeature(self.top_enum_proto, 5) 1531 pool = self.BuildPool() 1532 self.assertEqual(GetTestFeature(pool.top_enum), 5) 1533 1534 def testFileExtensionInherit(self): 1535 SetTestFeature(self.file_proto, 3) 1536 pool = self.BuildPool() 1537 self.assertEqual(GetTestFeature(pool.top_extension), 3) 1538 1539 def testFileExtensionOverride(self): 1540 SetTestFeature(self.file_proto, 3) 1541 SetTestFeature(self.top_extension_proto, 5) 1542 pool = self.BuildPool() 1543 self.assertEqual(GetTestFeature(pool.top_extension), 5) 1544 1545 def testFileServiceInherit(self): 1546 SetTestFeature(self.file_proto, 3) 1547 pool = self.BuildPool() 1548 self.assertEqual(GetTestFeature(pool.service), 3) 1549 1550 def testFileServiceOverride(self): 1551 SetTestFeature(self.file_proto, 3) 1552 SetTestFeature(self.service_proto, 5) 1553 pool = self.BuildPool() 1554 self.assertEqual(GetTestFeature(pool.service), 5) 1555 1556 def testMessageFieldInherit(self): 1557 SetTestFeature(self.top_message_proto, 3) 1558 pool = self.BuildPool() 1559 self.assertEqual(GetTestFeature(pool.field), 3) 1560 1561 def testMessageFieldOverride(self): 1562 SetTestFeature(self.top_message_proto, 3) 1563 SetTestFeature(self.field_proto, 5) 1564 pool = self.BuildPool() 1565 self.assertEqual(GetTestFeature(pool.field), 5) 1566 1567 def testMessageEnumInherit(self): 1568 SetTestFeature(self.top_message_proto, 3) 1569 pool = self.BuildPool() 1570 self.assertEqual(GetTestFeature(pool.nested_enum), 3) 1571 1572 def testMessageEnumOverride(self): 1573 SetTestFeature(self.top_message_proto, 3) 1574 SetTestFeature(self.nested_enum_proto, 5) 1575 pool = self.BuildPool() 1576 self.assertEqual(GetTestFeature(pool.nested_enum), 5) 1577 1578 def testMessageMessageInherit(self): 1579 SetTestFeature(self.top_message_proto, 3) 1580 pool = self.BuildPool() 1581 self.assertEqual(GetTestFeature(pool.nested_message), 3) 1582 1583 def testMessageMessageOverride(self): 1584 SetTestFeature(self.top_message_proto, 3) 1585 SetTestFeature(self.nested_message_proto, 5) 1586 pool = self.BuildPool() 1587 self.assertEqual(GetTestFeature(pool.nested_message), 5) 1588 1589 def testMessageExtensionInherit(self): 1590 SetTestFeature(self.top_message_proto, 3) 1591 pool = self.BuildPool() 1592 self.assertEqual(GetTestFeature(pool.nested_extension), 3) 1593 1594 def testMessageExtensionOverride(self): 1595 SetTestFeature(self.top_message_proto, 3) 1596 SetTestFeature(self.nested_extension_proto, 5) 1597 pool = self.BuildPool() 1598 self.assertEqual(GetTestFeature(pool.nested_extension), 5) 1599 1600 def testMessageOneofInherit(self): 1601 SetTestFeature(self.top_message_proto, 3) 1602 pool = self.BuildPool() 1603 self.assertEqual(GetTestFeature(pool.oneof), 3) 1604 1605 def testMessageOneofOverride(self): 1606 SetTestFeature(self.top_message_proto, 3) 1607 SetTestFeature(self.oneof_proto, 5) 1608 pool = self.BuildPool() 1609 self.assertEqual(GetTestFeature(pool.oneof), 5) 1610 1611 def testOneofFieldInherit(self): 1612 SetTestFeature(self.oneof_proto, 3) 1613 pool = self.BuildPool() 1614 self.assertEqual(GetTestFeature(pool.oneof_field), 3) 1615 1616 def testOneofFieldOverride(self): 1617 SetTestFeature(self.oneof_proto, 3) 1618 SetTestFeature(self.oneof_field_proto, 5) 1619 pool = self.BuildPool() 1620 self.assertEqual(GetTestFeature(pool.oneof_field), 5) 1621 1622 def testEnumValueInherit(self): 1623 SetTestFeature(self.top_enum_proto, 3) 1624 pool = self.BuildPool() 1625 self.assertEqual(GetTestFeature(pool.enum_value), 3) 1626 1627 def testEnumValueOverride(self): 1628 SetTestFeature(self.top_enum_proto, 3) 1629 SetTestFeature(self.enum_value_proto, 5) 1630 pool = self.BuildPool() 1631 self.assertEqual(GetTestFeature(pool.enum_value), 5) 1632 1633 def testServiceMethodInherit(self): 1634 SetTestFeature(self.service_proto, 3) 1635 pool = self.BuildPool() 1636 self.assertEqual(GetTestFeature(pool.method), 3) 1637 1638 def testServiceMethodOverride(self): 1639 SetTestFeature(self.service_proto, 3) 1640 SetTestFeature(self.method_proto, 5) 1641 pool = self.BuildPool() 1642 self.assertEqual(GetTestFeature(pool.method), 5) 1643 1644 1645if __name__ == '__main__': 1646 unittest.main() 1647