1# Protocol Buffers - Google's data interchange format 2# Copyright 2008 Google Inc. All rights reserved. 3# https://developers.google.com/protocol-buffers/ 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: 8# 9# * Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above 12# copyright notice, this list of conditions and the following disclaimer 13# in the documentation and/or other materials provided with the 14# distribution. 15# * Neither the name of Google Inc. nor the names of its 16# contributors may be used to endorse or promote products derived from 17# this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31"""Tests for google.protobuf.descriptor_pool.""" 32 33__author__ = '[email protected] (Matt Toia)' 34 35import copy 36import os 37import unittest 38import warnings 39 40from google.protobuf import unittest_import_pb2 41from google.protobuf import unittest_import_public_pb2 42from google.protobuf import unittest_pb2 43from google.protobuf import descriptor_pb2 44from google.protobuf.internal import api_implementation 45from google.protobuf.internal import descriptor_pool_test1_pb2 46from google.protobuf.internal import descriptor_pool_test2_pb2 47from google.protobuf.internal import factory_test1_pb2 48from google.protobuf.internal import factory_test2_pb2 49from google.protobuf.internal import file_options_test_pb2 50from google.protobuf.internal import more_messages_pb2 51from google.protobuf.internal import no_package_pb2 52from google.protobuf.internal import testing_refleaks 53from google.protobuf import descriptor 54from google.protobuf import descriptor_database 55from google.protobuf import descriptor_pool 56from google.protobuf import message_factory 57from google.protobuf import symbol_database 58 59 60 61warnings.simplefilter('error', DeprecationWarning) 62 63 64class DescriptorPoolTestBase(object): 65 66 def testFindFileByName(self): 67 name1 = 'google/protobuf/internal/factory_test1.proto' 68 file_desc1 = self.pool.FindFileByName(name1) 69 self.assertIsInstance(file_desc1, descriptor.FileDescriptor) 70 self.assertEqual(name1, file_desc1.name) 71 self.assertEqual('google.protobuf.python.internal', file_desc1.package) 72 self.assertIn('Factory1Message', file_desc1.message_types_by_name) 73 74 name2 = 'google/protobuf/internal/factory_test2.proto' 75 file_desc2 = self.pool.FindFileByName(name2) 76 self.assertIsInstance(file_desc2, descriptor.FileDescriptor) 77 self.assertEqual(name2, file_desc2.name) 78 self.assertEqual('google.protobuf.python.internal', file_desc2.package) 79 self.assertIn('Factory2Message', file_desc2.message_types_by_name) 80 81 def testFindFileByNameFailure(self): 82 with self.assertRaises(KeyError): 83 self.pool.FindFileByName('Does not exist') 84 85 def testFindFileContainingSymbol(self): 86 file_desc1 = self.pool.FindFileContainingSymbol( 87 'google.protobuf.python.internal.Factory1Message') 88 self.assertIsInstance(file_desc1, descriptor.FileDescriptor) 89 self.assertEqual('google/protobuf/internal/factory_test1.proto', 90 file_desc1.name) 91 self.assertEqual('google.protobuf.python.internal', file_desc1.package) 92 self.assertIn('Factory1Message', file_desc1.message_types_by_name) 93 94 file_desc2 = self.pool.FindFileContainingSymbol( 95 'google.protobuf.python.internal.Factory2Message') 96 self.assertIsInstance(file_desc2, descriptor.FileDescriptor) 97 self.assertEqual('google/protobuf/internal/factory_test2.proto', 98 file_desc2.name) 99 self.assertEqual('google.protobuf.python.internal', file_desc2.package) 100 self.assertIn('Factory2Message', file_desc2.message_types_by_name) 101 102 # Tests top level extension. 103 file_desc3 = self.pool.FindFileContainingSymbol( 104 'google.protobuf.python.internal.another_field') 105 self.assertIsInstance(file_desc3, descriptor.FileDescriptor) 106 self.assertEqual('google/protobuf/internal/factory_test2.proto', 107 file_desc3.name) 108 109 # Tests nested extension inside a message. 110 file_desc4 = self.pool.FindFileContainingSymbol( 111 'google.protobuf.python.internal.Factory2Message.one_more_field') 112 self.assertIsInstance(file_desc4, descriptor.FileDescriptor) 113 self.assertEqual('google/protobuf/internal/factory_test2.proto', 114 file_desc4.name) 115 116 file_desc5 = self.pool.FindFileContainingSymbol( 117 'protobuf_unittest.TestService') 118 self.assertIsInstance(file_desc5, descriptor.FileDescriptor) 119 self.assertEqual('google/protobuf/unittest.proto', 120 file_desc5.name) 121 # Tests the generated pool. 122 assert descriptor_pool.Default().FindFileContainingSymbol( 123 'google.protobuf.python.internal.Factory2Message.one_more_field') 124 assert descriptor_pool.Default().FindFileContainingSymbol( 125 'google.protobuf.python.internal.another_field') 126 assert descriptor_pool.Default().FindFileContainingSymbol( 127 'protobuf_unittest.TestService') 128 129 # Can find field. 130 file_desc6 = self.pool.FindFileContainingSymbol( 131 'google.protobuf.python.internal.Factory1Message.list_value') 132 self.assertIsInstance(file_desc6, descriptor.FileDescriptor) 133 self.assertEqual('google/protobuf/internal/factory_test1.proto', 134 file_desc6.name) 135 136 # Can find top level Enum value. 137 file_desc7 = self.pool.FindFileContainingSymbol( 138 'google.protobuf.python.internal.FACTORY_1_VALUE_0') 139 self.assertIsInstance(file_desc7, descriptor.FileDescriptor) 140 self.assertEqual('google/protobuf/internal/factory_test1.proto', 141 file_desc7.name) 142 143 # Can find nested Enum value. 144 file_desc8 = self.pool.FindFileContainingSymbol( 145 'protobuf_unittest.TestAllTypes.FOO') 146 self.assertIsInstance(file_desc8, descriptor.FileDescriptor) 147 self.assertEqual('google/protobuf/unittest.proto', 148 file_desc8.name) 149 150 # TODO(jieluo): Add tests for no package when b/13860351 is fixed. 151 152 self.assertRaises(KeyError, self.pool.FindFileContainingSymbol, 153 'google.protobuf.python.internal.Factory1Message.none_field') 154 155 def testFindFileContainingSymbolFailure(self): 156 with self.assertRaises(KeyError): 157 self.pool.FindFileContainingSymbol('Does not exist') 158 159 def testFindMessageTypeByName(self): 160 msg1 = self.pool.FindMessageTypeByName( 161 'google.protobuf.python.internal.Factory1Message') 162 self.assertIsInstance(msg1, descriptor.Descriptor) 163 self.assertEqual('Factory1Message', msg1.name) 164 self.assertEqual('google.protobuf.python.internal.Factory1Message', 165 msg1.full_name) 166 self.assertEqual(None, msg1.containing_type) 167 self.assertFalse(msg1.has_options) 168 169 nested_msg1 = msg1.nested_types[0] 170 self.assertEqual('NestedFactory1Message', nested_msg1.name) 171 self.assertEqual(msg1, nested_msg1.containing_type) 172 173 nested_enum1 = msg1.enum_types[0] 174 self.assertEqual('NestedFactory1Enum', nested_enum1.name) 175 self.assertEqual(msg1, nested_enum1.containing_type) 176 177 self.assertEqual(nested_msg1, msg1.fields_by_name[ 178 'nested_factory_1_message'].message_type) 179 self.assertEqual(nested_enum1, msg1.fields_by_name[ 180 'nested_factory_1_enum'].enum_type) 181 182 msg2 = self.pool.FindMessageTypeByName( 183 'google.protobuf.python.internal.Factory2Message') 184 self.assertIsInstance(msg2, descriptor.Descriptor) 185 self.assertEqual('Factory2Message', msg2.name) 186 self.assertEqual('google.protobuf.python.internal.Factory2Message', 187 msg2.full_name) 188 self.assertIsNone(msg2.containing_type) 189 190 nested_msg2 = msg2.nested_types[0] 191 self.assertEqual('NestedFactory2Message', nested_msg2.name) 192 self.assertEqual(msg2, nested_msg2.containing_type) 193 194 nested_enum2 = msg2.enum_types[0] 195 self.assertEqual('NestedFactory2Enum', nested_enum2.name) 196 self.assertEqual(msg2, nested_enum2.containing_type) 197 198 self.assertEqual(nested_msg2, msg2.fields_by_name[ 199 'nested_factory_2_message'].message_type) 200 self.assertEqual(nested_enum2, msg2.fields_by_name[ 201 'nested_factory_2_enum'].enum_type) 202 203 self.assertTrue(msg2.fields_by_name['int_with_default'].has_default_value) 204 self.assertEqual( 205 1776, msg2.fields_by_name['int_with_default'].default_value) 206 207 self.assertTrue( 208 msg2.fields_by_name['double_with_default'].has_default_value) 209 self.assertEqual( 210 9.99, msg2.fields_by_name['double_with_default'].default_value) 211 212 self.assertTrue( 213 msg2.fields_by_name['string_with_default'].has_default_value) 214 self.assertEqual( 215 'hello world', msg2.fields_by_name['string_with_default'].default_value) 216 217 self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default_value) 218 self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value) 219 220 self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default_value) 221 self.assertEqual( 222 1, msg2.fields_by_name['enum_with_default'].default_value) 223 224 msg3 = self.pool.FindMessageTypeByName( 225 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message') 226 self.assertEqual(nested_msg2, msg3) 227 228 self.assertTrue(msg2.fields_by_name['bytes_with_default'].has_default_value) 229 self.assertEqual( 230 b'a\xfb\x00c', 231 msg2.fields_by_name['bytes_with_default'].default_value) 232 233 self.assertEqual(1, len(msg2.oneofs)) 234 self.assertEqual(1, len(msg2.oneofs_by_name)) 235 self.assertEqual(2, len(msg2.oneofs[0].fields)) 236 for name in ['oneof_int', 'oneof_string']: 237 self.assertEqual(msg2.oneofs[0], 238 msg2.fields_by_name[name].containing_oneof) 239 self.assertIn(msg2.fields_by_name[name], msg2.oneofs[0].fields) 240 241 def testFindTypeErrors(self): 242 self.assertRaises(TypeError, self.pool.FindExtensionByNumber, '') 243 self.assertRaises(KeyError, self.pool.FindMethodByName, '') 244 245 # TODO(jieluo): Fix python to raise correct errors. 246 if api_implementation.Type() == 'python': 247 error_type = AttributeError 248 else: 249 error_type = TypeError 250 self.assertRaises(error_type, self.pool.FindMessageTypeByName, 0) 251 self.assertRaises(error_type, self.pool.FindFieldByName, 0) 252 self.assertRaises(error_type, self.pool.FindExtensionByName, 0) 253 self.assertRaises(error_type, self.pool.FindEnumTypeByName, 0) 254 self.assertRaises(error_type, self.pool.FindOneofByName, 0) 255 self.assertRaises(error_type, self.pool.FindServiceByName, 0) 256 self.assertRaises(error_type, self.pool.FindMethodByName, 0) 257 self.assertRaises(error_type, self.pool.FindFileContainingSymbol, 0) 258 if api_implementation.Type() == 'python': 259 error_type = KeyError 260 self.assertRaises(error_type, self.pool.FindFileByName, 0) 261 262 def testFindMessageTypeByNameFailure(self): 263 with self.assertRaises(KeyError): 264 self.pool.FindMessageTypeByName('Does not exist') 265 266 def testFindEnumTypeByName(self): 267 enum1 = self.pool.FindEnumTypeByName( 268 'google.protobuf.python.internal.Factory1Enum') 269 self.assertIsInstance(enum1, descriptor.EnumDescriptor) 270 self.assertEqual(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number) 271 self.assertEqual(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number) 272 self.assertFalse(enum1.has_options) 273 274 nested_enum1 = self.pool.FindEnumTypeByName( 275 'google.protobuf.python.internal.Factory1Message.NestedFactory1Enum') 276 self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor) 277 self.assertEqual( 278 0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number) 279 self.assertEqual( 280 1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number) 281 282 enum2 = self.pool.FindEnumTypeByName( 283 'google.protobuf.python.internal.Factory2Enum') 284 self.assertIsInstance(enum2, descriptor.EnumDescriptor) 285 self.assertEqual(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number) 286 self.assertEqual(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number) 287 288 nested_enum2 = self.pool.FindEnumTypeByName( 289 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum') 290 self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor) 291 self.assertEqual( 292 0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number) 293 self.assertEqual( 294 1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number) 295 296 def testFindEnumTypeByNameFailure(self): 297 with self.assertRaises(KeyError): 298 self.pool.FindEnumTypeByName('Does not exist') 299 300 def testFindFieldByName(self): 301 field = self.pool.FindFieldByName( 302 'google.protobuf.python.internal.Factory1Message.list_value') 303 self.assertEqual(field.name, 'list_value') 304 self.assertEqual(field.label, field.LABEL_REPEATED) 305 self.assertFalse(field.has_options) 306 307 with self.assertRaises(KeyError): 308 self.pool.FindFieldByName('Does not exist') 309 310 def testFindOneofByName(self): 311 oneof = self.pool.FindOneofByName( 312 'google.protobuf.python.internal.Factory2Message.oneof_field') 313 self.assertEqual(oneof.name, 'oneof_field') 314 with self.assertRaises(KeyError): 315 self.pool.FindOneofByName('Does not exist') 316 317 def testFindExtensionByName(self): 318 # An extension defined in a message. 319 extension = self.pool.FindExtensionByName( 320 'google.protobuf.python.internal.Factory2Message.one_more_field') 321 self.assertEqual(extension.name, 'one_more_field') 322 # An extension defined at file scope. 323 extension = self.pool.FindExtensionByName( 324 'google.protobuf.python.internal.another_field') 325 self.assertEqual(extension.name, 'another_field') 326 self.assertEqual(extension.number, 1002) 327 with self.assertRaises(KeyError): 328 self.pool.FindFieldByName('Does not exist') 329 330 def testFindAllExtensions(self): 331 factory1_message = self.pool.FindMessageTypeByName( 332 'google.protobuf.python.internal.Factory1Message') 333 factory2_message = self.pool.FindMessageTypeByName( 334 'google.protobuf.python.internal.Factory2Message') 335 # An extension defined in a message. 336 one_more_field = factory2_message.extensions_by_name['one_more_field'] 337 # An extension defined at file scope. 338 factory_test2 = self.pool.FindFileByName( 339 'google/protobuf/internal/factory_test2.proto') 340 another_field = factory_test2.extensions_by_name['another_field'] 341 342 extensions = self.pool.FindAllExtensions(factory1_message) 343 expected_extension_numbers = set([one_more_field, another_field]) 344 self.assertEqual(expected_extension_numbers, set(extensions)) 345 # Verify that mutating the returned list does not affect the pool. 346 extensions.append('unexpected_element') 347 # Get the extensions again, the returned value does not contain the 348 # 'unexpected_element'. 349 extensions = self.pool.FindAllExtensions(factory1_message) 350 self.assertEqual(expected_extension_numbers, set(extensions)) 351 352 def testFindExtensionByNumber(self): 353 factory1_message = self.pool.FindMessageTypeByName( 354 'google.protobuf.python.internal.Factory1Message') 355 # Build factory_test2.proto which will put extensions to the pool 356 self.pool.FindFileByName( 357 'google/protobuf/internal/factory_test2.proto') 358 359 # An extension defined in a message. 360 extension = self.pool.FindExtensionByNumber(factory1_message, 1001) 361 self.assertEqual(extension.name, 'one_more_field') 362 # An extension defined at file scope. 363 extension = self.pool.FindExtensionByNumber(factory1_message, 1002) 364 self.assertEqual(extension.name, 'another_field') 365 with self.assertRaises(KeyError): 366 extension = self.pool.FindExtensionByNumber(factory1_message, 1234567) 367 368 def testExtensionsAreNotFields(self): 369 with self.assertRaises(KeyError): 370 self.pool.FindFieldByName('google.protobuf.python.internal.another_field') 371 with self.assertRaises(KeyError): 372 self.pool.FindFieldByName( 373 'google.protobuf.python.internal.Factory2Message.one_more_field') 374 with self.assertRaises(KeyError): 375 self.pool.FindExtensionByName( 376 'google.protobuf.python.internal.Factory1Message.list_value') 377 378 def testFindService(self): 379 service = self.pool.FindServiceByName('protobuf_unittest.TestService') 380 self.assertEqual(service.full_name, 'protobuf_unittest.TestService') 381 with self.assertRaises(KeyError): 382 self.pool.FindServiceByName('Does not exist') 383 384 method = self.pool.FindMethodByName('protobuf_unittest.TestService.Foo') 385 self.assertIs(method.containing_service, service) 386 with self.assertRaises(KeyError): 387 self.pool.FindMethodByName('protobuf_unittest.TestService.Doesnotexist') 388 389 def testUserDefinedDB(self): 390 db = descriptor_database.DescriptorDatabase() 391 self.pool = descriptor_pool.DescriptorPool(db) 392 db.Add(self.factory_test1_fd) 393 db.Add(self.factory_test2_fd) 394 self.testFindMessageTypeByName() 395 396 def testAddSerializedFile(self): 397 if isinstance(self, SecondaryDescriptorFromDescriptorDB): 398 if api_implementation.Type() != 'python': 399 # Cpp extension cannot call Add on a DescriptorPool 400 # that uses a DescriptorDatabase. 401 # TODO(jieluo): Fix python and cpp extension diff. 402 return 403 self.pool = descriptor_pool.DescriptorPool() 404 file1 = self.pool.AddSerializedFile( 405 self.factory_test1_fd.SerializeToString()) 406 file2 = self.pool.AddSerializedFile( 407 self.factory_test2_fd.SerializeToString()) 408 self.assertEqual(file1.name, 409 'google/protobuf/internal/factory_test1.proto') 410 self.assertEqual(file2.name, 411 'google/protobuf/internal/factory_test2.proto') 412 self.testFindMessageTypeByName() 413 file_json = self.pool.AddSerializedFile( 414 more_messages_pb2.DESCRIPTOR.serialized_pb) 415 field = file_json.message_types_by_name['class'].fields_by_name['int_field'] 416 self.assertEqual(field.json_name, 'json_int') 417 418 419 def testEnumDefaultValue(self): 420 """Test the default value of enums which don't start at zero.""" 421 def _CheckDefaultValue(file_descriptor): 422 default_value = (file_descriptor 423 .message_types_by_name['DescriptorPoolTest1'] 424 .fields_by_name['nested_enum'] 425 .default_value) 426 self.assertEqual(default_value, 427 descriptor_pool_test1_pb2.DescriptorPoolTest1.BETA) 428 # First check what the generated descriptor contains. 429 _CheckDefaultValue(descriptor_pool_test1_pb2.DESCRIPTOR) 430 # Then check the generated pool. Normally this is the same descriptor. 431 file_descriptor = symbol_database.Default().pool.FindFileByName( 432 'google/protobuf/internal/descriptor_pool_test1.proto') 433 self.assertIs(file_descriptor, descriptor_pool_test1_pb2.DESCRIPTOR) 434 _CheckDefaultValue(file_descriptor) 435 436 if isinstance(self, SecondaryDescriptorFromDescriptorDB): 437 if api_implementation.Type() != 'python': 438 # Cpp extension cannot call Add on a DescriptorPool 439 # that uses a DescriptorDatabase. 440 # TODO(jieluo): Fix python and cpp extension diff. 441 return 442 # Then check the dynamic pool and its internal DescriptorDatabase. 443 descriptor_proto = descriptor_pb2.FileDescriptorProto.FromString( 444 descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) 445 self.pool.Add(descriptor_proto) 446 # And do the same check as above 447 file_descriptor = self.pool.FindFileByName( 448 'google/protobuf/internal/descriptor_pool_test1.proto') 449 _CheckDefaultValue(file_descriptor) 450 451 def testDefaultValueForCustomMessages(self): 452 """Check the value returned by non-existent fields.""" 453 def _CheckValueAndType(value, expected_value, expected_type): 454 self.assertEqual(value, expected_value) 455 self.assertIsInstance(value, expected_type) 456 457 def _CheckDefaultValues(msg): 458 try: 459 int64 = long 460 except NameError: # Python3 461 int64 = int 462 try: 463 unicode_type = unicode 464 except NameError: # Python3 465 unicode_type = str 466 _CheckValueAndType(msg.optional_int32, 0, int) 467 _CheckValueAndType(msg.optional_uint64, 0, (int64, int)) 468 _CheckValueAndType(msg.optional_float, 0, (float, int)) 469 _CheckValueAndType(msg.optional_double, 0, (float, int)) 470 _CheckValueAndType(msg.optional_bool, False, bool) 471 _CheckValueAndType(msg.optional_string, u'', unicode_type) 472 _CheckValueAndType(msg.optional_bytes, b'', bytes) 473 _CheckValueAndType(msg.optional_nested_enum, msg.FOO, int) 474 # First for the generated message 475 _CheckDefaultValues(unittest_pb2.TestAllTypes()) 476 # Then for a message built with from the DescriptorPool. 477 pool = descriptor_pool.DescriptorPool() 478 pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 479 unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) 480 pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 481 unittest_import_pb2.DESCRIPTOR.serialized_pb)) 482 pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 483 unittest_pb2.DESCRIPTOR.serialized_pb)) 484 message_class = message_factory.MessageFactory(pool).GetPrototype( 485 pool.FindMessageTypeByName( 486 unittest_pb2.TestAllTypes.DESCRIPTOR.full_name)) 487 _CheckDefaultValues(message_class()) 488 489 def testAddFileDescriptor(self): 490 if isinstance(self, SecondaryDescriptorFromDescriptorDB): 491 if api_implementation.Type() != 'python': 492 # Cpp extension cannot call Add on a DescriptorPool 493 # that uses a DescriptorDatabase. 494 # TODO(jieluo): Fix python and cpp extension diff. 495 return 496 file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto') 497 self.pool.Add(file_desc) 498 self.pool.AddSerializedFile(file_desc.SerializeToString()) 499 500 def testComplexNesting(self): 501 if isinstance(self, SecondaryDescriptorFromDescriptorDB): 502 if api_implementation.Type() != 'python': 503 # Cpp extension cannot call Add on a DescriptorPool 504 # that uses a DescriptorDatabase. 505 # TODO(jieluo): Fix python and cpp extension diff. 506 return 507 more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString( 508 more_messages_pb2.DESCRIPTOR.serialized_pb) 509 test1_desc = descriptor_pb2.FileDescriptorProto.FromString( 510 descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) 511 test2_desc = descriptor_pb2.FileDescriptorProto.FromString( 512 descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb) 513 self.pool.Add(more_messages_desc) 514 self.pool.Add(test1_desc) 515 self.pool.Add(test2_desc) 516 TEST1_FILE.CheckFile(self, self.pool) 517 TEST2_FILE.CheckFile(self, self.pool) 518 519 def testConflictRegister(self): 520 if isinstance(self, SecondaryDescriptorFromDescriptorDB): 521 if api_implementation.Type() != 'python': 522 # Cpp extension cannot call Add on a DescriptorPool 523 # that uses a DescriptorDatabase. 524 # TODO(jieluo): Fix python and cpp extension diff. 525 return 526 unittest_fd = descriptor_pb2.FileDescriptorProto.FromString( 527 unittest_pb2.DESCRIPTOR.serialized_pb) 528 conflict_fd = copy.deepcopy(unittest_fd) 529 conflict_fd.name = 'other_file' 530 if api_implementation.Type() != 'python': 531 pass 532 else: 533 pool = copy.deepcopy(self.pool) 534 file_descriptor = unittest_pb2.DESCRIPTOR 535 pool._AddDescriptor( 536 file_descriptor.message_types_by_name['TestAllTypes']) 537 pool._AddEnumDescriptor( 538 file_descriptor.enum_types_by_name['ForeignEnum']) 539 pool._AddServiceDescriptor( 540 file_descriptor.services_by_name['TestService']) 541 pool._AddExtensionDescriptor( 542 file_descriptor.extensions_by_name['optional_int32_extension']) 543 pool.Add(unittest_fd) 544 with warnings.catch_warnings(record=True) as w: 545 warnings.simplefilter('always') 546 pool.Add(conflict_fd) 547 self.assertTrue(len(w)) 548 self.assertIs(w[0].category, RuntimeWarning) 549 self.assertIn('Conflict register for file "other_file": ', 550 str(w[0].message)) 551 pool.FindFileByName(unittest_fd.name) 552 with self.assertRaises(TypeError): 553 pool.FindFileByName(conflict_fd.name) 554 555 556@testing_refleaks.TestCase 557class DefaultDescriptorPoolTest(DescriptorPoolTestBase, unittest.TestCase): 558 559 def setUp(self): 560 self.pool = descriptor_pool.Default() 561 self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( 562 factory_test1_pb2.DESCRIPTOR.serialized_pb) 563 self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( 564 factory_test2_pb2.DESCRIPTOR.serialized_pb) 565 566 def testFindMethods(self): 567 self.assertIs( 568 self.pool.FindFileByName('google/protobuf/unittest.proto'), 569 unittest_pb2.DESCRIPTOR) 570 self.assertIs( 571 self.pool.FindMessageTypeByName('protobuf_unittest.TestAllTypes'), 572 unittest_pb2.TestAllTypes.DESCRIPTOR) 573 self.assertIs( 574 self.pool.FindFieldByName( 575 'protobuf_unittest.TestAllTypes.optional_int32'), 576 unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32']) 577 self.assertIs( 578 self.pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'), 579 unittest_pb2.ForeignEnum.DESCRIPTOR) 580 self.assertIs( 581 self.pool.FindExtensionByName( 582 'protobuf_unittest.optional_int32_extension'), 583 unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension']) 584 self.assertIs( 585 self.pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'), 586 unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field']) 587 self.assertIs( 588 self.pool.FindServiceByName('protobuf_unittest.TestService'), 589 unittest_pb2.DESCRIPTOR.services_by_name['TestService']) 590 591 592@testing_refleaks.TestCase 593class CreateDescriptorPoolTest(DescriptorPoolTestBase, unittest.TestCase): 594 595 def setUp(self): 596 self.pool = descriptor_pool.DescriptorPool() 597 self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( 598 factory_test1_pb2.DESCRIPTOR.serialized_pb) 599 self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( 600 factory_test2_pb2.DESCRIPTOR.serialized_pb) 601 self.pool.Add(self.factory_test1_fd) 602 self.pool.Add(self.factory_test2_fd) 603 604 self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 605 unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) 606 self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 607 unittest_import_pb2.DESCRIPTOR.serialized_pb)) 608 self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 609 unittest_pb2.DESCRIPTOR.serialized_pb)) 610 self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 611 no_package_pb2.DESCRIPTOR.serialized_pb)) 612 613 614@testing_refleaks.TestCase 615class SecondaryDescriptorFromDescriptorDB(DescriptorPoolTestBase, 616 unittest.TestCase): 617 618 def setUp(self): 619 self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( 620 factory_test1_pb2.DESCRIPTOR.serialized_pb) 621 self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( 622 factory_test2_pb2.DESCRIPTOR.serialized_pb) 623 self.db = descriptor_database.DescriptorDatabase() 624 self.db.Add(self.factory_test1_fd) 625 self.db.Add(self.factory_test2_fd) 626 self.db.Add(descriptor_pb2.FileDescriptorProto.FromString( 627 unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) 628 self.db.Add(descriptor_pb2.FileDescriptorProto.FromString( 629 unittest_import_pb2.DESCRIPTOR.serialized_pb)) 630 self.db.Add(descriptor_pb2.FileDescriptorProto.FromString( 631 unittest_pb2.DESCRIPTOR.serialized_pb)) 632 self.db.Add(descriptor_pb2.FileDescriptorProto.FromString( 633 no_package_pb2.DESCRIPTOR.serialized_pb)) 634 self.pool = descriptor_pool.DescriptorPool(descriptor_db=self.db) 635 636 def testErrorCollector(self): 637 file_proto = descriptor_pb2.FileDescriptorProto() 638 file_proto.package = 'collector' 639 file_proto.name = 'error_file' 640 message_type = file_proto.message_type.add() 641 message_type.name = 'ErrorMessage' 642 field = message_type.field.add() 643 field.number = 1 644 field.name = 'nested_message_field' 645 field.label = descriptor.FieldDescriptor.LABEL_OPTIONAL 646 field.type = descriptor.FieldDescriptor.TYPE_MESSAGE 647 field.type_name = 'SubMessage' 648 oneof = message_type.oneof_decl.add() 649 oneof.name = 'MyOneof' 650 enum_type = file_proto.enum_type.add() 651 enum_type.name = 'MyEnum' 652 enum_value = enum_type.value.add() 653 enum_value.name = 'MyEnumValue' 654 enum_value.number = 0 655 self.db.Add(file_proto) 656 657 self.assertRaisesRegex(KeyError, 'SubMessage', 658 self.pool.FindMessageTypeByName, 659 'collector.ErrorMessage') 660 self.assertRaisesRegex(KeyError, 'SubMessage', self.pool.FindFileByName, 661 'error_file') 662 with self.assertRaises(KeyError) as exc: 663 self.pool.FindFileByName('none_file') 664 self.assertIn(str(exc.exception), ('\'none_file\'', 665 '\"Couldn\'t find file none_file\"')) 666 667 # Pure python _ConvertFileProtoToFileDescriptor() method has side effect 668 # that all the symbols found in the file will load into the pool even the 669 # file can not build. So when FindMessageTypeByName('ErrorMessage') was 670 # called the first time, a KeyError will be raised but call the find 671 # method later will return a descriptor which is not build. 672 # TODO(jieluo): fix pure python to revert the load if file can not be build 673 if api_implementation.Type() != 'python': 674 error_msg = ('Invalid proto descriptor for file "error_file":\\n ' 675 'collector.ErrorMessage.nested_message_field: "SubMessage" ' 676 'is not defined.\\n collector.ErrorMessage.MyOneof: Oneof ' 677 'must have at least one field.\\n\'') 678 with self.assertRaises(KeyError) as exc: 679 self.pool.FindMessageTypeByName('collector.ErrorMessage') 680 self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for ' 681 'message collector.ErrorMessage\\n' + error_msg) 682 683 with self.assertRaises(KeyError) as exc: 684 self.pool.FindFieldByName('collector.ErrorMessage.nested_message_field') 685 self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for field' 686 ' collector.ErrorMessage.nested_message_field\\n' 687 + error_msg) 688 689 with self.assertRaises(KeyError) as exc: 690 self.pool.FindEnumTypeByName('collector.MyEnum') 691 self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for enum' 692 ' collector.MyEnum\\n' + error_msg) 693 694 with self.assertRaises(KeyError) as exc: 695 self.pool.FindFileContainingSymbol('collector.MyEnumValue') 696 self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for symbol' 697 ' collector.MyEnumValue\\n' + error_msg) 698 699 with self.assertRaises(KeyError) as exc: 700 self.pool.FindOneofByName('collector.ErrorMessage.MyOneof') 701 self.assertEqual(str(exc.exception), '\'Couldn\\\'t build file for oneof' 702 ' collector.ErrorMessage.MyOneof\\n' + error_msg) 703 704 705class ProtoFile(object): 706 707 def __init__(self, name, package, messages, dependencies=None, 708 public_dependencies=None): 709 self.name = name 710 self.package = package 711 self.messages = messages 712 self.dependencies = dependencies or [] 713 self.public_dependencies = public_dependencies or [] 714 715 def CheckFile(self, test, pool): 716 file_desc = pool.FindFileByName(self.name) 717 test.assertEqual(self.name, file_desc.name) 718 test.assertEqual(self.package, file_desc.package) 719 dependencies_names = [f.name for f in file_desc.dependencies] 720 test.assertEqual(self.dependencies, dependencies_names) 721 public_dependencies_names = [f.name for f in file_desc.public_dependencies] 722 test.assertEqual(self.public_dependencies, public_dependencies_names) 723 for name, msg_type in self.messages.items(): 724 msg_type.CheckType(test, None, name, file_desc) 725 726 727class EnumType(object): 728 729 def __init__(self, values): 730 self.values = values 731 732 def CheckType(self, test, msg_desc, name, file_desc): 733 enum_desc = msg_desc.enum_types_by_name[name] 734 test.assertEqual(name, enum_desc.name) 735 expected_enum_full_name = '.'.join([msg_desc.full_name, name]) 736 test.assertEqual(expected_enum_full_name, enum_desc.full_name) 737 test.assertEqual(msg_desc, enum_desc.containing_type) 738 test.assertEqual(file_desc, enum_desc.file) 739 for index, (value, number) in enumerate(self.values): 740 value_desc = enum_desc.values_by_name[value] 741 test.assertEqual(value, value_desc.name) 742 test.assertEqual(index, value_desc.index) 743 test.assertEqual(number, value_desc.number) 744 test.assertEqual(enum_desc, value_desc.type) 745 test.assertIn(value, msg_desc.enum_values_by_name) 746 747 748class MessageType(object): 749 750 def __init__(self, type_dict, field_list, is_extendable=False, 751 extensions=None): 752 self.type_dict = type_dict 753 self.field_list = field_list 754 self.is_extendable = is_extendable 755 self.extensions = extensions or [] 756 757 def CheckType(self, test, containing_type_desc, name, file_desc): 758 if containing_type_desc is None: 759 desc = file_desc.message_types_by_name[name] 760 expected_full_name = '.'.join([file_desc.package, name]) 761 else: 762 desc = containing_type_desc.nested_types_by_name[name] 763 expected_full_name = '.'.join([containing_type_desc.full_name, name]) 764 765 test.assertEqual(name, desc.name) 766 test.assertEqual(expected_full_name, desc.full_name) 767 test.assertEqual(containing_type_desc, desc.containing_type) 768 test.assertEqual(desc.file, file_desc) 769 test.assertEqual(self.is_extendable, desc.is_extendable) 770 for name, subtype in self.type_dict.items(): 771 subtype.CheckType(test, desc, name, file_desc) 772 773 for index, (name, field) in enumerate(self.field_list): 774 field.CheckField(test, desc, name, index, file_desc) 775 776 for index, (name, field) in enumerate(self.extensions): 777 field.CheckField(test, desc, name, index, file_desc) 778 779 780class EnumField(object): 781 782 def __init__(self, number, type_name, default_value): 783 self.number = number 784 self.type_name = type_name 785 self.default_value = default_value 786 787 def CheckField(self, test, msg_desc, name, index, file_desc): 788 field_desc = msg_desc.fields_by_name[name] 789 enum_desc = msg_desc.enum_types_by_name[self.type_name] 790 test.assertEqual(name, field_desc.name) 791 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 792 test.assertEqual(expected_field_full_name, field_desc.full_name) 793 test.assertEqual(index, field_desc.index) 794 test.assertEqual(self.number, field_desc.number) 795 test.assertEqual(descriptor.FieldDescriptor.TYPE_ENUM, field_desc.type) 796 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_ENUM, 797 field_desc.cpp_type) 798 test.assertTrue(field_desc.has_default_value) 799 test.assertEqual(enum_desc.values_by_name[self.default_value].number, 800 field_desc.default_value) 801 test.assertFalse(enum_desc.values_by_name[self.default_value].has_options) 802 test.assertEqual(msg_desc, field_desc.containing_type) 803 test.assertEqual(enum_desc, field_desc.enum_type) 804 test.assertEqual(file_desc, enum_desc.file) 805 806 807class MessageField(object): 808 809 def __init__(self, number, type_name): 810 self.number = number 811 self.type_name = type_name 812 813 def CheckField(self, test, msg_desc, name, index, file_desc): 814 field_desc = msg_desc.fields_by_name[name] 815 field_type_desc = msg_desc.nested_types_by_name[self.type_name] 816 test.assertEqual(name, field_desc.name) 817 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 818 test.assertEqual(expected_field_full_name, field_desc.full_name) 819 test.assertEqual(index, field_desc.index) 820 test.assertEqual(self.number, field_desc.number) 821 test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) 822 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, 823 field_desc.cpp_type) 824 test.assertFalse(field_desc.has_default_value) 825 test.assertEqual(msg_desc, field_desc.containing_type) 826 test.assertEqual(field_type_desc, field_desc.message_type) 827 test.assertEqual(file_desc, field_desc.file) 828 test.assertEqual(field_desc.default_value, None) 829 830 831class StringField(object): 832 833 def __init__(self, number, default_value): 834 self.number = number 835 self.default_value = default_value 836 837 def CheckField(self, test, msg_desc, name, index, file_desc): 838 field_desc = msg_desc.fields_by_name[name] 839 test.assertEqual(name, field_desc.name) 840 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 841 test.assertEqual(expected_field_full_name, field_desc.full_name) 842 test.assertEqual(index, field_desc.index) 843 test.assertEqual(self.number, field_desc.number) 844 test.assertEqual(descriptor.FieldDescriptor.TYPE_STRING, field_desc.type) 845 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_STRING, 846 field_desc.cpp_type) 847 test.assertTrue(field_desc.has_default_value) 848 test.assertEqual(self.default_value, field_desc.default_value) 849 test.assertEqual(file_desc, field_desc.file) 850 851 852class ExtensionField(object): 853 854 def __init__(self, number, extended_type): 855 self.number = number 856 self.extended_type = extended_type 857 858 def CheckField(self, test, msg_desc, name, index, file_desc): 859 field_desc = msg_desc.extensions_by_name[name] 860 test.assertEqual(name, field_desc.name) 861 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 862 test.assertEqual(expected_field_full_name, field_desc.full_name) 863 test.assertEqual(self.number, field_desc.number) 864 test.assertEqual(index, field_desc.index) 865 test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) 866 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, 867 field_desc.cpp_type) 868 test.assertFalse(field_desc.has_default_value) 869 test.assertTrue(field_desc.is_extension) 870 test.assertEqual(msg_desc, field_desc.extension_scope) 871 test.assertEqual(msg_desc, field_desc.message_type) 872 test.assertEqual(self.extended_type, field_desc.containing_type.name) 873 test.assertEqual(file_desc, field_desc.file) 874 875 876@testing_refleaks.TestCase 877class AddDescriptorTest(unittest.TestCase): 878 879 def _TestMessage(self, prefix): 880 pool = descriptor_pool.DescriptorPool() 881 pool._AddDescriptor(unittest_pb2.TestAllTypes.DESCRIPTOR) 882 self.assertEqual( 883 'protobuf_unittest.TestAllTypes', 884 pool.FindMessageTypeByName( 885 prefix + 'protobuf_unittest.TestAllTypes').full_name) 886 887 # AddDescriptor is not recursive. 888 with self.assertRaises(KeyError): 889 pool.FindMessageTypeByName( 890 prefix + 'protobuf_unittest.TestAllTypes.NestedMessage') 891 892 pool._AddDescriptor(unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR) 893 self.assertEqual( 894 'protobuf_unittest.TestAllTypes.NestedMessage', 895 pool.FindMessageTypeByName( 896 prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').full_name) 897 898 # Files are implicitly also indexed when messages are added. 899 self.assertEqual( 900 'google/protobuf/unittest.proto', 901 pool.FindFileByName( 902 'google/protobuf/unittest.proto').name) 903 904 self.assertEqual( 905 'google/protobuf/unittest.proto', 906 pool.FindFileContainingSymbol( 907 prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').name) 908 909 @unittest.skipIf(api_implementation.Type() != 'python', 910 'Only pure python allows _Add*()') 911 def testMessage(self): 912 self._TestMessage('') 913 self._TestMessage('.') 914 915 def _TestEnum(self, prefix): 916 pool = descriptor_pool.DescriptorPool() 917 if api_implementation.Type() == 'cpp': 918 pool.AddEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) 919 else: 920 pool._AddEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) 921 self.assertEqual( 922 'protobuf_unittest.ForeignEnum', 923 pool.FindEnumTypeByName( 924 prefix + 'protobuf_unittest.ForeignEnum').full_name) 925 926 # AddEnumDescriptor is not recursive. 927 with self.assertRaises(KeyError): 928 pool.FindEnumTypeByName( 929 prefix + 'protobuf_unittest.ForeignEnum.NestedEnum') 930 931 if api_implementation.Type() == 'cpp': 932 pool.AddEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) 933 else: 934 pool._AddEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) 935 self.assertEqual( 936 'protobuf_unittest.TestAllTypes.NestedEnum', 937 pool.FindEnumTypeByName( 938 prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) 939 940 # Files are implicitly also indexed when enums are added. 941 self.assertEqual( 942 'google/protobuf/unittest.proto', 943 pool.FindFileByName( 944 'google/protobuf/unittest.proto').name) 945 946 self.assertEqual( 947 'google/protobuf/unittest.proto', 948 pool.FindFileContainingSymbol( 949 prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').name) 950 951 @unittest.skipIf(api_implementation.Type() != 'python', 952 'Only pure python allows _Add*()') 953 def testEnum(self): 954 self._TestEnum('') 955 self._TestEnum('.') 956 957 @unittest.skipIf(api_implementation.Type() != 'python', 958 'Only pure python allows _Add*()') 959 def testService(self): 960 pool = descriptor_pool.DescriptorPool() 961 with self.assertRaises(KeyError): 962 pool.FindServiceByName('protobuf_unittest.TestService') 963 pool._AddServiceDescriptor(unittest_pb2._TESTSERVICE) 964 self.assertEqual( 965 'protobuf_unittest.TestService', 966 pool.FindServiceByName('protobuf_unittest.TestService').full_name) 967 968 @unittest.skipIf(api_implementation.Type() != 'python', 969 'Only pure python allows _Add*()') 970 def testFile(self): 971 pool = descriptor_pool.DescriptorPool() 972 pool._AddFileDescriptor(unittest_pb2.DESCRIPTOR) 973 self.assertEqual( 974 'google/protobuf/unittest.proto', 975 pool.FindFileByName( 976 'google/protobuf/unittest.proto').name) 977 978 # AddFileDescriptor is not recursive; messages and enums within files must 979 # be explicitly registered. 980 with self.assertRaises(KeyError): 981 pool.FindFileContainingSymbol( 982 'protobuf_unittest.TestAllTypes') 983 984 def testEmptyDescriptorPool(self): 985 # Check that an empty DescriptorPool() contains no messages. 986 pool = descriptor_pool.DescriptorPool() 987 proto_file_name = descriptor_pb2.DESCRIPTOR.name 988 self.assertRaises(KeyError, pool.FindFileByName, proto_file_name) 989 # Add the above file to the pool 990 file_descriptor = descriptor_pb2.FileDescriptorProto() 991 descriptor_pb2.DESCRIPTOR.CopyToProto(file_descriptor) 992 pool.Add(file_descriptor) 993 # Now it exists. 994 self.assertTrue(pool.FindFileByName(proto_file_name)) 995 996 def testCustomDescriptorPool(self): 997 # Create a new pool, and add a file descriptor. 998 pool = descriptor_pool.DescriptorPool() 999 file_desc = descriptor_pb2.FileDescriptorProto( 1000 name='some/file.proto', package='package') 1001 file_desc.message_type.add(name='Message') 1002 pool.Add(file_desc) 1003 self.assertEqual(pool.FindFileByName('some/file.proto').name, 1004 'some/file.proto') 1005 self.assertEqual(pool.FindMessageTypeByName('package.Message').name, 1006 'Message') 1007 # Test no package 1008 file_proto = descriptor_pb2.FileDescriptorProto( 1009 name='some/filename/container.proto') 1010 message_proto = file_proto.message_type.add( 1011 name='TopMessage') 1012 message_proto.field.add( 1013 name='bb', 1014 number=1, 1015 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 1016 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) 1017 enum_proto = file_proto.enum_type.add(name='TopEnum') 1018 enum_proto.value.add(name='FOREIGN_FOO', number=4) 1019 file_proto.service.add(name='TopService') 1020 pool = descriptor_pool.DescriptorPool() 1021 pool.Add(file_proto) 1022 self.assertEqual('TopMessage', 1023 pool.FindMessageTypeByName('TopMessage').name) 1024 self.assertEqual('TopEnum', pool.FindEnumTypeByName('TopEnum').name) 1025 self.assertEqual('TopService', pool.FindServiceByName('TopService').name) 1026 1027 def testFileDescriptorOptionsWithCustomDescriptorPool(self): 1028 # Create a descriptor pool, and add a new FileDescriptorProto to it. 1029 pool = descriptor_pool.DescriptorPool() 1030 file_name = 'file_descriptor_options_with_custom_descriptor_pool.proto' 1031 file_descriptor_proto = descriptor_pb2.FileDescriptorProto(name=file_name) 1032 extension_id = file_options_test_pb2.foo_options 1033 file_descriptor_proto.options.Extensions[extension_id].foo_name = 'foo' 1034 pool.Add(file_descriptor_proto) 1035 # The options set on the FileDescriptorProto should be available in the 1036 # descriptor even if they contain extensions that cannot be deserialized 1037 # using the pool. 1038 file_descriptor = pool.FindFileByName(file_name) 1039 options = file_descriptor.GetOptions() 1040 self.assertEqual('foo', options.Extensions[extension_id].foo_name) 1041 # The object returned by GetOptions() is cached. 1042 self.assertIs(options, file_descriptor.GetOptions()) 1043 1044 def testAddTypeError(self): 1045 pool = descriptor_pool.DescriptorPool() 1046 if api_implementation.Type() != 'python': 1047 with self.assertRaises(TypeError): 1048 pool.AddDescriptor(0) 1049 with self.assertRaises(TypeError): 1050 pool.AddEnumDescriptor(0) 1051 with self.assertRaises(TypeError): 1052 pool.AddServiceDescriptor(0) 1053 with self.assertRaises(TypeError): 1054 pool.AddExtensionDescriptor(0) 1055 with self.assertRaises(TypeError): 1056 pool.AddFileDescriptor(0) 1057 else: 1058 with self.assertRaises(TypeError): 1059 pool._AddDescriptor(0) 1060 with self.assertRaises(TypeError): 1061 pool._AddEnumDescriptor(0) 1062 with self.assertRaises(TypeError): 1063 pool._AddServiceDescriptor(0) 1064 with self.assertRaises(TypeError): 1065 pool._AddExtensionDescriptor(0) 1066 with self.assertRaises(TypeError): 1067 pool._AddFileDescriptor(0) 1068 1069 1070TEST1_FILE = ProtoFile( 1071 'google/protobuf/internal/descriptor_pool_test1.proto', 1072 'google.protobuf.python.internal', 1073 { 1074 'DescriptorPoolTest1': MessageType({ 1075 'NestedEnum': EnumType([('ALPHA', 1), ('BETA', 2)]), 1076 'NestedMessage': MessageType({ 1077 'NestedEnum': EnumType([('EPSILON', 5), ('ZETA', 6)]), 1078 'DeepNestedMessage': MessageType({ 1079 'NestedEnum': EnumType([('ETA', 7), ('THETA', 8)]), 1080 }, [ 1081 ('nested_enum', EnumField(1, 'NestedEnum', 'ETA')), 1082 ('nested_field', StringField(2, 'theta')), 1083 ]), 1084 }, [ 1085 ('nested_enum', EnumField(1, 'NestedEnum', 'ZETA')), 1086 ('nested_field', StringField(2, 'beta')), 1087 ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), 1088 ]) 1089 }, [ 1090 ('nested_enum', EnumField(1, 'NestedEnum', 'BETA')), 1091 ('nested_message', MessageField(2, 'NestedMessage')), 1092 ], is_extendable=True), 1093 1094 'DescriptorPoolTest2': MessageType({ 1095 'NestedEnum': EnumType([('GAMMA', 3), ('DELTA', 4)]), 1096 'NestedMessage': MessageType({ 1097 'NestedEnum': EnumType([('IOTA', 9), ('KAPPA', 10)]), 1098 'DeepNestedMessage': MessageType({ 1099 'NestedEnum': EnumType([('LAMBDA', 11), ('MU', 12)]), 1100 }, [ 1101 ('nested_enum', EnumField(1, 'NestedEnum', 'MU')), 1102 ('nested_field', StringField(2, 'lambda')), 1103 ]), 1104 }, [ 1105 ('nested_enum', EnumField(1, 'NestedEnum', 'IOTA')), 1106 ('nested_field', StringField(2, 'delta')), 1107 ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), 1108 ]) 1109 }, [ 1110 ('nested_enum', EnumField(1, 'NestedEnum', 'GAMMA')), 1111 ('nested_message', MessageField(2, 'NestedMessage')), 1112 ]), 1113 }) 1114 1115 1116TEST2_FILE = ProtoFile( 1117 'google/protobuf/internal/descriptor_pool_test2.proto', 1118 'google.protobuf.python.internal', 1119 { 1120 'DescriptorPoolTest3': MessageType({ 1121 'NestedEnum': EnumType([('NU', 13), ('XI', 14)]), 1122 'NestedMessage': MessageType({ 1123 'NestedEnum': EnumType([('OMICRON', 15), ('PI', 16)]), 1124 'DeepNestedMessage': MessageType({ 1125 'NestedEnum': EnumType([('RHO', 17), ('SIGMA', 18)]), 1126 }, [ 1127 ('nested_enum', EnumField(1, 'NestedEnum', 'RHO')), 1128 ('nested_field', StringField(2, 'sigma')), 1129 ]), 1130 }, [ 1131 ('nested_enum', EnumField(1, 'NestedEnum', 'PI')), 1132 ('nested_field', StringField(2, 'nu')), 1133 ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), 1134 ]) 1135 }, [ 1136 ('nested_enum', EnumField(1, 'NestedEnum', 'XI')), 1137 ('nested_message', MessageField(2, 'NestedMessage')), 1138 ], extensions=[ 1139 ('descriptor_pool_test', 1140 ExtensionField(1001, 'DescriptorPoolTest1')), 1141 ]), 1142 }, 1143 dependencies=['google/protobuf/internal/descriptor_pool_test1.proto', 1144 'google/protobuf/internal/more_messages.proto'], 1145 public_dependencies=['google/protobuf/internal/more_messages.proto']) 1146 1147 1148if __name__ == '__main__': 1149 unittest.main() 1150