blob: 49e96a46a8ab7864a046990906539a0e811452fc [file] [log] [blame]
Jisi Liu46e8ff62015-10-05 11:59:43 -07001#! /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
37import json
38import math
39import sys
40
Jisi Liudbea00a2015-10-05 16:08:22 -070041try:
42 import unittest2 as unittest
43except ImportError:
44 import unittest
CH Albach5477f8c2016-01-29 18:10:50 -080045from google.protobuf import any_pb2
46from google.protobuf import duration_pb2
47from google.protobuf import field_mask_pb2
48from google.protobuf import struct_pb2
49from google.protobuf import timestamp_pb2
50from google.protobuf import wrappers_pb2
Feng Xiaoe841bac2015-12-11 17:09:20 -080051from google.protobuf.internal import well_known_types
Jisi Liu46e8ff62015-10-05 11:59:43 -070052from google.protobuf import json_format
53from google.protobuf.util import json_format_proto3_pb2
54
55
56class JsonFormatBase(unittest.TestCase):
57
58 def FillAllFields(self, message):
59 message.int32_value = 20
60 message.int64_value = -20
61 message.uint32_value = 3120987654
62 message.uint64_value = 12345678900
63 message.float_value = float('-inf')
64 message.double_value = 3.1415
65 message.bool_value = True
66 message.string_value = 'foo'
67 message.bytes_value = b'bar'
68 message.message_value.value = 10
69 message.enum_value = json_format_proto3_pb2.BAR
70 # Repeated
71 message.repeated_int32_value.append(0x7FFFFFFF)
72 message.repeated_int32_value.append(-2147483648)
73 message.repeated_int64_value.append(9007199254740992)
74 message.repeated_int64_value.append(-9007199254740992)
75 message.repeated_uint32_value.append(0xFFFFFFF)
76 message.repeated_uint32_value.append(0x7FFFFFF)
77 message.repeated_uint64_value.append(9007199254740992)
78 message.repeated_uint64_value.append(9007199254740991)
79 message.repeated_float_value.append(0)
80
81 message.repeated_double_value.append(1E-15)
82 message.repeated_double_value.append(float('inf'))
83 message.repeated_bool_value.append(True)
84 message.repeated_bool_value.append(False)
85 message.repeated_string_value.append('Few symbols!#$,;')
86 message.repeated_string_value.append('bar')
87 message.repeated_bytes_value.append(b'foo')
88 message.repeated_bytes_value.append(b'bar')
89 message.repeated_message_value.add().value = 10
90 message.repeated_message_value.add().value = 11
91 message.repeated_enum_value.append(json_format_proto3_pb2.FOO)
92 message.repeated_enum_value.append(json_format_proto3_pb2.BAR)
93 self.message = message
94
95 def CheckParseBack(self, message, parsed_message):
96 json_format.Parse(json_format.MessageToJson(message),
97 parsed_message)
98 self.assertEqual(message, parsed_message)
99
100 def CheckError(self, text, error_message):
101 message = json_format_proto3_pb2.TestMessage()
102 self.assertRaisesRegexp(
103 json_format.ParseError,
104 error_message,
105 json_format.Parse, text, message)
106
107
108class JsonFormatTest(JsonFormatBase):
109
110 def testEmptyMessageToJson(self):
111 message = json_format_proto3_pb2.TestMessage()
112 self.assertEqual(json_format.MessageToJson(message),
113 '{}')
114 parsed_message = json_format_proto3_pb2.TestMessage()
115 self.CheckParseBack(message, parsed_message)
116
117 def testPartialMessageToJson(self):
118 message = json_format_proto3_pb2.TestMessage(
119 string_value='test',
120 repeated_int32_value=[89, 4])
121 self.assertEqual(json.loads(json_format.MessageToJson(message)),
122 json.loads('{"stringValue": "test", '
123 '"repeatedInt32Value": [89, 4]}'))
124 parsed_message = json_format_proto3_pb2.TestMessage()
125 self.CheckParseBack(message, parsed_message)
126
127 def testAllFieldsToJson(self):
128 message = json_format_proto3_pb2.TestMessage()
129 text = ('{"int32Value": 20, '
130 '"int64Value": "-20", '
131 '"uint32Value": 3120987654,'
132 '"uint64Value": "12345678900",'
133 '"floatValue": "-Infinity",'
134 '"doubleValue": 3.1415,'
135 '"boolValue": true,'
136 '"stringValue": "foo",'
137 '"bytesValue": "YmFy",'
138 '"messageValue": {"value": 10},'
139 '"enumValue": "BAR",'
140 '"repeatedInt32Value": [2147483647, -2147483648],'
141 '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],'
142 '"repeatedUint32Value": [268435455, 134217727],'
143 '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],'
144 '"repeatedFloatValue": [0],'
145 '"repeatedDoubleValue": [1e-15, "Infinity"],'
146 '"repeatedBoolValue": [true, false],'
147 '"repeatedStringValue": ["Few symbols!#$,;", "bar"],'
148 '"repeatedBytesValue": ["Zm9v", "YmFy"],'
149 '"repeatedMessageValue": [{"value": 10}, {"value": 11}],'
150 '"repeatedEnumValue": ["FOO", "BAR"]'
151 '}')
152 self.FillAllFields(message)
153 self.assertEqual(
154 json.loads(json_format.MessageToJson(message)),
155 json.loads(text))
156 parsed_message = json_format_proto3_pb2.TestMessage()
157 json_format.Parse(text, parsed_message)
158 self.assertEqual(message, parsed_message)
159
160 def testJsonEscapeString(self):
161 message = json_format_proto3_pb2.TestMessage()
162 if sys.version_info[0] < 3:
163 message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9'
164 else:
165 message.string_value = '&\n<\"\r>\b\t\f\\\001/'
166 message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8')
167 self.assertEqual(
168 json_format.MessageToJson(message),
169 '{\n "stringValue": '
170 '"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}')
171 parsed_message = json_format_proto3_pb2.TestMessage()
172 self.CheckParseBack(message, parsed_message)
173 text = u'{"int32Value": "\u0031"}'
174 json_format.Parse(text, message)
175 self.assertEqual(message.int32_value, 1)
176
177 def testAlwaysSeriliaze(self):
178 message = json_format_proto3_pb2.TestMessage(
179 string_value='foo')
180 self.assertEqual(
181 json.loads(json_format.MessageToJson(message, True)),
182 json.loads('{'
183 '"repeatedStringValue": [],'
184 '"stringValue": "foo",'
185 '"repeatedBoolValue": [],'
186 '"repeatedUint32Value": [],'
187 '"repeatedInt32Value": [],'
188 '"enumValue": "FOO",'
189 '"int32Value": 0,'
190 '"floatValue": 0,'
191 '"int64Value": "0",'
192 '"uint32Value": 0,'
193 '"repeatedBytesValue": [],'
194 '"repeatedUint64Value": [],'
195 '"repeatedDoubleValue": [],'
196 '"bytesValue": "",'
197 '"boolValue": false,'
198 '"repeatedEnumValue": [],'
199 '"uint64Value": "0",'
200 '"doubleValue": 0,'
201 '"repeatedFloatValue": [],'
202 '"repeatedInt64Value": [],'
203 '"repeatedMessageValue": []}'))
204 parsed_message = json_format_proto3_pb2.TestMessage()
205 self.CheckParseBack(message, parsed_message)
206
207 def testMapFields(self):
208 message = json_format_proto3_pb2.TestMap()
209 message.bool_map[True] = 1
210 message.bool_map[False] = 2
211 message.int32_map[1] = 2
212 message.int32_map[2] = 3
213 message.int64_map[1] = 2
214 message.int64_map[2] = 3
215 message.uint32_map[1] = 2
216 message.uint32_map[2] = 3
217 message.uint64_map[1] = 2
218 message.uint64_map[2] = 3
219 message.string_map['1'] = 2
220 message.string_map['null'] = 3
221 self.assertEqual(
222 json.loads(json_format.MessageToJson(message, True)),
223 json.loads('{'
224 '"boolMap": {"false": 2, "true": 1},'
225 '"int32Map": {"1": 2, "2": 3},'
226 '"int64Map": {"1": 2, "2": 3},'
227 '"uint32Map": {"1": 2, "2": 3},'
228 '"uint64Map": {"1": 2, "2": 3},'
229 '"stringMap": {"1": 2, "null": 3}'
230 '}'))
231 parsed_message = json_format_proto3_pb2.TestMap()
232 self.CheckParseBack(message, parsed_message)
233
234 def testOneofFields(self):
235 message = json_format_proto3_pb2.TestOneof()
236 # Always print does not affect oneof fields.
237 self.assertEqual(
238 json_format.MessageToJson(message, True),
239 '{}')
240 message.oneof_int32_value = 0
241 self.assertEqual(
242 json_format.MessageToJson(message, True),
243 '{\n'
244 ' "oneofInt32Value": 0\n'
245 '}')
246 parsed_message = json_format_proto3_pb2.TestOneof()
247 self.CheckParseBack(message, parsed_message)
248
249 def testTimestampMessage(self):
250 message = json_format_proto3_pb2.TestTimestamp()
251 message.value.seconds = 0
252 message.value.nanos = 0
253 message.repeated_value.add().seconds = 20
254 message.repeated_value[0].nanos = 1
255 message.repeated_value.add().seconds = 0
256 message.repeated_value[1].nanos = 10000
257 message.repeated_value.add().seconds = 100000000
258 message.repeated_value[2].nanos = 0
259 # Maximum time
260 message.repeated_value.add().seconds = 253402300799
261 message.repeated_value[3].nanos = 999999999
262 # Minimum time
263 message.repeated_value.add().seconds = -62135596800
264 message.repeated_value[4].nanos = 0
265 self.assertEqual(
266 json.loads(json_format.MessageToJson(message, True)),
267 json.loads('{'
268 '"value": "1970-01-01T00:00:00Z",'
269 '"repeatedValue": ['
270 ' "1970-01-01T00:00:20.000000001Z",'
271 ' "1970-01-01T00:00:00.000010Z",'
272 ' "1973-03-03T09:46:40Z",'
273 ' "9999-12-31T23:59:59.999999999Z",'
274 ' "0001-01-01T00:00:00Z"'
275 ']'
276 '}'))
277 parsed_message = json_format_proto3_pb2.TestTimestamp()
278 self.CheckParseBack(message, parsed_message)
Feng Xiaoe841bac2015-12-11 17:09:20 -0800279 text = (r'{"value": "1970-01-01T00:00:00.01+08:00",'
Jisi Liu46e8ff62015-10-05 11:59:43 -0700280 r'"repeatedValue":['
Feng Xiaoe841bac2015-12-11 17:09:20 -0800281 r' "1970-01-01T00:00:00.01+08:30",'
282 r' "1970-01-01T00:00:00.01-01:23"]}')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700283 json_format.Parse(text, parsed_message)
Feng Xiaoe841bac2015-12-11 17:09:20 -0800284 self.assertEqual(parsed_message.value.seconds, -8 * 3600)
Jisi Liu46e8ff62015-10-05 11:59:43 -0700285 self.assertEqual(parsed_message.value.nanos, 10000000)
Feng Xiaoe841bac2015-12-11 17:09:20 -0800286 self.assertEqual(parsed_message.repeated_value[0].seconds, -8.5 * 3600)
287 self.assertEqual(parsed_message.repeated_value[1].seconds, 3600 + 23 * 60)
Jisi Liu46e8ff62015-10-05 11:59:43 -0700288
289 def testDurationMessage(self):
290 message = json_format_proto3_pb2.TestDuration()
291 message.value.seconds = 1
292 message.repeated_value.add().seconds = 0
293 message.repeated_value[0].nanos = 10
294 message.repeated_value.add().seconds = -1
295 message.repeated_value[1].nanos = -1000
296 message.repeated_value.add().seconds = 10
297 message.repeated_value[2].nanos = 11000000
298 message.repeated_value.add().seconds = -315576000000
299 message.repeated_value.add().seconds = 315576000000
300 self.assertEqual(
301 json.loads(json_format.MessageToJson(message, True)),
302 json.loads('{'
303 '"value": "1s",'
304 '"repeatedValue": ['
305 ' "0.000000010s",'
306 ' "-1.000001s",'
307 ' "10.011s",'
308 ' "-315576000000s",'
309 ' "315576000000s"'
310 ']'
311 '}'))
312 parsed_message = json_format_proto3_pb2.TestDuration()
313 self.CheckParseBack(message, parsed_message)
314
315 def testFieldMaskMessage(self):
316 message = json_format_proto3_pb2.TestFieldMask()
317 message.value.paths.append('foo.bar')
318 message.value.paths.append('bar')
319 self.assertEqual(
320 json_format.MessageToJson(message, True),
321 '{\n'
322 ' "value": "foo.bar,bar"\n'
323 '}')
324 parsed_message = json_format_proto3_pb2.TestFieldMask()
325 self.CheckParseBack(message, parsed_message)
326
327 def testWrapperMessage(self):
328 message = json_format_proto3_pb2.TestWrapper()
329 message.bool_value.value = False
330 message.int32_value.value = 0
331 message.string_value.value = ''
332 message.bytes_value.value = b''
333 message.repeated_bool_value.add().value = True
334 message.repeated_bool_value.add().value = False
CH Albach5477f8c2016-01-29 18:10:50 -0800335 message.repeated_int32_value.add()
Jisi Liu46e8ff62015-10-05 11:59:43 -0700336 self.assertEqual(
337 json.loads(json_format.MessageToJson(message, True)),
338 json.loads('{\n'
339 ' "int32Value": 0,'
340 ' "boolValue": false,'
341 ' "stringValue": "",'
342 ' "bytesValue": "",'
343 ' "repeatedBoolValue": [true, false],'
CH Albach5477f8c2016-01-29 18:10:50 -0800344 ' "repeatedInt32Value": [0],'
Jisi Liu46e8ff62015-10-05 11:59:43 -0700345 ' "repeatedUint32Value": [],'
346 ' "repeatedFloatValue": [],'
347 ' "repeatedDoubleValue": [],'
348 ' "repeatedBytesValue": [],'
349 ' "repeatedInt64Value": [],'
350 ' "repeatedUint64Value": [],'
351 ' "repeatedStringValue": []'
352 '}'))
353 parsed_message = json_format_proto3_pb2.TestWrapper()
354 self.CheckParseBack(message, parsed_message)
355
CH Albach5477f8c2016-01-29 18:10:50 -0800356 def testStructMessage(self):
357 message = json_format_proto3_pb2.TestStruct()
358 message.value['name'] = 'Jim'
359 message.value['age'] = 10
360 message.value['attend'] = True
361 message.value['email'] = None
362 message.value.get_or_create_struct('address')['city'] = 'SFO'
363 message.value['address']['house_number'] = 1024
364 struct_list = message.value.get_or_create_list('list')
365 struct_list.extend([6, 'seven', True, False, None])
366 struct_list.add_struct()['subkey2'] = 9
367 message.repeated_value.add()['age'] = 11
368 message.repeated_value.add()
369 self.assertEqual(
370 json.loads(json_format.MessageToJson(message, False)),
371 json.loads(
372 '{'
373 ' "value": {'
374 ' "address": {'
375 ' "city": "SFO", '
376 ' "house_number": 1024'
377 ' }, '
378 ' "age": 10, '
379 ' "name": "Jim", '
380 ' "attend": true, '
381 ' "email": null, '
382 ' "list": [6, "seven", true, false, null, {"subkey2": 9}]'
383 ' },'
384 ' "repeatedValue": [{"age": 11}, {}]'
385 '}'))
386 parsed_message = json_format_proto3_pb2.TestStruct()
387 self.CheckParseBack(message, parsed_message)
388
389 def testValueMessage(self):
390 message = json_format_proto3_pb2.TestValue()
391 message.value.string_value = 'hello'
392 message.repeated_value.add().number_value = 11.1
393 message.repeated_value.add().bool_value = False
394 message.repeated_value.add().null_value = 0
395 self.assertEqual(
396 json.loads(json_format.MessageToJson(message, False)),
397 json.loads(
398 '{'
399 ' "value": "hello",'
400 ' "repeatedValue": [11.1, false, null]'
401 '}'))
402 parsed_message = json_format_proto3_pb2.TestValue()
403 self.CheckParseBack(message, parsed_message)
404 # Can't parse back if the Value message is not set.
405 message.repeated_value.add()
406 self.assertEqual(
407 json.loads(json_format.MessageToJson(message, False)),
408 json.loads(
409 '{'
410 ' "value": "hello",'
411 ' "repeatedValue": [11.1, false, null, null]'
412 '}'))
413
414 def testListValueMessage(self):
415 message = json_format_proto3_pb2.TestListValue()
416 message.value.values.add().number_value = 11.1
417 message.value.values.add().null_value = 0
418 message.value.values.add().bool_value = True
419 message.value.values.add().string_value = 'hello'
420 message.value.values.add().struct_value['name'] = 'Jim'
421 message.repeated_value.add().values.add().number_value = 1
422 message.repeated_value.add()
423 self.assertEqual(
424 json.loads(json_format.MessageToJson(message, False)),
425 json.loads(
426 '{"value": [11.1, null, true, "hello", {"name": "Jim"}]\n,'
427 '"repeatedValue": [[1], []]}'))
428 parsed_message = json_format_proto3_pb2.TestListValue()
429 self.CheckParseBack(message, parsed_message)
430
431 def testAnyMessage(self):
432 message = json_format_proto3_pb2.TestAny()
433 value1 = json_format_proto3_pb2.MessageType()
434 value2 = json_format_proto3_pb2.MessageType()
435 value1.value = 1234
436 value2.value = 5678
437 message.value.Pack(value1)
438 message.repeated_value.add().Pack(value1)
439 message.repeated_value.add().Pack(value2)
440 message.repeated_value.add()
441 self.assertEqual(
442 json.loads(json_format.MessageToJson(message, True)),
443 json.loads(
444 '{\n'
445 ' "repeatedValue": [ {\n'
446 ' "@type": "type.googleapis.com/proto3.MessageType",\n'
447 ' "value": 1234\n'
448 ' }, {\n'
449 ' "@type": "type.googleapis.com/proto3.MessageType",\n'
450 ' "value": 5678\n'
451 ' },\n'
452 ' {}],\n'
453 ' "value": {\n'
454 ' "@type": "type.googleapis.com/proto3.MessageType",\n'
455 ' "value": 1234\n'
456 ' }\n'
457 '}\n'))
458 parsed_message = json_format_proto3_pb2.TestAny()
459 self.CheckParseBack(message, parsed_message)
460
461 def testWellKnownInAnyMessage(self):
462 message = any_pb2.Any()
463 int32_value = wrappers_pb2.Int32Value()
464 int32_value.value = 1234
465 message.Pack(int32_value)
466 self.assertEqual(
467 json.loads(json_format.MessageToJson(message, True)),
468 json.loads(
469 '{\n'
470 ' "@type": \"type.googleapis.com/google.protobuf.Int32Value\",\n'
471 ' "value": 1234\n'
472 '}\n'))
473 parsed_message = any_pb2.Any()
474 self.CheckParseBack(message, parsed_message)
475
476 timestamp = timestamp_pb2.Timestamp()
477 message.Pack(timestamp)
478 self.assertEqual(
479 json.loads(json_format.MessageToJson(message, True)),
480 json.loads(
481 '{\n'
482 ' "@type": "type.googleapis.com/google.protobuf.Timestamp",\n'
483 ' "value": "1970-01-01T00:00:00Z"\n'
484 '}\n'))
485 self.CheckParseBack(message, parsed_message)
486
487 duration = duration_pb2.Duration()
488 duration.seconds = 1
489 message.Pack(duration)
490 self.assertEqual(
491 json.loads(json_format.MessageToJson(message, True)),
492 json.loads(
493 '{\n'
494 ' "@type": "type.googleapis.com/google.protobuf.Duration",\n'
495 ' "value": "1s"\n'
496 '}\n'))
497 self.CheckParseBack(message, parsed_message)
498
499 field_mask = field_mask_pb2.FieldMask()
500 field_mask.paths.append('foo.bar')
501 field_mask.paths.append('bar')
502 message.Pack(field_mask)
503 self.assertEqual(
504 json.loads(json_format.MessageToJson(message, True)),
505 json.loads(
506 '{\n'
507 ' "@type": "type.googleapis.com/google.protobuf.FieldMask",\n'
508 ' "value": "foo.bar,bar"\n'
509 '}\n'))
510 self.CheckParseBack(message, parsed_message)
511
512 struct_message = struct_pb2.Struct()
513 struct_message['name'] = 'Jim'
514 message.Pack(struct_message)
515 self.assertEqual(
516 json.loads(json_format.MessageToJson(message, True)),
517 json.loads(
518 '{\n'
519 ' "@type": "type.googleapis.com/google.protobuf.Struct",\n'
520 ' "value": {"name": "Jim"}\n'
521 '}\n'))
522 self.CheckParseBack(message, parsed_message)
523
524 nested_any = any_pb2.Any()
525 int32_value.value = 5678
526 nested_any.Pack(int32_value)
527 message.Pack(nested_any)
528 self.assertEqual(
529 json.loads(json_format.MessageToJson(message, True)),
530 json.loads(
531 '{\n'
532 ' "@type": "type.googleapis.com/google.protobuf.Any",\n'
533 ' "value": {\n'
534 ' "@type": "type.googleapis.com/google.protobuf.Int32Value",\n'
535 ' "value": 5678\n'
536 ' }\n'
537 '}\n'))
538 self.CheckParseBack(message, parsed_message)
539
Jisi Liu46e8ff62015-10-05 11:59:43 -0700540 def testParseNull(self):
541 message = json_format_proto3_pb2.TestMessage()
Jisi Liu46e8ff62015-10-05 11:59:43 -0700542 parsed_message = json_format_proto3_pb2.TestMessage()
543 self.FillAllFields(parsed_message)
544 json_format.Parse('{"int32Value": null, '
545 '"int64Value": null, '
546 '"uint32Value": null,'
547 '"uint64Value": null,'
548 '"floatValue": null,'
549 '"doubleValue": null,'
550 '"boolValue": null,'
551 '"stringValue": null,'
552 '"bytesValue": null,'
553 '"messageValue": null,'
554 '"enumValue": null,'
CH Albach5477f8c2016-01-29 18:10:50 -0800555 '"repeatedInt32Value": null,'
Jisi Liu46e8ff62015-10-05 11:59:43 -0700556 '"repeatedInt64Value": null,'
557 '"repeatedUint32Value": null,'
558 '"repeatedUint64Value": null,'
559 '"repeatedFloatValue": null,'
560 '"repeatedDoubleValue": null,'
561 '"repeatedBoolValue": null,'
562 '"repeatedStringValue": null,'
563 '"repeatedBytesValue": null,'
564 '"repeatedMessageValue": null,'
565 '"repeatedEnumValue": null'
566 '}',
567 parsed_message)
568 self.assertEqual(message, parsed_message)
CH Albach5477f8c2016-01-29 18:10:50 -0800569 self.assertRaisesRegexp(
570 json_format.ParseError,
571 'Failed to parse repeatedInt32Value field: '
572 'null is not allowed to be used as an element in a repeated field.',
573 json_format.Parse,
574 '{"repeatedInt32Value":[1, null]}',
575 parsed_message)
Jisi Liu46e8ff62015-10-05 11:59:43 -0700576
577 def testNanFloat(self):
578 message = json_format_proto3_pb2.TestMessage()
579 message.float_value = float('nan')
580 text = '{\n "floatValue": "NaN"\n}'
581 self.assertEqual(json_format.MessageToJson(message), text)
582 parsed_message = json_format_proto3_pb2.TestMessage()
583 json_format.Parse(text, parsed_message)
584 self.assertTrue(math.isnan(parsed_message.float_value))
585
586 def testParseEmptyText(self):
587 self.CheckError('',
Feng Xiaoe841bac2015-12-11 17:09:20 -0800588 r'Failed to load JSON: (Expecting value)|(No JSON).')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700589
590 def testParseBadEnumValue(self):
591 self.CheckError(
592 '{"enumValue": 1}',
593 'Enum value must be a string literal with double quotes. '
594 'Type "proto3.EnumType" has no value named 1.')
595 self.CheckError(
596 '{"enumValue": "baz"}',
597 'Enum value must be a string literal with double quotes. '
598 'Type "proto3.EnumType" has no value named baz.')
599
600 def testParseBadIdentifer(self):
601 self.CheckError('{int32Value: 1}',
Jisi Liua783eaf2015-10-05 15:06:06 -0700602 (r'Failed to load JSON: Expecting property name'
603 r'( enclosed in double quotes)?: line 1'))
Jisi Liu46e8ff62015-10-05 11:59:43 -0700604 self.CheckError('{"unknownName": 1}',
605 'Message type "proto3.TestMessage" has no field named '
606 '"unknownName".')
607
608 def testDuplicateField(self):
Jie Luo2850a982015-10-09 17:07:03 -0700609 # Duplicate key check is not supported for python2.6
610 if sys.version_info < (2, 7):
611 return
Jisi Liu46e8ff62015-10-05 11:59:43 -0700612 self.CheckError('{"int32Value": 1,\n"int32Value":2}',
Feng Xiaoe841bac2015-12-11 17:09:20 -0800613 'Failed to load JSON: duplicate key int32Value.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700614
615 def testInvalidBoolValue(self):
616 self.CheckError('{"boolValue": 1}',
617 'Failed to parse boolValue field: '
618 'Expected true or false without quotes.')
619 self.CheckError('{"boolValue": "true"}',
620 'Failed to parse boolValue field: '
621 'Expected true or false without quotes.')
622
623 def testInvalidIntegerValue(self):
624 message = json_format_proto3_pb2.TestMessage()
625 text = '{"int32Value": 0x12345}'
626 self.assertRaises(json_format.ParseError,
627 json_format.Parse, text, message)
628 self.CheckError('{"int32Value": 012345}',
Jisi Liua783eaf2015-10-05 15:06:06 -0700629 (r'Failed to load JSON: Expecting \'?,\'? delimiter: '
Feng Xiaoe841bac2015-12-11 17:09:20 -0800630 r'line 1.'))
Jisi Liu46e8ff62015-10-05 11:59:43 -0700631 self.CheckError('{"int32Value": 1.0}',
632 'Failed to parse int32Value field: '
Feng Xiaoe841bac2015-12-11 17:09:20 -0800633 'Couldn\'t parse integer: 1.0.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700634 self.CheckError('{"int32Value": " 1 "}',
635 'Failed to parse int32Value field: '
Feng Xiaoe841bac2015-12-11 17:09:20 -0800636 'Couldn\'t parse integer: " 1 ".')
637 self.CheckError('{"int32Value": "1 "}',
638 'Failed to parse int32Value field: '
639 'Couldn\'t parse integer: "1 ".')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700640 self.CheckError('{"int32Value": 12345678901234567890}',
641 'Failed to parse int32Value field: Value out of range: '
Feng Xiaoe841bac2015-12-11 17:09:20 -0800642 '12345678901234567890.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700643 self.CheckError('{"int32Value": 1e5}',
644 'Failed to parse int32Value field: '
Feng Xiaoe841bac2015-12-11 17:09:20 -0800645 'Couldn\'t parse integer: 100000.0.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700646 self.CheckError('{"uint32Value": -1}',
Feng Xiaoe841bac2015-12-11 17:09:20 -0800647 'Failed to parse uint32Value field: '
648 'Value out of range: -1.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700649
650 def testInvalidFloatValue(self):
651 self.CheckError('{"floatValue": "nan"}',
652 'Failed to parse floatValue field: Couldn\'t '
Feng Xiaoe841bac2015-12-11 17:09:20 -0800653 'parse float "nan", use "NaN" instead.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700654
655 def testInvalidBytesValue(self):
656 self.CheckError('{"bytesValue": "AQI"}',
Feng Xiaoe841bac2015-12-11 17:09:20 -0800657 'Failed to parse bytesValue field: Incorrect padding.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700658 self.CheckError('{"bytesValue": "AQI*"}',
Feng Xiaoe841bac2015-12-11 17:09:20 -0800659 'Failed to parse bytesValue field: Incorrect padding.')
Jisi Liu46e8ff62015-10-05 11:59:43 -0700660
661 def testInvalidMap(self):
662 message = json_format_proto3_pb2.TestMap()
663 text = '{"int32Map": {"null": 2, "2": 3}}'
664 self.assertRaisesRegexp(
665 json_format.ParseError,
Feng Xiaoe841bac2015-12-11 17:09:20 -0800666 'Failed to parse int32Map field: invalid literal',
Jisi Liu46e8ff62015-10-05 11:59:43 -0700667 json_format.Parse, text, message)
668 text = '{"int32Map": {1: 2, "2": 3}}'
669 self.assertRaisesRegexp(
670 json_format.ParseError,
Jisi Liua783eaf2015-10-05 15:06:06 -0700671 (r'Failed to load JSON: Expecting property name'
672 r'( enclosed in double quotes)?: line 1'),
Jisi Liu46e8ff62015-10-05 11:59:43 -0700673 json_format.Parse, text, message)
Jisi Liu46e8ff62015-10-05 11:59:43 -0700674 text = '{"boolMap": {"null": 1}}'
675 self.assertRaisesRegexp(
676 json_format.ParseError,
Feng Xiaoe841bac2015-12-11 17:09:20 -0800677 'Failed to parse boolMap field: Expected "true" or "false", not null.',
Jisi Liu46e8ff62015-10-05 11:59:43 -0700678 json_format.Parse, text, message)
Jie Luo2850a982015-10-09 17:07:03 -0700679 if sys.version_info < (2, 7):
680 return
681 text = r'{"stringMap": {"a": 3, "\u0061": 2}}'
682 self.assertRaisesRegexp(
683 json_format.ParseError,
684 'Failed to load JSON: duplicate key a',
685 json_format.Parse, text, message)
Jisi Liu46e8ff62015-10-05 11:59:43 -0700686
687 def testInvalidTimestamp(self):
688 message = json_format_proto3_pb2.TestTimestamp()
689 text = '{"value": "10000-01-01T00:00:00.00Z"}'
690 self.assertRaisesRegexp(
691 json_format.ParseError,
692 'time data \'10000-01-01T00:00:00\' does not match'
Feng Xiaoe841bac2015-12-11 17:09:20 -0800693 ' format \'%Y-%m-%dT%H:%M:%S\'.',
Jisi Liu46e8ff62015-10-05 11:59:43 -0700694 json_format.Parse, text, message)
695 text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}'
696 self.assertRaisesRegexp(
Feng Xiaoe841bac2015-12-11 17:09:20 -0800697 well_known_types.ParseError,
Jisi Liu46e8ff62015-10-05 11:59:43 -0700698 'nanos 0123456789012 more than 9 fractional digits.',
699 json_format.Parse, text, message)
700 text = '{"value": "1972-01-01T01:00:00.01+08"}'
701 self.assertRaisesRegexp(
Feng Xiaoe841bac2015-12-11 17:09:20 -0800702 well_known_types.ParseError,
703 (r'Invalid timezone offset value: \+08.'),
Jisi Liu46e8ff62015-10-05 11:59:43 -0700704 json_format.Parse, text, message)
705 # Time smaller than minimum time.
706 text = '{"value": "0000-01-01T00:00:00Z"}'
707 self.assertRaisesRegexp(
708 json_format.ParseError,
Feng Xiaoe841bac2015-12-11 17:09:20 -0800709 'Failed to parse value field: year is out of range.',
Jisi Liu46e8ff62015-10-05 11:59:43 -0700710 json_format.Parse, text, message)
711 # Time bigger than maxinum time.
712 message.value.seconds = 253402300800
713 self.assertRaisesRegexp(
Feng Xiaoe841bac2015-12-11 17:09:20 -0800714 OverflowError,
715 'date value out of range',
Jisi Liu46e8ff62015-10-05 11:59:43 -0700716 json_format.MessageToJson, message)
717
718 def testInvalidOneof(self):
719 message = json_format_proto3_pb2.TestOneof()
720 text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}'
721 self.assertRaisesRegexp(
722 json_format.ParseError,
723 'Message type "proto3.TestOneof"'
724 ' should not have multiple "oneof_value" oneof fields.',
725 json_format.Parse, text, message)
726
CH Albach5477f8c2016-01-29 18:10:50 -0800727 def testInvalidListValue(self):
728 message = json_format_proto3_pb2.TestListValue()
729 text = '{"value": 1234}'
730 self.assertRaisesRegexp(
731 json_format.ParseError,
732 r'Failed to parse value field: ListValue must be in \[\] which is 1234',
733 json_format.Parse, text, message)
734
735 def testInvalidStruct(self):
736 message = json_format_proto3_pb2.TestStruct()
737 text = '{"value": 1234}'
738 self.assertRaisesRegexp(
739 json_format.ParseError,
740 'Failed to parse value field: Struct must be in a dict which is 1234',
741 json_format.Parse, text, message)
742
743 def testInvalidAny(self):
744 message = any_pb2.Any()
745 text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}'
746 self.assertRaisesRegexp(
747 KeyError,
748 'value',
749 json_format.Parse, text, message)
750 text = '{"value": 1234}'
751 self.assertRaisesRegexp(
752 json_format.ParseError,
753 '@type is missing when parsing any message.',
754 json_format.Parse, text, message)
755 text = '{"@type": "type.googleapis.com/MessageNotExist", "value": 1234}'
756 self.assertRaisesRegexp(
757 TypeError,
758 'Can not find message descriptor by type_url: '
759 'type.googleapis.com/MessageNotExist.',
760 json_format.Parse, text, message)
761 # Only last part is to be used.
762 text = (r'{"@type": "incorrect.googleapis.com/google.protobuf.Int32Value",'
763 r'"value": 1234}')
764 json_format.Parse(text, message)
765
Jisi Liu46e8ff62015-10-05 11:59:43 -0700766
767if __name__ == '__main__':
768 unittest.main()