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