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