1#! /usr/bin/python 2# 3# Protocol Buffers - Google's data interchange format 4# Copyright 2008 Google Inc. All rights reserved. 5# http://code.google.com/p/protobuf/ 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# TODO(robinson): Flesh this out considerably. We focused on reflection_test.py 34# first, since it's testing the subtler code, and since it provides decent 35# indirect testing of the protocol compiler output. 36 37"""Unittest that directly tests the output of the pure-Python protocol 38compiler. See //google/protobuf/reflection_test.py for a test which 39further ensures that we can use Python protocol message objects as we expect. 40""" 41 42__author__ = 'robinson@google.com (Will Robinson)' 43 44import unittest 45from google.protobuf.internal import test_bad_identifiers_pb2 46from google.protobuf import unittest_custom_options_pb2 47from google.protobuf import unittest_import_pb2 48from google.protobuf import unittest_import_public_pb2 49from google.protobuf import unittest_mset_pb2 50from google.protobuf import unittest_pb2 51from google.protobuf import unittest_no_generic_services_pb2 52from google.protobuf import service 53 54MAX_EXTENSION = 536870912 55 56 57class GeneratorTest(unittest.TestCase): 58 59 def testNestedMessageDescriptor(self): 60 field_name = 'optional_nested_message' 61 proto_type = unittest_pb2.TestAllTypes 62 self.assertEqual( 63 proto_type.NestedMessage.DESCRIPTOR, 64 proto_type.DESCRIPTOR.fields_by_name[field_name].message_type) 65 66 def testEnums(self): 67 # We test only module-level enums here. 68 # TODO(robinson): Examine descriptors directly to check 69 # enum descriptor output. 70 self.assertEqual(4, unittest_pb2.FOREIGN_FOO) 71 self.assertEqual(5, unittest_pb2.FOREIGN_BAR) 72 self.assertEqual(6, unittest_pb2.FOREIGN_BAZ) 73 74 proto = unittest_pb2.TestAllTypes() 75 self.assertEqual(1, proto.FOO) 76 self.assertEqual(1, unittest_pb2.TestAllTypes.FOO) 77 self.assertEqual(2, proto.BAR) 78 self.assertEqual(2, unittest_pb2.TestAllTypes.BAR) 79 self.assertEqual(3, proto.BAZ) 80 self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ) 81 82 def testExtremeDefaultValues(self): 83 message = unittest_pb2.TestExtremeDefaultValues() 84 85 # Python pre-2.6 does not have isinf() or isnan() functions, so we have 86 # to provide our own. 87 def isnan(val): 88 # NaN is never equal to itself. 89 return val != val 90 def isinf(val): 91 # Infinity times zero equals NaN. 92 return not isnan(val) and isnan(val * 0) 93 94 self.assertTrue(isinf(message.inf_double)) 95 self.assertTrue(message.inf_double > 0) 96 self.assertTrue(isinf(message.neg_inf_double)) 97 self.assertTrue(message.neg_inf_double < 0) 98 self.assertTrue(isnan(message.nan_double)) 99 100 self.assertTrue(isinf(message.inf_float)) 101 self.assertTrue(message.inf_float > 0) 102 self.assertTrue(isinf(message.neg_inf_float)) 103 self.assertTrue(message.neg_inf_float < 0) 104 self.assertTrue(isnan(message.nan_float)) 105 self.assertEqual("? ? ?? ?? ??? ??/ ??-", message.cpp_trigraph) 106 107 def testHasDefaultValues(self): 108 desc = unittest_pb2.TestAllTypes.DESCRIPTOR 109 110 expected_has_default_by_name = { 111 'optional_int32': False, 112 'repeated_int32': False, 113 'optional_nested_message': False, 114 'default_int32': True, 115 } 116 117 has_default_by_name = dict( 118 [(f.name, f.has_default_value) 119 for f in desc.fields 120 if f.name in expected_has_default_by_name]) 121 self.assertEqual(expected_has_default_by_name, has_default_by_name) 122 123 def testContainingTypeBehaviorForExtensions(self): 124 self.assertEqual(unittest_pb2.optional_int32_extension.containing_type, 125 unittest_pb2.TestAllExtensions.DESCRIPTOR) 126 self.assertEqual(unittest_pb2.TestRequired.single.containing_type, 127 unittest_pb2.TestAllExtensions.DESCRIPTOR) 128 129 def testExtensionScope(self): 130 self.assertEqual(unittest_pb2.optional_int32_extension.extension_scope, 131 None) 132 self.assertEqual(unittest_pb2.TestRequired.single.extension_scope, 133 unittest_pb2.TestRequired.DESCRIPTOR) 134 135 def testIsExtension(self): 136 self.assertTrue(unittest_pb2.optional_int32_extension.is_extension) 137 self.assertTrue(unittest_pb2.TestRequired.single.is_extension) 138 139 message_descriptor = unittest_pb2.TestRequired.DESCRIPTOR 140 non_extension_descriptor = message_descriptor.fields_by_name['a'] 141 self.assertTrue(not non_extension_descriptor.is_extension) 142 143 def testOptions(self): 144 proto = unittest_mset_pb2.TestMessageSet() 145 self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format) 146 147 def testMessageWithCustomOptions(self): 148 proto = unittest_custom_options_pb2.TestMessageWithCustomOptions() 149 enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions() 150 self.assertTrue(enum_options is not None) 151 # TODO(gps): We really should test for the presense of the enum_opt1 152 # extension and for its value to be set to -789. 153 154 def testNestedTypes(self): 155 self.assertEquals( 156 set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types), 157 set([ 158 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, 159 unittest_pb2.TestAllTypes.OptionalGroup.DESCRIPTOR, 160 unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR, 161 ])) 162 self.assertEqual(unittest_pb2.TestEmptyMessage.DESCRIPTOR.nested_types, []) 163 self.assertEqual( 164 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.nested_types, []) 165 166 def testContainingType(self): 167 self.assertTrue( 168 unittest_pb2.TestEmptyMessage.DESCRIPTOR.containing_type is None) 169 self.assertTrue( 170 unittest_pb2.TestAllTypes.DESCRIPTOR.containing_type is None) 171 self.assertEqual( 172 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, 173 unittest_pb2.TestAllTypes.DESCRIPTOR) 174 self.assertEqual( 175 unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, 176 unittest_pb2.TestAllTypes.DESCRIPTOR) 177 self.assertEqual( 178 unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR.containing_type, 179 unittest_pb2.TestAllTypes.DESCRIPTOR) 180 181 def testContainingTypeInEnumDescriptor(self): 182 self.assertTrue(unittest_pb2._FOREIGNENUM.containing_type is None) 183 self.assertEqual(unittest_pb2._TESTALLTYPES_NESTEDENUM.containing_type, 184 unittest_pb2.TestAllTypes.DESCRIPTOR) 185 186 def testPackage(self): 187 self.assertEqual( 188 unittest_pb2.TestAllTypes.DESCRIPTOR.file.package, 189 'protobuf_unittest') 190 desc = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR 191 self.assertEqual(desc.file.package, 'protobuf_unittest') 192 self.assertEqual( 193 unittest_import_pb2.ImportMessage.DESCRIPTOR.file.package, 194 'protobuf_unittest_import') 195 196 self.assertEqual( 197 unittest_pb2._FOREIGNENUM.file.package, 'protobuf_unittest') 198 self.assertEqual( 199 unittest_pb2._TESTALLTYPES_NESTEDENUM.file.package, 200 'protobuf_unittest') 201 self.assertEqual( 202 unittest_import_pb2._IMPORTENUM.file.package, 203 'protobuf_unittest_import') 204 205 def testExtensionRange(self): 206 self.assertEqual( 207 unittest_pb2.TestAllTypes.DESCRIPTOR.extension_ranges, []) 208 self.assertEqual( 209 unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, 210 [(1, MAX_EXTENSION)]) 211 self.assertEqual( 212 unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, 213 [(42, 43), (4143, 4244), (65536, MAX_EXTENSION)]) 214 215 def testFileDescriptor(self): 216 self.assertEqual(unittest_pb2.DESCRIPTOR.name, 217 'google/protobuf/unittest.proto') 218 self.assertEqual(unittest_pb2.DESCRIPTOR.package, 'protobuf_unittest') 219 self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None) 220 221 def testNoGenericServices(self): 222 self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage")) 223 self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO")) 224 self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension")) 225 226 # Make sure unittest_no_generic_services_pb2 has no services subclassing 227 # Proto2 Service class. 228 if hasattr(unittest_no_generic_services_pb2, "TestService"): 229 self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService, 230 service.Service)) 231 232 def testMessageTypesByName(self): 233 file_type = unittest_pb2.DESCRIPTOR 234 self.assertEqual( 235 unittest_pb2._TESTALLTYPES, 236 file_type.message_types_by_name[unittest_pb2._TESTALLTYPES.name]) 237 238 # Nested messages shouldn't be included in the message_types_by_name 239 # dictionary (like in the C++ API). 240 self.assertFalse( 241 unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in 242 file_type.message_types_by_name) 243 244 def testPublicImports(self): 245 # Test public imports as embedded message. 246 all_type_proto = unittest_pb2.TestAllTypes() 247 self.assertEqual(0, all_type_proto.optional_public_import_message.e) 248 249 # PublicImportMessage is actually defined in unittest_import_public_pb2 250 # module, and is public imported by unittest_import_pb2 module. 251 public_import_proto = unittest_import_pb2.PublicImportMessage() 252 self.assertEqual(0, public_import_proto.e) 253 self.assertTrue(unittest_import_public_pb2.PublicImportMessage is 254 unittest_import_pb2.PublicImportMessage) 255 256 def testBadIdentifiers(self): 257 # We're just testing that the code was imported without problems. 258 message = test_bad_identifiers_pb2.TestBadIdentifiers() 259 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message], 260 "foo") 261 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor], 262 "bar") 263 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection], 264 "baz") 265 self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service], 266 "qux") 267 268if __name__ == '__main__': 269 unittest.main() 270