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 os 38import sys 39 40try: 41 import unittest2 as unittest #PY26 42except ImportError: 43 import unittest 44 45from google.protobuf import unittest_import_pb2 46from google.protobuf import unittest_import_public_pb2 47from google.protobuf import unittest_pb2 48from google.protobuf import descriptor_pb2 49from google.protobuf.internal import api_implementation 50from google.protobuf.internal import descriptor_pool_test1_pb2 51from google.protobuf.internal import descriptor_pool_test2_pb2 52from google.protobuf.internal import factory_test1_pb2 53from google.protobuf.internal import factory_test2_pb2 54from google.protobuf.internal import more_messages_pb2 55from google.protobuf import descriptor 56from google.protobuf import descriptor_database 57from google.protobuf import descriptor_pool 58from google.protobuf import message_factory 59from google.protobuf import symbol_database 60 61 62class DescriptorPoolTest(unittest.TestCase): 63 64 def setUp(self): 65 self.pool = descriptor_pool.DescriptorPool() 66 self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( 67 factory_test1_pb2.DESCRIPTOR.serialized_pb) 68 self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( 69 factory_test2_pb2.DESCRIPTOR.serialized_pb) 70 self.pool.Add(self.factory_test1_fd) 71 self.pool.Add(self.factory_test2_fd) 72 73 def testFindFileByName(self): 74 name1 = 'google/protobuf/internal/factory_test1.proto' 75 file_desc1 = self.pool.FindFileByName(name1) 76 self.assertIsInstance(file_desc1, descriptor.FileDescriptor) 77 self.assertEqual(name1, file_desc1.name) 78 self.assertEqual('google.protobuf.python.internal', file_desc1.package) 79 self.assertIn('Factory1Message', file_desc1.message_types_by_name) 80 81 name2 = 'google/protobuf/internal/factory_test2.proto' 82 file_desc2 = self.pool.FindFileByName(name2) 83 self.assertIsInstance(file_desc2, descriptor.FileDescriptor) 84 self.assertEqual(name2, file_desc2.name) 85 self.assertEqual('google.protobuf.python.internal', file_desc2.package) 86 self.assertIn('Factory2Message', file_desc2.message_types_by_name) 87 88 def testFindFileByNameFailure(self): 89 with self.assertRaises(KeyError): 90 self.pool.FindFileByName('Does not exist') 91 92 def testFindFileContainingSymbol(self): 93 file_desc1 = self.pool.FindFileContainingSymbol( 94 'google.protobuf.python.internal.Factory1Message') 95 self.assertIsInstance(file_desc1, descriptor.FileDescriptor) 96 self.assertEqual('google/protobuf/internal/factory_test1.proto', 97 file_desc1.name) 98 self.assertEqual('google.protobuf.python.internal', file_desc1.package) 99 self.assertIn('Factory1Message', file_desc1.message_types_by_name) 100 101 file_desc2 = self.pool.FindFileContainingSymbol( 102 'google.protobuf.python.internal.Factory2Message') 103 self.assertIsInstance(file_desc2, descriptor.FileDescriptor) 104 self.assertEqual('google/protobuf/internal/factory_test2.proto', 105 file_desc2.name) 106 self.assertEqual('google.protobuf.python.internal', file_desc2.package) 107 self.assertIn('Factory2Message', file_desc2.message_types_by_name) 108 109 def testFindFileContainingSymbolFailure(self): 110 with self.assertRaises(KeyError): 111 self.pool.FindFileContainingSymbol('Does not exist') 112 113 def testFindMessageTypeByName(self): 114 msg1 = self.pool.FindMessageTypeByName( 115 'google.protobuf.python.internal.Factory1Message') 116 self.assertIsInstance(msg1, descriptor.Descriptor) 117 self.assertEqual('Factory1Message', msg1.name) 118 self.assertEqual('google.protobuf.python.internal.Factory1Message', 119 msg1.full_name) 120 self.assertEqual(None, msg1.containing_type) 121 122 nested_msg1 = msg1.nested_types[0] 123 self.assertEqual('NestedFactory1Message', nested_msg1.name) 124 self.assertEqual(msg1, nested_msg1.containing_type) 125 126 nested_enum1 = msg1.enum_types[0] 127 self.assertEqual('NestedFactory1Enum', nested_enum1.name) 128 self.assertEqual(msg1, nested_enum1.containing_type) 129 130 self.assertEqual(nested_msg1, msg1.fields_by_name[ 131 'nested_factory_1_message'].message_type) 132 self.assertEqual(nested_enum1, msg1.fields_by_name[ 133 'nested_factory_1_enum'].enum_type) 134 135 msg2 = self.pool.FindMessageTypeByName( 136 'google.protobuf.python.internal.Factory2Message') 137 self.assertIsInstance(msg2, descriptor.Descriptor) 138 self.assertEqual('Factory2Message', msg2.name) 139 self.assertEqual('google.protobuf.python.internal.Factory2Message', 140 msg2.full_name) 141 self.assertIsNone(msg2.containing_type) 142 143 nested_msg2 = msg2.nested_types[0] 144 self.assertEqual('NestedFactory2Message', nested_msg2.name) 145 self.assertEqual(msg2, nested_msg2.containing_type) 146 147 nested_enum2 = msg2.enum_types[0] 148 self.assertEqual('NestedFactory2Enum', nested_enum2.name) 149 self.assertEqual(msg2, nested_enum2.containing_type) 150 151 self.assertEqual(nested_msg2, msg2.fields_by_name[ 152 'nested_factory_2_message'].message_type) 153 self.assertEqual(nested_enum2, msg2.fields_by_name[ 154 'nested_factory_2_enum'].enum_type) 155 156 self.assertTrue(msg2.fields_by_name['int_with_default'].has_default_value) 157 self.assertEqual( 158 1776, msg2.fields_by_name['int_with_default'].default_value) 159 160 self.assertTrue( 161 msg2.fields_by_name['double_with_default'].has_default_value) 162 self.assertEqual( 163 9.99, msg2.fields_by_name['double_with_default'].default_value) 164 165 self.assertTrue( 166 msg2.fields_by_name['string_with_default'].has_default_value) 167 self.assertEqual( 168 'hello world', msg2.fields_by_name['string_with_default'].default_value) 169 170 self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default_value) 171 self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value) 172 173 self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default_value) 174 self.assertEqual( 175 1, msg2.fields_by_name['enum_with_default'].default_value) 176 177 msg3 = self.pool.FindMessageTypeByName( 178 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message') 179 self.assertEqual(nested_msg2, msg3) 180 181 self.assertTrue(msg2.fields_by_name['bytes_with_default'].has_default_value) 182 self.assertEqual( 183 b'a\xfb\x00c', 184 msg2.fields_by_name['bytes_with_default'].default_value) 185 186 self.assertEqual(1, len(msg2.oneofs)) 187 self.assertEqual(1, len(msg2.oneofs_by_name)) 188 self.assertEqual(2, len(msg2.oneofs[0].fields)) 189 for name in ['oneof_int', 'oneof_string']: 190 self.assertEqual(msg2.oneofs[0], 191 msg2.fields_by_name[name].containing_oneof) 192 self.assertIn(msg2.fields_by_name[name], msg2.oneofs[0].fields) 193 194 def testFindMessageTypeByNameFailure(self): 195 with self.assertRaises(KeyError): 196 self.pool.FindMessageTypeByName('Does not exist') 197 198 def testFindEnumTypeByName(self): 199 enum1 = self.pool.FindEnumTypeByName( 200 'google.protobuf.python.internal.Factory1Enum') 201 self.assertIsInstance(enum1, descriptor.EnumDescriptor) 202 self.assertEqual(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number) 203 self.assertEqual(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number) 204 205 nested_enum1 = self.pool.FindEnumTypeByName( 206 'google.protobuf.python.internal.Factory1Message.NestedFactory1Enum') 207 self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor) 208 self.assertEqual( 209 0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number) 210 self.assertEqual( 211 1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number) 212 213 enum2 = self.pool.FindEnumTypeByName( 214 'google.protobuf.python.internal.Factory2Enum') 215 self.assertIsInstance(enum2, descriptor.EnumDescriptor) 216 self.assertEqual(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number) 217 self.assertEqual(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number) 218 219 nested_enum2 = self.pool.FindEnumTypeByName( 220 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum') 221 self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor) 222 self.assertEqual( 223 0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number) 224 self.assertEqual( 225 1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number) 226 227 def testFindEnumTypeByNameFailure(self): 228 with self.assertRaises(KeyError): 229 self.pool.FindEnumTypeByName('Does not exist') 230 231 def testFindFieldByName(self): 232 field = self.pool.FindFieldByName( 233 'google.protobuf.python.internal.Factory1Message.list_value') 234 self.assertEqual(field.name, 'list_value') 235 self.assertEqual(field.label, field.LABEL_REPEATED) 236 with self.assertRaises(KeyError): 237 self.pool.FindFieldByName('Does not exist') 238 239 def testFindExtensionByName(self): 240 # An extension defined in a message. 241 extension = self.pool.FindExtensionByName( 242 'google.protobuf.python.internal.Factory2Message.one_more_field') 243 self.assertEqual(extension.name, 'one_more_field') 244 # An extension defined at file scope. 245 extension = self.pool.FindExtensionByName( 246 'google.protobuf.python.internal.another_field') 247 self.assertEqual(extension.name, 'another_field') 248 self.assertEqual(extension.number, 1002) 249 with self.assertRaises(KeyError): 250 self.pool.FindFieldByName('Does not exist') 251 252 def testExtensionsAreNotFields(self): 253 with self.assertRaises(KeyError): 254 self.pool.FindFieldByName('google.protobuf.python.internal.another_field') 255 with self.assertRaises(KeyError): 256 self.pool.FindFieldByName( 257 'google.protobuf.python.internal.Factory2Message.one_more_field') 258 with self.assertRaises(KeyError): 259 self.pool.FindExtensionByName( 260 'google.protobuf.python.internal.Factory1Message.list_value') 261 262 def testUserDefinedDB(self): 263 db = descriptor_database.DescriptorDatabase() 264 self.pool = descriptor_pool.DescriptorPool(db) 265 db.Add(self.factory_test1_fd) 266 db.Add(self.factory_test2_fd) 267 self.testFindMessageTypeByName() 268 269 def testAddSerializedFile(self): 270 self.pool = descriptor_pool.DescriptorPool() 271 self.pool.AddSerializedFile(self.factory_test1_fd.SerializeToString()) 272 self.pool.AddSerializedFile(self.factory_test2_fd.SerializeToString()) 273 self.testFindMessageTypeByName() 274 275 def testComplexNesting(self): 276 more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString( 277 more_messages_pb2.DESCRIPTOR.serialized_pb) 278 test1_desc = descriptor_pb2.FileDescriptorProto.FromString( 279 descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) 280 test2_desc = descriptor_pb2.FileDescriptorProto.FromString( 281 descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb) 282 self.pool.Add(more_messages_desc) 283 self.pool.Add(test1_desc) 284 self.pool.Add(test2_desc) 285 TEST1_FILE.CheckFile(self, self.pool) 286 TEST2_FILE.CheckFile(self, self.pool) 287 288 289 def testEnumDefaultValue(self): 290 """Test the default value of enums which don't start at zero.""" 291 def _CheckDefaultValue(file_descriptor): 292 default_value = (file_descriptor 293 .message_types_by_name['DescriptorPoolTest1'] 294 .fields_by_name['nested_enum'] 295 .default_value) 296 self.assertEqual(default_value, 297 descriptor_pool_test1_pb2.DescriptorPoolTest1.BETA) 298 # First check what the generated descriptor contains. 299 _CheckDefaultValue(descriptor_pool_test1_pb2.DESCRIPTOR) 300 # Then check the generated pool. Normally this is the same descriptor. 301 file_descriptor = symbol_database.Default().pool.FindFileByName( 302 'google/protobuf/internal/descriptor_pool_test1.proto') 303 self.assertIs(file_descriptor, descriptor_pool_test1_pb2.DESCRIPTOR) 304 _CheckDefaultValue(file_descriptor) 305 306 # Then check the dynamic pool and its internal DescriptorDatabase. 307 descriptor_proto = descriptor_pb2.FileDescriptorProto.FromString( 308 descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) 309 self.pool.Add(descriptor_proto) 310 # And do the same check as above 311 file_descriptor = self.pool.FindFileByName( 312 'google/protobuf/internal/descriptor_pool_test1.proto') 313 _CheckDefaultValue(file_descriptor) 314 315 def testDefaultValueForCustomMessages(self): 316 """Check the value returned by non-existent fields.""" 317 def _CheckValueAndType(value, expected_value, expected_type): 318 self.assertEqual(value, expected_value) 319 self.assertIsInstance(value, expected_type) 320 321 def _CheckDefaultValues(msg): 322 try: 323 int64 = long 324 except NameError: # Python3 325 int64 = int 326 try: 327 unicode_type = unicode 328 except NameError: # Python3 329 unicode_type = str 330 _CheckValueAndType(msg.optional_int32, 0, int) 331 _CheckValueAndType(msg.optional_uint64, 0, (int64, int)) 332 _CheckValueAndType(msg.optional_float, 0, (float, int)) 333 _CheckValueAndType(msg.optional_double, 0, (float, int)) 334 _CheckValueAndType(msg.optional_bool, False, bool) 335 _CheckValueAndType(msg.optional_string, u'', unicode_type) 336 _CheckValueAndType(msg.optional_bytes, b'', bytes) 337 _CheckValueAndType(msg.optional_nested_enum, msg.FOO, int) 338 # First for the generated message 339 _CheckDefaultValues(unittest_pb2.TestAllTypes()) 340 # Then for a message built with from the DescriptorPool. 341 pool = descriptor_pool.DescriptorPool() 342 pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 343 unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) 344 pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 345 unittest_import_pb2.DESCRIPTOR.serialized_pb)) 346 pool.Add(descriptor_pb2.FileDescriptorProto.FromString( 347 unittest_pb2.DESCRIPTOR.serialized_pb)) 348 message_class = message_factory.MessageFactory(pool).GetPrototype( 349 pool.FindMessageTypeByName( 350 unittest_pb2.TestAllTypes.DESCRIPTOR.full_name)) 351 _CheckDefaultValues(message_class()) 352 353 354class ProtoFile(object): 355 356 def __init__(self, name, package, messages, dependencies=None, 357 public_dependencies=None): 358 self.name = name 359 self.package = package 360 self.messages = messages 361 self.dependencies = dependencies or [] 362 self.public_dependencies = public_dependencies or [] 363 364 def CheckFile(self, test, pool): 365 file_desc = pool.FindFileByName(self.name) 366 test.assertEqual(self.name, file_desc.name) 367 test.assertEqual(self.package, file_desc.package) 368 dependencies_names = [f.name for f in file_desc.dependencies] 369 test.assertEqual(self.dependencies, dependencies_names) 370 public_dependencies_names = [f.name for f in file_desc.public_dependencies] 371 test.assertEqual(self.public_dependencies, public_dependencies_names) 372 for name, msg_type in self.messages.items(): 373 msg_type.CheckType(test, None, name, file_desc) 374 375 376class EnumType(object): 377 378 def __init__(self, values): 379 self.values = values 380 381 def CheckType(self, test, msg_desc, name, file_desc): 382 enum_desc = msg_desc.enum_types_by_name[name] 383 test.assertEqual(name, enum_desc.name) 384 expected_enum_full_name = '.'.join([msg_desc.full_name, name]) 385 test.assertEqual(expected_enum_full_name, enum_desc.full_name) 386 test.assertEqual(msg_desc, enum_desc.containing_type) 387 test.assertEqual(file_desc, enum_desc.file) 388 for index, (value, number) in enumerate(self.values): 389 value_desc = enum_desc.values_by_name[value] 390 test.assertEqual(value, value_desc.name) 391 test.assertEqual(index, value_desc.index) 392 test.assertEqual(number, value_desc.number) 393 test.assertEqual(enum_desc, value_desc.type) 394 test.assertIn(value, msg_desc.enum_values_by_name) 395 396 397class MessageType(object): 398 399 def __init__(self, type_dict, field_list, is_extendable=False, 400 extensions=None): 401 self.type_dict = type_dict 402 self.field_list = field_list 403 self.is_extendable = is_extendable 404 self.extensions = extensions or [] 405 406 def CheckType(self, test, containing_type_desc, name, file_desc): 407 if containing_type_desc is None: 408 desc = file_desc.message_types_by_name[name] 409 expected_full_name = '.'.join([file_desc.package, name]) 410 else: 411 desc = containing_type_desc.nested_types_by_name[name] 412 expected_full_name = '.'.join([containing_type_desc.full_name, name]) 413 414 test.assertEqual(name, desc.name) 415 test.assertEqual(expected_full_name, desc.full_name) 416 test.assertEqual(containing_type_desc, desc.containing_type) 417 test.assertEqual(desc.file, file_desc) 418 test.assertEqual(self.is_extendable, desc.is_extendable) 419 for name, subtype in self.type_dict.items(): 420 subtype.CheckType(test, desc, name, file_desc) 421 422 for index, (name, field) in enumerate(self.field_list): 423 field.CheckField(test, desc, name, index) 424 425 for index, (name, field) in enumerate(self.extensions): 426 field.CheckField(test, desc, name, index) 427 428 429class EnumField(object): 430 431 def __init__(self, number, type_name, default_value): 432 self.number = number 433 self.type_name = type_name 434 self.default_value = default_value 435 436 def CheckField(self, test, msg_desc, name, index): 437 field_desc = msg_desc.fields_by_name[name] 438 enum_desc = msg_desc.enum_types_by_name[self.type_name] 439 test.assertEqual(name, field_desc.name) 440 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 441 test.assertEqual(expected_field_full_name, field_desc.full_name) 442 test.assertEqual(index, field_desc.index) 443 test.assertEqual(self.number, field_desc.number) 444 test.assertEqual(descriptor.FieldDescriptor.TYPE_ENUM, field_desc.type) 445 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_ENUM, 446 field_desc.cpp_type) 447 test.assertTrue(field_desc.has_default_value) 448 test.assertEqual(enum_desc.values_by_name[self.default_value].number, 449 field_desc.default_value) 450 test.assertEqual(msg_desc, field_desc.containing_type) 451 test.assertEqual(enum_desc, field_desc.enum_type) 452 453 454class MessageField(object): 455 456 def __init__(self, number, type_name): 457 self.number = number 458 self.type_name = type_name 459 460 def CheckField(self, test, msg_desc, name, index): 461 field_desc = msg_desc.fields_by_name[name] 462 field_type_desc = msg_desc.nested_types_by_name[self.type_name] 463 test.assertEqual(name, field_desc.name) 464 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 465 test.assertEqual(expected_field_full_name, field_desc.full_name) 466 test.assertEqual(index, field_desc.index) 467 test.assertEqual(self.number, field_desc.number) 468 test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) 469 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, 470 field_desc.cpp_type) 471 test.assertFalse(field_desc.has_default_value) 472 test.assertEqual(msg_desc, field_desc.containing_type) 473 test.assertEqual(field_type_desc, field_desc.message_type) 474 475 476class StringField(object): 477 478 def __init__(self, number, default_value): 479 self.number = number 480 self.default_value = default_value 481 482 def CheckField(self, test, msg_desc, name, index): 483 field_desc = msg_desc.fields_by_name[name] 484 test.assertEqual(name, field_desc.name) 485 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 486 test.assertEqual(expected_field_full_name, field_desc.full_name) 487 test.assertEqual(index, field_desc.index) 488 test.assertEqual(self.number, field_desc.number) 489 test.assertEqual(descriptor.FieldDescriptor.TYPE_STRING, field_desc.type) 490 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_STRING, 491 field_desc.cpp_type) 492 test.assertTrue(field_desc.has_default_value) 493 test.assertEqual(self.default_value, field_desc.default_value) 494 495 496class ExtensionField(object): 497 498 def __init__(self, number, extended_type): 499 self.number = number 500 self.extended_type = extended_type 501 502 def CheckField(self, test, msg_desc, name, index): 503 field_desc = msg_desc.extensions_by_name[name] 504 test.assertEqual(name, field_desc.name) 505 expected_field_full_name = '.'.join([msg_desc.full_name, name]) 506 test.assertEqual(expected_field_full_name, field_desc.full_name) 507 test.assertEqual(self.number, field_desc.number) 508 test.assertEqual(index, field_desc.index) 509 test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) 510 test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, 511 field_desc.cpp_type) 512 test.assertFalse(field_desc.has_default_value) 513 test.assertTrue(field_desc.is_extension) 514 test.assertEqual(msg_desc, field_desc.extension_scope) 515 test.assertEqual(msg_desc, field_desc.message_type) 516 test.assertEqual(self.extended_type, field_desc.containing_type.name) 517 518 519class AddDescriptorTest(unittest.TestCase): 520 521 def _TestMessage(self, prefix): 522 pool = descriptor_pool.DescriptorPool() 523 pool.AddDescriptor(unittest_pb2.TestAllTypes.DESCRIPTOR) 524 self.assertEqual( 525 'protobuf_unittest.TestAllTypes', 526 pool.FindMessageTypeByName( 527 prefix + 'protobuf_unittest.TestAllTypes').full_name) 528 529 # AddDescriptor is not recursive. 530 with self.assertRaises(KeyError): 531 pool.FindMessageTypeByName( 532 prefix + 'protobuf_unittest.TestAllTypes.NestedMessage') 533 534 pool.AddDescriptor(unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR) 535 self.assertEqual( 536 'protobuf_unittest.TestAllTypes.NestedMessage', 537 pool.FindMessageTypeByName( 538 prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').full_name) 539 540 # Files are implicitly also indexed when messages are added. 541 self.assertEqual( 542 'google/protobuf/unittest.proto', 543 pool.FindFileByName( 544 'google/protobuf/unittest.proto').name) 545 546 self.assertEqual( 547 'google/protobuf/unittest.proto', 548 pool.FindFileContainingSymbol( 549 prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').name) 550 551 @unittest.skipIf(api_implementation.Type() == 'cpp', 552 'With the cpp implementation, Add() must be called first') 553 def testMessage(self): 554 self._TestMessage('') 555 self._TestMessage('.') 556 557 def _TestEnum(self, prefix): 558 pool = descriptor_pool.DescriptorPool() 559 pool.AddEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) 560 self.assertEqual( 561 'protobuf_unittest.ForeignEnum', 562 pool.FindEnumTypeByName( 563 prefix + 'protobuf_unittest.ForeignEnum').full_name) 564 565 # AddEnumDescriptor is not recursive. 566 with self.assertRaises(KeyError): 567 pool.FindEnumTypeByName( 568 prefix + 'protobuf_unittest.ForeignEnum.NestedEnum') 569 570 pool.AddEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) 571 self.assertEqual( 572 'protobuf_unittest.TestAllTypes.NestedEnum', 573 pool.FindEnumTypeByName( 574 prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) 575 576 # Files are implicitly also indexed when enums are added. 577 self.assertEqual( 578 'google/protobuf/unittest.proto', 579 pool.FindFileByName( 580 'google/protobuf/unittest.proto').name) 581 582 self.assertEqual( 583 'google/protobuf/unittest.proto', 584 pool.FindFileContainingSymbol( 585 prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').name) 586 587 @unittest.skipIf(api_implementation.Type() == 'cpp', 588 'With the cpp implementation, Add() must be called first') 589 def testEnum(self): 590 self._TestEnum('') 591 self._TestEnum('.') 592 593 @unittest.skipIf(api_implementation.Type() == 'cpp', 594 'With the cpp implementation, Add() must be called first') 595 def testFile(self): 596 pool = descriptor_pool.DescriptorPool() 597 pool.AddFileDescriptor(unittest_pb2.DESCRIPTOR) 598 self.assertEqual( 599 'google/protobuf/unittest.proto', 600 pool.FindFileByName( 601 'google/protobuf/unittest.proto').name) 602 603 # AddFileDescriptor is not recursive; messages and enums within files must 604 # be explicitly registered. 605 with self.assertRaises(KeyError): 606 pool.FindFileContainingSymbol( 607 'protobuf_unittest.TestAllTypes') 608 609 def testEmptyDescriptorPool(self): 610 # Check that an empty DescriptorPool() contains no messages. 611 pool = descriptor_pool.DescriptorPool() 612 proto_file_name = descriptor_pb2.DESCRIPTOR.name 613 self.assertRaises(KeyError, pool.FindFileByName, proto_file_name) 614 # Add the above file to the pool 615 file_descriptor = descriptor_pb2.FileDescriptorProto() 616 descriptor_pb2.DESCRIPTOR.CopyToProto(file_descriptor) 617 pool.Add(file_descriptor) 618 # Now it exists. 619 self.assertTrue(pool.FindFileByName(proto_file_name)) 620 621 def testCustomDescriptorPool(self): 622 # Create a new pool, and add a file descriptor. 623 pool = descriptor_pool.DescriptorPool() 624 file_desc = descriptor_pb2.FileDescriptorProto( 625 name='some/file.proto', package='package') 626 file_desc.message_type.add(name='Message') 627 pool.Add(file_desc) 628 self.assertEqual(pool.FindFileByName('some/file.proto').name, 629 'some/file.proto') 630 self.assertEqual(pool.FindMessageTypeByName('package.Message').name, 631 'Message') 632 633 634@unittest.skipIf( 635 api_implementation.Type() != 'cpp', 636 'default_pool is only supported by the C++ implementation') 637class DefaultPoolTest(unittest.TestCase): 638 639 def testFindMethods(self): 640 # pylint: disable=g-import-not-at-top 641 from google.protobuf.pyext import _message 642 pool = _message.default_pool 643 self.assertIs( 644 pool.FindFileByName('google/protobuf/unittest.proto'), 645 unittest_pb2.DESCRIPTOR) 646 self.assertIs( 647 pool.FindMessageTypeByName('protobuf_unittest.TestAllTypes'), 648 unittest_pb2.TestAllTypes.DESCRIPTOR) 649 self.assertIs( 650 pool.FindFieldByName('protobuf_unittest.TestAllTypes.optional_int32'), 651 unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32']) 652 self.assertIs( 653 pool.FindExtensionByName('protobuf_unittest.optional_int32_extension'), 654 unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension']) 655 self.assertIs( 656 pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'), 657 unittest_pb2.ForeignEnum.DESCRIPTOR) 658 self.assertIs( 659 pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'), 660 unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field']) 661 662 def testAddFileDescriptor(self): 663 # pylint: disable=g-import-not-at-top 664 from google.protobuf.pyext import _message 665 pool = _message.default_pool 666 file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto') 667 pool.Add(file_desc) 668 pool.AddSerializedFile(file_desc.SerializeToString()) 669 670 671TEST1_FILE = ProtoFile( 672 'google/protobuf/internal/descriptor_pool_test1.proto', 673 'google.protobuf.python.internal', 674 { 675 'DescriptorPoolTest1': MessageType({ 676 'NestedEnum': EnumType([('ALPHA', 1), ('BETA', 2)]), 677 'NestedMessage': MessageType({ 678 'NestedEnum': EnumType([('EPSILON', 5), ('ZETA', 6)]), 679 'DeepNestedMessage': MessageType({ 680 'NestedEnum': EnumType([('ETA', 7), ('THETA', 8)]), 681 }, [ 682 ('nested_enum', EnumField(1, 'NestedEnum', 'ETA')), 683 ('nested_field', StringField(2, 'theta')), 684 ]), 685 }, [ 686 ('nested_enum', EnumField(1, 'NestedEnum', 'ZETA')), 687 ('nested_field', StringField(2, 'beta')), 688 ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), 689 ]) 690 }, [ 691 ('nested_enum', EnumField(1, 'NestedEnum', 'BETA')), 692 ('nested_message', MessageField(2, 'NestedMessage')), 693 ], is_extendable=True), 694 695 'DescriptorPoolTest2': MessageType({ 696 'NestedEnum': EnumType([('GAMMA', 3), ('DELTA', 4)]), 697 'NestedMessage': MessageType({ 698 'NestedEnum': EnumType([('IOTA', 9), ('KAPPA', 10)]), 699 'DeepNestedMessage': MessageType({ 700 'NestedEnum': EnumType([('LAMBDA', 11), ('MU', 12)]), 701 }, [ 702 ('nested_enum', EnumField(1, 'NestedEnum', 'MU')), 703 ('nested_field', StringField(2, 'lambda')), 704 ]), 705 }, [ 706 ('nested_enum', EnumField(1, 'NestedEnum', 'IOTA')), 707 ('nested_field', StringField(2, 'delta')), 708 ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), 709 ]) 710 }, [ 711 ('nested_enum', EnumField(1, 'NestedEnum', 'GAMMA')), 712 ('nested_message', MessageField(2, 'NestedMessage')), 713 ]), 714 }) 715 716 717TEST2_FILE = ProtoFile( 718 'google/protobuf/internal/descriptor_pool_test2.proto', 719 'google.protobuf.python.internal', 720 { 721 'DescriptorPoolTest3': MessageType({ 722 'NestedEnum': EnumType([('NU', 13), ('XI', 14)]), 723 'NestedMessage': MessageType({ 724 'NestedEnum': EnumType([('OMICRON', 15), ('PI', 16)]), 725 'DeepNestedMessage': MessageType({ 726 'NestedEnum': EnumType([('RHO', 17), ('SIGMA', 18)]), 727 }, [ 728 ('nested_enum', EnumField(1, 'NestedEnum', 'RHO')), 729 ('nested_field', StringField(2, 'sigma')), 730 ]), 731 }, [ 732 ('nested_enum', EnumField(1, 'NestedEnum', 'PI')), 733 ('nested_field', StringField(2, 'nu')), 734 ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), 735 ]) 736 }, [ 737 ('nested_enum', EnumField(1, 'NestedEnum', 'XI')), 738 ('nested_message', MessageField(2, 'NestedMessage')), 739 ], extensions=[ 740 ('descriptor_pool_test', 741 ExtensionField(1001, 'DescriptorPoolTest1')), 742 ]), 743 }, 744 dependencies=['google/protobuf/internal/descriptor_pool_test1.proto', 745 'google/protobuf/internal/more_messages.proto'], 746 public_dependencies=['google/protobuf/internal/more_messages.proto']) 747 748 749if __name__ == '__main__': 750 unittest.main() 751