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 38import warnings 39 40try: 41 import unittest2 as unittest #PY26 42except ImportError: 43 import unittest 44 45from google.protobuf import unittest_custom_options_pb2 46from google.protobuf import unittest_import_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 test_util 51from google.protobuf import descriptor 52from google.protobuf import descriptor_pool 53from google.protobuf import symbol_database 54from google.protobuf import text_format 55 56 57TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """ 58name: 'TestEmptyMessage' 59""" 60 61 62warnings.simplefilter('error', DeprecationWarning) 63 64 65class DescriptorTest(unittest.TestCase): 66 67 def setUp(self): 68 file_proto = descriptor_pb2.FileDescriptorProto( 69 name='some/filename/some.proto', 70 package='protobuf_unittest') 71 message_proto = file_proto.message_type.add( 72 name='NestedMessage') 73 message_proto.field.add( 74 name='bb', 75 number=1, 76 type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, 77 label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) 78 enum_proto = message_proto.enum_type.add( 79 name='ForeignEnum') 80 enum_proto.value.add(name='FOREIGN_FOO', number=4) 81 enum_proto.value.add(name='FOREIGN_BAR', number=5) 82 enum_proto.value.add(name='FOREIGN_BAZ', number=6) 83 84 file_proto.message_type.add(name='ResponseMessage') 85 service_proto = file_proto.service.add( 86 name='Service') 87 method_proto = service_proto.method.add( 88 name='CallMethod', 89 input_type='.protobuf_unittest.NestedMessage', 90 output_type='.protobuf_unittest.ResponseMessage') 91 92 # Note: Calling DescriptorPool.Add() multiple times with the same file only 93 # works if the input is canonical; in particular, all type names must be 94 # fully qualified. 95 self.pool = self.GetDescriptorPool() 96 self.pool.Add(file_proto) 97 self.my_file = self.pool.FindFileByName(file_proto.name) 98 self.my_message = self.my_file.message_types_by_name[message_proto.name] 99 self.my_enum = self.my_message.enum_types_by_name[enum_proto.name] 100 self.my_service = self.my_file.services_by_name[service_proto.name] 101 self.my_method = self.my_service.methods_by_name[method_proto.name] 102 103 def GetDescriptorPool(self): 104 return symbol_database.Default().pool 105 106 def testEnumValueName(self): 107 self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), 108 'FOREIGN_FOO') 109 110 self.assertEqual( 111 self.my_message.enum_types_by_name[ 112 'ForeignEnum'].values_by_number[4].name, 113 self.my_message.EnumValueName('ForeignEnum', 4)) 114 with self.assertRaises(KeyError): 115 self.my_message.EnumValueName('ForeignEnum', 999) 116 with self.assertRaises(KeyError): 117 self.my_message.EnumValueName('NoneEnum', 999) 118 with self.assertRaises(TypeError): 119 self.my_message.EnumValueName() 120 121 def testEnumFixups(self): 122 self.assertEqual(self.my_enum, self.my_enum.values[0].type) 123 124 def testContainingTypeFixups(self): 125 self.assertEqual(self.my_message, self.my_message.fields[0].containing_type) 126 self.assertEqual(self.my_message, self.my_enum.containing_type) 127 128 def testContainingServiceFixups(self): 129 self.assertEqual(self.my_service, self.my_method.containing_service) 130 131 def testGetOptions(self): 132 self.assertEqual(self.my_enum.GetOptions(), 133 descriptor_pb2.EnumOptions()) 134 self.assertEqual(self.my_enum.values[0].GetOptions(), 135 descriptor_pb2.EnumValueOptions()) 136 self.assertEqual(self.my_message.GetOptions(), 137 descriptor_pb2.MessageOptions()) 138 self.assertEqual(self.my_message.fields[0].GetOptions(), 139 descriptor_pb2.FieldOptions()) 140 self.assertEqual(self.my_method.GetOptions(), 141 descriptor_pb2.MethodOptions()) 142 self.assertEqual(self.my_service.GetOptions(), 143 descriptor_pb2.ServiceOptions()) 144 145 def testSimpleCustomOptions(self): 146 file_descriptor = unittest_custom_options_pb2.DESCRIPTOR 147 message_descriptor = (unittest_custom_options_pb2. 148 TestMessageWithCustomOptions.DESCRIPTOR) 149 field_descriptor = message_descriptor.fields_by_name['field1'] 150 oneof_descriptor = message_descriptor.oneofs_by_name['AnOneof'] 151 enum_descriptor = message_descriptor.enum_types_by_name['AnEnum'] 152 enum_value_descriptor = (message_descriptor. 153 enum_values_by_name['ANENUM_VAL2']) 154 other_enum_value_descriptor = (message_descriptor. 155 enum_values_by_name['ANENUM_VAL1']) 156 service_descriptor = (unittest_custom_options_pb2. 157 TestServiceWithCustomOptions.DESCRIPTOR) 158 method_descriptor = service_descriptor.FindMethodByName('Foo') 159 160 file_options = file_descriptor.GetOptions() 161 file_opt1 = unittest_custom_options_pb2.file_opt1 162 self.assertEqual(9876543210, file_options.Extensions[file_opt1]) 163 message_options = message_descriptor.GetOptions() 164 message_opt1 = unittest_custom_options_pb2.message_opt1 165 self.assertEqual(-56, message_options.Extensions[message_opt1]) 166 field_options = field_descriptor.GetOptions() 167 field_opt1 = unittest_custom_options_pb2.field_opt1 168 self.assertEqual(8765432109, field_options.Extensions[field_opt1]) 169 field_opt2 = unittest_custom_options_pb2.field_opt2 170 self.assertEqual(42, field_options.Extensions[field_opt2]) 171 oneof_options = oneof_descriptor.GetOptions() 172 oneof_opt1 = unittest_custom_options_pb2.oneof_opt1 173 self.assertEqual(-99, oneof_options.Extensions[oneof_opt1]) 174 enum_options = enum_descriptor.GetOptions() 175 enum_opt1 = unittest_custom_options_pb2.enum_opt1 176 self.assertEqual(-789, enum_options.Extensions[enum_opt1]) 177 enum_value_options = enum_value_descriptor.GetOptions() 178 enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1 179 self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1]) 180 181 service_options = service_descriptor.GetOptions() 182 service_opt1 = unittest_custom_options_pb2.service_opt1 183 self.assertEqual(-9876543210, service_options.Extensions[service_opt1]) 184 method_options = method_descriptor.GetOptions() 185 method_opt1 = unittest_custom_options_pb2.method_opt1 186 self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, 187 method_options.Extensions[method_opt1]) 188 189 message_descriptor = ( 190 unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR) 191 self.assertTrue(file_descriptor.has_options) 192 self.assertFalse(message_descriptor.has_options) 193 self.assertTrue(field_descriptor.has_options) 194 self.assertTrue(oneof_descriptor.has_options) 195 self.assertTrue(enum_descriptor.has_options) 196 self.assertTrue(enum_value_descriptor.has_options) 197 self.assertFalse(other_enum_value_descriptor.has_options) 198 199 def testCustomOptionsCopyTo(self): 200 message_descriptor = (unittest_custom_options_pb2. 201 TestMessageWithCustomOptions.DESCRIPTOR) 202 message_proto = descriptor_pb2.DescriptorProto() 203 message_descriptor.CopyToProto(message_proto) 204 self.assertEqual(len(message_proto.options.ListFields()), 205 2) 206 207 def testDifferentCustomOptionTypes(self): 208 kint32min = -2**31 209 kint64min = -2**63 210 kint32max = 2**31 - 1 211 kint64max = 2**63 - 1 212 kuint32max = 2**32 - 1 213 kuint64max = 2**64 - 1 214 215 message_descriptor =\ 216 unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR 217 message_options = message_descriptor.GetOptions() 218 self.assertEqual(False, message_options.Extensions[ 219 unittest_custom_options_pb2.bool_opt]) 220 self.assertEqual(kint32min, message_options.Extensions[ 221 unittest_custom_options_pb2.int32_opt]) 222 self.assertEqual(kint64min, message_options.Extensions[ 223 unittest_custom_options_pb2.int64_opt]) 224 self.assertEqual(0, message_options.Extensions[ 225 unittest_custom_options_pb2.uint32_opt]) 226 self.assertEqual(0, message_options.Extensions[ 227 unittest_custom_options_pb2.uint64_opt]) 228 self.assertEqual(kint32min, message_options.Extensions[ 229 unittest_custom_options_pb2.sint32_opt]) 230 self.assertEqual(kint64min, message_options.Extensions[ 231 unittest_custom_options_pb2.sint64_opt]) 232 self.assertEqual(0, message_options.Extensions[ 233 unittest_custom_options_pb2.fixed32_opt]) 234 self.assertEqual(0, message_options.Extensions[ 235 unittest_custom_options_pb2.fixed64_opt]) 236 self.assertEqual(kint32min, message_options.Extensions[ 237 unittest_custom_options_pb2.sfixed32_opt]) 238 self.assertEqual(kint64min, message_options.Extensions[ 239 unittest_custom_options_pb2.sfixed64_opt]) 240 241 message_descriptor =\ 242 unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR 243 message_options = message_descriptor.GetOptions() 244 self.assertEqual(True, message_options.Extensions[ 245 unittest_custom_options_pb2.bool_opt]) 246 self.assertEqual(kint32max, message_options.Extensions[ 247 unittest_custom_options_pb2.int32_opt]) 248 self.assertEqual(kint64max, message_options.Extensions[ 249 unittest_custom_options_pb2.int64_opt]) 250 self.assertEqual(kuint32max, message_options.Extensions[ 251 unittest_custom_options_pb2.uint32_opt]) 252 self.assertEqual(kuint64max, message_options.Extensions[ 253 unittest_custom_options_pb2.uint64_opt]) 254 self.assertEqual(kint32max, message_options.Extensions[ 255 unittest_custom_options_pb2.sint32_opt]) 256 self.assertEqual(kint64max, message_options.Extensions[ 257 unittest_custom_options_pb2.sint64_opt]) 258 self.assertEqual(kuint32max, message_options.Extensions[ 259 unittest_custom_options_pb2.fixed32_opt]) 260 self.assertEqual(kuint64max, message_options.Extensions[ 261 unittest_custom_options_pb2.fixed64_opt]) 262 self.assertEqual(kint32max, message_options.Extensions[ 263 unittest_custom_options_pb2.sfixed32_opt]) 264 self.assertEqual(kint64max, message_options.Extensions[ 265 unittest_custom_options_pb2.sfixed64_opt]) 266 267 message_descriptor =\ 268 unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR 269 message_options = message_descriptor.GetOptions() 270 self.assertEqual(-100, message_options.Extensions[ 271 unittest_custom_options_pb2.int32_opt]) 272 self.assertAlmostEqual(12.3456789, message_options.Extensions[ 273 unittest_custom_options_pb2.float_opt], 6) 274 self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[ 275 unittest_custom_options_pb2.double_opt]) 276 self.assertEqual("Hello, \"World\"", message_options.Extensions[ 277 unittest_custom_options_pb2.string_opt]) 278 self.assertEqual(b"Hello\0World", message_options.Extensions[ 279 unittest_custom_options_pb2.bytes_opt]) 280 dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum 281 self.assertEqual( 282 dummy_enum.TEST_OPTION_ENUM_TYPE2, 283 message_options.Extensions[unittest_custom_options_pb2.enum_opt]) 284 285 message_descriptor =\ 286 unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR 287 message_options = message_descriptor.GetOptions() 288 self.assertAlmostEqual(12, message_options.Extensions[ 289 unittest_custom_options_pb2.float_opt], 6) 290 self.assertAlmostEqual(154, message_options.Extensions[ 291 unittest_custom_options_pb2.double_opt]) 292 293 message_descriptor =\ 294 unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR 295 message_options = message_descriptor.GetOptions() 296 self.assertAlmostEqual(-12, message_options.Extensions[ 297 unittest_custom_options_pb2.float_opt], 6) 298 self.assertAlmostEqual(-154, message_options.Extensions[ 299 unittest_custom_options_pb2.double_opt]) 300 301 def testComplexExtensionOptions(self): 302 descriptor =\ 303 unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR 304 options = descriptor.GetOptions() 305 self.assertEqual(42, options.Extensions[ 306 unittest_custom_options_pb2.complex_opt1].foo) 307 self.assertEqual(324, options.Extensions[ 308 unittest_custom_options_pb2.complex_opt1].Extensions[ 309 unittest_custom_options_pb2.quux]) 310 self.assertEqual(876, options.Extensions[ 311 unittest_custom_options_pb2.complex_opt1].Extensions[ 312 unittest_custom_options_pb2.corge].qux) 313 self.assertEqual(987, options.Extensions[ 314 unittest_custom_options_pb2.complex_opt2].baz) 315 self.assertEqual(654, options.Extensions[ 316 unittest_custom_options_pb2.complex_opt2].Extensions[ 317 unittest_custom_options_pb2.grault]) 318 self.assertEqual(743, options.Extensions[ 319 unittest_custom_options_pb2.complex_opt2].bar.foo) 320 self.assertEqual(1999, options.Extensions[ 321 unittest_custom_options_pb2.complex_opt2].bar.Extensions[ 322 unittest_custom_options_pb2.quux]) 323 self.assertEqual(2008, options.Extensions[ 324 unittest_custom_options_pb2.complex_opt2].bar.Extensions[ 325 unittest_custom_options_pb2.corge].qux) 326 self.assertEqual(741, options.Extensions[ 327 unittest_custom_options_pb2.complex_opt2].Extensions[ 328 unittest_custom_options_pb2.garply].foo) 329 self.assertEqual(1998, options.Extensions[ 330 unittest_custom_options_pb2.complex_opt2].Extensions[ 331 unittest_custom_options_pb2.garply].Extensions[ 332 unittest_custom_options_pb2.quux]) 333 self.assertEqual(2121, options.Extensions[ 334 unittest_custom_options_pb2.complex_opt2].Extensions[ 335 unittest_custom_options_pb2.garply].Extensions[ 336 unittest_custom_options_pb2.corge].qux) 337 self.assertEqual(1971, options.Extensions[ 338 unittest_custom_options_pb2.ComplexOptionType2 339 .ComplexOptionType4.complex_opt4].waldo) 340 self.assertEqual(321, options.Extensions[ 341 unittest_custom_options_pb2.complex_opt2].fred.waldo) 342 self.assertEqual(9, options.Extensions[ 343 unittest_custom_options_pb2.complex_opt3].qux) 344 self.assertEqual(22, options.Extensions[ 345 unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh) 346 self.assertEqual(24, options.Extensions[ 347 unittest_custom_options_pb2.complexopt6].xyzzy) 348 349 # Check that aggregate options were parsed and saved correctly in 350 # the appropriate descriptors. 351 def testAggregateOptions(self): 352 file_descriptor = unittest_custom_options_pb2.DESCRIPTOR 353 message_descriptor =\ 354 unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR 355 field_descriptor = message_descriptor.fields_by_name["fieldname"] 356 enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR 357 enum_value_descriptor = enum_descriptor.values_by_name["VALUE"] 358 service_descriptor =\ 359 unittest_custom_options_pb2.AggregateService.DESCRIPTOR 360 method_descriptor = service_descriptor.FindMethodByName("Method") 361 362 # Tests for the different types of data embedded in fileopt 363 file_options = file_descriptor.GetOptions().Extensions[ 364 unittest_custom_options_pb2.fileopt] 365 self.assertEqual(100, file_options.i) 366 self.assertEqual("FileAnnotation", file_options.s) 367 self.assertEqual("NestedFileAnnotation", file_options.sub.s) 368 self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[ 369 unittest_custom_options_pb2.fileopt].s) 370 self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[ 371 unittest_custom_options_pb2.AggregateMessageSetElement 372 .message_set_extension].s) 373 374 # Simple tests for all the other types of annotations 375 self.assertEqual( 376 "MessageAnnotation", 377 message_descriptor.GetOptions().Extensions[ 378 unittest_custom_options_pb2.msgopt].s) 379 self.assertEqual( 380 "FieldAnnotation", 381 field_descriptor.GetOptions().Extensions[ 382 unittest_custom_options_pb2.fieldopt].s) 383 self.assertEqual( 384 "EnumAnnotation", 385 enum_descriptor.GetOptions().Extensions[ 386 unittest_custom_options_pb2.enumopt].s) 387 self.assertEqual( 388 "EnumValueAnnotation", 389 enum_value_descriptor.GetOptions().Extensions[ 390 unittest_custom_options_pb2.enumvalopt].s) 391 self.assertEqual( 392 "ServiceAnnotation", 393 service_descriptor.GetOptions().Extensions[ 394 unittest_custom_options_pb2.serviceopt].s) 395 self.assertEqual( 396 "MethodAnnotation", 397 method_descriptor.GetOptions().Extensions[ 398 unittest_custom_options_pb2.methodopt].s) 399 400 def testNestedOptions(self): 401 nested_message =\ 402 unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR 403 self.assertEqual(1001, nested_message.GetOptions().Extensions[ 404 unittest_custom_options_pb2.message_opt1]) 405 nested_field = nested_message.fields_by_name["nested_field"] 406 self.assertEqual(1002, nested_field.GetOptions().Extensions[ 407 unittest_custom_options_pb2.field_opt1]) 408 outer_message =\ 409 unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR 410 nested_enum = outer_message.enum_types_by_name["NestedEnum"] 411 self.assertEqual(1003, nested_enum.GetOptions().Extensions[ 412 unittest_custom_options_pb2.enum_opt1]) 413 nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"] 414 self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[ 415 unittest_custom_options_pb2.enum_value_opt1]) 416 nested_extension = outer_message.extensions_by_name["nested_extension"] 417 self.assertEqual(1005, nested_extension.GetOptions().Extensions[ 418 unittest_custom_options_pb2.field_opt2]) 419 420 def testFileDescriptorReferences(self): 421 self.assertEqual(self.my_enum.file, self.my_file) 422 self.assertEqual(self.my_message.file, self.my_file) 423 424 def testFileDescriptor(self): 425 self.assertEqual(self.my_file.name, 'some/filename/some.proto') 426 self.assertEqual(self.my_file.package, 'protobuf_unittest') 427 self.assertEqual(self.my_file.pool, self.pool) 428 self.assertFalse(self.my_file.has_options) 429 self.assertEqual('proto2', self.my_file.syntax) 430 file_proto = descriptor_pb2.FileDescriptorProto() 431 self.my_file.CopyToProto(file_proto) 432 self.assertEqual(self.my_file.serialized_pb, 433 file_proto.SerializeToString()) 434 # Generated modules also belong to the default pool. 435 self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default()) 436 437 @unittest.skipIf( 438 api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, 439 'Immutability of descriptors is only enforced in v2 implementation') 440 def testImmutableCppDescriptor(self): 441 file_descriptor = unittest_pb2.DESCRIPTOR 442 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 443 field_descriptor = message_descriptor.fields_by_name['optional_int32'] 444 enum_descriptor = message_descriptor.enum_types_by_name['NestedEnum'] 445 oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] 446 with self.assertRaises(AttributeError): 447 message_descriptor.fields_by_name = None 448 with self.assertRaises(TypeError): 449 message_descriptor.fields_by_name['Another'] = None 450 with self.assertRaises(TypeError): 451 message_descriptor.fields.append(None) 452 with self.assertRaises(AttributeError): 453 field_descriptor.containing_type = message_descriptor 454 with self.assertRaises(AttributeError): 455 file_descriptor.has_options = False 456 with self.assertRaises(AttributeError): 457 field_descriptor.has_options = False 458 with self.assertRaises(AttributeError): 459 oneof_descriptor.has_options = False 460 with self.assertRaises(AttributeError): 461 enum_descriptor.has_options = False 462 with self.assertRaises(AttributeError) as e: 463 message_descriptor.has_options = True 464 self.assertEqual('attribute is not writable: has_options', 465 str(e.exception)) 466 467 def testDefault(self): 468 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 469 field = message_descriptor.fields_by_name['repeated_int32'] 470 self.assertEqual(field.default_value, []) 471 field = message_descriptor.fields_by_name['repeated_nested_message'] 472 self.assertEqual(field.default_value, []) 473 field = message_descriptor.fields_by_name['optionalgroup'] 474 self.assertEqual(field.default_value, None) 475 field = message_descriptor.fields_by_name['optional_nested_message'] 476 self.assertEqual(field.default_value, None) 477 478 479class NewDescriptorTest(DescriptorTest): 480 """Redo the same tests as above, but with a separate DescriptorPool.""" 481 482 def GetDescriptorPool(self): 483 return descriptor_pool.DescriptorPool() 484 485 486class GeneratedDescriptorTest(unittest.TestCase): 487 """Tests for the properties of descriptors in generated code.""" 488 489 def CheckMessageDescriptor(self, message_descriptor): 490 # Basic properties 491 self.assertEqual(message_descriptor.name, 'TestAllTypes') 492 self.assertEqual(message_descriptor.full_name, 493 'protobuf_unittest.TestAllTypes') 494 # Test equality and hashability 495 self.assertEqual(message_descriptor, message_descriptor) 496 self.assertEqual(message_descriptor.fields[0].containing_type, 497 message_descriptor) 498 self.assertIn(message_descriptor, [message_descriptor]) 499 self.assertIn(message_descriptor, {message_descriptor: None}) 500 # Test field containers 501 self.CheckDescriptorSequence(message_descriptor.fields) 502 self.CheckDescriptorMapping(message_descriptor.fields_by_name) 503 self.CheckDescriptorMapping(message_descriptor.fields_by_number) 504 self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name) 505 self.CheckDescriptorMapping(message_descriptor.enum_types_by_name) 506 self.CheckDescriptorMapping(message_descriptor.enum_values_by_name) 507 self.CheckDescriptorMapping(message_descriptor.oneofs_by_name) 508 self.CheckDescriptorMapping(message_descriptor.enum_types[0].values_by_name) 509 # Test extension range 510 self.assertEqual(message_descriptor.extension_ranges, []) 511 512 def CheckFieldDescriptor(self, field_descriptor): 513 # Basic properties 514 self.assertEqual(field_descriptor.name, 'optional_int32') 515 self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32') 516 self.assertEqual(field_descriptor.full_name, 517 'protobuf_unittest.TestAllTypes.optional_int32') 518 self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes') 519 self.assertEqual(field_descriptor.file, unittest_pb2.DESCRIPTOR) 520 # Test equality and hashability 521 self.assertEqual(field_descriptor, field_descriptor) 522 self.assertEqual( 523 field_descriptor.containing_type.fields_by_name['optional_int32'], 524 field_descriptor) 525 self.assertEqual( 526 field_descriptor.containing_type.fields_by_camelcase_name[ 527 'optionalInt32'], 528 field_descriptor) 529 self.assertIn(field_descriptor, [field_descriptor]) 530 self.assertIn(field_descriptor, {field_descriptor: None}) 531 self.assertEqual(None, field_descriptor.extension_scope) 532 self.assertEqual(None, field_descriptor.enum_type) 533 if api_implementation.Type() == 'cpp': 534 # For test coverage only 535 self.assertEqual(field_descriptor.id, field_descriptor.id) 536 537 def CheckDescriptorSequence(self, sequence): 538 # Verifies that a property like 'messageDescriptor.fields' has all the 539 # properties of an immutable abc.Sequence. 540 self.assertNotEqual(sequence, 541 unittest_pb2.TestAllExtensions.DESCRIPTOR.fields) 542 self.assertNotEqual(sequence, []) 543 self.assertNotEqual(sequence, 1) 544 self.assertFalse(sequence == 1) # Only for cpp test coverage 545 self.assertEqual(sequence, sequence) 546 expected_list = list(sequence) 547 self.assertEqual(expected_list, sequence) 548 self.assertGreater(len(sequence), 0) # Sized 549 self.assertEqual(len(sequence), len(expected_list)) # Iterable 550 self.assertEqual(sequence[len(sequence) -1], sequence[-1]) 551 item = sequence[0] 552 self.assertEqual(item, sequence[0]) 553 self.assertIn(item, sequence) # Container 554 self.assertEqual(sequence.index(item), 0) 555 self.assertEqual(sequence.count(item), 1) 556 other_item = unittest_pb2.NestedTestAllTypes.DESCRIPTOR.fields[0] 557 self.assertNotIn(other_item, sequence) 558 self.assertEqual(sequence.count(other_item), 0) 559 self.assertRaises(ValueError, sequence.index, other_item) 560 self.assertRaises(ValueError, sequence.index, []) 561 reversed_iterator = reversed(sequence) 562 self.assertEqual(list(reversed_iterator), list(sequence)[::-1]) 563 self.assertRaises(StopIteration, next, reversed_iterator) 564 expected_list[0] = 'change value' 565 self.assertNotEqual(expected_list, sequence) 566 # TODO(jieluo): Change __repr__ support for DescriptorSequence. 567 if api_implementation.Type() == 'python': 568 self.assertEqual(str(list(sequence)), str(sequence)) 569 else: 570 self.assertEqual(str(sequence)[0], '<') 571 572 def CheckDescriptorMapping(self, mapping): 573 # Verifies that a property like 'messageDescriptor.fields' has all the 574 # properties of an immutable abc.Mapping. 575 self.assertNotEqual( 576 mapping, unittest_pb2.TestAllExtensions.DESCRIPTOR.fields_by_name) 577 self.assertNotEqual(mapping, {}) 578 self.assertNotEqual(mapping, 1) 579 self.assertFalse(mapping == 1) # Only for cpp test coverage 580 excepted_dict = dict(mapping.items()) 581 self.assertEqual(mapping, excepted_dict) 582 self.assertEqual(mapping, mapping) 583 self.assertGreater(len(mapping), 0) # Sized 584 self.assertEqual(len(mapping), len(excepted_dict)) # Iterable 585 if sys.version_info >= (3,): 586 key, item = next(iter(mapping.items())) 587 else: 588 key, item = mapping.items()[0] 589 self.assertIn(key, mapping) # Container 590 self.assertEqual(mapping.get(key), item) 591 with self.assertRaises(TypeError): 592 mapping.get() 593 # TODO(jieluo): Fix python and cpp extension diff. 594 if api_implementation.Type() == 'python': 595 self.assertRaises(TypeError, mapping.get, []) 596 else: 597 self.assertEqual(None, mapping.get([])) 598 # keys(), iterkeys() &co 599 item = (next(iter(mapping.keys())), next(iter(mapping.values()))) 600 self.assertEqual(item, next(iter(mapping.items()))) 601 if sys.version_info < (3,): 602 def CheckItems(seq, iterator): 603 self.assertEqual(next(iterator), seq[0]) 604 self.assertEqual(list(iterator), seq[1:]) 605 CheckItems(mapping.keys(), mapping.iterkeys()) 606 CheckItems(mapping.values(), mapping.itervalues()) 607 CheckItems(mapping.items(), mapping.iteritems()) 608 excepted_dict[key] = 'change value' 609 self.assertNotEqual(mapping, excepted_dict) 610 del excepted_dict[key] 611 excepted_dict['new_key'] = 'new' 612 self.assertNotEqual(mapping, excepted_dict) 613 self.assertRaises(KeyError, mapping.__getitem__, 'key_error') 614 self.assertRaises(KeyError, mapping.__getitem__, len(mapping) + 1) 615 # TODO(jieluo): Add __repr__ support for DescriptorMapping. 616 if api_implementation.Type() == 'python': 617 self.assertEqual(len(str(dict(mapping.items()))), len(str(mapping))) 618 else: 619 self.assertEqual(str(mapping)[0], '<') 620 621 def testDescriptor(self): 622 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 623 self.CheckMessageDescriptor(message_descriptor) 624 field_descriptor = message_descriptor.fields_by_name['optional_int32'] 625 self.CheckFieldDescriptor(field_descriptor) 626 field_descriptor = message_descriptor.fields_by_camelcase_name[ 627 'optionalInt32'] 628 self.CheckFieldDescriptor(field_descriptor) 629 enum_descriptor = unittest_pb2.DESCRIPTOR.enum_types_by_name[ 630 'ForeignEnum'] 631 self.assertEqual(None, enum_descriptor.containing_type) 632 # Test extension range 633 self.assertEqual( 634 unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, 635 [(1, 536870912)]) 636 self.assertEqual( 637 unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, 638 [(42, 43), (4143, 4244), (65536, 536870912)]) 639 640 def testCppDescriptorContainer(self): 641 containing_file = unittest_pb2.DESCRIPTOR 642 self.CheckDescriptorSequence(containing_file.dependencies) 643 self.CheckDescriptorMapping(containing_file.message_types_by_name) 644 self.CheckDescriptorMapping(containing_file.enum_types_by_name) 645 self.CheckDescriptorMapping(containing_file.services_by_name) 646 self.CheckDescriptorMapping(containing_file.extensions_by_name) 647 self.CheckDescriptorMapping( 648 unittest_pb2.TestNestedExtension.DESCRIPTOR.extensions_by_name) 649 650 def testCppDescriptorContainer_Iterator(self): 651 # Same test with the iterator 652 enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] 653 values_iter = iter(enum.values) 654 del enum 655 self.assertEqual('FOO', next(values_iter).name) 656 657 def testDescriptorNestedTypesContainer(self): 658 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 659 nested_message_descriptor = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR 660 self.assertEqual(len(message_descriptor.nested_types), 3) 661 self.assertFalse(None in message_descriptor.nested_types) 662 self.assertTrue( 663 nested_message_descriptor in message_descriptor.nested_types) 664 665 def testServiceDescriptor(self): 666 service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService'] 667 self.assertEqual(service_descriptor.name, 'TestService') 668 self.assertEqual(service_descriptor.methods[0].name, 'Foo') 669 self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR) 670 self.assertEqual(service_descriptor.index, 0) 671 self.CheckDescriptorMapping(service_descriptor.methods_by_name) 672 673 def testOneofDescriptor(self): 674 message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR 675 oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] 676 self.assertFalse(oneof_descriptor.has_options) 677 self.assertEqual(message_descriptor, oneof_descriptor.containing_type) 678 self.assertEqual('oneof_field', oneof_descriptor.name) 679 self.assertEqual('protobuf_unittest.TestAllTypes.oneof_field', 680 oneof_descriptor.full_name) 681 self.assertEqual(0, oneof_descriptor.index) 682 683 684class DescriptorCopyToProtoTest(unittest.TestCase): 685 """Tests for CopyTo functions of Descriptor.""" 686 687 def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii): 688 expected_proto = expected_class() 689 text_format.Merge(expected_ascii, expected_proto) 690 691 self.assertEqual( 692 actual_proto, expected_proto, 693 'Not equal,\nActual:\n%s\nExpected:\n%s\n' 694 % (str(actual_proto), str(expected_proto))) 695 696 def _InternalTestCopyToProto(self, desc, expected_proto_class, 697 expected_proto_ascii): 698 actual = expected_proto_class() 699 desc.CopyToProto(actual) 700 self._AssertProtoEqual( 701 actual, expected_proto_class, expected_proto_ascii) 702 703 def testCopyToProto_EmptyMessage(self): 704 self._InternalTestCopyToProto( 705 unittest_pb2.TestEmptyMessage.DESCRIPTOR, 706 descriptor_pb2.DescriptorProto, 707 TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII) 708 709 def testCopyToProto_NestedMessage(self): 710 TEST_NESTED_MESSAGE_ASCII = """ 711 name: 'NestedMessage' 712 field: < 713 name: 'bb' 714 number: 1 715 label: 1 # Optional 716 type: 5 # TYPE_INT32 717 > 718 """ 719 720 self._InternalTestCopyToProto( 721 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, 722 descriptor_pb2.DescriptorProto, 723 TEST_NESTED_MESSAGE_ASCII) 724 725 def testCopyToProto_ForeignNestedMessage(self): 726 TEST_FOREIGN_NESTED_ASCII = """ 727 name: 'TestForeignNested' 728 field: < 729 name: 'foreign_nested' 730 number: 1 731 label: 1 # Optional 732 type: 11 # TYPE_MESSAGE 733 type_name: '.protobuf_unittest.TestAllTypes.NestedMessage' 734 > 735 """ 736 737 self._InternalTestCopyToProto( 738 unittest_pb2.TestForeignNested.DESCRIPTOR, 739 descriptor_pb2.DescriptorProto, 740 TEST_FOREIGN_NESTED_ASCII) 741 742 def testCopyToProto_ForeignEnum(self): 743 TEST_FOREIGN_ENUM_ASCII = """ 744 name: 'ForeignEnum' 745 value: < 746 name: 'FOREIGN_FOO' 747 number: 4 748 > 749 value: < 750 name: 'FOREIGN_BAR' 751 number: 5 752 > 753 value: < 754 name: 'FOREIGN_BAZ' 755 number: 6 756 > 757 """ 758 759 self._InternalTestCopyToProto( 760 unittest_pb2.ForeignEnum.DESCRIPTOR, 761 descriptor_pb2.EnumDescriptorProto, 762 TEST_FOREIGN_ENUM_ASCII) 763 764 def testCopyToProto_Options(self): 765 TEST_DEPRECATED_FIELDS_ASCII = """ 766 name: 'TestDeprecatedFields' 767 field: < 768 name: 'deprecated_int32' 769 number: 1 770 label: 1 # Optional 771 type: 5 # TYPE_INT32 772 options: < 773 deprecated: true 774 > 775 > 776 field { 777 name: "deprecated_int32_in_oneof" 778 number: 2 779 label: LABEL_OPTIONAL 780 type: TYPE_INT32 781 options { 782 deprecated: true 783 } 784 oneof_index: 0 785 } 786 oneof_decl { 787 name: "oneof_fields" 788 } 789 """ 790 791 self._InternalTestCopyToProto( 792 unittest_pb2.TestDeprecatedFields.DESCRIPTOR, 793 descriptor_pb2.DescriptorProto, 794 TEST_DEPRECATED_FIELDS_ASCII) 795 796 def testCopyToProto_AllExtensions(self): 797 TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """ 798 name: 'TestEmptyMessageWithExtensions' 799 extension_range: < 800 start: 1 801 end: 536870912 802 > 803 """ 804 805 self._InternalTestCopyToProto( 806 unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR, 807 descriptor_pb2.DescriptorProto, 808 TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII) 809 810 def testCopyToProto_SeveralExtensions(self): 811 TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """ 812 name: 'TestMultipleExtensionRanges' 813 extension_range: < 814 start: 42 815 end: 43 816 > 817 extension_range: < 818 start: 4143 819 end: 4244 820 > 821 extension_range: < 822 start: 65536 823 end: 536870912 824 > 825 """ 826 827 self._InternalTestCopyToProto( 828 unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR, 829 descriptor_pb2.DescriptorProto, 830 TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) 831 832 def testCopyToProto_FileDescriptor(self): 833 UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" 834 name: 'google/protobuf/unittest_import.proto' 835 package: 'protobuf_unittest_import' 836 dependency: 'google/protobuf/unittest_import_public.proto' 837 message_type: < 838 name: 'ImportMessage' 839 field: < 840 name: 'd' 841 number: 1 842 label: 1 # Optional 843 type: 5 # TYPE_INT32 844 > 845 > 846 """ + 847 """enum_type: < 848 name: 'ImportEnum' 849 value: < 850 name: 'IMPORT_FOO' 851 number: 7 852 > 853 value: < 854 name: 'IMPORT_BAR' 855 number: 8 856 > 857 value: < 858 name: 'IMPORT_BAZ' 859 number: 9 860 > 861 > 862 enum_type: < 863 name: 'ImportEnumForMap' 864 value: < 865 name: 'UNKNOWN' 866 number: 0 867 > 868 value: < 869 name: 'FOO' 870 number: 1 871 > 872 value: < 873 name: 'BAR' 874 number: 2 875 > 876 > 877 options: < 878 java_package: 'com.google.protobuf.test' 879 optimize_for: 1 # SPEED 880 """ + 881 """ 882 cc_enable_arenas: true 883 > 884 public_dependency: 0 885 """) 886 self._InternalTestCopyToProto( 887 unittest_import_pb2.DESCRIPTOR, 888 descriptor_pb2.FileDescriptorProto, 889 UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) 890 891 def testCopyToProto_ServiceDescriptor(self): 892 TEST_SERVICE_ASCII = """ 893 name: 'TestService' 894 method: < 895 name: 'Foo' 896 input_type: '.protobuf_unittest.FooRequest' 897 output_type: '.protobuf_unittest.FooResponse' 898 > 899 method: < 900 name: 'Bar' 901 input_type: '.protobuf_unittest.BarRequest' 902 output_type: '.protobuf_unittest.BarResponse' 903 > 904 """ 905 self._InternalTestCopyToProto( 906 unittest_pb2.TestService.DESCRIPTOR, 907 descriptor_pb2.ServiceDescriptorProto, 908 TEST_SERVICE_ASCII) 909 910 @unittest.skipIf( 911 api_implementation.Type() == 'python', 912 'It is not implemented in python.') 913 # TODO(jieluo): Add support for pure python or remove in c extension. 914 def testCopyToProto_MethodDescriptor(self): 915 expected_ascii = """ 916 name: 'Foo' 917 input_type: '.protobuf_unittest.FooRequest' 918 output_type: '.protobuf_unittest.FooResponse' 919 """ 920 method_descriptor = unittest_pb2.TestService.DESCRIPTOR.FindMethodByName( 921 'Foo') 922 self._InternalTestCopyToProto( 923 method_descriptor, 924 descriptor_pb2.MethodDescriptorProto, 925 expected_ascii) 926 927 @unittest.skipIf( 928 api_implementation.Type() == 'python', 929 'Pure python does not raise error.') 930 # TODO(jieluo): Fix pure python to check with the proto type. 931 def testCopyToProto_TypeError(self): 932 file_proto = descriptor_pb2.FileDescriptorProto() 933 self.assertRaises(TypeError, 934 unittest_pb2.TestEmptyMessage.DESCRIPTOR.CopyToProto, 935 file_proto) 936 self.assertRaises(TypeError, 937 unittest_pb2.ForeignEnum.DESCRIPTOR.CopyToProto, 938 file_proto) 939 self.assertRaises(TypeError, 940 unittest_pb2.TestService.DESCRIPTOR.CopyToProto, 941 file_proto) 942 proto = descriptor_pb2.DescriptorProto() 943 self.assertRaises(TypeError, 944 unittest_import_pb2.DESCRIPTOR.CopyToProto, 945 proto) 946 947 948class MakeDescriptorTest(unittest.TestCase): 949 950 def testMakeDescriptorWithNestedFields(self): 951 file_descriptor_proto = descriptor_pb2.FileDescriptorProto() 952 file_descriptor_proto.name = 'Foo2' 953 message_type = file_descriptor_proto.message_type.add() 954 message_type.name = file_descriptor_proto.name 955 nested_type = message_type.nested_type.add() 956 nested_type.name = 'Sub' 957 enum_type = nested_type.enum_type.add() 958 enum_type.name = 'FOO' 959 enum_type_val = enum_type.value.add() 960 enum_type_val.name = 'BAR' 961 enum_type_val.number = 3 962 field = message_type.field.add() 963 field.number = 1 964 field.name = 'uint64_field' 965 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 966 field.type = descriptor.FieldDescriptor.TYPE_UINT64 967 field = message_type.field.add() 968 field.number = 2 969 field.name = 'nested_message_field' 970 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 971 field.type = descriptor.FieldDescriptor.TYPE_MESSAGE 972 field.type_name = 'Sub' 973 enum_field = nested_type.field.add() 974 enum_field.number = 2 975 enum_field.name = 'bar_field' 976 enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 977 enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM 978 enum_field.type_name = 'Foo2.Sub.FOO' 979 980 result = descriptor.MakeDescriptor(message_type) 981 self.assertEqual(result.fields[0].cpp_type, 982 descriptor.FieldDescriptor.CPPTYPE_UINT64) 983 self.assertEqual(result.fields[1].cpp_type, 984 descriptor.FieldDescriptor.CPPTYPE_MESSAGE) 985 self.assertEqual(result.fields[1].message_type.containing_type, 986 result) 987 self.assertEqual(result.nested_types[0].fields[0].full_name, 988 'Foo2.Sub.bar_field') 989 self.assertEqual(result.nested_types[0].fields[0].enum_type, 990 result.nested_types[0].enum_types[0]) 991 self.assertFalse(result.has_options) 992 self.assertFalse(result.fields[0].has_options) 993 if api_implementation.Type() == 'cpp': 994 with self.assertRaises(AttributeError): 995 result.fields[0].has_options = False 996 997 def testMakeDescriptorWithUnsignedIntField(self): 998 file_descriptor_proto = descriptor_pb2.FileDescriptorProto() 999 file_descriptor_proto.name = 'Foo' 1000 message_type = file_descriptor_proto.message_type.add() 1001 message_type.name = file_descriptor_proto.name 1002 enum_type = message_type.enum_type.add() 1003 enum_type.name = 'FOO' 1004 enum_type_val = enum_type.value.add() 1005 enum_type_val.name = 'BAR' 1006 enum_type_val.number = 3 1007 field = message_type.field.add() 1008 field.number = 1 1009 field.name = 'uint64_field' 1010 field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 1011 field.type = descriptor.FieldDescriptor.TYPE_UINT64 1012 enum_field = message_type.field.add() 1013 enum_field.number = 2 1014 enum_field.name = 'bar_field' 1015 enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED 1016 enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM 1017 enum_field.type_name = 'Foo.FOO' 1018 1019 result = descriptor.MakeDescriptor(message_type) 1020 self.assertEqual(result.fields[0].cpp_type, 1021 descriptor.FieldDescriptor.CPPTYPE_UINT64) 1022 1023 1024 def testMakeDescriptorWithOptions(self): 1025 descriptor_proto = descriptor_pb2.DescriptorProto() 1026 aggregate_message = unittest_custom_options_pb2.AggregateMessage 1027 aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto) 1028 reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto) 1029 1030 options = reformed_descriptor.GetOptions() 1031 self.assertEqual(101, 1032 options.Extensions[unittest_custom_options_pb2.msgopt].i) 1033 1034 def testCamelcaseName(self): 1035 descriptor_proto = descriptor_pb2.DescriptorProto() 1036 descriptor_proto.name = 'Bar' 1037 names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar'] 1038 camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar'] 1039 for index in range(len(names)): 1040 field = descriptor_proto.field.add() 1041 field.number = index + 1 1042 field.name = names[index] 1043 result = descriptor.MakeDescriptor(descriptor_proto) 1044 for index in range(len(camelcase_names)): 1045 self.assertEqual(result.fields[index].camelcase_name, 1046 camelcase_names[index]) 1047 1048 def testJsonName(self): 1049 descriptor_proto = descriptor_pb2.DescriptorProto() 1050 descriptor_proto.name = 'TestJsonName' 1051 names = ['field_name', 'fieldName', 'FieldName', 1052 '_field_name', 'FIELD_NAME', 'json_name'] 1053 json_names = ['fieldName', 'fieldName', 'FieldName', 1054 'FieldName', 'FIELDNAME', '@type'] 1055 for index in range(len(names)): 1056 field = descriptor_proto.field.add() 1057 field.number = index + 1 1058 field.name = names[index] 1059 field.json_name = '@type' 1060 result = descriptor.MakeDescriptor(descriptor_proto) 1061 for index in range(len(json_names)): 1062 self.assertEqual(result.fields[index].json_name, 1063 json_names[index]) 1064 1065 1066if __name__ == '__main__': 1067 unittest.main() 1068