1# Protocol Buffers - Google's data interchange format 2# Copyright 2008 Google Inc. All rights reserved. 3# https://developers.google.com/protocol-buffers/ 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: 8# 9# * Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above 12# copyright notice, this list of conditions and the following disclaimer 13# in the documentation and/or other materials provided with the 14# distribution. 15# * Neither the name of Google Inc. nor the names of its 16# contributors may be used to endorse or promote products derived from 17# this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31# TODO(robinson): Flesh this out considerably. We focused on reflection_test.py 32# first, since it's testing the subtler code, and since it provides decent 33# indirect testing of the protocol compiler output. 34 35"""Unittest that directly tests the output of the pure-Python protocol 36compiler. See //google/protobuf/internal/reflection_test.py for a test which 37further ensures that we can use Python protocol message objects as we expect. 38""" 39 40__author__ = '[email protected] (Will Robinson)' 41 42import unittest 43 44from google.protobuf.internal import test_bad_identifiers_pb2 45from google.protobuf import unittest_custom_options_pb2 46from google.protobuf import unittest_import_pb2 47from google.protobuf import unittest_import_public_pb2 48from google.protobuf import unittest_mset_pb2 49from google.protobuf import unittest_mset_wire_format_pb2 50from google.protobuf import unittest_no_generic_services_pb2 51from google.protobuf import unittest_pb2 52from google.protobuf import service 53from google.protobuf import symbol_database 54 55MAX_EXTENSION = 536870912 56 57 58class GeneratorTest(unittest.TestCase): 59 60 def testNestedMessageDescriptor(self): 61 field_name = 'optional_nested_message' 62 proto_type = unittest_pb2.TestAllTypes 63 self.assertEqual( 64 proto_type.NestedMessage.DESCRIPTOR, 65 proto_type.DESCRIPTOR.fields_by_name[field_name].message_type) 66 67 def testEnums(self): 68 # We test only module-level enums here. 69 # TODO(robinson): Examine descriptors directly to check 70 # enum descriptor output. 71 self.assertEqual(4, unittest_pb2.FOREIGN_FOO) 72 self.assertEqual(5, unittest_pb2.FOREIGN_BAR) 73 self.assertEqual(6, unittest_pb2.FOREIGN_BAZ) 74 75 proto = unittest_pb2.TestAllTypes() 76 self.assertEqual(1, proto.FOO) 77 self.assertEqual(1, unittest_pb2.TestAllTypes.FOO) 78 self.assertEqual(2, proto.BAR) 79 self.assertEqual(2, unittest_pb2.TestAllTypes.BAR) 80 self.assertEqual(3, proto.BAZ) 81 self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ) 82 83 def testExtremeDefaultValues(self): 84 message = unittest_pb2.TestExtremeDefaultValues() 85 86 # Python pre-2.6 does not have isinf() or isnan() functions, so we have 87 # to provide our own. 88 def isnan(val): 89 # NaN is never equal to itself. 90 return val != val 91 def isinf(val): 92 # Infinity times zero equals NaN. 93 return not isnan(val) and isnan(val * 0) 94 95 self.assertTrue(isinf(message.inf_double)) 96 self.assertTrue(message.inf_double > 0) 97 self.assertTrue(isinf(message.neg_inf_double)) 98 self.assertTrue(message.neg_inf_double < 0) 99 self.assertTrue(isnan(message.nan_double)) 100 101 self.assertTrue(isinf(message.inf_float)) 102 self.assertTrue(message.inf_float > 0) 103 self.assertTrue(isinf(message.neg_inf_float)) 104 self.assertTrue(message.neg_inf_float < 0) 105 self.assertTrue(isnan(message.nan_float)) 106 self.assertEqual("? ? ?? ?? ??? ??/ ??-", message.cpp_trigraph) 107 108 def testHasDefaultValues(self): 109 desc = unittest_pb2.TestAllTypes.DESCRIPTOR 110 111 expected_has_default_by_name = { 112 'optional_int32': False, 113 'repeated_int32': False, 114 'optional_nested_message': False, 115 'default_int32': True, 116 } 117 118 has_default_by_name = dict( 119 [(f.name, f.has_default_value) 120 for f in desc.fields 121 if f.name in expected_has_default_by_name]) 122 self.assertEqual(expected_has_default_by_name, has_default_by_name) 123 124 def testContainingTypeBehaviorForExtensions(self): 125 self.assertEqual(unittest_pb2.optional_int32_extension.containing_type, 126 unittest_pb2.TestAllExtensions.DESCRIPTOR) 127 self.assertEqual(unittest_pb2.TestRequired.single.containing_type, 128 unittest_pb2.TestAllExtensions.DESCRIPTOR) 129 130 def testExtensionScope(self): 131 self.assertEqual(unittest_pb2.optional_int32_extension.extension_scope, 132 None) 133 self.assertEqual(unittest_pb2.TestRequired.single.extension_scope, 134 unittest_pb2.TestRequired.DESCRIPTOR) 135 136 def testIsExtension(self): 137 self.assertTrue(unittest_pb2.optional_int32_extension.is_extension) 138 self.assertTrue(unittest_pb2.TestRequired.single.is_extension) 139 140 message_descriptor = unittest_pb2.TestRequired.DESCRIPTOR 141 non_extension_descriptor = message_descriptor.fields_by_name['a'] 142 self.assertTrue(not non_extension_descriptor.is_extension) 143 144 def testOptions(self): 145 proto = unittest_mset_wire_format_pb2.TestMessageSet() 146 self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format) 147 148 def testMessageWithCustomOptions(self): 149 proto = unittest_custom_options_pb2.TestMessageWithCustomOptions() 150 enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions() 151 self.assertTrue(enum_options is not None) 152 # TODO(gps): We really should test for the presence of the enum_opt1 153 # extension and for its value to be set to -789. 154 155 def testNestedTypes(self): 156 self.assertEqual( 157 set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types), 158 set([ 159 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, 160 unittest_pb2.TestAllTypes.OptionalGroup.DESCRIPTOR, 161 unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR, 162 ])) 163 self.assertEqual(unittest_pb2.TestEmptyMessage.DESCRIPTOR.nested_types, []) 164 self.assertEqual( 165 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.nested_types, []) 166 167 def testContainingType(self): 168 self.assertTrue( 169 unittest_pb2.TestEmptyMessage.DESCRIPTOR.containing_type is None) 170 self.assertTrue( 171 unittest_pb2.TestAllTypes.DESCRIPTOR.containing_type is None) 172 self.assertEqual( 173 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, 174 unittest_pb2.TestAllTypes.DESCRIPTOR) 175 self.assertEqual( 176 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, 177 unittest_pb2.TestAllTypes.DESCRIPTOR) 178 self.assertEqual( 179 unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR.containing_type, 180 unittest_pb2.TestAllTypes.DESCRIPTOR) 181 182 def testContainingTypeInEnumDescriptor(self): 183 self.assertTrue(unittest_pb2._FOREIGNENUM.containing_type is None) 184 self.assertEqual(unittest_pb2._TESTALLTYPES_NESTEDENUM.containing_type, 185 unittest_pb2.TestAllTypes.DESCRIPTOR) 186 187 def testPackage(self): 188 self.assertEqual( 189 unittest_pb2.TestAllTypes.DESCRIPTOR.file.package, 190 'protobuf_unittest') 191 desc = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR 192 self.assertEqual(desc.file.package, 'protobuf_unittest') 193 self.assertEqual( 194 unittest_import_pb2.ImportMessage.DESCRIPTOR.file.package, 195 'protobuf_unittest_import') 196 197 self.assertEqual( 198 unittest_pb2._FOREIGNENUM.file.package, 'protobuf_unittest') 199 self.assertEqual( 200 unittest_pb2._TESTALLTYPES_NESTEDENUM.file.package, 201 'protobuf_unittest') 202 self.assertEqual( 203 unittest_import_pb2._IMPORTENUM.file.package, 204 'protobuf_unittest_import') 205 206 def testExtensionRange(self): 207 self.assertEqual( 208 unittest_pb2.TestAllTypes.DESCRIPTOR.extension_ranges, []) 209 self.assertEqual( 210 unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, 211 [(1, MAX_EXTENSION)]) 212 self.assertEqual( 213 unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, 214 [(42, 43), (4143, 4244), (65536, MAX_EXTENSION)]) 215 216 def testFileDescriptor(self): 217 self.assertEqual(unittest_pb2.DESCRIPTOR.name, 218 'google/protobuf/unittest.proto') 219 self.assertEqual(unittest_pb2.DESCRIPTOR.package, 'protobuf_unittest') 220 self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None) 221 self.assertEqual(unittest_pb2.DESCRIPTOR.dependencies, 222 [unittest_import_pb2.DESCRIPTOR]) 223 self.assertEqual(unittest_import_pb2.DESCRIPTOR.dependencies, 224 [unittest_import_public_pb2.DESCRIPTOR]) 225 self.assertEqual(unittest_import_pb2.DESCRIPTOR.public_dependencies, 226 [unittest_import_public_pb2.DESCRIPTOR]) 227 def testNoGenericServices(self): 228 self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage")) 229 self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO")) 230 self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension")) 231 232 # Make sure unittest_no_generic_services_pb2 has no services subclassing 233 # Proto2 Service class. 234 if hasattr(unittest_no_generic_services_pb2, "TestService"): 235 self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService, 236 service.Service)) 237 238 def testMessageTypesByName(self): 239 file_type = unittest_pb2.DESCRIPTOR 240 self.assertEqual( 241 unittest_pb2._TESTALLTYPES, 242 file_type.message_types_by_name[unittest_pb2._TESTALLTYPES.name]) 243 244 # Nested messages shouldn't be included in the message_types_by_name 245 # dictionary (like in the C++ API). 246 self.assertFalse( 247 unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in 248 file_type.message_types_by_name) 249 250 def testEnumTypesByName(self): 251 file_type = unittest_pb2.DESCRIPTOR 252 self.assertEqual( 253 unittest_pb2._FOREIGNENUM, 254 file_type.enum_types_by_name[unittest_pb2._FOREIGNENUM.name]) 255 256 def testExtensionsByName(self): 257 file_type = unittest_pb2.DESCRIPTOR 258 self.assertEqual( 259 unittest_pb2.my_extension_string, 260 file_type.extensions_by_name[unittest_pb2.my_extension_string.name]) 261 262 def testPublicImports(self): 263 # Test public imports as embedded message. 264 all_type_proto = unittest_pb2.TestAllTypes() 265 self.assertEqual(0, all_type_proto.optional_public_import_message.e) 266 267 # PublicImportMessage is actually defined in unittest_import_public_pb2 268 # module, and is public imported by unittest_import_pb2 module. 269 public_import_proto = unittest_import_pb2.PublicImportMessage() 270 self.assertEqual(0, public_import_proto.e) 271 self.assertTrue(unittest_import_public_pb2.PublicImportMessage is 272 unittest_import_pb2.PublicImportMessage) 273 274 def testBadIdentifiers(self): 275 # We're just testing that the code was imported without problems. 276 message = test_bad_identifiers_pb2.TestBadIdentifiers() 277 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message], 278 "foo") 279 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor], 280 "bar") 281 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection], 282 "baz") 283 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service], 284 "qux") 285 286 def testOneof(self): 287 desc = unittest_pb2.TestAllTypes.DESCRIPTOR 288 self.assertEqual(1, len(desc.oneofs)) 289 self.assertEqual('oneof_field', desc.oneofs[0].name) 290 self.assertEqual(0, desc.oneofs[0].index) 291 self.assertIs(desc, desc.oneofs[0].containing_type) 292 self.assertIs(desc.oneofs[0], desc.oneofs_by_name['oneof_field']) 293 nested_names = set(['oneof_uint32', 'oneof_nested_message', 294 'oneof_string', 'oneof_bytes']) 295 self.assertEqual( 296 nested_names, 297 set([field.name for field in desc.oneofs[0].fields])) 298 for field_name, field_desc in desc.fields_by_name.items(): 299 if field_name in nested_names: 300 self.assertIs(desc.oneofs[0], field_desc.containing_oneof) 301 else: 302 self.assertIsNone(field_desc.containing_oneof) 303 304 def testEnumWithDupValue(self): 305 self.assertEqual('FOO1', 306 unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.FOO1)) 307 self.assertEqual('FOO1', 308 unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.FOO2)) 309 self.assertEqual('BAR1', 310 unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.BAR1)) 311 self.assertEqual('BAR1', 312 unittest_pb2.TestEnumWithDupValue.Name(unittest_pb2.BAR2)) 313 314 315class SymbolDatabaseRegistrationTest(unittest.TestCase): 316 """Checks that messages, enums and files are correctly registered.""" 317 318 def testGetSymbol(self): 319 self.assertEqual( 320 unittest_pb2.TestAllTypes, symbol_database.Default().GetSymbol( 321 'protobuf_unittest.TestAllTypes')) 322 self.assertEqual( 323 unittest_pb2.TestAllTypes.NestedMessage, 324 symbol_database.Default().GetSymbol( 325 'protobuf_unittest.TestAllTypes.NestedMessage')) 326 with self.assertRaises(KeyError): 327 symbol_database.Default().GetSymbol('protobuf_unittest.NestedMessage') 328 self.assertEqual( 329 unittest_pb2.TestAllTypes.OptionalGroup, 330 symbol_database.Default().GetSymbol( 331 'protobuf_unittest.TestAllTypes.OptionalGroup')) 332 self.assertEqual( 333 unittest_pb2.TestAllTypes.RepeatedGroup, 334 symbol_database.Default().GetSymbol( 335 'protobuf_unittest.TestAllTypes.RepeatedGroup')) 336 337 def testEnums(self): 338 self.assertEqual( 339 'protobuf_unittest.ForeignEnum', 340 symbol_database.Default().pool.FindEnumTypeByName( 341 'protobuf_unittest.ForeignEnum').full_name) 342 self.assertEqual( 343 'protobuf_unittest.TestAllTypes.NestedEnum', 344 symbol_database.Default().pool.FindEnumTypeByName( 345 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) 346 347 def testFindFileByName(self): 348 self.assertEqual( 349 'google/protobuf/unittest.proto', 350 symbol_database.Default().pool.FindFileByName( 351 'google/protobuf/unittest.proto').name) 352 353if __name__ == '__main__': 354 unittest.main() 355