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"""Unittest for google.protobuf.internal.descriptor.""" 34 35__author__ = 'robinson@google.com (Will Robinson)' 36 37import sys 38 39try: 40 import unittest2 as unittest #PY26 41except ImportError: 42 import unittest 43 44from google.protobuf import unittest_custom_options_pb2 45from google.protobuf import unittest_import_pb2 46from google.protobuf import unittest_pb2 47from google.protobuf import descriptor_pb2 48from google.protobuf.internal import api_implementation 49from google.protobuf.internal import test_util 50from google.protobuf import descriptor 51from google.protobuf import descriptor_pool 52from google.protobuf import symbol_database 53from google.protobuf import text_format 54 55 56TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """ 57name: 'TestEmptyMessage' 58""" 59 60 61class DescriptorTest(unittest.TestCase): 62 63 def setUp(self): 64 file_proto = descriptor_pb2.FileDescriptorProto( 65 name='some/filename/some.proto', 66 package='protobuf_unittest') 67 message_proto = file_proto.message_type.add( 68 name='NestedMessage') 69 message_proto.field.add( 70 name='bb', 71 number=1, 72 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 73 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) 74 enum_proto = message_proto.enum_type.add( 75 name='ForeignEnum') 76 enum_proto.value.add(name='FOREIGN_FOO', number=4) 77 enum_proto.value.add(name='FOREIGN_BAR', number=5) 78 enum_proto.value.add(name='FOREIGN_BAZ', number=6) 79 80 self.pool = self.GetDescriptorPool() 81 self.pool.Add(file_proto) 82 self.my_file = self.pool.FindFileByName(file_proto.name) 83 self.my_message = self.my_file.message_types_by_name[message_proto.name] 84 self.my_enum = self.my_message.enum_types_by_name[enum_proto.name] 85 86 self.my_method = descriptor.MethodDescriptor( 87 name='Bar', 88 full_name='protobuf_unittest.TestService.Bar', 89 index=0, 90 containing_service=None, 91 input_type=None, 92 output_type=None) 93 self.my_service = descriptor.ServiceDescriptor( 94 name='TestServiceWithOptions', 95 full_name='protobuf_unittest.TestServiceWithOptions', 96 file=self.my_file, 97 index=0, 98 methods=[ 99 self.my_method 100 ]) 101 102 def GetDescriptorPool(self): 103 return symbol_database.Default().pool 104 105 def testEnumValueName(self): 106 self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), 107 'FOREIGN_FOO') 108 109 self.assertEqual( 110 self.my_message.enum_types_by_name[ 111 'ForeignEnum'].values_by_number[4].name, 112 self.my_message.EnumValueName('ForeignEnum', 4)) 113 114 def testEnumFixups(self): 115 self.assertEqual(self.my_enum, self.my_enum.values[0].type) 116 117 def testContainingTypeFixups(self): 118 self.assertEqual(self.my_message, self.my_message.fields[0].containing_type) 119 self.assertEqual(self.my_message, self.my_enum.containing_type) 120 121 def testContainingServiceFixups(self): 122 self.assertEqual(self.my_service, self.my_method.containing_service) 123 124 def testGetOptions(self): 125 self.assertEqual(self.my_enum.GetOptions(), 126 descriptor_pb2.EnumOptions()) 127 self.assertEqual(self.my_enum.values[0].GetOptions(), 128 descriptor_pb2.EnumValueOptions()) 129 self.assertEqual(self.my_message.GetOptions(), 130 descriptor_pb2.MessageOptions()) 131 self.assertEqual(self.my_message.fields[0].GetOptions(), 132 descriptor_pb2.FieldOptions()) 133 self.assertEqual(self.my_method.GetOptions(), 134 descriptor_pb2.MethodOptions()) 135 self.assertEqual(self.my_service.GetOptions(), 136 descriptor_pb2.ServiceOptions()) 137 138 def testSimpleCustomOptions(self): 139 file_descriptor = unittest_custom_options_pb2.DESCRIPTOR 140 message_descriptor =\ 141 unittest_custom_options_pb2.TestMessageWithCustomOptions.DESCRIPTOR 142 field_descriptor = message_descriptor.fields_by_name["field1"] 143 enum_descriptor = message_descriptor.enum_types_by_name["AnEnum"] 144 enum_value_descriptor =\ 145 message_descriptor.enum_values_by_name["ANENUM_VAL2"] 146 service_descriptor =\ 147 unittest_custom_options_pb2.TestServiceWithCustomOptions.DESCRIPTOR 148 method_descriptor = service_descriptor.FindMethodByName("Foo") 149 150 file_options = file_descriptor.GetOptions() 151 file_opt1 = unittest_custom_options_pb2.file_opt1 152 self.assertEqual(9876543210, file_options.Extensions[file_opt1]) 153 message_options = message_descriptor.GetOptions() 154 message_opt1 = unittest_custom_options_pb2.message_opt1 155 self.assertEqual(-56, message_options.Extensions[message_opt1]) 156 field_options = field_descriptor.GetOptions() 157 field_opt1 = unittest_custom_options_pb2.field_opt1 158 self.assertEqual(8765432109, field_options.Extensions[field_opt1]) 159 field_opt2 = unittest_custom_options_pb2.field_opt2 160 self.assertEqual(42, field_options.Extensions[field_opt2]) 161 enum_options = enum_descriptor.GetOptions() 162 enum_opt1 = unittest_custom_options_pb2.enum_opt1 163 self.assertEqual(-789, enum_options.Extensions[enum_opt1]) 164 enum_value_options = enum_value_descriptor.GetOptions() 165 enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1 166 self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1]) 167 168 service_options = service_descriptor.GetOptions() 169 service_opt1 = unittest_custom_options_pb2.service_opt1 170 self.assertEqual(-9876543210, service_options.Extensions[service_opt1]) 171 method_options = method_descriptor.GetOptions() 172 method_opt1 = unittest_custom_options_pb2.method_opt1 173 self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, 174 method_options.Extensions[method_opt1]) 175 176 message_descriptor = ( 177 unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR) 178 self.assertTrue(file_descriptor.has_options) 179 self.assertFalse(message_descriptor.has_options) 180 181 def testDifferentCustomOptionTypes(self): 182 kint32min = -2**31 183 kint64min = -2**63 184 kint32max = 2**31 - 1 185 kint64max = 2**63 - 1 186 kuint32max = 2**32 - 1 187 kuint64max = 2**64 - 1 188 189 message_descriptor =\ 190 unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR 191 message_options = message_descriptor.GetOptions() 192 self.assertEqual(False, message_options.Extensions[ 193 unittest_custom_options_pb2.bool_opt]) 194 self.assertEqual(kint32min, message_options.Extensions[ 195 unittest_custom_options_pb2.int32_opt]) 196 self.assertEqual(kint64min, message_options.Extensions[ 197 unittest_custom_options_pb2.int64_opt]) 198 self.assertEqual(0, message_options.Extensions[ 199 unittest_custom_options_pb2.uint32_opt]) 200 self.assertEqual(0, message_options.Extensions[ 201 unittest_custom_options_pb2.uint64_opt]) 202 self.assertEqual(kint32min, message_options.Extensions[ 203 unittest_custom_options_pb2.sint32_opt]) 204 self.assertEqual(kint64min, message_options.Extensions[ 205 unittest_custom_options_pb2.sint64_opt]) 206 self.assertEqual(0, message_options.Extensions[ 207 unittest_custom_options_pb2.fixed32_opt]) 208 self.assertEqual(0, message_options.Extensions[ 209 unittest_custom_options_pb2.fixed64_opt]) 210 self.assertEqual(kint32min, message_options.Extensions[ 211 unittest_custom_options_pb2.sfixed32_opt]) 212 self.assertEqual(kint64min, message_options.Extensions[ 213 unittest_custom_options_pb2.sfixed64_opt]) 214 215 message_descriptor =\ 216 unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR 217 message_options = message_descriptor.GetOptions() 218 self.assertEqual(True, message_options.Extensions[ 219 unittest_custom_options_pb2.bool_opt]) 220 self.assertEqual(kint32max, message_options.Extensions[ 221 unittest_custom_options_pb2.int32_opt]) 222 self.assertEqual(kint64max, message_options.Extensions[ 223 unittest_custom_options_pb2.int64_opt]) 224 self.assertEqual(kuint32max, message_options.Extensions[ 225 unittest_custom_options_pb2.uint32_opt]) 226 self.assertEqual(kuint64max, message_options.Extensions[ 227 unittest_custom_options_pb2.uint64_opt]) 228 self.assertEqual(kint32max, message_options.Extensions[ 229 unittest_custom_options_pb2.sint32_opt]) 230 self.assertEqual(kint64max, message_options.Extensions[ 231 unittest_custom_options_pb2.sint64_opt]) 232 self.assertEqual(kuint32max, message_options.Extensions[ 233 unittest_custom_options_pb2.fixed32_opt]) 234 self.assertEqual(kuint64max, message_options.Extensions[ 235 unittest_custom_options_pb2.fixed64_opt]) 236 self.assertEqual(kint32max, message_options.Extensions[ 237 unittest_custom_options_pb2.sfixed32_opt]) 238 self.assertEqual(kint64max, message_options.Extensions[ 239 unittest_custom_options_pb2.sfixed64_opt]) 240 241 message_descriptor =\ 242 unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR 243 message_options = message_descriptor.GetOptions() 244 self.assertEqual(-100, message_options.Extensions[ 245 unittest_custom_options_pb2.int32_opt]) 246 self.assertAlmostEqual(12.3456789, message_options.Extensions[ 247 unittest_custom_options_pb2.float_opt], 6) 248 self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[ 249 unittest_custom_options_pb2.double_opt]) 250 self.assertEqual("Hello, \"World\"", message_options.Extensions[ 251 unittest_custom_options_pb2.string_opt]) 252 self.assertEqual(b"Hello\0World", message_options.Extensions[ 253 unittest_custom_options_pb2.bytes_opt]) 254 dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum 255 self.assertEqual( 256 dummy_enum.TEST_OPTION_ENUM_TYPE2, 257 message_options.Extensions[unittest_custom_options_pb2.enum_opt]) 258 259 message_descriptor =\ 260 unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR 261 message_options = message_descriptor.GetOptions() 262 self.assertAlmostEqual(12, message_options.Extensions[ 263 unittest_custom_options_pb2.float_opt], 6) 264 self.assertAlmostEqual(154, message_options.Extensions[ 265 unittest_custom_options_pb2.double_opt]) 266 267 message_descriptor =\ 268 unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR 269 message_options = message_descriptor.GetOptions() 270 self.assertAlmostEqual(-12, message_options.Extensions[ 271 unittest_custom_options_pb2.float_opt], 6) 272 self.assertAlmostEqual(-154, message_options.Extensions[ 273 unittest_custom_options_pb2.double_opt]) 274 275 def testComplexExtensionOptions(self): 276 descriptor =\ 277 unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR 278 options = descriptor.GetOptions() 279 self.assertEqual(42, options.Extensions[ 280 unittest_custom_options_pb2.complex_opt1].foo) 281 self.assertEqual(324, options.Extensions[ 282 unittest_custom_options_pb2.complex_opt1].Extensions[ 283 unittest_custom_options_pb2.quux]) 284 self.assertEqual(876, options.Extensions[ 285 unittest_custom_options_pb2.complex_opt1].Extensions[ 286 unittest_custom_options_pb2.corge].qux) 287 self.assertEqual(987, options.Extensions[ 288 unittest_custom_options_pb2.complex_opt2].baz) 289 self.assertEqual(654, options.Extensions[ 290 unittest_custom_options_pb2.complex_opt2].Extensions[ 291 unittest_custom_options_pb2.grault]) 292 self.assertEqual(743, options.Extensions[ 293 unittest_custom_options_pb2.complex_opt2].bar.foo) 294 self.assertEqual(1999, options.Extensions[ 295 unittest_custom_options_pb2.complex_opt2].bar.Extensions[ 296 unittest_custom_options_pb2.quux]) 297 self.assertEqual(2008, options.Extensions[ 298 unittest_custom_options_pb2.complex_opt2].bar.Extensions[ 299 unittest_custom_options_pb2.corge].qux) 300 self.assertEqual(741, options.Extensions[ 301 unittest_custom_options_pb2.complex_opt2].Extensions[ 302 unittest_custom_options_pb2.garply].foo) 303 self.assertEqual(1998, options.Extensions[ 304 unittest_custom_options_pb2.complex_opt2].Extensions[ 305 unittest_custom_options_pb2.garply].Extensions[ 306 unittest_custom_options_pb2.quux]) 307 self.assertEqual(2121, options.Extensions[ 308 unittest_custom_options_pb2.complex_opt2].Extensions[ 309 unittest_custom_options_pb2.garply].Extensions[ 310 unittest_custom_options_pb2.corge].qux) 311 self.assertEqual(1971, options.Extensions[ 312 unittest_custom_options_pb2.ComplexOptionType2 313 .ComplexOptionType4.complex_opt4].waldo) 314 self.assertEqual(321, options.Extensions[ 315 unittest_custom_options_pb2.complex_opt2].fred.waldo) 316 self.assertEqual(9, options.Extensions[ 317 unittest_custom_options_pb2.complex_opt3].qux) 318 self.assertEqual(22, options.Extensions[ 319 unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh) 320 self.assertEqual(24, options.Extensions[ 321 unittest_custom_options_pb2.complexopt6].xyzzy) 322 323 # Check that aggregate options were parsed and saved correctly in 324 # the appropriate descriptors. 325 def testAggregateOptions(self): 326 file_descriptor = unittest_custom_options_pb2.DESCRIPTOR 327 message_descriptor =\ 328 unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR 329 field_descriptor = message_descriptor.fields_by_name["fieldname"] 330 enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR 331 enum_value_descriptor = enum_descriptor.values_by_name["VALUE"] 332 service_descriptor =\ 333 unittest_custom_options_pb2.AggregateService.DESCRIPTOR 334 method_descriptor = service_descriptor.FindMethodByName("Method") 335 336 # Tests for the different types of data embedded in fileopt 337 file_options = file_descriptor.GetOptions().Extensions[ 338 unittest_custom_options_pb2.fileopt] 339 self.assertEqual(100, file_options.i) 340 self.assertEqual("FileAnnotation", file_options.s) 341 self.assertEqual("NestedFileAnnotation", file_options.sub.s) 342 self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[ 343 unittest_custom_options_pb2.fileopt].s) 344 self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[ 345 unittest_custom_options_pb2.AggregateMessageSetElement 346 .message_set_extension].s) 347 348 # Simple tests for all the other types of annotations 349 self.assertEqual( 350 "MessageAnnotation", 351 message_descriptor.GetOptions().Extensions[ 352 unittest_custom_options_pb2.msgopt].s) 353 self.assertEqual( 354 "FieldAnnotation", 355 field_descriptor.GetOptions().Extensions[ 356 unittest_custom_options_pb2.fieldopt].s) 357 self.assertEqual( 358 "EnumAnnotation", 359 enum_descriptor.GetOptions().Extensions[ 360 unittest_custom_options_pb2.enumopt].s) 361 self.assertEqual( 362 "EnumValueAnnotation", 363 enum_value_descriptor.GetOptions().Extensions[ 364 unittest_custom_options_pb2.enumvalopt].s) 365 self.assertEqual( 366 "ServiceAnnotation", 367 service_descriptor.GetOptions().Extensions[ 368 unittest_custom_options_pb2.serviceopt].s) 369 self.assertEqual( 370 "MethodAnnotation", 371 method_descriptor.GetOptions().Extensions[ 372 unittest_custom_options_pb2.methodopt].s) 373 374 def testNestedOptions(self): 375 nested_message =\ 376 unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR 377 self.assertEqual(1001, nested_message.GetOptions().Extensions[ 378 unittest_custom_options_pb2.message_opt1]) 379 nested_field = nested_message.fields_by_name["nested_field"] 380 self.assertEqual(1002, nested_field.GetOptions().Extensions[ 381 unittest_custom_options_pb2.field_opt1]) 382 outer_message =\ 383 unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR 384 nested_enum = outer_message.enum_types_by_name["NestedEnum"] 385 self.assertEqual(1003, nested_enum.GetOptions().Extensions[ 386 unittest_custom_options_pb2.enum_opt1]) 387 nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"] 388 self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[ 389 unittest_custom_options_pb2.enum_value_opt1]) 390 nested_extension = outer_message.extensions_by_name["nested_extension"] 391 self.assertEqual(1005, nested_extension.GetOptions().Extensions[ 392 unittest_custom_options_pb2.field_opt2]) 393 394 def testFileDescriptorReferences(self): 395 self.assertEqual(self.my_enum.file, self.my_file) 396 self.assertEqual(self.my_message.file, self.my_file) 397 398 def testFileDescriptor(self): 399 self.assertEqual(self.my_file.name, 'some/filename/some.proto') 400 self.assertEqual(self.my_file.package, 'protobuf_unittest') 401 self.assertEqual(self.my_file.pool, self.pool) 402 # Generated modules also belong to the default pool. 403 self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default()) 404 405 @unittest.skipIf( 406 api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, 407 'Immutability of descriptors is only enforced in v2 implementation') 408 def testImmutableCppDescriptor(self): 409 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 410 with self.assertRaises(AttributeError): 411 message_descriptor.fields_by_name = None 412 with self.assertRaises(TypeError): 413 message_descriptor.fields_by_name['Another'] = None 414 with self.assertRaises(TypeError): 415 message_descriptor.fields.append(None) 416 417 418class NewDescriptorTest(DescriptorTest): 419 """Redo the same tests as above, but with a separate DescriptorPool.""" 420 421 def GetDescriptorPool(self): 422 return descriptor_pool.DescriptorPool() 423 424 425class GeneratedDescriptorTest(unittest.TestCase): 426 """Tests for the properties of descriptors in generated code.""" 427 428 def CheckMessageDescriptor(self, message_descriptor): 429 # Basic properties 430 self.assertEqual(message_descriptor.name, 'TestAllTypes') 431 self.assertEqual(message_descriptor.full_name, 432 'protobuf_unittest.TestAllTypes') 433 # Test equality and hashability 434 self.assertEqual(message_descriptor, message_descriptor) 435 self.assertEqual(message_descriptor.fields[0].containing_type, 436 message_descriptor) 437 self.assertIn(message_descriptor, [message_descriptor]) 438 self.assertIn(message_descriptor, {message_descriptor: None}) 439 # Test field containers 440 self.CheckDescriptorSequence(message_descriptor.fields) 441 self.CheckDescriptorMapping(message_descriptor.fields_by_name) 442 self.CheckDescriptorMapping(message_descriptor.fields_by_number) 443 self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name) 444 445 def CheckFieldDescriptor(self, field_descriptor): 446 # Basic properties 447 self.assertEqual(field_descriptor.name, 'optional_int32') 448 self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32') 449 self.assertEqual(field_descriptor.full_name, 450 'protobuf_unittest.TestAllTypes.optional_int32') 451 self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes') 452 # Test equality and hashability 453 self.assertEqual(field_descriptor, field_descriptor) 454 self.assertEqual( 455 field_descriptor.containing_type.fields_by_name['optional_int32'], 456 field_descriptor) 457 self.assertEqual( 458 field_descriptor.containing_type.fields_by_camelcase_name[ 459 'optionalInt32'], 460 field_descriptor) 461 self.assertIn(field_descriptor, [field_descriptor]) 462 self.assertIn(field_descriptor, {field_descriptor: None}) 463 464 def CheckDescriptorSequence(self, sequence): 465 # Verifies that a property like 'messageDescriptor.fields' has all the 466 # properties of an immutable abc.Sequence. 467 self.assertGreater(len(sequence), 0) # Sized 468 self.assertEqual(len(sequence), len(list(sequence))) # Iterable 469 item = sequence[0] 470 self.assertEqual(item, sequence[0]) 471 self.assertIn(item, sequence) # Container 472 self.assertEqual(sequence.index(item), 0) 473 self.assertEqual(sequence.count(item), 1) 474 reversed_iterator = reversed(sequence) 475 self.assertEqual(list(reversed_iterator), list(sequence)[::-1]) 476 self.assertRaises(StopIteration, next, reversed_iterator) 477 478 def CheckDescriptorMapping(self, mapping): 479 # Verifies that a property like 'messageDescriptor.fields' has all the 480 # properties of an immutable abc.Mapping. 481 self.assertGreater(len(mapping), 0) # Sized 482 self.assertEqual(len(mapping), len(list(mapping))) # Iterable 483 if sys.version_info >= (3,): 484 key, item = next(iter(mapping.items())) 485 else: 486 key, item = mapping.items()[0] 487 self.assertIn(key, mapping) # Container 488 self.assertEqual(mapping.get(key), item) 489 # keys(), iterkeys() &co 490 item = (next(iter(mapping.keys())), next(iter(mapping.values()))) 491 self.assertEqual(item, next(iter(mapping.items()))) 492 if sys.version_info < (3,): 493 def CheckItems(seq, iterator): 494 self.assertEqual(next(iterator), seq[0]) 495 self.assertEqual(list(iterator), seq[1:]) 496 CheckItems(mapping.keys(), mapping.iterkeys()) 497 CheckItems(mapping.values(), mapping.itervalues()) 498 CheckItems(mapping.items(), mapping.iteritems()) 499 500 def testDescriptor(self): 501 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 502 self.CheckMessageDescriptor(message_descriptor) 503 field_descriptor = message_descriptor.fields_by_name['optional_int32'] 504 self.CheckFieldDescriptor(field_descriptor) 505 field_descriptor = message_descriptor.fields_by_camelcase_name[ 506 'optionalInt32'] 507 self.CheckFieldDescriptor(field_descriptor) 508 509 def testCppDescriptorContainer(self): 510 # Check that the collection is still valid even if the parent disappeared. 511 enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] 512 values = enum.values 513 del enum 514 self.assertEqual('FOO', values[0].name) 515 516 def testCppDescriptorContainer_Iterator(self): 517 # Same test with the iterator 518 enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] 519 values_iter = iter(enum.values) 520 del enum 521 self.assertEqual('FOO', next(values_iter).name) 522 523 524class DescriptorCopyToProtoTest(unittest.TestCase): 525 """Tests for CopyTo functions of Descriptor.""" 526 527 def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii): 528 expected_proto = expected_class() 529 text_format.Merge(expected_ascii, expected_proto) 530 531 self.assertEqual( 532 actual_proto, expected_proto, 533 'Not equal,\nActual:\n%s\nExpected:\n%s\n' 534 % (str(actual_proto), str(expected_proto))) 535 536 def _InternalTestCopyToProto(self, desc, expected_proto_class, 537 expected_proto_ascii): 538 actual = expected_proto_class() 539 desc.CopyToProto(actual) 540 self._AssertProtoEqual( 541 actual, expected_proto_class, expected_proto_ascii) 542 543 def testCopyToProto_EmptyMessage(self): 544 self._InternalTestCopyToProto( 545 unittest_pb2.TestEmptyMessage.DESCRIPTOR, 546 descriptor_pb2.DescriptorProto, 547 TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII) 548 549 def testCopyToProto_NestedMessage(self): 550 TEST_NESTED_MESSAGE_ASCII = """ 551 name: 'NestedMessage' 552 field: < 553 name: 'bb' 554 number: 1 555 label: 1 # Optional 556 type: 5 # TYPE_INT32 557 > 558 """ 559 560 self._InternalTestCopyToProto( 561 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, 562 descriptor_pb2.DescriptorProto, 563 TEST_NESTED_MESSAGE_ASCII) 564 565 def testCopyToProto_ForeignNestedMessage(self): 566 TEST_FOREIGN_NESTED_ASCII = """ 567 name: 'TestForeignNested' 568 field: < 569 name: 'foreign_nested' 570 number: 1 571 label: 1 # Optional 572 type: 11 # TYPE_MESSAGE 573 type_name: '.protobuf_unittest.TestAllTypes.NestedMessage' 574 > 575 """ 576 577 self._InternalTestCopyToProto( 578 unittest_pb2.TestForeignNested.DESCRIPTOR, 579 descriptor_pb2.DescriptorProto, 580 TEST_FOREIGN_NESTED_ASCII) 581 582 def testCopyToProto_ForeignEnum(self): 583 TEST_FOREIGN_ENUM_ASCII = """ 584 name: 'ForeignEnum' 585 value: < 586 name: 'FOREIGN_FOO' 587 number: 4 588 > 589 value: < 590 name: 'FOREIGN_BAR' 591 number: 5 592 > 593 value: < 594 name: 'FOREIGN_BAZ' 595 number: 6 596 > 597 """ 598 599 self._InternalTestCopyToProto( 600 unittest_pb2.ForeignEnum.DESCRIPTOR, 601 descriptor_pb2.EnumDescriptorProto, 602 TEST_FOREIGN_ENUM_ASCII) 603 604 def testCopyToProto_Options(self): 605 TEST_DEPRECATED_FIELDS_ASCII = """ 606 name: 'TestDeprecatedFields' 607 field: < 608 name: 'deprecated_int32' 609 number: 1 610 label: 1 # Optional 611 type: 5 # TYPE_INT32 612 options: < 613 deprecated: true 614 > 615 > 616 """ 617 618 self._InternalTestCopyToProto( 619 unittest_pb2.TestDeprecatedFields.DESCRIPTOR, 620 descriptor_pb2.DescriptorProto, 621 TEST_DEPRECATED_FIELDS_ASCII) 622 623 def testCopyToProto_AllExtensions(self): 624 TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """ 625 name: 'TestEmptyMessageWithExtensions' 626 extension_range: < 627 start: 1 628 end: 536870912 629 > 630 """ 631 632 self._InternalTestCopyToProto( 633 unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR, 634 descriptor_pb2.DescriptorProto, 635 TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII) 636 637 def testCopyToProto_SeveralExtensions(self): 638 TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """ 639 name: 'TestMultipleExtensionRanges' 640 extension_range: < 641 start: 42 642 end: 43 643 > 644 extension_range: < 645 start: 4143 646 end: 4244 647 > 648 extension_range: < 649 start: 65536 650 end: 536870912 651 > 652 """ 653 654 self._InternalTestCopyToProto( 655 unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR, 656 descriptor_pb2.DescriptorProto, 657 TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) 658 659 # Disable this test so we can make changes to the proto file. 660 # TODO(xiaofeng): Enable this test after cl/55530659 is submitted. 661 # 662 # def testCopyToProto_FileDescriptor(self): 663 # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" 664 # name: 'google/protobuf/unittest_import.proto' 665 # package: 'protobuf_unittest_import' 666 # dependency: 'google/protobuf/unittest_import_public.proto' 667 # message_type: < 668 # name: 'ImportMessage' 669 # field: < 670 # name: 'd' 671 # number: 1 672 # label: 1 # Optional 673 # type: 5 # TYPE_INT32 674 # > 675 # > 676 # """ + 677 # """enum_type: < 678 # name: 'ImportEnum' 679 # value: < 680 # name: 'IMPORT_FOO' 681 # number: 7 682 # > 683 # value: < 684 # name: 'IMPORT_BAR' 685 # number: 8 686 # > 687 # value: < 688 # name: 'IMPORT_BAZ' 689 # number: 9 690 # > 691 # > 692 # options: < 693 # java_package: 'com.google.protobuf.test' 694 # optimize_for: 1 # SPEED 695 # > 696 # public_dependency: 0 697 # """) 698 # self._InternalTestCopyToProto( 699 # unittest_import_pb2.DESCRIPTOR, 700 # descriptor_pb2.FileDescriptorProto, 701 # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) 702 703 def testCopyToProto_ServiceDescriptor(self): 704 TEST_SERVICE_ASCII = """ 705 name: 'TestService' 706 method: < 707 name: 'Foo' 708 input_type: '.protobuf_unittest.FooRequest' 709 output_type: '.protobuf_unittest.FooResponse' 710 > 711 method: < 712 name: 'Bar' 713 input_type: '.protobuf_unittest.BarRequest' 714 output_type: '.protobuf_unittest.BarResponse' 715 > 716 """ 717 # TODO(rocking): enable this test after the proto descriptor change is 718 # checked in. 719 #self._InternalTestCopyToProto( 720 # unittest_pb2.TestService.DESCRIPTOR, 721 # descriptor_pb2.ServiceDescriptorProto, 722 # TEST_SERVICE_ASCII) 723 724 725class MakeDescriptorTest(unittest.TestCase): 726 727 def testMakeDescriptorWithNestedFields(self): 728 file_descriptor_proto = descriptor_pb2.FileDescriptorProto() 729 file_descriptor_proto.name = 'Foo2' 730 message_type = file_descriptor_proto.message_type.add() 731 message_type.name = file_descriptor_proto.name 732 nested_type = message_type.nested_type.add() 733 nested_type.name = 'Sub' 734 enum_type = nested_type.enum_type.add() 735 enum_type.name = 'FOO' 736 enum_type_val = enum_type.value.add() 737 enum_type_val.name = 'BAR' 738 enum_type_val.number = 3 739 field = message_type.field.add() 740 field.number = 1 741 field.name = 'uint64_field' 742 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 743 field.type = descriptor.FieldDescriptor.TYPE_UINT64 744 field = message_type.field.add() 745 field.number = 2 746 field.name = 'nested_message_field' 747 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 748 field.type = descriptor.FieldDescriptor.TYPE_MESSAGE 749 field.type_name = 'Sub' 750 enum_field = nested_type.field.add() 751 enum_field.number = 2 752 enum_field.name = 'bar_field' 753 enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 754 enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM 755 enum_field.type_name = 'Foo2.Sub.FOO' 756 757 result = descriptor.MakeDescriptor(message_type) 758 self.assertEqual(result.fields[0].cpp_type, 759 descriptor.FieldDescriptor.CPPTYPE_UINT64) 760 self.assertEqual(result.fields[1].cpp_type, 761 descriptor.FieldDescriptor.CPPTYPE_MESSAGE) 762 self.assertEqual(result.fields[1].message_type.containing_type, 763 result) 764 self.assertEqual(result.nested_types[0].fields[0].full_name, 765 'Foo2.Sub.bar_field') 766 self.assertEqual(result.nested_types[0].fields[0].enum_type, 767 result.nested_types[0].enum_types[0]) 768 769 def testMakeDescriptorWithUnsignedIntField(self): 770 file_descriptor_proto = descriptor_pb2.FileDescriptorProto() 771 file_descriptor_proto.name = 'Foo' 772 message_type = file_descriptor_proto.message_type.add() 773 message_type.name = file_descriptor_proto.name 774 enum_type = message_type.enum_type.add() 775 enum_type.name = 'FOO' 776 enum_type_val = enum_type.value.add() 777 enum_type_val.name = 'BAR' 778 enum_type_val.number = 3 779 field = message_type.field.add() 780 field.number = 1 781 field.name = 'uint64_field' 782 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 783 field.type = descriptor.FieldDescriptor.TYPE_UINT64 784 enum_field = message_type.field.add() 785 enum_field.number = 2 786 enum_field.name = 'bar_field' 787 enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 788 enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM 789 enum_field.type_name = 'Foo.FOO' 790 791 result = descriptor.MakeDescriptor(message_type) 792 self.assertEqual(result.fields[0].cpp_type, 793 descriptor.FieldDescriptor.CPPTYPE_UINT64) 794 795 796 def testMakeDescriptorWithOptions(self): 797 descriptor_proto = descriptor_pb2.DescriptorProto() 798 aggregate_message = unittest_custom_options_pb2.AggregateMessage 799 aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto) 800 reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto) 801 802 options = reformed_descriptor.GetOptions() 803 self.assertEqual(101, 804 options.Extensions[unittest_custom_options_pb2.msgopt].i) 805 806 def testCamelcaseName(self): 807 descriptor_proto = descriptor_pb2.DescriptorProto() 808 descriptor_proto.name = 'Bar' 809 names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar'] 810 camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar'] 811 for index in range(len(names)): 812 field = descriptor_proto.field.add() 813 field.number = index + 1 814 field.name = names[index] 815 result = descriptor.MakeDescriptor(descriptor_proto) 816 for index in range(len(camelcase_names)): 817 self.assertEqual(result.fields[index].camelcase_name, 818 camelcase_names[index]) 819 820 821if __name__ == '__main__': 822 unittest.main() 823