• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright 2010 Google Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18"""Tests for apitools.base.protorpclite.descriptor."""
19import platform
20import types
21
22import six
23import unittest2
24
25from apitools.base.protorpclite import descriptor
26from apitools.base.protorpclite import message_types
27from apitools.base.protorpclite import messages
28from apitools.base.protorpclite import test_util
29
30
31RUSSIA = u'\u0420\u043e\u0441\u0441\u0438\u044f'
32
33
34class ModuleInterfaceTest(test_util.ModuleInterfaceTest,
35                          test_util.TestCase):
36
37    MODULE = descriptor
38
39
40class DescribeEnumValueTest(test_util.TestCase):
41
42    def testDescribe(self):
43        class MyEnum(messages.Enum):
44            MY_NAME = 10
45
46        expected = descriptor.EnumValueDescriptor()
47        expected.name = 'MY_NAME'
48        expected.number = 10
49
50        described = descriptor.describe_enum_value(MyEnum.MY_NAME)
51        described.check_initialized()
52        self.assertEquals(expected, described)
53
54
55class DescribeEnumTest(test_util.TestCase):
56
57    def testEmptyEnum(self):
58        class EmptyEnum(messages.Enum):
59            pass
60
61        expected = descriptor.EnumDescriptor()
62        expected.name = 'EmptyEnum'
63
64        described = descriptor.describe_enum(EmptyEnum)
65        described.check_initialized()
66        self.assertEquals(expected, described)
67
68    def testNestedEnum(self):
69        class MyScope(messages.Message):
70
71            class NestedEnum(messages.Enum):
72                pass
73
74        expected = descriptor.EnumDescriptor()
75        expected.name = 'NestedEnum'
76
77        described = descriptor.describe_enum(MyScope.NestedEnum)
78        described.check_initialized()
79        self.assertEquals(expected, described)
80
81    @unittest2.skipIf('PyPy' in platform.python_implementation(),
82                      'todo: reenable this')
83    def testEnumWithItems(self):
84        class EnumWithItems(messages.Enum):
85            A = 3
86            B = 1
87            C = 2
88
89        expected = descriptor.EnumDescriptor()
90        expected.name = 'EnumWithItems'
91
92        a = descriptor.EnumValueDescriptor()
93        a.name = 'A'
94        a.number = 3
95
96        b = descriptor.EnumValueDescriptor()
97        b.name = 'B'
98        b.number = 1
99
100        c = descriptor.EnumValueDescriptor()
101        c.name = 'C'
102        c.number = 2
103
104        expected.values = [b, c, a]
105
106        described = descriptor.describe_enum(EnumWithItems)
107        described.check_initialized()
108        self.assertEquals(expected, described)
109
110
111class DescribeFieldTest(test_util.TestCase):
112
113    def testLabel(self):
114        for repeated, required, expected_label in (
115                (True, False, descriptor.FieldDescriptor.Label.REPEATED),
116                (False, True, descriptor.FieldDescriptor.Label.REQUIRED),
117                (False, False, descriptor.FieldDescriptor.Label.OPTIONAL)):
118            field = messages.IntegerField(
119                10, required=required, repeated=repeated)
120            field.name = 'a_field'
121
122            expected = descriptor.FieldDescriptor()
123            expected.name = 'a_field'
124            expected.number = 10
125            expected.label = expected_label
126            expected.variant = descriptor.FieldDescriptor.Variant.INT64
127
128            described = descriptor.describe_field(field)
129            described.check_initialized()
130            self.assertEquals(expected, described)
131
132    def testDefault(self):
133        test_cases = (
134            (messages.IntegerField, 200, '200'),
135            (messages.FloatField, 1.5, '1.5'),
136            (messages.FloatField, 1e6, '1000000.0'),
137            (messages.BooleanField, True, 'true'),
138            (messages.BooleanField, False, 'false'),
139            (messages.BytesField,
140             b''.join([six.int2byte(x) for x in (31, 32, 33)]),
141             b'\\x1f !'),
142            (messages.StringField, RUSSIA, RUSSIA),
143        )
144        for field_class, default, expected_default in test_cases:
145            field = field_class(10, default=default)
146            field.name = u'a_field'
147
148            expected = descriptor.FieldDescriptor()
149            expected.name = u'a_field'
150            expected.number = 10
151            expected.label = descriptor.FieldDescriptor.Label.OPTIONAL
152            expected.variant = field_class.DEFAULT_VARIANT
153            expected.default_value = expected_default
154
155            described = descriptor.describe_field(field)
156            described.check_initialized()
157            self.assertEquals(expected, described)
158
159    def testDefault_EnumField(self):
160        class MyEnum(messages.Enum):
161
162            VAL = 1
163
164        module_name = test_util.get_module_name(MyEnum)
165        field = messages.EnumField(MyEnum, 10, default=MyEnum.VAL)
166        field.name = 'a_field'
167
168        expected = descriptor.FieldDescriptor()
169        expected.name = 'a_field'
170        expected.number = 10
171        expected.label = descriptor.FieldDescriptor.Label.OPTIONAL
172        expected.variant = messages.EnumField.DEFAULT_VARIANT
173        expected.type_name = '%s.MyEnum' % module_name
174        expected.default_value = '1'
175
176        described = descriptor.describe_field(field)
177        self.assertEquals(expected, described)
178
179    def testMessageField(self):
180        field = messages.MessageField(descriptor.FieldDescriptor, 10)
181        field.name = 'a_field'
182
183        expected = descriptor.FieldDescriptor()
184        expected.name = 'a_field'
185        expected.number = 10
186        expected.label = descriptor.FieldDescriptor.Label.OPTIONAL
187        expected.variant = messages.MessageField.DEFAULT_VARIANT
188        expected.type_name = (
189            'apitools.base.protorpclite.descriptor.FieldDescriptor')
190
191        described = descriptor.describe_field(field)
192        described.check_initialized()
193        self.assertEquals(expected, described)
194
195    def testDateTimeField(self):
196        field = message_types.DateTimeField(20)
197        field.name = 'a_timestamp'
198
199        expected = descriptor.FieldDescriptor()
200        expected.name = 'a_timestamp'
201        expected.number = 20
202        expected.label = descriptor.FieldDescriptor.Label.OPTIONAL
203        expected.variant = messages.MessageField.DEFAULT_VARIANT
204        expected.type_name = (
205            'apitools.base.protorpclite.message_types.DateTimeMessage')
206
207        described = descriptor.describe_field(field)
208        described.check_initialized()
209        self.assertEquals(expected, described)
210
211
212class DescribeMessageTest(test_util.TestCase):
213
214    def testEmptyDefinition(self):
215        class MyMessage(messages.Message):
216            pass
217
218        expected = descriptor.MessageDescriptor()
219        expected.name = 'MyMessage'
220
221        described = descriptor.describe_message(MyMessage)
222        described.check_initialized()
223        self.assertEquals(expected, described)
224
225    def testDefinitionWithFields(self):
226        class MessageWithFields(messages.Message):
227            field1 = messages.IntegerField(10)
228            field2 = messages.StringField(30)
229            field3 = messages.IntegerField(20)
230
231        expected = descriptor.MessageDescriptor()
232        expected.name = 'MessageWithFields'
233
234        expected.fields = [
235            descriptor.describe_field(
236                MessageWithFields.field_by_name('field1')),
237            descriptor.describe_field(
238                MessageWithFields.field_by_name('field3')),
239            descriptor.describe_field(
240                MessageWithFields.field_by_name('field2')),
241        ]
242
243        described = descriptor.describe_message(MessageWithFields)
244        described.check_initialized()
245        self.assertEquals(expected, described)
246
247    def testNestedEnum(self):
248        class MessageWithEnum(messages.Message):
249
250            class Mood(messages.Enum):
251                GOOD = 1
252                BAD = 2
253                UGLY = 3
254
255            class Music(messages.Enum):
256                CLASSIC = 1
257                JAZZ = 2
258                BLUES = 3
259
260        expected = descriptor.MessageDescriptor()
261        expected.name = 'MessageWithEnum'
262
263        expected.enum_types = [descriptor.describe_enum(MessageWithEnum.Mood),
264                               descriptor.describe_enum(MessageWithEnum.Music)]
265
266        described = descriptor.describe_message(MessageWithEnum)
267        described.check_initialized()
268        self.assertEquals(expected, described)
269
270    def testNestedMessage(self):
271        class MessageWithMessage(messages.Message):
272
273            class Nesty(messages.Message):
274                pass
275
276        expected = descriptor.MessageDescriptor()
277        expected.name = 'MessageWithMessage'
278
279        expected.message_types = [
280            descriptor.describe_message(MessageWithMessage.Nesty)]
281
282        described = descriptor.describe_message(MessageWithMessage)
283        described.check_initialized()
284        self.assertEquals(expected, described)
285
286
287class DescribeFileTest(test_util.TestCase):
288    """Test describing modules."""
289
290    def LoadModule(self, module_name, source):
291        result = {
292            '__name__': module_name,
293            'messages': messages,
294        }
295        exec(source, result)
296
297        module = types.ModuleType(module_name)
298        for name, value in result.items():
299            setattr(module, name, value)
300
301        return module
302
303    def testEmptyModule(self):
304        """Test describing an empty file."""
305        module = types.ModuleType('my.package.name')
306
307        expected = descriptor.FileDescriptor()
308        expected.package = 'my.package.name'
309
310        described = descriptor.describe_file(module)
311        described.check_initialized()
312        self.assertEquals(expected, described)
313
314    def testNoPackageName(self):
315        """Test describing a module with no module name."""
316        module = types.ModuleType('')
317
318        expected = descriptor.FileDescriptor()
319
320        described = descriptor.describe_file(module)
321        described.check_initialized()
322        self.assertEquals(expected, described)
323
324    def testPackageName(self):
325        """Test using the 'package' module attribute."""
326        module = types.ModuleType('my.module.name')
327        module.package = 'my.package.name'
328
329        expected = descriptor.FileDescriptor()
330        expected.package = 'my.package.name'
331
332        described = descriptor.describe_file(module)
333        described.check_initialized()
334        self.assertEquals(expected, described)
335
336    def testMain(self):
337        """Test using the 'package' module attribute."""
338        module = types.ModuleType('__main__')
339        module.__file__ = '/blim/blam/bloom/my_package.py'
340
341        expected = descriptor.FileDescriptor()
342        expected.package = 'my_package'
343
344        described = descriptor.describe_file(module)
345        described.check_initialized()
346        self.assertEquals(expected, described)
347
348    def testMessages(self):
349        """Test that messages are described."""
350        module = self.LoadModule('my.package',
351                                 'class Message1(messages.Message): pass\n'
352                                 'class Message2(messages.Message): pass\n')
353
354        message1 = descriptor.MessageDescriptor()
355        message1.name = 'Message1'
356
357        message2 = descriptor.MessageDescriptor()
358        message2.name = 'Message2'
359
360        expected = descriptor.FileDescriptor()
361        expected.package = 'my.package'
362        expected.message_types = [message1, message2]
363
364        described = descriptor.describe_file(module)
365        described.check_initialized()
366        self.assertEquals(expected, described)
367
368    def testEnums(self):
369        """Test that enums are described."""
370        module = self.LoadModule('my.package',
371                                 'class Enum1(messages.Enum): pass\n'
372                                 'class Enum2(messages.Enum): pass\n')
373
374        enum1 = descriptor.EnumDescriptor()
375        enum1.name = 'Enum1'
376
377        enum2 = descriptor.EnumDescriptor()
378        enum2.name = 'Enum2'
379
380        expected = descriptor.FileDescriptor()
381        expected.package = 'my.package'
382        expected.enum_types = [enum1, enum2]
383
384        described = descriptor.describe_file(module)
385        described.check_initialized()
386        self.assertEquals(expected, described)
387
388
389class DescribeFileSetTest(test_util.TestCase):
390    """Test describing multiple modules."""
391
392    def testNoModules(self):
393        """Test what happens when no modules provided."""
394        described = descriptor.describe_file_set([])
395        described.check_initialized()
396        # The described FileSet.files will be None.
397        self.assertEquals(descriptor.FileSet(), described)
398
399    def testWithModules(self):
400        """Test what happens when no modules provided."""
401        modules = [types.ModuleType('package1'), types.ModuleType('package1')]
402
403        file1 = descriptor.FileDescriptor()
404        file1.package = 'package1'
405        file2 = descriptor.FileDescriptor()
406        file2.package = 'package2'
407
408        expected = descriptor.FileSet()
409        expected.files = [file1, file1]
410
411        described = descriptor.describe_file_set(modules)
412        described.check_initialized()
413        self.assertEquals(expected, described)
414
415
416class DescribeTest(test_util.TestCase):
417
418    def testModule(self):
419        self.assertEquals(descriptor.describe_file(test_util),
420                          descriptor.describe(test_util))
421
422    def testField(self):
423        self.assertEquals(
424            descriptor.describe_field(test_util.NestedMessage.a_value),
425            descriptor.describe(test_util.NestedMessage.a_value))
426
427    def testEnumValue(self):
428        self.assertEquals(
429            descriptor.describe_enum_value(
430                test_util.OptionalMessage.SimpleEnum.VAL1),
431            descriptor.describe(test_util.OptionalMessage.SimpleEnum.VAL1))
432
433    def testMessage(self):
434        self.assertEquals(descriptor.describe_message(test_util.NestedMessage),
435                          descriptor.describe(test_util.NestedMessage))
436
437    def testEnum(self):
438        self.assertEquals(
439            descriptor.describe_enum(test_util.OptionalMessage.SimpleEnum),
440            descriptor.describe(test_util.OptionalMessage.SimpleEnum))
441
442    def testUndescribable(self):
443        class NonService(object):
444
445            def fn(self):
446                pass
447
448        for value in (NonService,
449                      NonService.fn,
450                      1,
451                      'string',
452                      1.2,
453                      None):
454            self.assertEquals(None, descriptor.describe(value))
455
456
457class ModuleFinderTest(test_util.TestCase):
458
459    def testFindMessage(self):
460        self.assertEquals(
461            descriptor.describe_message(descriptor.FileSet),
462            descriptor.import_descriptor_loader(
463                'apitools.base.protorpclite.descriptor.FileSet'))
464
465    def testFindField(self):
466        self.assertEquals(
467            descriptor.describe_field(descriptor.FileSet.files),
468            descriptor.import_descriptor_loader(
469                'apitools.base.protorpclite.descriptor.FileSet.files'))
470
471    def testFindEnumValue(self):
472        self.assertEquals(
473            descriptor.describe_enum_value(
474                test_util.OptionalMessage.SimpleEnum.VAL1),
475            descriptor.import_descriptor_loader(
476                'apitools.base.protorpclite.test_util.'
477                'OptionalMessage.SimpleEnum.VAL1'))
478
479
480class DescriptorLibraryTest(test_util.TestCase):
481
482    def setUp(self):
483        self.packageless = descriptor.MessageDescriptor()
484        self.packageless.name = 'Packageless'
485        self.library = descriptor.DescriptorLibrary(
486            descriptors={
487                'not.real.Packageless': self.packageless,
488                'Packageless': self.packageless,
489            })
490
491    def testLookupPackage(self):
492        self.assertEquals('csv', self.library.lookup_package('csv'))
493        self.assertEquals(
494            'apitools.base.protorpclite',
495            self.library.lookup_package('apitools.base.protorpclite'))
496
497    def testLookupNonPackages(self):
498        lib = 'apitools.base.protorpclite.descriptor.DescriptorLibrary'
499        for name in ('', 'a', lib):
500            self.assertRaisesWithRegexpMatch(
501                messages.DefinitionNotFoundError,
502                'Could not find definition for %s' % name,
503                self.library.lookup_package, name)
504
505    def testNoPackage(self):
506        self.assertRaisesWithRegexpMatch(
507            messages.DefinitionNotFoundError,
508            'Could not find definition for not.real',
509            self.library.lookup_package, 'not.real.Packageless')
510
511        self.assertEquals(None, self.library.lookup_package('Packageless'))
512
513
514if __name__ == '__main__':
515    unittest2.main()
516