Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: third_party/google-endpoints/apitools/base/py/encoding_test.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #
2 # Copyright 2015 Google Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import base64
17 import datetime
18 import json
19 import sys
20
21 import unittest2
22
23 from apitools.base.protorpclite import message_types
24 from apitools.base.protorpclite import messages
25 from apitools.base.protorpclite import util
26 from apitools.base.py import encoding
27 from apitools.base.py import exceptions
28 from apitools.base.py import extra_types
29
30
31 class SimpleMessage(messages.Message):
32 field = messages.StringField(1)
33 repfield = messages.StringField(2, repeated=True)
34
35
36 class BytesMessage(messages.Message):
37 field = messages.BytesField(1)
38 repfield = messages.BytesField(2, repeated=True)
39
40
41 class TimeMessage(messages.Message):
42 timefield = message_types.DateTimeField(3)
43
44
45 @encoding.MapUnrecognizedFields('additional_properties')
46 class AdditionalPropertiesMessage(messages.Message):
47
48 class AdditionalProperty(messages.Message):
49 key = messages.StringField(1)
50 value = messages.StringField(2)
51
52 additional_properties = messages.MessageField(
53 'AdditionalProperty', 1, repeated=True)
54
55
56 @encoding.MapUnrecognizedFields('additional_properties')
57 class UnrecognizedEnumMessage(messages.Message):
58
59 class ThisEnum(messages.Enum):
60 VALUE_ONE = 1
61 VALUE_TWO = 2
62
63 class AdditionalProperty(messages.Message):
64 key = messages.StringField(1)
65 value = messages.EnumField('UnrecognizedEnumMessage.ThisEnum', 2)
66
67 additional_properties = messages.MessageField(
68 AdditionalProperty, 1, repeated=True)
69
70
71 class CompoundPropertyType(messages.Message):
72 index = messages.IntegerField(1)
73 name = messages.StringField(2)
74
75
76 class MessageWithEnum(messages.Message):
77
78 class ThisEnum(messages.Enum):
79 VALUE_ONE = 1
80 VALUE_TWO = 2
81
82 field_one = messages.EnumField(ThisEnum, 1)
83 field_two = messages.EnumField(ThisEnum, 2, default=ThisEnum.VALUE_TWO)
84 ignored_field = messages.EnumField(ThisEnum, 3)
85
86
87 @encoding.MapUnrecognizedFields('additional_properties')
88 class AdditionalMessagePropertiesMessage(messages.Message):
89
90 class AdditionalProperty(messages.Message):
91 key = messages.StringField(1)
92 value = messages.MessageField(CompoundPropertyType, 2)
93
94 additional_properties = messages.MessageField(
95 'AdditionalProperty', 1, repeated=True)
96
97
98 class HasNestedMessage(messages.Message):
99 nested = messages.MessageField(AdditionalPropertiesMessage, 1)
100 nested_list = messages.StringField(2, repeated=True)
101
102
103 class ExtraNestedMessage(messages.Message):
104 nested = messages.MessageField(HasNestedMessage, 1)
105
106
107 class MessageWithRemappings(messages.Message):
108
109 class SomeEnum(messages.Enum):
110 enum_value = 1
111 second_value = 2
112
113 enum_field = messages.EnumField(SomeEnum, 1)
114 double_encoding = messages.EnumField(SomeEnum, 2)
115 another_field = messages.StringField(3)
116 repeated_enum = messages.EnumField(SomeEnum, 4, repeated=True)
117 repeated_field = messages.StringField(5, repeated=True)
118
119
120 @encoding.MapUnrecognizedFields('additional_properties')
121 class RepeatedJsonValueMessage(messages.Message):
122
123 class AdditionalProperty(messages.Message):
124 key = messages.StringField(1)
125 value = messages.MessageField(extra_types.JsonValue, 2, repeated=True)
126
127 additional_properties = messages.MessageField('AdditionalProperty', 1,
128 repeated=True)
129
130
131 encoding.AddCustomJsonEnumMapping(MessageWithRemappings.SomeEnum,
132 'enum_value', 'wire_name')
133 encoding.AddCustomJsonFieldMapping(MessageWithRemappings,
134 'double_encoding', 'doubleEncoding')
135 encoding.AddCustomJsonFieldMapping(MessageWithRemappings,
136 'another_field', 'anotherField')
137 encoding.AddCustomJsonFieldMapping(MessageWithRemappings,
138 'repeated_field', 'repeatedField')
139
140
141 class EncodingTest(unittest2.TestCase):
142
143 def testCopyProtoMessage(self):
144 msg = SimpleMessage(field='abc')
145 new_msg = encoding.CopyProtoMessage(msg)
146 self.assertEqual(msg.field, new_msg.field)
147 msg.field = 'def'
148 self.assertNotEqual(msg.field, new_msg.field)
149
150 def testBytesEncoding(self):
151 b64_str = 'AAc+'
152 b64_msg = '{"field": "%s"}' % b64_str
153 urlsafe_b64_str = 'AAc-'
154 urlsafe_b64_msg = '{"field": "%s"}' % urlsafe_b64_str
155 data = base64.b64decode(b64_str)
156 msg = BytesMessage(field=data)
157 self.assertEqual(
158 msg, encoding.JsonToMessage(BytesMessage, urlsafe_b64_msg))
159 self.assertEqual(msg, encoding.JsonToMessage(BytesMessage, b64_msg))
160 self.assertEqual(urlsafe_b64_msg, encoding.MessageToJson(msg))
161
162 enc_rep_msg = '{"repfield": ["%(b)s", "%(b)s"]}' % {
163 'b': urlsafe_b64_str}
164 rep_msg = BytesMessage(repfield=[data, data])
165 self.assertEqual(
166 rep_msg, encoding.JsonToMessage(BytesMessage, enc_rep_msg))
167 self.assertEqual(enc_rep_msg, encoding.MessageToJson(rep_msg))
168
169 def testIncludeFields(self):
170 msg = SimpleMessage()
171 self.assertEqual('{}', encoding.MessageToJson(msg))
172 self.assertEqual(
173 '{"field": null}',
174 encoding.MessageToJson(msg, include_fields=['field']))
175 self.assertEqual(
176 '{"repfield": []}',
177 encoding.MessageToJson(msg, include_fields=['repfield']))
178
179 def testNestedIncludeFields(self):
180 msg = HasNestedMessage(
181 nested=AdditionalPropertiesMessage(
182 additional_properties=[]))
183 self.assertEqual(
184 '{"nested": null}',
185 encoding.MessageToJson(msg, include_fields=['nested']))
186 self.assertEqual(
187 '{"nested": {"additional_properties": []}}',
188 encoding.MessageToJson(
189 msg, include_fields=['nested.additional_properties']))
190 # pylint: disable=redefined-variable-type
191 msg = ExtraNestedMessage(nested=msg)
192 self.assertEqual(
193 '{"nested": {"nested": null}}',
194 encoding.MessageToJson(msg, include_fields=['nested.nested']))
195 self.assertEqual(
196 '{"nested": {"nested_list": []}}',
197 encoding.MessageToJson(msg, include_fields=['nested.nested_list']))
198 self.assertEqual(
199 '{"nested": {"nested": {"additional_properties": []}}}',
200 encoding.MessageToJson(
201 msg, include_fields=['nested.nested.additional_properties']))
202
203 def testAdditionalPropertyMapping(self):
204 msg = AdditionalPropertiesMessage()
205 msg.additional_properties = [
206 AdditionalPropertiesMessage.AdditionalProperty(
207 key='key_one', value='value_one'),
208 AdditionalPropertiesMessage.AdditionalProperty(
209 key='key_two', value='value_two'),
210 ]
211
212 encoded_msg = encoding.MessageToJson(msg)
213 self.assertEqual(
214 {'key_one': 'value_one', 'key_two': 'value_two'},
215 json.loads(encoded_msg))
216
217 new_msg = encoding.JsonToMessage(type(msg), encoded_msg)
218 self.assertEqual(
219 set(('key_one', 'key_two')),
220 set([x.key for x in new_msg.additional_properties]))
221 self.assertIsNot(msg, new_msg)
222
223 new_msg.additional_properties.pop()
224 self.assertEqual(1, len(new_msg.additional_properties))
225 self.assertEqual(2, len(msg.additional_properties))
226
227 def testNumericPropertyName(self):
228 json_msg = '{"nested": {"123": "def"}}'
229 msg = encoding.JsonToMessage(HasNestedMessage, json_msg)
230 self.assertEqual(1, len(msg.nested.additional_properties))
231
232 def testAdditionalMessageProperties(self):
233 json_msg = '{"input": {"index": 0, "name": "output"}}'
234 result = encoding.JsonToMessage(
235 AdditionalMessagePropertiesMessage, json_msg)
236 self.assertEqual(1, len(result.additional_properties))
237 self.assertEqual(0, result.additional_properties[0].value.index)
238
239 def testUnrecognizedEnum(self):
240 json_msg = '{"input": "VALUE_ONE"}'
241 result = encoding.JsonToMessage(
242 UnrecognizedEnumMessage, json_msg)
243 self.assertEqual(1, len(result.additional_properties))
244 self.assertEqual(UnrecognizedEnumMessage.ThisEnum.VALUE_ONE,
245 result.additional_properties[0].value)
246
247 def testNestedFieldMapping(self):
248 nested_msg = AdditionalPropertiesMessage()
249 nested_msg.additional_properties = [
250 AdditionalPropertiesMessage.AdditionalProperty(
251 key='key_one', value='value_one'),
252 AdditionalPropertiesMessage.AdditionalProperty(
253 key='key_two', value='value_two'),
254 ]
255 msg = HasNestedMessage(nested=nested_msg)
256
257 encoded_msg = encoding.MessageToJson(msg)
258 self.assertEqual(
259 {'nested': {'key_one': 'value_one', 'key_two': 'value_two'}},
260 json.loads(encoded_msg))
261
262 new_msg = encoding.JsonToMessage(type(msg), encoded_msg)
263 self.assertEqual(
264 set(('key_one', 'key_two')),
265 set([x.key for x in new_msg.nested.additional_properties]))
266
267 new_msg.nested.additional_properties.pop()
268 self.assertEqual(1, len(new_msg.nested.additional_properties))
269 self.assertEqual(2, len(msg.nested.additional_properties))
270
271 def testValidEnums(self):
272 message_json = '{"field_one": "VALUE_ONE"}'
273 message = encoding.JsonToMessage(MessageWithEnum, message_json)
274 self.assertEqual(MessageWithEnum.ThisEnum.VALUE_ONE, message.field_one)
275 self.assertEqual(MessageWithEnum.ThisEnum.VALUE_TWO, message.field_two)
276 self.assertEqual(json.loads(message_json),
277 json.loads(encoding.MessageToJson(message)))
278
279 def testIgnoredEnums(self):
280 json_with_typo = '{"field_one": "VALUE_OEN"}'
281 message = encoding.JsonToMessage(MessageWithEnum, json_with_typo)
282 self.assertEqual(None, message.field_one)
283 self.assertEqual(('VALUE_OEN', messages.Variant.ENUM),
284 message.get_unrecognized_field_info('field_one'))
285 self.assertEqual(json.loads(json_with_typo),
286 json.loads(encoding.MessageToJson(message)))
287
288 empty_json = ''
289 message = encoding.JsonToMessage(MessageWithEnum, empty_json)
290 self.assertEqual(None, message.field_one)
291
292 def testIgnoredEnumsWithDefaults(self):
293 json_with_typo = '{"field_two": "VALUE_OEN"}'
294 message = encoding.JsonToMessage(MessageWithEnum, json_with_typo)
295 self.assertEqual(MessageWithEnum.ThisEnum.VALUE_TWO, message.field_two)
296 self.assertEqual(json.loads(json_with_typo),
297 json.loads(encoding.MessageToJson(message)))
298
299 def testUnknownNestedRoundtrip(self):
300 json_message = '{"field": "abc", "submessage": {"a": 1, "b": "foo"}}'
301 message = encoding.JsonToMessage(SimpleMessage, json_message)
302 self.assertEqual(json.loads(json_message),
303 json.loads(encoding.MessageToJson(message)))
304
305 def testJsonDatetime(self):
306 msg = TimeMessage(timefield=datetime.datetime(
307 2014, 7, 2, 23, 33, 25, 541000,
308 tzinfo=util.TimeZoneOffset(datetime.timedelta(0))))
309 self.assertEqual(
310 '{"timefield": "2014-07-02T23:33:25.541000+00:00"}',
311 encoding.MessageToJson(msg))
312
313 def testEnumRemapping(self):
314 msg = MessageWithRemappings(
315 enum_field=MessageWithRemappings.SomeEnum.enum_value)
316 json_message = encoding.MessageToJson(msg)
317 self.assertEqual('{"enum_field": "wire_name"}', json_message)
318 self.assertEqual(
319 msg, encoding.JsonToMessage(MessageWithRemappings, json_message))
320
321 def testRepeatedEnumRemapping(self):
322 msg = MessageWithRemappings(
323 repeated_enum=[
324 MessageWithRemappings.SomeEnum.enum_value,
325 MessageWithRemappings.SomeEnum.second_value,
326 ])
327 json_message = encoding.MessageToJson(msg)
328 self.assertEqual('{"repeated_enum": ["wire_name", "second_value"]}',
329 json_message)
330 self.assertEqual(
331 msg, encoding.JsonToMessage(MessageWithRemappings, json_message))
332
333 def testFieldRemapping(self):
334 msg = MessageWithRemappings(another_field='abc')
335 json_message = encoding.MessageToJson(msg)
336 self.assertEqual('{"anotherField": "abc"}', json_message)
337 self.assertEqual(
338 msg, encoding.JsonToMessage(MessageWithRemappings, json_message))
339
340 def testRepeatedFieldRemapping(self):
341 msg = MessageWithRemappings(repeated_field=['abc', 'def'])
342 json_message = encoding.MessageToJson(msg)
343 self.assertEqual('{"repeatedField": ["abc", "def"]}', json_message)
344 self.assertEqual(
345 msg, encoding.JsonToMessage(MessageWithRemappings, json_message))
346
347 def testMultipleRemapping(self):
348 msg = MessageWithRemappings(
349 double_encoding=MessageWithRemappings.SomeEnum.enum_value)
350 json_message = encoding.MessageToJson(msg)
351 self.assertEqual('{"doubleEncoding": "wire_name"}', json_message)
352 self.assertEqual(
353 msg, encoding.JsonToMessage(MessageWithRemappings, json_message))
354
355 def testRepeatedRemapping(self):
356 # Should allow remapping if the mapping remains the same.
357 encoding.AddCustomJsonEnumMapping(MessageWithRemappings.SomeEnum,
358 'enum_value', 'wire_name')
359 encoding.AddCustomJsonFieldMapping(MessageWithRemappings,
360 'double_encoding', 'doubleEncoding')
361 encoding.AddCustomJsonFieldMapping(MessageWithRemappings,
362 'another_field', 'anotherField')
363 encoding.AddCustomJsonFieldMapping(MessageWithRemappings,
364 'repeated_field', 'repeatedField')
365
366 # Should raise errors if the remapping changes the mapping.
367 self.assertRaises(
368 exceptions.InvalidDataError,
369 encoding.AddCustomJsonFieldMapping,
370 MessageWithRemappings, 'double_encoding', 'something_else')
371 self.assertRaises(
372 exceptions.InvalidDataError,
373 encoding.AddCustomJsonFieldMapping,
374 MessageWithRemappings, 'enum_field', 'anotherField')
375 self.assertRaises(
376 exceptions.InvalidDataError,
377 encoding.AddCustomJsonEnumMapping,
378 MessageWithRemappings.SomeEnum, 'enum_value', 'another_name')
379 self.assertRaises(
380 exceptions.InvalidDataError,
381 encoding.AddCustomJsonEnumMapping,
382 MessageWithRemappings.SomeEnum, 'second_value', 'wire_name')
383
384 def testMessageToRepr(self):
385 # Using the same string returned by MessageToRepr, with the
386 # module names fixed.
387 # pylint: disable=bad-whitespace
388 msg = SimpleMessage(field='field', repfield=['field', 'field', ],)
389 # pylint: enable=bad-whitespace
390 self.assertEqual(
391 encoding.MessageToRepr(msg),
392 r"%s.SimpleMessage(field='field',repfield=['field','field',],)" % (
393 __name__,))
394 self.assertEqual(
395 encoding.MessageToRepr(msg, no_modules=True),
396 r"SimpleMessage(field='field',repfield=['field','field',],)")
397
398 def testMessageToReprWithTime(self):
399 msg = TimeMessage(timefield=datetime.datetime(
400 2014, 7, 2, 23, 33, 25, 541000,
401 tzinfo=util.TimeZoneOffset(datetime.timedelta(0))))
402 self.assertEqual(
403 encoding.MessageToRepr(msg, multiline=True),
404 ('%s.TimeMessage(\n '
405 'timefield=datetime.datetime(2014, 7, 2, 23, 33, 25, 541000, '
406 'tzinfo=apitools.base.protorpclite.util.TimeZoneOffset('
407 'datetime.timedelta(0))),\n)') % __name__)
408 self.assertEqual(
409 encoding.MessageToRepr(msg, multiline=True, no_modules=True),
410 'TimeMessage(\n '
411 'timefield=datetime.datetime(2014, 7, 2, 23, 33, 25, 541000, '
412 'tzinfo=TimeZoneOffset(datetime.timedelta(0))),\n)')
413
414 def testPackageMappingsNoPackage(self):
415 this_module_name = util.get_package_for_module(__name__)
416 full_type_name = 'MessageWithEnum.ThisEnum'
417 full_key = '%s.%s' % (this_module_name, full_type_name)
418 self.assertEqual(full_key,
419 encoding._GetTypeKey(MessageWithEnum.ThisEnum, ''))
420
421 def testPackageMappingsWithPackage(self):
422 this_module_name = util.get_package_for_module(__name__)
423 full_type_name = 'MessageWithEnum.ThisEnum'
424 full_key = '%s.%s' % (this_module_name, full_type_name)
425 this_module = sys.modules[__name__]
426 new_package = 'new_package'
427 try:
428 setattr(this_module, 'package', new_package)
429 new_key = '%s.%s' % (new_package, full_type_name)
430 self.assertEqual(
431 new_key,
432 encoding._GetTypeKey(MessageWithEnum.ThisEnum, ''))
433 self.assertEqual(
434 full_key,
435 encoding._GetTypeKey(MessageWithEnum.ThisEnum, new_package))
436 finally:
437 delattr(this_module, 'package')
438
439 def testRepeatedJsonValuesAsRepeatedProperty(self):
440 encoded_msg = '{"a": [{"one": 1}]}'
441 msg = encoding.JsonToMessage(RepeatedJsonValueMessage, encoded_msg)
442 self.assertEqual(encoded_msg, encoding.MessageToJson(msg))
OLDNEW
« no previous file with comments | « third_party/google-endpoints/apitools/base/py/encoding.py ('k') | third_party/google-endpoints/apitools/base/py/exceptions.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698