summaryrefslogtreecommitdiff
path: root/simplejson/tests
diff options
context:
space:
mode:
authorNick Babcock <nbabcock19@hotmail.com>2015-07-10 17:25:50 -0400
committerNick Babcock <nbabcock19@hotmail.com>2015-07-10 17:25:50 -0400
commita9e5e7256c9fb27126813c9430be1dab5f27f7ba (patch)
tree488eb7357fd5e781395161b7aa6be5aabea6a8ed /simplejson/tests
parent49724ee06f038d27ab3d4adbe4ed403692799aa1 (diff)
parent0bcdf20cc525c1343b796cb8f247ea5213c6557e (diff)
downloadsimplejson-a9e5e7256c9fb27126813c9430be1dab5f27f7ba.tar.gz
Merge branch 'master' into iterable_as_array-gh1
Conflicts: CHANGES.txt conf.py index.rst setup.py simplejson/__init__.py simplejson/_speedups.c simplejson/encoder.py simplejson/tests/test_tuple.py
Diffstat (limited to 'simplejson/tests')
-rw-r--r--simplejson/tests/__init__.py83
-rw-r--r--simplejson/tests/test_bigint_as_string.py67
-rw-r--r--simplejson/tests/test_bitsize_int_as_string.py73
-rw-r--r--simplejson/tests/test_decimal.py48
-rw-r--r--simplejson/tests/test_decode.py24
-rw-r--r--simplejson/tests/test_default.py2
-rw-r--r--simplejson/tests/test_dump.py121
-rw-r--r--simplejson/tests/test_encode_basestring_ascii.py9
-rw-r--r--simplejson/tests/test_encode_for_html.py8
-rw-r--r--simplejson/tests/test_errors.py41
-rw-r--r--simplejson/tests/test_fail.py105
-rw-r--r--simplejson/tests/test_float.py34
-rw-r--r--simplejson/tests/test_for_json.py97
-rw-r--r--simplejson/tests/test_indent.py30
-rw-r--r--simplejson/tests/test_item_sort_key.py20
-rw-r--r--simplejson/tests/test_namedtuple.py61
-rw-r--r--simplejson/tests/test_pass1.py21
-rw-r--r--simplejson/tests/test_pass2.py2
-rw-r--r--simplejson/tests/test_pass3.py2
-rw-r--r--simplejson/tests/test_recursion.py2
-rw-r--r--simplejson/tests/test_scanstring.py133
-rw-r--r--simplejson/tests/test_separators.py6
-rw-r--r--simplejson/tests/test_speedups.py33
-rw-r--r--simplejson/tests/test_subclass.py37
-rw-r--r--simplejson/tests/test_tool.py97
-rw-r--r--simplejson/tests/test_tuple.py8
-rw-r--r--simplejson/tests/test_unicode.py102
27 files changed, 1060 insertions, 206 deletions
diff --git a/simplejson/tests/__init__.py b/simplejson/tests/__init__.py
index 8d2e443..8c1a4f1 100644
--- a/simplejson/tests/__init__.py
+++ b/simplejson/tests/__init__.py
@@ -1,18 +1,26 @@
+from __future__ import absolute_import
import unittest
import doctest
+import sys
-class OptionalExtensionTestSuite(unittest.TestSuite):
+class NoExtensionTestSuite(unittest.TestSuite):
def run(self, result):
import simplejson
- run = unittest.TestSuite.run
- run(self, result)
simplejson._toggle_speedups(False)
- run(self, result)
+ result = unittest.TestSuite.run(self, result)
simplejson._toggle_speedups(True)
return result
+class TestMissingSpeedups(unittest.TestCase):
+ def runTest(self):
+ if hasattr(sys, 'pypy_translation_info'):
+ "PyPy doesn't need speedups! :)"
+ elif hasattr(self, 'skipTest'):
+ self.skipTest('_speedups.so is missing!')
+
+
def additional_tests(suite=None):
import simplejson
import simplejson.encoder
@@ -26,35 +34,50 @@ def additional_tests(suite=None):
def all_tests_suite():
- suite = unittest.TestLoader().loadTestsFromNames([
- 'simplejson.tests.test_check_circular',
- 'simplejson.tests.test_decode',
- 'simplejson.tests.test_default',
- 'simplejson.tests.test_dump',
- 'simplejson.tests.test_encode_basestring_ascii',
- 'simplejson.tests.test_encode_for_html',
- 'simplejson.tests.test_errors',
- 'simplejson.tests.test_fail',
- 'simplejson.tests.test_float',
- 'simplejson.tests.test_indent',
- 'simplejson.tests.test_pass1',
- 'simplejson.tests.test_pass2',
- 'simplejson.tests.test_pass3',
- 'simplejson.tests.test_recursion',
- 'simplejson.tests.test_scanstring',
- 'simplejson.tests.test_separators',
- 'simplejson.tests.test_speedups',
- 'simplejson.tests.test_unicode',
- 'simplejson.tests.test_decimal',
- 'simplejson.tests.test_tuple',
- 'simplejson.tests.test_namedtuple',
- ])
- suite = additional_tests(suite)
- return OptionalExtensionTestSuite([suite])
+ def get_suite():
+ return additional_tests(
+ unittest.TestLoader().loadTestsFromNames([
+ 'simplejson.tests.test_bitsize_int_as_string',
+ 'simplejson.tests.test_bigint_as_string',
+ 'simplejson.tests.test_check_circular',
+ 'simplejson.tests.test_decode',
+ 'simplejson.tests.test_default',
+ 'simplejson.tests.test_dump',
+ 'simplejson.tests.test_encode_basestring_ascii',
+ 'simplejson.tests.test_encode_for_html',
+ 'simplejson.tests.test_errors',
+ 'simplejson.tests.test_fail',
+ 'simplejson.tests.test_float',
+ 'simplejson.tests.test_indent',
+ 'simplejson.tests.test_pass1',
+ 'simplejson.tests.test_pass2',
+ 'simplejson.tests.test_pass3',
+ 'simplejson.tests.test_recursion',
+ 'simplejson.tests.test_scanstring',
+ 'simplejson.tests.test_separators',
+ 'simplejson.tests.test_speedups',
+ 'simplejson.tests.test_unicode',
+ 'simplejson.tests.test_decimal',
+ 'simplejson.tests.test_tuple',
+ 'simplejson.tests.test_namedtuple',
+ 'simplejson.tests.test_tool',
+ 'simplejson.tests.test_for_json',
+ 'simplejson.tests.test_subclass',
+ ]))
+ suite = get_suite()
+ import simplejson
+ if simplejson._import_c_make_encoder() is None:
+ suite.addTest(TestMissingSpeedups())
+ else:
+ suite = unittest.TestSuite([
+ suite,
+ NoExtensionTestSuite([get_suite()]),
+ ])
+ return suite
def main():
- runner = unittest.TextTestRunner()
+ runner = unittest.TextTestRunner(verbosity=1 + sys.argv.count('-v'))
suite = all_tests_suite()
raise SystemExit(not runner.run(suite).wasSuccessful())
diff --git a/simplejson/tests/test_bigint_as_string.py b/simplejson/tests/test_bigint_as_string.py
new file mode 100644
index 0000000..2cf2cc2
--- /dev/null
+++ b/simplejson/tests/test_bigint_as_string.py
@@ -0,0 +1,67 @@
+from unittest import TestCase
+
+import simplejson as json
+
+
+class TestBigintAsString(TestCase):
+ # Python 2.5, at least the one that ships on Mac OS X, calculates
+ # 2 ** 53 as 0! It manages to calculate 1 << 53 correctly.
+ values = [(200, 200),
+ ((1 << 53) - 1, 9007199254740991),
+ ((1 << 53), '9007199254740992'),
+ ((1 << 53) + 1, '9007199254740993'),
+ (-100, -100),
+ ((-1 << 53), '-9007199254740992'),
+ ((-1 << 53) - 1, '-9007199254740993'),
+ ((-1 << 53) + 1, -9007199254740991)]
+
+ options = (
+ {"bigint_as_string": True},
+ {"int_as_string_bitcount": 53}
+ )
+
+ def test_ints(self):
+ for opts in self.options:
+ for val, expect in self.values:
+ self.assertEqual(
+ val,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, **opts)))
+
+ def test_lists(self):
+ for opts in self.options:
+ for val, expect in self.values:
+ val = [val, val]
+ expect = [expect, expect]
+ self.assertEqual(
+ val,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, **opts)))
+
+ def test_dicts(self):
+ for opts in self.options:
+ for val, expect in self.values:
+ val = {'k': val}
+ expect = {'k': expect}
+ self.assertEqual(
+ val,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, **opts)))
+
+ def test_dict_keys(self):
+ for opts in self.options:
+ for val, _ in self.values:
+ expect = {str(val): 'value'}
+ val = {val: 'value'}
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, **opts)))
diff --git a/simplejson/tests/test_bitsize_int_as_string.py b/simplejson/tests/test_bitsize_int_as_string.py
new file mode 100644
index 0000000..fd7d103
--- /dev/null
+++ b/simplejson/tests/test_bitsize_int_as_string.py
@@ -0,0 +1,73 @@
+from unittest import TestCase
+
+import simplejson as json
+
+
+class TestBitSizeIntAsString(TestCase):
+ # Python 2.5, at least the one that ships on Mac OS X, calculates
+ # 2 ** 31 as 0! It manages to calculate 1 << 31 correctly.
+ values = [
+ (200, 200),
+ ((1 << 31) - 1, (1 << 31) - 1),
+ ((1 << 31), str(1 << 31)),
+ ((1 << 31) + 1, str((1 << 31) + 1)),
+ (-100, -100),
+ ((-1 << 31), str(-1 << 31)),
+ ((-1 << 31) - 1, str((-1 << 31) - 1)),
+ ((-1 << 31) + 1, (-1 << 31) + 1),
+ ]
+
+ def test_invalid_counts(self):
+ for n in ['foo', -1, 0, 1.0]:
+ self.assertRaises(
+ TypeError,
+ json.dumps, 0, int_as_string_bitcount=n)
+
+ def test_ints_outside_range_fails(self):
+ self.assertNotEqual(
+ str(1 << 15),
+ json.loads(json.dumps(1 << 15, int_as_string_bitcount=16)),
+ )
+
+ def test_ints(self):
+ for val, expect in self.values:
+ self.assertEqual(
+ val,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, int_as_string_bitcount=31)),
+ )
+
+ def test_lists(self):
+ for val, expect in self.values:
+ val = [val, val]
+ expect = [expect, expect]
+ self.assertEqual(
+ val,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, int_as_string_bitcount=31)))
+
+ def test_dicts(self):
+ for val, expect in self.values:
+ val = {'k': val}
+ expect = {'k': expect}
+ self.assertEqual(
+ val,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, int_as_string_bitcount=31)))
+
+ def test_dict_keys(self):
+ for val, _ in self.values:
+ expect = {str(val): 'value'}
+ val = {val: 'value'}
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val)))
+ self.assertEqual(
+ expect,
+ json.loads(json.dumps(val, int_as_string_bitcount=31)))
diff --git a/simplejson/tests/test_decimal.py b/simplejson/tests/test_decimal.py
index 09f062e..2b0940b 100644
--- a/simplejson/tests/test_decimal.py
+++ b/simplejson/tests/test_decimal.py
@@ -1,6 +1,7 @@
+import decimal
from decimal import Decimal
from unittest import TestCase
-from StringIO import StringIO
+from simplejson.compat import StringIO, reload_module
import simplejson as json
@@ -10,35 +11,40 @@ class TestDecimal(TestCase):
sio = StringIO()
json.dump(obj, sio, **kw)
res = json.dumps(obj, **kw)
- self.assertEquals(res, sio.getvalue())
+ self.assertEqual(res, sio.getvalue())
return res
def loads(self, s, **kw):
sio = StringIO(s)
res = json.loads(s, **kw)
- self.assertEquals(res, json.load(sio, **kw))
+ self.assertEqual(res, json.load(sio, **kw))
return res
def test_decimal_encode(self):
for d in map(Decimal, self.NUMS):
- self.assertEquals(self.dumps(d, use_decimal=True), str(d))
-
+ self.assertEqual(self.dumps(d, use_decimal=True), str(d))
+
def test_decimal_decode(self):
for s in self.NUMS:
- self.assertEquals(self.loads(s, parse_float=Decimal), Decimal(s))
-
+ self.assertEqual(self.loads(s, parse_float=Decimal), Decimal(s))
+
+ def test_stringify_key(self):
+ for d in map(Decimal, self.NUMS):
+ v = {d: d}
+ self.assertEqual(
+ self.loads(
+ self.dumps(v, use_decimal=True), parse_float=Decimal),
+ {str(d): d})
+
def test_decimal_roundtrip(self):
for d in map(Decimal, self.NUMS):
# The type might not be the same (int and Decimal) but they
# should still compare equal.
- self.assertEquals(
- self.loads(
- self.dumps(d, use_decimal=True), parse_float=Decimal),
- d)
- self.assertEquals(
- self.loads(
- self.dumps([d], use_decimal=True), parse_float=Decimal),
- [d])
+ for v in [d, [d], {'': d}]:
+ self.assertEqual(
+ self.loads(
+ self.dumps(v, use_decimal=True), parse_float=Decimal),
+ v)
def test_decimal_defaults(self):
d = Decimal('1.1')
@@ -46,10 +52,20 @@ class TestDecimal(TestCase):
self.assertRaises(TypeError, json.dumps, d, use_decimal=False)
self.assertEqual('1.1', json.dumps(d))
self.assertEqual('1.1', json.dumps(d, use_decimal=True))
- self.assertRaises(TypeError, json.dump, d, StringIO(), use_decimal=False)
+ self.assertRaises(TypeError, json.dump, d, StringIO(),
+ use_decimal=False)
sio = StringIO()
json.dump(d, sio)
self.assertEqual('1.1', sio.getvalue())
sio = StringIO()
json.dump(d, sio, use_decimal=True)
self.assertEqual('1.1', sio.getvalue())
+
+ def test_decimal_reload(self):
+ # Simulate a subinterpreter that reloads the Python modules but not
+ # the C code https://github.com/simplejson/simplejson/issues/34
+ global Decimal
+ Decimal = reload_module(decimal).Decimal
+ import simplejson.encoder
+ simplejson.encoder.Decimal = Decimal
+ self.test_decimal_roundtrip()
diff --git a/simplejson/tests/test_decode.py b/simplejson/tests/test_decode.py
index a140a13..30b692a 100644
--- a/simplejson/tests/test_decode.py
+++ b/simplejson/tests/test_decode.py
@@ -1,8 +1,9 @@
+from __future__ import absolute_import
import decimal
from unittest import TestCase
-from StringIO import StringIO
import simplejson as json
+from simplejson.compat import StringIO
from simplejson import OrderedDict
class TestDecode(TestCase):
@@ -13,19 +14,19 @@ class TestDecode(TestCase):
def test_decimal(self):
rval = json.loads('1.1', parse_float=decimal.Decimal)
self.assertTrue(isinstance(rval, decimal.Decimal))
- self.assertEquals(rval, decimal.Decimal('1.1'))
+ self.assertEqual(rval, decimal.Decimal('1.1'))
def test_float(self):
rval = json.loads('1', parse_int=float)
self.assertTrue(isinstance(rval, float))
- self.assertEquals(rval, 1.0)
+ self.assertEqual(rval, 1.0)
def test_decoder_optimizations(self):
# Several optimizations were made that skip over calls to
# the whitespace regex, so this test is designed to try and
# exercise the uncommon cases. The array cases are already covered.
rval = json.loads('{ "key" : "value" , "k":"v" }')
- self.assertEquals(rval, {"key":"value", "k":"v"})
+ self.assertEqual(rval, {"key":"value", "k":"v"})
def test_empty_objects(self):
s = '{}'
@@ -81,3 +82,18 @@ class TestDecode(TestCase):
self.assertEqual(
({'a': {}}, 9),
cls(object_pairs_hook=dict).raw_decode("{\"a\": {}}"))
+ # https://github.com/simplejson/simplejson/pull/38
+ self.assertEqual(
+ ({'a': {}}, 11),
+ cls().raw_decode(" \n{\"a\": {}}"))
+
+ def test_bounds_checking(self):
+ # https://github.com/simplejson/simplejson/issues/98
+ j = json.decoder.JSONDecoder()
+ for i in [4, 5, 6, -1, -2, -3, -4, -5, -6]:
+ self.assertRaises(ValueError, j.scan_once, '1234', i)
+ self.assertRaises(ValueError, j.raw_decode, '1234', i)
+ x, y = sorted(['128931233', '472389423'], key=id)
+ diff = id(x) - id(y)
+ self.assertRaises(ValueError, j.scan_once, y, diff)
+ self.assertRaises(ValueError, j.raw_decode, y, i)
diff --git a/simplejson/tests/test_default.py b/simplejson/tests/test_default.py
index 139e42b..d1eacb8 100644
--- a/simplejson/tests/test_default.py
+++ b/simplejson/tests/test_default.py
@@ -4,6 +4,6 @@ import simplejson as json
class TestDefault(TestCase):
def test_default(self):
- self.assertEquals(
+ self.assertEqual(
json.dumps(type, default=repr),
json.dumps(repr(type)))
diff --git a/simplejson/tests/test_dump.py b/simplejson/tests/test_dump.py
index 8b34004..3661de0 100644
--- a/simplejson/tests/test_dump.py
+++ b/simplejson/tests/test_dump.py
@@ -1,27 +1,130 @@
from unittest import TestCase
-from cStringIO import StringIO
-
+from simplejson.compat import StringIO, long_type, b, binary_type, PY3
import simplejson as json
+def as_text_type(s):
+ if PY3 and isinstance(s, binary_type):
+ return s.decode('ascii')
+ return s
+
class TestDump(TestCase):
def test_dump(self):
sio = StringIO()
json.dump({}, sio)
- self.assertEquals(sio.getvalue(), '{}')
+ self.assertEqual(sio.getvalue(), '{}')
+
+ def test_constants(self):
+ for c in [None, True, False]:
+ self.assertTrue(json.loads(json.dumps(c)) is c)
+ self.assertTrue(json.loads(json.dumps([c]))[0] is c)
+ self.assertTrue(json.loads(json.dumps({'a': c}))['a'] is c)
+
+ def test_stringify_key(self):
+ items = [(b('bytes'), 'bytes'),
+ (1.0, '1.0'),
+ (10, '10'),
+ (True, 'true'),
+ (False, 'false'),
+ (None, 'null'),
+ (long_type(100), '100')]
+ for k, expect in items:
+ self.assertEqual(
+ json.loads(json.dumps({k: expect})),
+ {expect: expect})
+ self.assertEqual(
+ json.loads(json.dumps({k: expect}, sort_keys=True)),
+ {expect: expect})
+ self.assertRaises(TypeError, json.dumps, {json: 1})
+ for v in [{}, {'other': 1}, {b('derp'): 1, 'herp': 2}]:
+ for sort_keys in [False, True]:
+ v0 = dict(v)
+ v0[json] = 1
+ v1 = dict((as_text_type(key), val) for (key, val) in v.items())
+ self.assertEqual(
+ json.loads(json.dumps(v0, skipkeys=True, sort_keys=sort_keys)),
+ v1)
+ self.assertEqual(
+ json.loads(json.dumps({'': v0}, skipkeys=True, sort_keys=sort_keys)),
+ {'': v1})
+ self.assertEqual(
+ json.loads(json.dumps([v0], skipkeys=True, sort_keys=sort_keys)),
+ [v1])
def test_dumps(self):
- self.assertEquals(json.dumps({}), '{}')
+ self.assertEqual(json.dumps({}), '{}')
def test_encode_truefalse(self):
- self.assertEquals(json.dumps(
+ self.assertEqual(json.dumps(
{True: False, False: True}, sort_keys=True),
'{"false": true, "true": false}')
- self.assertEquals(json.dumps(
- {2: 3.0, 4.0: 5L, False: 1, 6L: True, "7": 0}, sort_keys=True),
- '{"false": 1, "2": 3.0, "4.0": 5, "6": true, "7": 0}')
+ self.assertEqual(
+ json.dumps(
+ {2: 3.0,
+ 4.0: long_type(5),
+ False: 1,
+ long_type(6): True,
+ "7": 0},
+ sort_keys=True),
+ '{"2": 3.0, "4.0": 5, "6": true, "7": 0, "false": 1}')
def test_ordered_dict(self):
# http://bugs.python.org/issue6105
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
s = json.dumps(json.OrderedDict(items))
- self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}') \ No newline at end of file
+ self.assertEqual(
+ s,
+ '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}')
+
+ def test_indent_unknown_type_acceptance(self):
+ """
+ A test against the regression mentioned at `github issue 29`_.
+
+ The indent parameter should accept any type which pretends to be
+ an instance of int or long when it comes to being multiplied by
+ strings, even if it is not actually an int or long, for
+ backwards compatibility.
+
+ .. _github issue 29:
+ http://github.com/simplejson/simplejson/issue/29
+ """
+
+ class AwesomeInt(object):
+ """An awesome reimplementation of integers"""
+
+ def __init__(self, *args, **kwargs):
+ if len(args) > 0:
+ # [construct from literals, objects, etc.]
+ # ...
+
+ # Finally, if args[0] is an integer, store it
+ if isinstance(args[0], int):
+ self._int = args[0]
+
+ # [various methods]
+
+ def __mul__(self, other):
+ # [various ways to multiply AwesomeInt objects]
+ # ... finally, if the right-hand operand is not awesome enough,
+ # try to do a normal integer multiplication
+ if hasattr(self, '_int'):
+ return self._int * other
+ else:
+ raise NotImplementedError("To do non-awesome things with"
+ " this object, please construct it from an integer!")
+
+ s = json.dumps([0, 1, 2], indent=AwesomeInt(3))
+ self.assertEqual(s, '[\n 0,\n 1,\n 2\n]')
+
+ def test_accumulator(self):
+ # the C API uses an accumulator that collects after 100,000 appends
+ lst = [0] * 100000
+ self.assertEqual(json.loads(json.dumps(lst)), lst)
+
+ def test_sort_keys(self):
+ # https://github.com/simplejson/simplejson/issues/106
+ for num_keys in range(2, 32):
+ p = dict((str(x), x) for x in range(num_keys))
+ sio = StringIO()
+ json.dump(p, sio, sort_keys=True)
+ self.assertEqual(sio.getvalue(), json.dumps(p, sort_keys=True))
+ self.assertEqual(json.loads(sio.getvalue()), p)
diff --git a/simplejson/tests/test_encode_basestring_ascii.py b/simplejson/tests/test_encode_basestring_ascii.py
index 6c40961..49706bf 100644
--- a/simplejson/tests/test_encode_basestring_ascii.py
+++ b/simplejson/tests/test_encode_basestring_ascii.py
@@ -1,6 +1,7 @@
from unittest import TestCase
import simplejson.encoder
+from simplejson.compat import b
CASES = [
(u'/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'),
@@ -11,9 +12,9 @@ CASES = [
(u' s p a c e d ', '" s p a c e d "'),
(u'\U0001d120', '"\\ud834\\udd20"'),
(u'\u03b1\u03a9', '"\\u03b1\\u03a9"'),
- ('\xce\xb1\xce\xa9', '"\\u03b1\\u03a9"'),
+ (b('\xce\xb1\xce\xa9'), '"\\u03b1\\u03a9"'),
(u'\u03b1\u03a9', '"\\u03b1\\u03a9"'),
- ('\xce\xb1\xce\xa9', '"\\u03b1\\u03a9"'),
+ (b('\xce\xb1\xce\xa9'), '"\\u03b1\\u03a9"'),
(u'\u03b1\u03a9', '"\\u03b1\\u03a9"'),
(u'\u03b1\u03a9', '"\\u03b1\\u03a9"'),
(u"`1~!@#$%^&*()_+-={':[,]}|;.</>?", '"`1~!@#$%^&*()_+-={\':[,]}|;.</>?"'),
@@ -34,10 +35,10 @@ class TestEncodeBaseStringAscii(TestCase):
fname = encode_basestring_ascii.__name__
for input_string, expect in CASES:
result = encode_basestring_ascii(input_string)
- #self.assertEquals(result, expect,
+ #self.assertEqual(result, expect,
# '{0!r} != {1!r} for {2}({3!r})'.format(
# result, expect, fname, input_string))
- self.assertEquals(result, expect,
+ self.assertEqual(result, expect,
'%r != %r for %s(%r)' % (result, expect, fname, input_string))
def test_sorted_dict(self):
diff --git a/simplejson/tests/test_encode_for_html.py b/simplejson/tests/test_encode_for_html.py
index c2d5f80..f995254 100644
--- a/simplejson/tests/test_encode_for_html.py
+++ b/simplejson/tests/test_encode_for_html.py
@@ -1,14 +1,12 @@
import unittest
-import simplejson.decoder
-import simplejson.encoder
-
+import simplejson as json
class TestEncodeForHTML(unittest.TestCase):
def setUp(self):
- self.decoder = simplejson.decoder.JSONDecoder()
- self.encoder = simplejson.encoder.JSONEncoderForHTML()
+ self.decoder = json.JSONDecoder()
+ self.encoder = json.JSONEncoderForHTML()
def test_basic_encode(self):
self.assertEqual(r'"\u0026"', self.encoder.encode('&'))
diff --git a/simplejson/tests/test_errors.py b/simplejson/tests/test_errors.py
index 620ccf3..8dede38 100644
--- a/simplejson/tests/test_errors.py
+++ b/simplejson/tests/test_errors.py
@@ -1,6 +1,8 @@
+import sys, pickle
from unittest import TestCase
import simplejson as json
+from simplejson.compat import u, b
class TestErrors(TestCase):
def test_string_keys_error(self):
@@ -11,24 +13,39 @@ class TestErrors(TestCase):
err = None
try:
json.loads('{}\na\nb')
- except json.JSONDecodeError, e:
- err = e
+ except json.JSONDecodeError:
+ err = sys.exc_info()[1]
else:
self.fail('Expected JSONDecodeError')
- self.assertEquals(err.lineno, 2)
- self.assertEquals(err.colno, 1)
- self.assertEquals(err.endlineno, 3)
- self.assertEquals(err.endcolno, 2)
+ self.assertEqual(err.lineno, 2)
+ self.assertEqual(err.colno, 1)
+ self.assertEqual(err.endlineno, 3)
+ self.assertEqual(err.endcolno, 2)
def test_scan_error(self):
err = None
- for t in (str, unicode):
+ for t in (u, b):
try:
json.loads(t('{"asdf": "'))
- except json.JSONDecodeError, e:
- err = e
+ except json.JSONDecodeError:
+ err = sys.exc_info()[1]
else:
self.fail('Expected JSONDecodeError')
- self.assertEquals(err.lineno, 1)
- self.assertEquals(err.colno, 9)
- \ No newline at end of file
+ self.assertEqual(err.lineno, 1)
+ self.assertEqual(err.colno, 10)
+
+ def test_error_is_pickable(self):
+ err = None
+ try:
+ json.loads('{}\na\nb')
+ except json.JSONDecodeError:
+ err = sys.exc_info()[1]
+ else:
+ self.fail('Expected JSONDecodeError')
+ s = pickle.dumps(err)
+ e = pickle.loads(s)
+
+ self.assertEqual(err.msg, e.msg)
+ self.assertEqual(err.doc, e.doc)
+ self.assertEqual(err.pos, e.pos)
+ self.assertEqual(err.end, e.end)
diff --git a/simplejson/tests/test_fail.py b/simplejson/tests/test_fail.py
index 646c0f4..788f3a5 100644
--- a/simplejson/tests/test_fail.py
+++ b/simplejson/tests/test_fail.py
@@ -1,15 +1,16 @@
+import sys
from unittest import TestCase
import simplejson as json
-# Fri Dec 30 18:57:26 2005
+# 2007-10-05
JSONDOCS = [
# http://json.org/JSON_checker/test/fail1.json
'"A JSON payload should be an object or array, not a string."',
# http://json.org/JSON_checker/test/fail2.json
'["Unclosed array"',
# http://json.org/JSON_checker/test/fail3.json
- '{unquoted_key: "keys must be quoted}',
+ '{unquoted_key: "keys must be quoted"}',
# http://json.org/JSON_checker/test/fail4.json
'["extra comma",]',
# http://json.org/JSON_checker/test/fail5.json
@@ -35,7 +36,7 @@ JSONDOCS = [
# http://json.org/JSON_checker/test/fail15.json
'["Illegal backslash escape: \\x15"]',
# http://json.org/JSON_checker/test/fail16.json
- '["Illegal backslash escape: \\\'"]',
+ '[\\naked]',
# http://json.org/JSON_checker/test/fail17.json
'["Illegal backslash escape: \\017"]',
# http://json.org/JSON_checker/test/fail18.json
@@ -52,8 +53,51 @@ JSONDOCS = [
'["Bad value", truth]',
# http://json.org/JSON_checker/test/fail24.json
"['single quote']",
+ # http://json.org/JSON_checker/test/fail25.json
+ '["\ttab\tcharacter\tin\tstring\t"]',
+ # http://json.org/JSON_checker/test/fail26.json
+ '["tab\\ character\\ in\\ string\\ "]',
+ # http://json.org/JSON_checker/test/fail27.json
+ '["line\nbreak"]',
+ # http://json.org/JSON_checker/test/fail28.json
+ '["line\\\nbreak"]',
+ # http://json.org/JSON_checker/test/fail29.json
+ '[0e]',
+ # http://json.org/JSON_checker/test/fail30.json
+ '[0e+]',
+ # http://json.org/JSON_checker/test/fail31.json
+ '[0e+-1]',
+ # http://json.org/JSON_checker/test/fail32.json
+ '{"Comma instead if closing brace": true,',
+ # http://json.org/JSON_checker/test/fail33.json
+ '["mismatch"}',
# http://code.google.com/p/simplejson/issues/detail?id=3
u'["A\u001FZ control characters in string"]',
+ # misc based on coverage
+ '{',
+ '{]',
+ '{"foo": "bar"]',
+ '{"foo": "bar"',
+ 'nul',
+ 'nulx',
+ '-',
+ '-x',
+ '-e',
+ '-e0',
+ '-Infinite',
+ '-Inf',
+ 'Infinit',
+ 'Infinite',
+ 'NaM',
+ 'NuN',
+ 'falsy',
+ 'fal',
+ 'trug',
+ 'tru',
+ '1e',
+ '1ex',
+ '1e-',
+ '1e-x',
]
SKIPS = {
@@ -73,7 +117,6 @@ class TestFail(TestCase):
except json.JSONDecodeError:
pass
else:
- #self.fail("Expected failure for fail{0}.json: {1!r}".format(idx, doc))
self.fail("Expected failure for fail%d.json: %r" % (idx, doc))
def test_array_decoder_issue46(self):
@@ -81,11 +124,53 @@ class TestFail(TestCase):
for doc in [u'[,]', '[,]']:
try:
json.loads(doc)
- except json.JSONDecodeError, e:
- self.assertEquals(e.pos, 1)
- self.assertEquals(e.lineno, 1)
- self.assertEquals(e.colno, 1)
- except Exception, e:
+ except json.JSONDecodeError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.pos, 1)
+ self.assertEqual(e.lineno, 1)
+ self.assertEqual(e.colno, 2)
+ except Exception:
+ e = sys.exc_info()[1]
+ self.fail("Unexpected exception raised %r %s" % (e, e))
+ else:
+ self.fail("Unexpected success parsing '[,]'")
+
+ def test_truncated_input(self):
+ test_cases = [
+ ('', 'Expecting value', 0),
+ ('[', "Expecting value or ']'", 1),
+ ('[42', "Expecting ',' delimiter", 3),
+ ('[42,', 'Expecting value', 4),
+ ('["', 'Unterminated string starting at', 1),
+ ('["spam', 'Unterminated string starting at', 1),
+ ('["spam"', "Expecting ',' delimiter", 7),
+ ('["spam",', 'Expecting value', 8),
+ ('{', 'Expecting property name enclosed in double quotes', 1),
+ ('{"', 'Unterminated string starting at', 1),
+ ('{"spam', 'Unterminated string starting at', 1),
+ ('{"spam"', "Expecting ':' delimiter", 7),
+ ('{"spam":', 'Expecting value', 8),
+ ('{"spam":42', "Expecting ',' delimiter", 10),
+ ('{"spam":42,', 'Expecting property name enclosed in double quotes',
+ 11),
+ ('"', 'Unterminated string starting at', 0),
+ ('"spam', 'Unterminated string starting at', 0),
+ ('[,', "Expecting value", 1),
+ ]
+ for data, msg, idx in test_cases:
+ try:
+ json.loads(data)
+ except json.JSONDecodeError:
+ e = sys.exc_info()[1]
+ self.assertEqual(
+ e.msg[:len(msg)],
+ msg,
+ "%r doesn't start with %r for %r" % (e.msg, msg, data))
+ self.assertEqual(
+ e.pos, idx,
+ "pos %r != %r for %r" % (e.pos, idx, data))
+ except Exception:
+ e = sys.exc_info()[1]
self.fail("Unexpected exception raised %r %s" % (e, e))
else:
- self.fail("Unexpected success parsing '[,]'") \ No newline at end of file
+ self.fail("Unexpected success parsing '%r'" % (data,))
diff --git a/simplejson/tests/test_float.py b/simplejson/tests/test_float.py
index 94502c6..e382ec2 100644
--- a/simplejson/tests/test_float.py
+++ b/simplejson/tests/test_float.py
@@ -1,19 +1,35 @@
import math
from unittest import TestCase
-
+from simplejson.compat import long_type, text_type
import simplejson as json
+from simplejson.decoder import NaN, PosInf, NegInf
class TestFloat(TestCase):
+ def test_degenerates_allow(self):
+ for inf in (PosInf, NegInf):
+ self.assertEqual(json.loads(json.dumps(inf)), inf)
+ # Python 2.5 doesn't have math.isnan
+ nan = json.loads(json.dumps(NaN))
+ self.assertTrue((0 + nan) != nan)
+
+ def test_degenerates_ignore(self):
+ for f in (PosInf, NegInf, NaN):
+ self.assertEqual(json.loads(json.dumps(f, ignore_nan=True)), None)
+
+ def test_degenerates_deny(self):
+ for f in (PosInf, NegInf, NaN):
+ self.assertRaises(ValueError, json.dumps, f, allow_nan=False)
+
def test_floats(self):
for num in [1617161771.7650001, math.pi, math.pi**100,
math.pi**-100, 3.1]:
- self.assertEquals(float(json.dumps(num)), num)
- self.assertEquals(json.loads(json.dumps(num)), num)
- self.assertEquals(json.loads(unicode(json.dumps(num))), num)
+ self.assertEqual(float(json.dumps(num)), num)
+ self.assertEqual(json.loads(json.dumps(num)), num)
+ self.assertEqual(json.loads(text_type(json.dumps(num))), num)
def test_ints(self):
- for num in [1, 1L, 1<<32, 1<<64]:
- self.assertEquals(json.dumps(num), str(num))
- self.assertEquals(int(json.dumps(num)), num)
- self.assertEquals(json.loads(json.dumps(num)), num)
- self.assertEquals(json.loads(unicode(json.dumps(num))), num)
+ for num in [1, long_type(1), 1<<32, 1<<64]:
+ self.assertEqual(json.dumps(num), str(num))
+ self.assertEqual(int(json.dumps(num)), num)
+ self.assertEqual(json.loads(json.dumps(num)), num)
+ self.assertEqual(json.loads(text_type(json.dumps(num))), num)
diff --git a/simplejson/tests/test_for_json.py b/simplejson/tests/test_for_json.py
new file mode 100644
index 0000000..b791b88
--- /dev/null
+++ b/simplejson/tests/test_for_json.py
@@ -0,0 +1,97 @@
+import unittest
+import simplejson as json
+
+
+class ForJson(object):
+ def for_json(self):
+ return {'for_json': 1}
+
+
+class NestedForJson(object):
+ def for_json(self):
+ return {'nested': ForJson()}
+
+
+class ForJsonList(object):
+ def for_json(self):
+ return ['list']
+
+
+class DictForJson(dict):
+ def for_json(self):
+ return {'alpha': 1}
+
+
+class ListForJson(list):
+ def for_json(self):
+ return ['list']
+
+
+class TestForJson(unittest.TestCase):
+ def assertRoundTrip(self, obj, other, for_json=True):
+ if for_json is None:
+ # None will use the default
+ s = json.dumps(obj)
+ else:
+ s = json.dumps(obj, for_json=for_json)
+ self.assertEqual(
+ json.loads(s),
+ other)
+
+ def test_for_json_encodes_stand_alone_object(self):
+ self.assertRoundTrip(
+ ForJson(),
+ ForJson().for_json())
+
+ def test_for_json_encodes_object_nested_in_dict(self):
+ self.assertRoundTrip(
+ {'hooray': ForJson()},
+ {'hooray': ForJson().for_json()})
+
+ def test_for_json_encodes_object_nested_in_list_within_dict(self):
+ self.assertRoundTrip(
+ {'list': [0, ForJson(), 2, 3]},
+ {'list': [0, ForJson().for_json(), 2, 3]})
+
+ def test_for_json_encodes_object_nested_within_object(self):
+ self.assertRoundTrip(
+ NestedForJson(),
+ {'nested': {'for_json': 1}})
+
+ def test_for_json_encodes_list(self):
+ self.assertRoundTrip(
+ ForJsonList(),
+ ForJsonList().for_json())
+
+ def test_for_json_encodes_list_within_object(self):
+ self.assertRoundTrip(
+ {'nested': ForJsonList()},
+ {'nested': ForJsonList().for_json()})
+
+ def test_for_json_encodes_dict_subclass(self):
+ self.assertRoundTrip(
+ DictForJson(a=1),
+ DictForJson(a=1).for_json())
+
+ def test_for_json_encodes_list_subclass(self):
+ self.assertRoundTrip(
+ ListForJson(['l']),
+ ListForJson(['l']).for_json())
+
+ def test_for_json_ignored_if_not_true_with_dict_subclass(self):
+ for for_json in (None, False):
+ self.assertRoundTrip(
+ DictForJson(a=1),
+ {'a': 1},
+ for_json=for_json)
+
+ def test_for_json_ignored_if_not_true_with_list_subclass(self):
+ for for_json in (None, False):
+ self.assertRoundTrip(
+ ListForJson(['l']),
+ ['l'],
+ for_json=for_json)
+
+ def test_raises_typeerror_if_for_json_not_true_with_object(self):
+ self.assertRaises(TypeError, json.dumps, ForJson())
+ self.assertRaises(TypeError, json.dumps, ForJson(), for_json=False)
diff --git a/simplejson/tests/test_indent.py b/simplejson/tests/test_indent.py
index 1e6bdb1..cea25a5 100644
--- a/simplejson/tests/test_indent.py
+++ b/simplejson/tests/test_indent.py
@@ -1,8 +1,8 @@
from unittest import TestCase
+import textwrap
import simplejson as json
-import textwrap
-from StringIO import StringIO
+from simplejson.compat import StringIO
class TestIndent(TestCase):
def test_indent(self):
@@ -42,26 +42,26 @@ class TestIndent(TestCase):
h3 = json.loads(d3)
h4 = json.loads(d4)
- self.assertEquals(h1, h)
- self.assertEquals(h2, h)
- self.assertEquals(h3, h)
- self.assertEquals(h4, h)
- self.assertEquals(d3, expect.replace('\t', ' '))
- self.assertEquals(d4, expect.replace('\t', ' '))
+ self.assertEqual(h1, h)
+ self.assertEqual(h2, h)
+ self.assertEqual(h3, h)
+ self.assertEqual(h4, h)
+ self.assertEqual(d3, expect.replace('\t', ' '))
+ self.assertEqual(d4, expect.replace('\t', ' '))
# NOTE: Python 2.4 textwrap.dedent converts tabs to spaces,
# so the following is expected to fail. Python 2.4 is not a
# supported platform in simplejson 2.1.0+.
- self.assertEquals(d2, expect)
+ self.assertEqual(d2, expect)
def test_indent0(self):
h = {3: 1}
def check(indent, expected):
d1 = json.dumps(h, indent=indent)
- self.assertEquals(d1, expected)
+ self.assertEqual(d1, expected)
sio = StringIO()
json.dump(h, sio, indent=indent)
- self.assertEquals(sio.getvalue(), expected)
+ self.assertEqual(sio.getvalue(), expected)
# indent=0 should emit newlines
check(0, '{\n"3": 1\n}')
@@ -73,14 +73,14 @@ class TestIndent(TestCase):
expect = '[\n1,\n2,\n3,\n4\n]'
expect_spaces = '[\n1, \n2, \n3, \n4\n]'
# Ensure that separators still works
- self.assertEquals(
+ self.assertEqual(
expect_spaces,
json.dumps(lst, indent=0, separators=(', ', ': ')))
# Force the new defaults
- self.assertEquals(
+ self.assertEqual(
expect,
json.dumps(lst, indent=0, separators=(',', ': ')))
# Added in 2.1.4
- self.assertEquals(
+ self.assertEqual(
expect,
- json.dumps(lst, indent=0)) \ No newline at end of file
+ json.dumps(lst, indent=0))
diff --git a/simplejson/tests/test_item_sort_key.py b/simplejson/tests/test_item_sort_key.py
new file mode 100644
index 0000000..b05bfc8
--- /dev/null
+++ b/simplejson/tests/test_item_sort_key.py
@@ -0,0 +1,20 @@
+from unittest import TestCase
+
+import simplejson as json
+from operator import itemgetter
+
+class TestItemSortKey(TestCase):
+ def test_simple_first(self):
+ a = {'a': 1, 'c': 5, 'jack': 'jill', 'pick': 'axe', 'array': [1, 5, 6, 9], 'tuple': (83, 12, 3), 'crate': 'dog', 'zeak': 'oh'}
+ self.assertEqual(
+ '{"a": 1, "c": 5, "crate": "dog", "jack": "jill", "pick": "axe", "zeak": "oh", "array": [1, 5, 6, 9], "tuple": [83, 12, 3]}',
+ json.dumps(a, item_sort_key=json.simple_first))
+
+ def test_case(self):
+ a = {'a': 1, 'c': 5, 'Jack': 'jill', 'pick': 'axe', 'Array': [1, 5, 6, 9], 'tuple': (83, 12, 3), 'crate': 'dog', 'zeak': 'oh'}
+ self.assertEqual(
+ '{"Array": [1, 5, 6, 9], "Jack": "jill", "a": 1, "c": 5, "crate": "dog", "pick": "axe", "tuple": [83, 12, 3], "zeak": "oh"}',
+ json.dumps(a, item_sort_key=itemgetter(0)))
+ self.assertEqual(
+ '{"a": 1, "Array": [1, 5, 6, 9], "c": 5, "crate": "dog", "Jack": "jill", "pick": "axe", "tuple": [83, 12, 3], "zeak": "oh"}',
+ json.dumps(a, item_sort_key=lambda kv: kv[0].lower()))
diff --git a/simplejson/tests/test_namedtuple.py b/simplejson/tests/test_namedtuple.py
index 18da218..4387894 100644
--- a/simplejson/tests/test_namedtuple.py
+++ b/simplejson/tests/test_namedtuple.py
@@ -1,6 +1,7 @@
+from __future__ import absolute_import
import unittest
import simplejson as json
-from StringIO import StringIO
+from simplejson.compat import StringIO
try:
from collections import namedtuple
@@ -21,11 +22,36 @@ else:
Value = namedtuple('Value', ['value'])
Point = namedtuple('Point', ['x', 'y'])
+class DuckValue(object):
+ def __init__(self, *args):
+ self.value = Value(*args)
+
+ def _asdict(self):
+ return self.value._asdict()
+
+class DuckPoint(object):
+ def __init__(self, *args):
+ self.point = Point(*args)
+
+ def _asdict(self):
+ return self.point._asdict()
+
+class DeadDuck(object):
+ _asdict = None
+
+class DeadDict(dict):
+ _asdict = None
+
+CONSTRUCTORS = [
+ lambda v: v,
+ lambda v: [v],
+ lambda v: [{'key': v}],
+]
+
class TestNamedTuple(unittest.TestCase):
def test_namedtuple_dumps(self):
- for v in [Value(1), Point(1, 2)]:
+ for v in [Value(1), Point(1, 2), DuckValue(1), DuckPoint(1, 2)]:
d = v._asdict()
- l = list(v)
self.assertEqual(d, json.loads(json.dumps(v)))
self.assertEqual(
d,
@@ -35,6 +61,10 @@ class TestNamedTuple(unittest.TestCase):
d,
json.loads(json.dumps(v, namedtuple_as_object=True,
tuple_as_array=False)))
+
+ def test_namedtuple_dumps_false(self):
+ for v in [Value(1), Point(1, 2)]:
+ l = list(v)
self.assertEqual(
l,
json.loads(json.dumps(v, namedtuple_as_object=False)))
@@ -42,9 +72,8 @@ class TestNamedTuple(unittest.TestCase):
tuple_as_array=False, namedtuple_as_object=False)
def test_namedtuple_dump(self):
- for v in [Value(1), Point(1, 2)]:
+ for v in [Value(1), Point(1, 2), DuckValue(1), DuckPoint(1, 2)]:
d = v._asdict()
- l = list(v)
sio = StringIO()
json.dump(v, sio)
self.assertEqual(d, json.loads(sio.getvalue()))
@@ -62,6 +91,10 @@ class TestNamedTuple(unittest.TestCase):
self.assertEqual(
d,
json.loads(sio.getvalue()))
+
+ def test_namedtuple_dump_false(self):
+ for v in [Value(1), Point(1, 2)]:
+ l = list(v)
sio = StringIO()
json.dump(v, sio, namedtuple_as_object=False)
self.assertEqual(
@@ -69,3 +102,21 @@ class TestNamedTuple(unittest.TestCase):
json.loads(sio.getvalue()))
self.assertRaises(TypeError, json.dump, v, StringIO(),
tuple_as_array=False, namedtuple_as_object=False)
+
+ def test_asdict_not_callable_dump(self):
+ for f in CONSTRUCTORS:
+ self.assertRaises(TypeError,
+ json.dump, f(DeadDuck()), StringIO(), namedtuple_as_object=True)
+ sio = StringIO()
+ json.dump(f(DeadDict()), sio, namedtuple_as_object=True)
+ self.assertEqual(
+ json.dumps(f({})),
+ sio.getvalue())
+
+ def test_asdict_not_callable_dumps(self):
+ for f in CONSTRUCTORS:
+ self.assertRaises(TypeError,
+ json.dumps, f(DeadDuck()), namedtuple_as_object=True)
+ self.assertEqual(
+ json.dumps(f({})),
+ json.dumps(f(DeadDict()), namedtuple_as_object=True))
diff --git a/simplejson/tests/test_pass1.py b/simplejson/tests/test_pass1.py
index c3d6302..f0b5b10 100644
--- a/simplejson/tests/test_pass1.py
+++ b/simplejson/tests/test_pass1.py
@@ -18,7 +18,7 @@ JSON = r'''
"real": -9876.543210,
"e": 0.123456789e-12,
"E": 1.234567890E+34,
- "": 23456789012E666,
+ "": 23456789012E66,
"zero": 0,
"one": 1,
"space": " ",
@@ -44,8 +44,7 @@ JSON = r'''
,
-4 , 5 , 6 ,7 ],
- "compact": [1,2,3,4,5,6,7],
+4 , 5 , 6 ,7 ],"compact": [1,2,3,4,5,6,7],
"jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
"quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
"\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
@@ -56,9 +55,11 @@ JSON = r'''
99.44
,
-1066
-
-
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
,"rosebud"]
'''
@@ -67,10 +68,4 @@ class TestPass1(TestCase):
# test in/out equivalence and parsing
res = json.loads(JSON)
out = json.dumps(res)
- self.assertEquals(res, json.loads(out))
- try:
- json.dumps(res, allow_nan=False)
- except ValueError:
- pass
- else:
- self.fail("23456789012E666 should be out of range")
+ self.assertEqual(res, json.loads(out))
diff --git a/simplejson/tests/test_pass2.py b/simplejson/tests/test_pass2.py
index de4ee00..5d812b3 100644
--- a/simplejson/tests/test_pass2.py
+++ b/simplejson/tests/test_pass2.py
@@ -11,4 +11,4 @@ class TestPass2(TestCase):
# test in/out equivalence and parsing
res = json.loads(JSON)
out = json.dumps(res)
- self.assertEquals(res, json.loads(out))
+ self.assertEqual(res, json.loads(out))
diff --git a/simplejson/tests/test_pass3.py b/simplejson/tests/test_pass3.py
index f591aba..821d60b 100644
--- a/simplejson/tests/test_pass3.py
+++ b/simplejson/tests/test_pass3.py
@@ -17,4 +17,4 @@ class TestPass3(TestCase):
# test in/out equivalence and parsing
res = json.loads(JSON)
out = json.dumps(res)
- self.assertEquals(res, json.loads(out))
+ self.assertEqual(res, json.loads(out))
diff --git a/simplejson/tests/test_recursion.py b/simplejson/tests/test_recursion.py
index 83a1d88..662eb66 100644
--- a/simplejson/tests/test_recursion.py
+++ b/simplejson/tests/test_recursion.py
@@ -57,7 +57,7 @@ class TestRecursion(TestCase):
def test_defaultrecursion(self):
enc = RecursiveJSONEncoder()
- self.assertEquals(enc.encode(JSONTestObject), '"JSONTestObject"')
+ self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"')
enc.recurse = True
try:
enc.encode(JSONTestObject)
diff --git a/simplejson/tests/test_scanstring.py b/simplejson/tests/test_scanstring.py
index a7fcd46..3d98f0d 100644
--- a/simplejson/tests/test_scanstring.py
+++ b/simplejson/tests/test_scanstring.py
@@ -3,8 +3,17 @@ from unittest import TestCase
import simplejson as json
import simplejson.decoder
+from simplejson.compat import b, PY3
class TestScanString(TestCase):
+ # The bytes type is intentionally not used in most of these tests
+ # under Python 3 because the decoder immediately coerces to str before
+ # calling scanstring. In Python 2 we are testing the code paths
+ # for both unicode and str.
+ #
+ # The reason this is done is because Python 3 would require
+ # entirely different code paths for parsing bytes and str.
+ #
def test_py_scanstring(self):
self._test_scanstring(simplejson.decoder.py_scanstring)
@@ -14,104 +23,172 @@ class TestScanString(TestCase):
self._test_scanstring(simplejson.decoder.c_scanstring)
def _test_scanstring(self, scanstring):
- self.assertEquals(
- scanstring('"z\\ud834\\udd20x"', 1, None, True),
- (u'z\U0001d120x', 16))
-
if sys.maxunicode == 65535:
- self.assertEquals(
+ self.assertEqual(
scanstring(u'"z\U0001d120x"', 1, None, True),
(u'z\U0001d120x', 6))
else:
- self.assertEquals(
+ self.assertEqual(
scanstring(u'"z\U0001d120x"', 1, None, True),
(u'z\U0001d120x', 5))
- self.assertEquals(
+ self.assertEqual(
scanstring('"\\u007b"', 1, None, True),
(u'{', 8))
- self.assertEquals(
+ self.assertEqual(
scanstring('"A JSON payload should be an object or array, not a string."', 1, None, True),
(u'A JSON payload should be an object or array, not a string.', 60))
- self.assertEquals(
+ self.assertEqual(
scanstring('["Unclosed array"', 2, None, True),
(u'Unclosed array', 17))
- self.assertEquals(
+ self.assertEqual(
scanstring('["extra comma",]', 2, None, True),
(u'extra comma', 14))
- self.assertEquals(
+ self.assertEqual(
scanstring('["double extra comma",,]', 2, None, True),
(u'double extra comma', 21))
- self.assertEquals(
+ self.assertEqual(
scanstring('["Comma after the close"],', 2, None, True),
(u'Comma after the close', 24))
- self.assertEquals(
+ self.assertEqual(
scanstring('["Extra close"]]', 2, None, True),
(u'Extra close', 14))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Extra comma": true,}', 2, None, True),
(u'Extra comma', 14))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Extra value after close": true} "misplaced quoted value"', 2, None, True),
(u'Extra value after close', 26))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Illegal expression": 1 + 2}', 2, None, True),
(u'Illegal expression', 21))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Illegal invocation": alert()}', 2, None, True),
(u'Illegal invocation', 21))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Numbers cannot have leading zeroes": 013}', 2, None, True),
(u'Numbers cannot have leading zeroes', 37))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Numbers cannot be hex": 0x14}', 2, None, True),
(u'Numbers cannot be hex', 24))
- self.assertEquals(
+ self.assertEqual(
scanstring('[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', 21, None, True),
(u'Too deep', 30))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Missing colon" null}', 2, None, True),
(u'Missing colon', 16))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Double colon":: null}', 2, None, True),
(u'Double colon', 15))
- self.assertEquals(
+ self.assertEqual(
scanstring('{"Comma instead of colon", null}', 2, None, True),
(u'Comma instead of colon', 25))
- self.assertEquals(
+ self.assertEqual(
scanstring('["Colon instead of comma": false]', 2, None, True),
(u'Colon instead of comma', 25))
- self.assertEquals(
+ self.assertEqual(
scanstring('["Bad value", truth]', 2, None, True),
(u'Bad value', 12))
+ for c in map(chr, range(0x00, 0x1f)):
+ self.assertEqual(
+ scanstring(c + '"', 0, None, False),
+ (c, 2))
+ self.assertRaises(
+ ValueError,
+ scanstring, c + '"', 0, None, True)
+
+ self.assertRaises(ValueError, scanstring, '', 0, None, True)
+ self.assertRaises(ValueError, scanstring, 'a', 0, None, True)
+ self.assertRaises(ValueError, scanstring, '\\', 0, None, True)
+ self.assertRaises(ValueError, scanstring, '\\u', 0, None, True)
+ self.assertRaises(ValueError, scanstring, '\\u0', 0, None, True)
+ self.assertRaises(ValueError, scanstring, '\\u01', 0, None, True)
+ self.assertRaises(ValueError, scanstring, '\\u012', 0, None, True)
+ self.assertRaises(ValueError, scanstring, '\\u0123', 0, None, True)
+ if sys.maxunicode > 65535:
+ self.assertRaises(ValueError,
+ scanstring, '\\ud834\\u"', 0, None, True)
+ self.assertRaises(ValueError,
+ scanstring, '\\ud834\\x0123"', 0, None, True)
+
def test_issue3623(self):
self.assertRaises(ValueError, json.decoder.scanstring, "xxx", 1,
"xxx")
self.assertRaises(UnicodeDecodeError,
- json.encoder.encode_basestring_ascii, "xx\xff")
+ json.encoder.encode_basestring_ascii, b("xx\xff"))
def test_overflow(self):
- # Python 2.5 does not have maxsize
- maxsize = getattr(sys, 'maxsize', sys.maxint)
+ # Python 2.5 does not have maxsize, Python 3 does not have maxint
+ maxsize = getattr(sys, 'maxsize', getattr(sys, 'maxint', None))
+ assert maxsize is not None
self.assertRaises(OverflowError, json.decoder.scanstring, "xxx",
maxsize + 1)
+ def test_surrogates(self):
+ scanstring = json.decoder.scanstring
+
+ def assertScan(given, expect, test_utf8=True):
+ givens = [given]
+ if not PY3 and test_utf8:
+ givens.append(given.encode('utf8'))
+ for given in givens:
+ (res, count) = scanstring(given, 1, None, True)
+ self.assertEqual(len(given), count)
+ self.assertEqual(res, expect)
+
+ assertScan(
+ u'"z\\ud834\\u0079x"',
+ u'z\ud834yx')
+ assertScan(
+ u'"z\\ud834\\udd20x"',
+ u'z\U0001d120x')
+ assertScan(
+ u'"z\\ud834\\ud834\\udd20x"',
+ u'z\ud834\U0001d120x')
+ assertScan(
+ u'"z\\ud834x"',
+ u'z\ud834x')
+ assertScan(
+ u'"z\\udd20x"',
+ u'z\udd20x')
+ assertScan(
+ u'"z\ud834x"',
+ u'z\ud834x')
+ # It may look strange to join strings together, but Python is drunk.
+ # https://gist.github.com/etrepum/5538443
+ assertScan(
+ u'"z\\ud834\udd20x12345"',
+ u''.join([u'z\ud834', u'\udd20x12345']))
+ assertScan(
+ u'"z\ud834\\udd20x"',
+ u''.join([u'z\ud834', u'\udd20x']))
+ # these have different behavior given UTF8 input, because the surrogate
+ # pair may be joined (in maxunicode > 65535 builds)
+ assertScan(
+ u''.join([u'"z\ud834', u'\udd20x"']),
+ u''.join([u'z\ud834', u'\udd20x']),
+ test_utf8=False)
+
+ self.assertRaises(ValueError,
+ scanstring, u'"z\\ud83x"', 1, None, True)
+ self.assertRaises(ValueError,
+ scanstring, u'"z\\ud834\\udd2x"', 1, None, True)
diff --git a/simplejson/tests/test_separators.py b/simplejson/tests/test_separators.py
index cbda93c..91b4d4f 100644
--- a/simplejson/tests/test_separators.py
+++ b/simplejson/tests/test_separators.py
@@ -37,6 +37,6 @@ class TestSeparators(TestCase):
h1 = json.loads(d1)
h2 = json.loads(d2)
- self.assertEquals(h1, h)
- self.assertEquals(h2, h)
- self.assertEquals(d2, expect)
+ self.assertEqual(h1, h)
+ self.assertEqual(h2, h)
+ self.assertEqual(d2, expect)
diff --git a/simplejson/tests/test_speedups.py b/simplejson/tests/test_speedups.py
index 825ecf2..0a2b63b 100644
--- a/simplejson/tests/test_speedups.py
+++ b/simplejson/tests/test_speedups.py
@@ -1,20 +1,39 @@
+import sys
+import unittest
from unittest import TestCase
from simplejson import encoder, scanner
+
def has_speedups():
return encoder.c_make_encoder is not None
+
+def skip_if_speedups_missing(func):
+ def wrapper(*args, **kwargs):
+ if not has_speedups():
+ if hasattr(unittest, 'SkipTest'):
+ raise unittest.SkipTest("C Extension not available")
+ else:
+ sys.stdout.write("C Extension not available")
+ return
+ return func(*args, **kwargs)
+
+ return wrapper
+
+
class TestDecode(TestCase):
+ @skip_if_speedups_missing
def test_make_scanner(self):
- if not has_speedups():
- return
self.assertRaises(AttributeError, scanner.c_make_scanner, 1)
+ @skip_if_speedups_missing
def test_make_encoder(self):
- if not has_speedups():
- return
- self.assertRaises(TypeError, encoder.c_make_encoder,
+ self.assertRaises(
+ TypeError,
+ encoder.c_make_encoder,
None,
- "\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75",
- None)
+ ("\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7"
+ "\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75"),
+ None
+ )
diff --git a/simplejson/tests/test_subclass.py b/simplejson/tests/test_subclass.py
new file mode 100644
index 0000000..2bae3b6
--- /dev/null
+++ b/simplejson/tests/test_subclass.py
@@ -0,0 +1,37 @@
+from unittest import TestCase
+import simplejson as json
+
+from decimal import Decimal
+
+class AlternateInt(int):
+ def __repr__(self):
+ return 'invalid json'
+ __str__ = __repr__
+
+
+class AlternateFloat(float):
+ def __repr__(self):
+ return 'invalid json'
+ __str__ = __repr__
+
+
+# class AlternateDecimal(Decimal):
+# def __repr__(self):
+# return 'invalid json'
+
+
+class TestSubclass(TestCase):
+ def test_int(self):
+ self.assertEqual(json.dumps(AlternateInt(1)), '1')
+ self.assertEqual(json.dumps(AlternateInt(-1)), '-1')
+ self.assertEqual(json.loads(json.dumps({AlternateInt(1): 1})), {'1': 1})
+
+ def test_float(self):
+ self.assertEqual(json.dumps(AlternateFloat(1.0)), '1.0')
+ self.assertEqual(json.dumps(AlternateFloat(-1.0)), '-1.0')
+ self.assertEqual(json.loads(json.dumps({AlternateFloat(1.0): 1})), {'1.0': 1})
+
+ # NOTE: Decimal subclasses are not supported as-is
+ # def test_decimal(self):
+ # self.assertEqual(json.dumps(AlternateDecimal('1.0')), '1.0')
+ # self.assertEqual(json.dumps(AlternateDecimal('-1.0')), '-1.0')
diff --git a/simplejson/tests/test_tool.py b/simplejson/tests/test_tool.py
new file mode 100644
index 0000000..ac2a14c
--- /dev/null
+++ b/simplejson/tests/test_tool.py
@@ -0,0 +1,97 @@
+from __future__ import with_statement
+import os
+import sys
+import textwrap
+import unittest
+import subprocess
+import tempfile
+try:
+ # Python 3.x
+ from test.support import strip_python_stderr
+except ImportError:
+ # Python 2.6+
+ try:
+ from test.test_support import strip_python_stderr
+ except ImportError:
+ # Python 2.5
+ import re
+ def strip_python_stderr(stderr):
+ return re.sub(
+ r"\[\d+ refs\]\r?\n?$".encode(),
+ "".encode(),
+ stderr).strip()
+
+class TestTool(unittest.TestCase):
+ data = """
+
+ [["blorpie"],[ "whoops" ] , [
+ ],\t"d-shtaeou",\r"d-nthiouh",
+ "i-vhbjkhnth", {"nifty":87}, {"morefield" :\tfalse,"field"
+ :"yes"} ]
+ """
+
+ expect = textwrap.dedent("""\
+ [
+ [
+ "blorpie"
+ ],
+ [
+ "whoops"
+ ],
+ [],
+ "d-shtaeou",
+ "d-nthiouh",
+ "i-vhbjkhnth",
+ {
+ "nifty": 87
+ },
+ {
+ "field": "yes",
+ "morefield": false
+ }
+ ]
+ """)
+
+ def runTool(self, args=None, data=None):
+ argv = [sys.executable, '-m', 'simplejson.tool']
+ if args:
+ argv.extend(args)
+ proc = subprocess.Popen(argv,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ out, err = proc.communicate(data)
+ self.assertEqual(strip_python_stderr(err), ''.encode())
+ self.assertEqual(proc.returncode, 0)
+ return out
+
+ def test_stdin_stdout(self):
+ self.assertEqual(
+ self.runTool(data=self.data.encode()),
+ self.expect.encode())
+
+ def test_infile_stdout(self):
+ with tempfile.NamedTemporaryFile() as infile:
+ infile.write(self.data.encode())
+ infile.flush()
+ self.assertEqual(
+ self.runTool(args=[infile.name]),
+ self.expect.encode())
+
+ def test_infile_outfile(self):
+ with tempfile.NamedTemporaryFile() as infile:
+ infile.write(self.data.encode())
+ infile.flush()
+ # outfile will get overwritten by tool, so the delete
+ # may not work on some platforms. Do it manually.
+ outfile = tempfile.NamedTemporaryFile()
+ try:
+ self.assertEqual(
+ self.runTool(args=[infile.name, outfile.name]),
+ ''.encode())
+ with open(outfile.name, 'rb') as f:
+ self.assertEqual(f.read(), self.expect.encode())
+ finally:
+ outfile.close()
+ if os.path.exists(outfile.name):
+ os.unlink(outfile.name)
diff --git a/simplejson/tests/test_tuple.py b/simplejson/tests/test_tuple.py
index cff9a75..4ad7b0e 100644
--- a/simplejson/tests/test_tuple.py
+++ b/simplejson/tests/test_tuple.py
@@ -1,6 +1,6 @@
import unittest
-from StringIO import StringIO
+from simplejson.compat import StringIO
import simplejson as json
class TestTuples(unittest.TestCase):
@@ -13,7 +13,8 @@ class TestTuples(unittest.TestCase):
self.assertRaises(TypeError, json.dumps, t, tuple_as_array=False)
# Ensure that the "default" does not get called
self.assertEqual(expect, json.dumps(t, default=repr))
- self.assertEqual(expect, json.dumps(t, tuple_as_array=True, default=repr))
+ self.assertEqual(expect, json.dumps(t, tuple_as_array=True,
+ default=repr))
# Ensure that the "default" gets called
self.assertEqual(
json.dumps(repr(t)),
@@ -29,7 +30,8 @@ class TestTuples(unittest.TestCase):
sio = StringIO()
json.dump(t, sio, tuple_as_array=True)
self.assertEqual(expect, sio.getvalue())
- self.assertRaises(TypeError, json.dump, t, StringIO(), tuple_as_array=False)
+ self.assertRaises(TypeError, json.dump, t, StringIO(),
+ tuple_as_array=False)
# Ensure that the "default" does not get called
sio = StringIO()
json.dump(t, sio, default=repr)
diff --git a/simplejson/tests/test_unicode.py b/simplejson/tests/test_unicode.py
index 83fe65b..3b37f65 100644
--- a/simplejson/tests/test_unicode.py
+++ b/simplejson/tests/test_unicode.py
@@ -1,6 +1,9 @@
+import sys
+import codecs
from unittest import TestCase
import simplejson as json
+from simplejson.compat import unichr, text_type, b, u, BytesIO
class TestUnicode(TestCase):
def test_encoding1(self):
@@ -9,51 +12,51 @@ class TestUnicode(TestCase):
s = u.encode('utf-8')
ju = encoder.encode(u)
js = encoder.encode(s)
- self.assertEquals(ju, js)
+ self.assertEqual(ju, js)
def test_encoding2(self):
u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
s = u.encode('utf-8')
ju = json.dumps(u, encoding='utf-8')
js = json.dumps(s, encoding='utf-8')
- self.assertEquals(ju, js)
+ self.assertEqual(ju, js)
def test_encoding3(self):
u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
j = json.dumps(u)
- self.assertEquals(j, '"\\u03b1\\u03a9"')
+ self.assertEqual(j, '"\\u03b1\\u03a9"')
def test_encoding4(self):
u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
j = json.dumps([u])
- self.assertEquals(j, '["\\u03b1\\u03a9"]')
+ self.assertEqual(j, '["\\u03b1\\u03a9"]')
def test_encoding5(self):
u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
j = json.dumps(u, ensure_ascii=False)
- self.assertEquals(j, u'"' + u + u'"')
+ self.assertEqual(j, u'"' + u + u'"')
def test_encoding6(self):
u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
j = json.dumps([u], ensure_ascii=False)
- self.assertEquals(j, u'["' + u + u'"]')
+ self.assertEqual(j, u'["' + u + u'"]')
def test_big_unicode_encode(self):
u = u'\U0001d120'
- self.assertEquals(json.dumps(u), '"\\ud834\\udd20"')
- self.assertEquals(json.dumps(u, ensure_ascii=False), u'"\U0001d120"')
+ self.assertEqual(json.dumps(u), '"\\ud834\\udd20"')
+ self.assertEqual(json.dumps(u, ensure_ascii=False), u'"\U0001d120"')
def test_big_unicode_decode(self):
u = u'z\U0001d120x'
- self.assertEquals(json.loads('"' + u + '"'), u)
- self.assertEquals(json.loads('"z\\ud834\\udd20x"'), u)
+ self.assertEqual(json.loads('"' + u + '"'), u)
+ self.assertEqual(json.loads('"z\\ud834\\udd20x"'), u)
def test_unicode_decode(self):
for i in range(0, 0xd7ff):
u = unichr(i)
#s = '"\\u{0:04x}"'.format(i)
s = '"\\u%04x"' % (i,)
- self.assertEquals(json.loads(s), u)
+ self.assertEqual(json.loads(s), u)
def test_object_pairs_hook_with_unicode(self):
s = u'{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}'
@@ -72,38 +75,79 @@ class TestUnicode(TestCase):
def test_default_encoding(self):
- self.assertEquals(json.loads(u'{"a": "\xe9"}'.encode('utf-8')),
+ self.assertEqual(json.loads(u'{"a": "\xe9"}'.encode('utf-8')),
{'a': u'\xe9'})
def test_unicode_preservation(self):
- self.assertEquals(type(json.loads(u'""')), unicode)
- self.assertEquals(type(json.loads(u'"a"')), unicode)
- self.assertEquals(type(json.loads(u'["a"]')[0]), unicode)
+ self.assertEqual(type(json.loads(u'""')), text_type)
+ self.assertEqual(type(json.loads(u'"a"')), text_type)
+ self.assertEqual(type(json.loads(u'["a"]')[0]), text_type)
def test_ensure_ascii_false_returns_unicode(self):
# http://code.google.com/p/simplejson/issues/detail?id=48
- self.assertEquals(type(json.dumps([], ensure_ascii=False)), unicode)
- self.assertEquals(type(json.dumps(0, ensure_ascii=False)), unicode)
- self.assertEquals(type(json.dumps({}, ensure_ascii=False)), unicode)
- self.assertEquals(type(json.dumps("", ensure_ascii=False)), unicode)
+ self.assertEqual(type(json.dumps([], ensure_ascii=False)), text_type)
+ self.assertEqual(type(json.dumps(0, ensure_ascii=False)), text_type)
+ self.assertEqual(type(json.dumps({}, ensure_ascii=False)), text_type)
+ self.assertEqual(type(json.dumps("", ensure_ascii=False)), text_type)
def test_ensure_ascii_false_bytestring_encoding(self):
# http://code.google.com/p/simplejson/issues/detail?id=48
- doc1 = {u'quux': 'Arr\xc3\xaat sur images'}
- doc2 = {u'quux': u'Arr\xeat sur images'}
+ doc1 = {u'quux': b('Arr\xc3\xaat sur images')}
+ doc2 = {u'quux': u('Arr\xeat sur images')}
doc_ascii = '{"quux": "Arr\\u00eat sur images"}'
doc_unicode = u'{"quux": "Arr\xeat sur images"}'
- self.assertEquals(json.dumps(doc1), doc_ascii)
- self.assertEquals(json.dumps(doc2), doc_ascii)
- self.assertEquals(json.dumps(doc1, ensure_ascii=False), doc_unicode)
- self.assertEquals(json.dumps(doc2, ensure_ascii=False), doc_unicode)
+ self.assertEqual(json.dumps(doc1), doc_ascii)
+ self.assertEqual(json.dumps(doc2), doc_ascii)
+ self.assertEqual(json.dumps(doc1, ensure_ascii=False), doc_unicode)
+ self.assertEqual(json.dumps(doc2, ensure_ascii=False), doc_unicode)
def test_ensure_ascii_linebreak_encoding(self):
# http://timelessrepo.com/json-isnt-a-javascript-subset
s1 = u'\u2029\u2028'
s2 = s1.encode('utf8')
expect = '"\\u2029\\u2028"'
- self.assertEquals(json.dumps(s1), expect)
- self.assertEquals(json.dumps(s2), expect)
- self.assertEquals(json.dumps(s1, ensure_ascii=False), expect)
- self.assertEquals(json.dumps(s2, ensure_ascii=False), expect)
+ self.assertEqual(json.dumps(s1), expect)
+ self.assertEqual(json.dumps(s2), expect)
+ self.assertEqual(json.dumps(s1, ensure_ascii=False), expect)
+ self.assertEqual(json.dumps(s2, ensure_ascii=False), expect)
+
+ def test_invalid_escape_sequences(self):
+ # incomplete escape sequence
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u1')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u12')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u123')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u1234')
+ # invalid escape sequence
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u123x"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u12x4"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\u1x34"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ux234"')
+ if sys.maxunicode > 65535:
+ # invalid escape sequence for low surrogate
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\u"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\u0"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\u00"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\u000"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\u000x"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\u00x0"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\u0x00"')
+ self.assertRaises(json.JSONDecodeError, json.loads, '"\\ud800\\ux000"')
+
+ def test_ensure_ascii_still_works(self):
+ # in the ascii range, ensure that everything is the same
+ for c in map(unichr, range(0, 127)):
+ self.assertEqual(
+ json.dumps(c, ensure_ascii=False),
+ json.dumps(c))
+ snowman = u'\N{SNOWMAN}'
+ self.assertEqual(
+ json.dumps(c, ensure_ascii=False),
+ '"' + c + '"')
+
+ def test_strip_bom(self):
+ content = u"\u3053\u3093\u306b\u3061\u308f"
+ json_doc = codecs.BOM_UTF8 + b(json.dumps(content))
+ self.assertEqual(json.load(BytesIO(json_doc)), content)
+ for doc in json_doc, json_doc.decode('utf8'):
+ self.assertEqual(json.loads(doc), content)