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

Side by Side Diff: third_party/protobuf/python/google/protobuf/internal/json_format_test.py

Issue 1842653006: Update //third_party/protobuf to version 3. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 4 years, 8 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 #! /usr/bin/env python
2 #
3 # Protocol Buffers - Google's data interchange format
4 # Copyright 2008 Google Inc. All rights reserved.
5 # https://developers.google.com/protocol-buffers/
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 """Test for google.protobuf.json_format."""
34
35 __author__ = 'jieluo@google.com (Jie Luo)'
36
37 import json
38 import math
39 import sys
40
41 try:
42 import unittest2 as unittest
43 except ImportError:
44 import unittest
45 from google.protobuf.internal import well_known_types
46 from google.protobuf import json_format
47 from google.protobuf.util import json_format_proto3_pb2
48
49
50 class JsonFormatBase(unittest.TestCase):
51
52 def FillAllFields(self, message):
53 message.int32_value = 20
54 message.int64_value = -20
55 message.uint32_value = 3120987654
56 message.uint64_value = 12345678900
57 message.float_value = float('-inf')
58 message.double_value = 3.1415
59 message.bool_value = True
60 message.string_value = 'foo'
61 message.bytes_value = b'bar'
62 message.message_value.value = 10
63 message.enum_value = json_format_proto3_pb2.BAR
64 # Repeated
65 message.repeated_int32_value.append(0x7FFFFFFF)
66 message.repeated_int32_value.append(-2147483648)
67 message.repeated_int64_value.append(9007199254740992)
68 message.repeated_int64_value.append(-9007199254740992)
69 message.repeated_uint32_value.append(0xFFFFFFF)
70 message.repeated_uint32_value.append(0x7FFFFFF)
71 message.repeated_uint64_value.append(9007199254740992)
72 message.repeated_uint64_value.append(9007199254740991)
73 message.repeated_float_value.append(0)
74
75 message.repeated_double_value.append(1E-15)
76 message.repeated_double_value.append(float('inf'))
77 message.repeated_bool_value.append(True)
78 message.repeated_bool_value.append(False)
79 message.repeated_string_value.append('Few symbols!#$,;')
80 message.repeated_string_value.append('bar')
81 message.repeated_bytes_value.append(b'foo')
82 message.repeated_bytes_value.append(b'bar')
83 message.repeated_message_value.add().value = 10
84 message.repeated_message_value.add().value = 11
85 message.repeated_enum_value.append(json_format_proto3_pb2.FOO)
86 message.repeated_enum_value.append(json_format_proto3_pb2.BAR)
87 self.message = message
88
89 def CheckParseBack(self, message, parsed_message):
90 json_format.Parse(json_format.MessageToJson(message),
91 parsed_message)
92 self.assertEqual(message, parsed_message)
93
94 def CheckError(self, text, error_message):
95 message = json_format_proto3_pb2.TestMessage()
96 self.assertRaisesRegexp(
97 json_format.ParseError,
98 error_message,
99 json_format.Parse, text, message)
100
101
102 class JsonFormatTest(JsonFormatBase):
103
104 def testEmptyMessageToJson(self):
105 message = json_format_proto3_pb2.TestMessage()
106 self.assertEqual(json_format.MessageToJson(message),
107 '{}')
108 parsed_message = json_format_proto3_pb2.TestMessage()
109 self.CheckParseBack(message, parsed_message)
110
111 def testPartialMessageToJson(self):
112 message = json_format_proto3_pb2.TestMessage(
113 string_value='test',
114 repeated_int32_value=[89, 4])
115 self.assertEqual(json.loads(json_format.MessageToJson(message)),
116 json.loads('{"stringValue": "test", '
117 '"repeatedInt32Value": [89, 4]}'))
118 parsed_message = json_format_proto3_pb2.TestMessage()
119 self.CheckParseBack(message, parsed_message)
120
121 def testAllFieldsToJson(self):
122 message = json_format_proto3_pb2.TestMessage()
123 text = ('{"int32Value": 20, '
124 '"int64Value": "-20", '
125 '"uint32Value": 3120987654,'
126 '"uint64Value": "12345678900",'
127 '"floatValue": "-Infinity",'
128 '"doubleValue": 3.1415,'
129 '"boolValue": true,'
130 '"stringValue": "foo",'
131 '"bytesValue": "YmFy",'
132 '"messageValue": {"value": 10},'
133 '"enumValue": "BAR",'
134 '"repeatedInt32Value": [2147483647, -2147483648],'
135 '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],'
136 '"repeatedUint32Value": [268435455, 134217727],'
137 '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],'
138 '"repeatedFloatValue": [0],'
139 '"repeatedDoubleValue": [1e-15, "Infinity"],'
140 '"repeatedBoolValue": [true, false],'
141 '"repeatedStringValue": ["Few symbols!#$,;", "bar"],'
142 '"repeatedBytesValue": ["Zm9v", "YmFy"],'
143 '"repeatedMessageValue": [{"value": 10}, {"value": 11}],'
144 '"repeatedEnumValue": ["FOO", "BAR"]'
145 '}')
146 self.FillAllFields(message)
147 self.assertEqual(
148 json.loads(json_format.MessageToJson(message)),
149 json.loads(text))
150 parsed_message = json_format_proto3_pb2.TestMessage()
151 json_format.Parse(text, parsed_message)
152 self.assertEqual(message, parsed_message)
153
154 def testJsonEscapeString(self):
155 message = json_format_proto3_pb2.TestMessage()
156 if sys.version_info[0] < 3:
157 message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9'
158 else:
159 message.string_value = '&\n<\"\r>\b\t\f\\\001/'
160 message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8')
161 self.assertEqual(
162 json_format.MessageToJson(message),
163 '{\n "stringValue": '
164 '"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}')
165 parsed_message = json_format_proto3_pb2.TestMessage()
166 self.CheckParseBack(message, parsed_message)
167 text = u'{"int32Value": "\u0031"}'
168 json_format.Parse(text, message)
169 self.assertEqual(message.int32_value, 1)
170
171 def testAlwaysSeriliaze(self):
172 message = json_format_proto3_pb2.TestMessage(
173 string_value='foo')
174 self.assertEqual(
175 json.loads(json_format.MessageToJson(message, True)),
176 json.loads('{'
177 '"repeatedStringValue": [],'
178 '"stringValue": "foo",'
179 '"repeatedBoolValue": [],'
180 '"repeatedUint32Value": [],'
181 '"repeatedInt32Value": [],'
182 '"enumValue": "FOO",'
183 '"int32Value": 0,'
184 '"floatValue": 0,'
185 '"int64Value": "0",'
186 '"uint32Value": 0,'
187 '"repeatedBytesValue": [],'
188 '"repeatedUint64Value": [],'
189 '"repeatedDoubleValue": [],'
190 '"bytesValue": "",'
191 '"boolValue": false,'
192 '"repeatedEnumValue": [],'
193 '"uint64Value": "0",'
194 '"doubleValue": 0,'
195 '"repeatedFloatValue": [],'
196 '"repeatedInt64Value": [],'
197 '"repeatedMessageValue": []}'))
198 parsed_message = json_format_proto3_pb2.TestMessage()
199 self.CheckParseBack(message, parsed_message)
200
201 def testMapFields(self):
202 message = json_format_proto3_pb2.TestMap()
203 message.bool_map[True] = 1
204 message.bool_map[False] = 2
205 message.int32_map[1] = 2
206 message.int32_map[2] = 3
207 message.int64_map[1] = 2
208 message.int64_map[2] = 3
209 message.uint32_map[1] = 2
210 message.uint32_map[2] = 3
211 message.uint64_map[1] = 2
212 message.uint64_map[2] = 3
213 message.string_map['1'] = 2
214 message.string_map['null'] = 3
215 self.assertEqual(
216 json.loads(json_format.MessageToJson(message, True)),
217 json.loads('{'
218 '"boolMap": {"false": 2, "true": 1},'
219 '"int32Map": {"1": 2, "2": 3},'
220 '"int64Map": {"1": 2, "2": 3},'
221 '"uint32Map": {"1": 2, "2": 3},'
222 '"uint64Map": {"1": 2, "2": 3},'
223 '"stringMap": {"1": 2, "null": 3}'
224 '}'))
225 parsed_message = json_format_proto3_pb2.TestMap()
226 self.CheckParseBack(message, parsed_message)
227
228 def testOneofFields(self):
229 message = json_format_proto3_pb2.TestOneof()
230 # Always print does not affect oneof fields.
231 self.assertEqual(
232 json_format.MessageToJson(message, True),
233 '{}')
234 message.oneof_int32_value = 0
235 self.assertEqual(
236 json_format.MessageToJson(message, True),
237 '{\n'
238 ' "oneofInt32Value": 0\n'
239 '}')
240 parsed_message = json_format_proto3_pb2.TestOneof()
241 self.CheckParseBack(message, parsed_message)
242
243 def testTimestampMessage(self):
244 message = json_format_proto3_pb2.TestTimestamp()
245 message.value.seconds = 0
246 message.value.nanos = 0
247 message.repeated_value.add().seconds = 20
248 message.repeated_value[0].nanos = 1
249 message.repeated_value.add().seconds = 0
250 message.repeated_value[1].nanos = 10000
251 message.repeated_value.add().seconds = 100000000
252 message.repeated_value[2].nanos = 0
253 # Maximum time
254 message.repeated_value.add().seconds = 253402300799
255 message.repeated_value[3].nanos = 999999999
256 # Minimum time
257 message.repeated_value.add().seconds = -62135596800
258 message.repeated_value[4].nanos = 0
259 self.assertEqual(
260 json.loads(json_format.MessageToJson(message, True)),
261 json.loads('{'
262 '"value": "1970-01-01T00:00:00Z",'
263 '"repeatedValue": ['
264 ' "1970-01-01T00:00:20.000000001Z",'
265 ' "1970-01-01T00:00:00.000010Z",'
266 ' "1973-03-03T09:46:40Z",'
267 ' "9999-12-31T23:59:59.999999999Z",'
268 ' "0001-01-01T00:00:00Z"'
269 ']'
270 '}'))
271 parsed_message = json_format_proto3_pb2.TestTimestamp()
272 self.CheckParseBack(message, parsed_message)
273 text = (r'{"value": "1970-01-01T00:00:00.01+08:00",'
274 r'"repeatedValue":['
275 r' "1970-01-01T00:00:00.01+08:30",'
276 r' "1970-01-01T00:00:00.01-01:23"]}')
277 json_format.Parse(text, parsed_message)
278 self.assertEqual(parsed_message.value.seconds, -8 * 3600)
279 self.assertEqual(parsed_message.value.nanos, 10000000)
280 self.assertEqual(parsed_message.repeated_value[0].seconds, -8.5 * 3600)
281 self.assertEqual(parsed_message.repeated_value[1].seconds, 3600 + 23 * 60)
282
283 def testDurationMessage(self):
284 message = json_format_proto3_pb2.TestDuration()
285 message.value.seconds = 1
286 message.repeated_value.add().seconds = 0
287 message.repeated_value[0].nanos = 10
288 message.repeated_value.add().seconds = -1
289 message.repeated_value[1].nanos = -1000
290 message.repeated_value.add().seconds = 10
291 message.repeated_value[2].nanos = 11000000
292 message.repeated_value.add().seconds = -315576000000
293 message.repeated_value.add().seconds = 315576000000
294 self.assertEqual(
295 json.loads(json_format.MessageToJson(message, True)),
296 json.loads('{'
297 '"value": "1s",'
298 '"repeatedValue": ['
299 ' "0.000000010s",'
300 ' "-1.000001s",'
301 ' "10.011s",'
302 ' "-315576000000s",'
303 ' "315576000000s"'
304 ']'
305 '}'))
306 parsed_message = json_format_proto3_pb2.TestDuration()
307 self.CheckParseBack(message, parsed_message)
308
309 def testFieldMaskMessage(self):
310 message = json_format_proto3_pb2.TestFieldMask()
311 message.value.paths.append('foo.bar')
312 message.value.paths.append('bar')
313 self.assertEqual(
314 json_format.MessageToJson(message, True),
315 '{\n'
316 ' "value": "foo.bar,bar"\n'
317 '}')
318 parsed_message = json_format_proto3_pb2.TestFieldMask()
319 self.CheckParseBack(message, parsed_message)
320
321 def testWrapperMessage(self):
322 message = json_format_proto3_pb2.TestWrapper()
323 message.bool_value.value = False
324 message.int32_value.value = 0
325 message.string_value.value = ''
326 message.bytes_value.value = b''
327 message.repeated_bool_value.add().value = True
328 message.repeated_bool_value.add().value = False
329 self.assertEqual(
330 json.loads(json_format.MessageToJson(message, True)),
331 json.loads('{\n'
332 ' "int32Value": 0,'
333 ' "boolValue": false,'
334 ' "stringValue": "",'
335 ' "bytesValue": "",'
336 ' "repeatedBoolValue": [true, false],'
337 ' "repeatedInt32Value": [],'
338 ' "repeatedUint32Value": [],'
339 ' "repeatedFloatValue": [],'
340 ' "repeatedDoubleValue": [],'
341 ' "repeatedBytesValue": [],'
342 ' "repeatedInt64Value": [],'
343 ' "repeatedUint64Value": [],'
344 ' "repeatedStringValue": []'
345 '}'))
346 parsed_message = json_format_proto3_pb2.TestWrapper()
347 self.CheckParseBack(message, parsed_message)
348
349 def testParseNull(self):
350 message = json_format_proto3_pb2.TestMessage()
351 message.repeated_int32_value.append(1)
352 message.repeated_int32_value.append(2)
353 message.repeated_int32_value.append(3)
354 parsed_message = json_format_proto3_pb2.TestMessage()
355 self.FillAllFields(parsed_message)
356 json_format.Parse('{"int32Value": null, '
357 '"int64Value": null, '
358 '"uint32Value": null,'
359 '"uint64Value": null,'
360 '"floatValue": null,'
361 '"doubleValue": null,'
362 '"boolValue": null,'
363 '"stringValue": null,'
364 '"bytesValue": null,'
365 '"messageValue": null,'
366 '"enumValue": null,'
367 '"repeatedInt32Value": [1, 2, null, 3],'
368 '"repeatedInt64Value": null,'
369 '"repeatedUint32Value": null,'
370 '"repeatedUint64Value": null,'
371 '"repeatedFloatValue": null,'
372 '"repeatedDoubleValue": null,'
373 '"repeatedBoolValue": null,'
374 '"repeatedStringValue": null,'
375 '"repeatedBytesValue": null,'
376 '"repeatedMessageValue": null,'
377 '"repeatedEnumValue": null'
378 '}',
379 parsed_message)
380 self.assertEqual(message, parsed_message)
381
382 def testNanFloat(self):
383 message = json_format_proto3_pb2.TestMessage()
384 message.float_value = float('nan')
385 text = '{\n "floatValue": "NaN"\n}'
386 self.assertEqual(json_format.MessageToJson(message), text)
387 parsed_message = json_format_proto3_pb2.TestMessage()
388 json_format.Parse(text, parsed_message)
389 self.assertTrue(math.isnan(parsed_message.float_value))
390
391 def testParseEmptyText(self):
392 self.CheckError('',
393 r'Failed to load JSON: (Expecting value)|(No JSON).')
394
395 def testParseBadEnumValue(self):
396 self.CheckError(
397 '{"enumValue": 1}',
398 'Enum value must be a string literal with double quotes. '
399 'Type "proto3.EnumType" has no value named 1.')
400 self.CheckError(
401 '{"enumValue": "baz"}',
402 'Enum value must be a string literal with double quotes. '
403 'Type "proto3.EnumType" has no value named baz.')
404
405 def testParseBadIdentifer(self):
406 self.CheckError('{int32Value: 1}',
407 (r'Failed to load JSON: Expecting property name'
408 r'( enclosed in double quotes)?: line 1'))
409 self.CheckError('{"unknownName": 1}',
410 'Message type "proto3.TestMessage" has no field named '
411 '"unknownName".')
412
413 def testDuplicateField(self):
414 # Duplicate key check is not supported for python2.6
415 if sys.version_info < (2, 7):
416 return
417 self.CheckError('{"int32Value": 1,\n"int32Value":2}',
418 'Failed to load JSON: duplicate key int32Value.')
419
420 def testInvalidBoolValue(self):
421 self.CheckError('{"boolValue": 1}',
422 'Failed to parse boolValue field: '
423 'Expected true or false without quotes.')
424 self.CheckError('{"boolValue": "true"}',
425 'Failed to parse boolValue field: '
426 'Expected true or false without quotes.')
427
428 def testInvalidIntegerValue(self):
429 message = json_format_proto3_pb2.TestMessage()
430 text = '{"int32Value": 0x12345}'
431 self.assertRaises(json_format.ParseError,
432 json_format.Parse, text, message)
433 self.CheckError('{"int32Value": 012345}',
434 (r'Failed to load JSON: Expecting \'?,\'? delimiter: '
435 r'line 1.'))
436 self.CheckError('{"int32Value": 1.0}',
437 'Failed to parse int32Value field: '
438 'Couldn\'t parse integer: 1.0.')
439 self.CheckError('{"int32Value": " 1 "}',
440 'Failed to parse int32Value field: '
441 'Couldn\'t parse integer: " 1 ".')
442 self.CheckError('{"int32Value": "1 "}',
443 'Failed to parse int32Value field: '
444 'Couldn\'t parse integer: "1 ".')
445 self.CheckError('{"int32Value": 12345678901234567890}',
446 'Failed to parse int32Value field: Value out of range: '
447 '12345678901234567890.')
448 self.CheckError('{"int32Value": 1e5}',
449 'Failed to parse int32Value field: '
450 'Couldn\'t parse integer: 100000.0.')
451 self.CheckError('{"uint32Value": -1}',
452 'Failed to parse uint32Value field: '
453 'Value out of range: -1.')
454
455 def testInvalidFloatValue(self):
456 self.CheckError('{"floatValue": "nan"}',
457 'Failed to parse floatValue field: Couldn\'t '
458 'parse float "nan", use "NaN" instead.')
459
460 def testInvalidBytesValue(self):
461 self.CheckError('{"bytesValue": "AQI"}',
462 'Failed to parse bytesValue field: Incorrect padding.')
463 self.CheckError('{"bytesValue": "AQI*"}',
464 'Failed to parse bytesValue field: Incorrect padding.')
465
466 def testInvalidMap(self):
467 message = json_format_proto3_pb2.TestMap()
468 text = '{"int32Map": {"null": 2, "2": 3}}'
469 self.assertRaisesRegexp(
470 json_format.ParseError,
471 'Failed to parse int32Map field: invalid literal',
472 json_format.Parse, text, message)
473 text = '{"int32Map": {1: 2, "2": 3}}'
474 self.assertRaisesRegexp(
475 json_format.ParseError,
476 (r'Failed to load JSON: Expecting property name'
477 r'( enclosed in double quotes)?: line 1'),
478 json_format.Parse, text, message)
479 text = '{"boolMap": {"null": 1}}'
480 self.assertRaisesRegexp(
481 json_format.ParseError,
482 'Failed to parse boolMap field: Expected "true" or "false", not null.',
483 json_format.Parse, text, message)
484 if sys.version_info < (2, 7):
485 return
486 text = r'{"stringMap": {"a": 3, "\u0061": 2}}'
487 self.assertRaisesRegexp(
488 json_format.ParseError,
489 'Failed to load JSON: duplicate key a',
490 json_format.Parse, text, message)
491
492 def testInvalidTimestamp(self):
493 message = json_format_proto3_pb2.TestTimestamp()
494 text = '{"value": "10000-01-01T00:00:00.00Z"}'
495 self.assertRaisesRegexp(
496 json_format.ParseError,
497 'time data \'10000-01-01T00:00:00\' does not match'
498 ' format \'%Y-%m-%dT%H:%M:%S\'.',
499 json_format.Parse, text, message)
500 text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}'
501 self.assertRaisesRegexp(
502 well_known_types.ParseError,
503 'nanos 0123456789012 more than 9 fractional digits.',
504 json_format.Parse, text, message)
505 text = '{"value": "1972-01-01T01:00:00.01+08"}'
506 self.assertRaisesRegexp(
507 well_known_types.ParseError,
508 (r'Invalid timezone offset value: \+08.'),
509 json_format.Parse, text, message)
510 # Time smaller than minimum time.
511 text = '{"value": "0000-01-01T00:00:00Z"}'
512 self.assertRaisesRegexp(
513 json_format.ParseError,
514 'Failed to parse value field: year is out of range.',
515 json_format.Parse, text, message)
516 # Time bigger than maxinum time.
517 message.value.seconds = 253402300800
518 self.assertRaisesRegexp(
519 OverflowError,
520 'date value out of range',
521 json_format.MessageToJson, message)
522
523 def testInvalidOneof(self):
524 message = json_format_proto3_pb2.TestOneof()
525 text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}'
526 self.assertRaisesRegexp(
527 json_format.ParseError,
528 'Message type "proto3.TestOneof"'
529 ' should not have multiple "oneof_value" oneof fields.',
530 json_format.Parse, text, message)
531
532
533 if __name__ == '__main__':
534 unittest.main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698