json_format_test.py 21 KB

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