Home | History | Annotate | Download | only in internal
      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 (at] google.com (Will Robinson)'
     36 
     37 import sys
     38 
     39 try:
     40   import unittest2 as unittest  #PY26
     41 except ImportError:
     42   import unittest
     43 
     44 from google.protobuf import unittest_custom_options_pb2
     45 from google.protobuf import unittest_import_pb2
     46 from google.protobuf import unittest_pb2
     47 from google.protobuf import descriptor_pb2
     48 from google.protobuf.internal import api_implementation
     49 from google.protobuf.internal import test_util
     50 from google.protobuf import descriptor
     51 from google.protobuf import descriptor_pool
     52 from google.protobuf import symbol_database
     53 from google.protobuf import text_format
     54 
     55 
     56 TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
     57 name: 'TestEmptyMessage'
     58 """
     59 
     60 
     61 class 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 
    418 class 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 
    425 class 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 
    524 class 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 
    725 class 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 
    821 if __name__ == '__main__':
    822   unittest.main()
    823