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