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"""Unittest for google.protobuf.internal.descriptor."""
34
35__author__ = 'robinson@google.com (Will Robinson)'
36
37import unittest
38from google.protobuf import unittest_import_pb2
39from google.protobuf import unittest_pb2
40from google.protobuf import descriptor_pb2
41from google.protobuf import descriptor
42from google.protobuf import text_format
43
44
45TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
46name: 'TestEmptyMessage'
47"""
48
49
50class DescriptorTest(unittest.TestCase):
51
52  def setUp(self):
53    self.my_file = descriptor.FileDescriptor(
54        name='some/filename/some.proto',
55        package='protobuf_unittest'
56        )
57    self.my_enum = descriptor.EnumDescriptor(
58        name='ForeignEnum',
59        full_name='protobuf_unittest.ForeignEnum',
60        filename=None,
61        file=self.my_file,
62        values=[
63          descriptor.EnumValueDescriptor(name='FOREIGN_FOO', index=0, number=4),
64          descriptor.EnumValueDescriptor(name='FOREIGN_BAR', index=1, number=5),
65          descriptor.EnumValueDescriptor(name='FOREIGN_BAZ', index=2, number=6),
66        ])
67    self.my_message = descriptor.Descriptor(
68        name='NestedMessage',
69        full_name='protobuf_unittest.TestAllTypes.NestedMessage',
70        filename=None,
71        file=self.my_file,
72        containing_type=None,
73        fields=[
74          descriptor.FieldDescriptor(
75            name='bb',
76            full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb',
77            index=0, number=1,
78            type=5, cpp_type=1, label=1,
79            has_default_value=False, default_value=0,
80            message_type=None, enum_type=None, containing_type=None,
81            is_extension=False, extension_scope=None),
82        ],
83        nested_types=[],
84        enum_types=[
85          self.my_enum,
86        ],
87        extensions=[])
88    self.my_method = descriptor.MethodDescriptor(
89        name='Bar',
90        full_name='protobuf_unittest.TestService.Bar',
91        index=0,
92        containing_service=None,
93        input_type=None,
94        output_type=None)
95    self.my_service = descriptor.ServiceDescriptor(
96        name='TestServiceWithOptions',
97        full_name='protobuf_unittest.TestServiceWithOptions',
98        file=self.my_file,
99        index=0,
100        methods=[
101            self.my_method
102        ])
103
104  def testEnumFixups(self):
105    self.assertEqual(self.my_enum, self.my_enum.values[0].type)
106
107  def testContainingTypeFixups(self):
108    self.assertEqual(self.my_message, self.my_message.fields[0].containing_type)
109    self.assertEqual(self.my_message, self.my_enum.containing_type)
110
111  def testContainingServiceFixups(self):
112    self.assertEqual(self.my_service, self.my_method.containing_service)
113
114  def testGetOptions(self):
115    self.assertEqual(self.my_enum.GetOptions(),
116                     descriptor_pb2.EnumOptions())
117    self.assertEqual(self.my_enum.values[0].GetOptions(),
118                     descriptor_pb2.EnumValueOptions())
119    self.assertEqual(self.my_message.GetOptions(),
120                     descriptor_pb2.MessageOptions())
121    self.assertEqual(self.my_message.fields[0].GetOptions(),
122                     descriptor_pb2.FieldOptions())
123    self.assertEqual(self.my_method.GetOptions(),
124                     descriptor_pb2.MethodOptions())
125    self.assertEqual(self.my_service.GetOptions(),
126                     descriptor_pb2.ServiceOptions())
127
128  def testFileDescriptorReferences(self):
129    self.assertEqual(self.my_enum.file, self.my_file)
130    self.assertEqual(self.my_message.file, self.my_file)
131
132  def testFileDescriptor(self):
133    self.assertEqual(self.my_file.name, 'some/filename/some.proto')
134    self.assertEqual(self.my_file.package, 'protobuf_unittest')
135
136
137class DescriptorCopyToProtoTest(unittest.TestCase):
138  """Tests for CopyTo functions of Descriptor."""
139
140  def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii):
141    expected_proto = expected_class()
142    text_format.Merge(expected_ascii, expected_proto)
143
144    self.assertEqual(
145        actual_proto, expected_proto,
146        'Not equal,\nActual:\n%s\nExpected:\n%s\n'
147        % (str(actual_proto), str(expected_proto)))
148
149  def _InternalTestCopyToProto(self, desc, expected_proto_class,
150                               expected_proto_ascii):
151    actual = expected_proto_class()
152    desc.CopyToProto(actual)
153    self._AssertProtoEqual(
154        actual, expected_proto_class, expected_proto_ascii)
155
156  def testCopyToProto_EmptyMessage(self):
157    self._InternalTestCopyToProto(
158        unittest_pb2.TestEmptyMessage.DESCRIPTOR,
159        descriptor_pb2.DescriptorProto,
160        TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII)
161
162  def testCopyToProto_NestedMessage(self):
163    TEST_NESTED_MESSAGE_ASCII = """
164      name: 'NestedMessage'
165      field: <
166        name: 'bb'
167        number: 1
168        label: 1  # Optional
169        type: 5  # TYPE_INT32
170      >
171      """
172
173    self._InternalTestCopyToProto(
174        unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
175        descriptor_pb2.DescriptorProto,
176        TEST_NESTED_MESSAGE_ASCII)
177
178  def testCopyToProto_ForeignNestedMessage(self):
179    TEST_FOREIGN_NESTED_ASCII = """
180      name: 'TestForeignNested'
181      field: <
182        name: 'foreign_nested'
183        number: 1
184        label: 1  # Optional
185        type: 11  # TYPE_MESSAGE
186        type_name: '.protobuf_unittest.TestAllTypes.NestedMessage'
187      >
188      """
189
190    self._InternalTestCopyToProto(
191        unittest_pb2.TestForeignNested.DESCRIPTOR,
192        descriptor_pb2.DescriptorProto,
193        TEST_FOREIGN_NESTED_ASCII)
194
195  def testCopyToProto_ForeignEnum(self):
196    TEST_FOREIGN_ENUM_ASCII = """
197      name: 'ForeignEnum'
198      value: <
199        name: 'FOREIGN_FOO'
200        number: 4
201      >
202      value: <
203        name: 'FOREIGN_BAR'
204        number: 5
205      >
206      value: <
207        name: 'FOREIGN_BAZ'
208        number: 6
209      >
210      """
211
212    self._InternalTestCopyToProto(
213        unittest_pb2._FOREIGNENUM,
214        descriptor_pb2.EnumDescriptorProto,
215        TEST_FOREIGN_ENUM_ASCII)
216
217  def testCopyToProto_Options(self):
218    TEST_DEPRECATED_FIELDS_ASCII = """
219      name: 'TestDeprecatedFields'
220      field: <
221        name: 'deprecated_int32'
222        number: 1
223        label: 1  # Optional
224        type: 5  # TYPE_INT32
225        options: <
226          deprecated: true
227        >
228      >
229      """
230
231    self._InternalTestCopyToProto(
232        unittest_pb2.TestDeprecatedFields.DESCRIPTOR,
233        descriptor_pb2.DescriptorProto,
234        TEST_DEPRECATED_FIELDS_ASCII)
235
236  def testCopyToProto_AllExtensions(self):
237    TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """
238      name: 'TestEmptyMessageWithExtensions'
239      extension_range: <
240        start: 1
241        end: 536870912
242      >
243      """
244
245    self._InternalTestCopyToProto(
246        unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR,
247        descriptor_pb2.DescriptorProto,
248        TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII)
249
250  def testCopyToProto_SeveralExtensions(self):
251    TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """
252      name: 'TestMultipleExtensionRanges'
253      extension_range: <
254        start: 42
255        end: 43
256      >
257      extension_range: <
258        start: 4143
259        end: 4244
260      >
261      extension_range: <
262        start: 65536
263        end: 536870912
264      >
265      """
266
267    self._InternalTestCopyToProto(
268        unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR,
269        descriptor_pb2.DescriptorProto,
270        TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII)
271
272  def testCopyToProto_FileDescriptor(self):
273    UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = ("""
274      name: 'google/protobuf/unittest_import.proto'
275      package: 'protobuf_unittest_import'
276      message_type: <
277        name: 'ImportMessage'
278        field: <
279          name: 'd'
280          number: 1
281          label: 1  # Optional
282          type: 5  # TYPE_INT32
283        >
284      >
285      """ +
286      """enum_type: <
287        name: 'ImportEnum'
288        value: <
289          name: 'IMPORT_FOO'
290          number: 7
291        >
292        value: <
293          name: 'IMPORT_BAR'
294          number: 8
295        >
296        value: <
297          name: 'IMPORT_BAZ'
298          number: 9
299        >
300      >
301      options: <
302        java_package: 'com.google.protobuf.test'
303        optimize_for: 1  # SPEED
304      >
305      """)
306
307    self._InternalTestCopyToProto(
308        unittest_import_pb2.DESCRIPTOR,
309        descriptor_pb2.FileDescriptorProto,
310        UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII)
311
312  def testCopyToProto_ServiceDescriptor(self):
313    TEST_SERVICE_ASCII = """
314      name: 'TestService'
315      method: <
316        name: 'Foo'
317        input_type: '.protobuf_unittest.FooRequest'
318        output_type: '.protobuf_unittest.FooResponse'
319      >
320      method: <
321        name: 'Bar'
322        input_type: '.protobuf_unittest.BarRequest'
323        output_type: '.protobuf_unittest.BarResponse'
324      >
325      """
326
327    self._InternalTestCopyToProto(
328        unittest_pb2.TestService.DESCRIPTOR,
329        descriptor_pb2.ServiceDescriptorProto,
330        TEST_SERVICE_ASCII)
331
332
333if __name__ == '__main__':
334  unittest.main()
335