From ff27ee0b400030419cfd3c9966f275bfbcb569f8 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Tue, 30 Nov 2010 03:03:30 +0000 Subject: Issue #10572: Moved json tests to Lib/test/json_tests. Approved by Raymond Hettinger. --- Lib/json/tests/__init__.py | 35 ------- Lib/json/tests/test_decode.py | 69 ------------- Lib/json/tests/test_default.py | 9 -- Lib/json/tests/test_dump.py | 21 ---- Lib/json/tests/test_encode_basestring_ascii.py | 50 ---------- Lib/json/tests/test_fail.py | 85 ---------------- Lib/json/tests/test_float.py | 15 --- Lib/json/tests/test_indent.py | 45 --------- Lib/json/tests/test_pass1.py | 76 --------------- Lib/json/tests/test_pass2.py | 14 --- Lib/json/tests/test_pass3.py | 20 ---- Lib/json/tests/test_recursion.py | 67 ------------- Lib/json/tests/test_scanstring.py | 107 --------------------- Lib/json/tests/test_separators.py | 42 -------- Lib/json/tests/test_speedups.py | 23 ----- Lib/json/tests/test_unicode.py | 73 -------------- Lib/test/json_tests/__init__.py | 35 +++++++ Lib/test/json_tests/test_decode.py | 69 +++++++++++++ Lib/test/json_tests/test_default.py | 9 ++ Lib/test/json_tests/test_dump.py | 21 ++++ .../json_tests/test_encode_basestring_ascii.py | 50 ++++++++++ Lib/test/json_tests/test_fail.py | 85 ++++++++++++++++ Lib/test/json_tests/test_float.py | 15 +++ Lib/test/json_tests/test_indent.py | 45 +++++++++ Lib/test/json_tests/test_pass1.py | 76 +++++++++++++++ Lib/test/json_tests/test_pass2.py | 14 +++ Lib/test/json_tests/test_pass3.py | 20 ++++ Lib/test/json_tests/test_recursion.py | 67 +++++++++++++ Lib/test/json_tests/test_scanstring.py | 107 +++++++++++++++++++++ Lib/test/json_tests/test_separators.py | 42 ++++++++ Lib/test/json_tests/test_speedups.py | 23 +++++ Lib/test/json_tests/test_unicode.py | 73 ++++++++++++++ Lib/test/test_json.py | 4 +- Makefile.pre.in | 2 +- 34 files changed, 754 insertions(+), 754 deletions(-) delete mode 100644 Lib/json/tests/__init__.py delete mode 100644 Lib/json/tests/test_decode.py delete mode 100644 Lib/json/tests/test_default.py delete mode 100644 Lib/json/tests/test_dump.py delete mode 100644 Lib/json/tests/test_encode_basestring_ascii.py delete mode 100644 Lib/json/tests/test_fail.py delete mode 100644 Lib/json/tests/test_float.py delete mode 100644 Lib/json/tests/test_indent.py delete mode 100644 Lib/json/tests/test_pass1.py delete mode 100644 Lib/json/tests/test_pass2.py delete mode 100644 Lib/json/tests/test_pass3.py delete mode 100644 Lib/json/tests/test_recursion.py delete mode 100644 Lib/json/tests/test_scanstring.py delete mode 100644 Lib/json/tests/test_separators.py delete mode 100644 Lib/json/tests/test_speedups.py delete mode 100644 Lib/json/tests/test_unicode.py create mode 100644 Lib/test/json_tests/__init__.py create mode 100644 Lib/test/json_tests/test_decode.py create mode 100644 Lib/test/json_tests/test_default.py create mode 100644 Lib/test/json_tests/test_dump.py create mode 100644 Lib/test/json_tests/test_encode_basestring_ascii.py create mode 100644 Lib/test/json_tests/test_fail.py create mode 100644 Lib/test/json_tests/test_float.py create mode 100644 Lib/test/json_tests/test_indent.py create mode 100644 Lib/test/json_tests/test_pass1.py create mode 100644 Lib/test/json_tests/test_pass2.py create mode 100644 Lib/test/json_tests/test_pass3.py create mode 100644 Lib/test/json_tests/test_recursion.py create mode 100644 Lib/test/json_tests/test_scanstring.py create mode 100644 Lib/test/json_tests/test_separators.py create mode 100644 Lib/test/json_tests/test_speedups.py create mode 100644 Lib/test/json_tests/test_unicode.py diff --git a/Lib/json/tests/__init__.py b/Lib/json/tests/__init__.py deleted file mode 100644 index 1a1e3e6..0000000 --- a/Lib/json/tests/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -import os -import sys -import unittest -import doctest - -here = os.path.dirname(__file__) - -def test_suite(): - suite = additional_tests() - loader = unittest.TestLoader() - for fn in os.listdir(here): - if fn.startswith("test") and fn.endswith(".py"): - modname = "json.tests." + fn[:-3] - __import__(modname) - module = sys.modules[modname] - suite.addTests(loader.loadTestsFromModule(module)) - return suite - -def additional_tests(): - import json - import json.encoder - import json.decoder - suite = unittest.TestSuite() - for mod in (json, json.encoder, json.decoder): - suite.addTest(doctest.DocTestSuite(mod)) - return suite - -def main(): - suite = test_suite() - runner = unittest.TextTestRunner() - runner.run(suite) - -if __name__ == '__main__': - sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) - main() diff --git a/Lib/json/tests/test_decode.py b/Lib/json/tests/test_decode.py deleted file mode 100644 index f41e5b7..0000000 --- a/Lib/json/tests/test_decode.py +++ /dev/null @@ -1,69 +0,0 @@ -import decimal -from unittest import TestCase -from io import StringIO -from contextlib import contextmanager - -import json -import json.decoder -import json.scanner -from collections import OrderedDict - - -@contextmanager -def use_python_scanner(): - py_scanner = json.scanner.py_make_scanner - old_scanner = json.decoder.make_scanner - json.decoder.make_scanner = py_scanner - try: - yield - finally: - json.decoder.make_scanner = old_scanner - - -class TestDecode(TestCase): - def test_decimal(self): - rval = json.loads('1.1', parse_float=decimal.Decimal) - self.assertTrue(isinstance(rval, decimal.Decimal)) - self.assertEqual(rval, decimal.Decimal('1.1')) - - def test_float(self): - rval = json.loads('1', parse_int=float) - self.assertTrue(isinstance(rval, float)) - self.assertEqual(rval, 1.0) - - def test_object_pairs_hook(self): - s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' - p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), - ("qrt", 5), ("pad", 6), ("hoy", 7)] - self.assertEqual(json.loads(s), eval(s)) - self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) - self.assertEqual(json.load(StringIO(s), - object_pairs_hook=lambda x: x), p) - od = json.loads(s, object_pairs_hook = OrderedDict) - self.assertEqual(od, OrderedDict(p)) - self.assertEqual(type(od), OrderedDict) - # the object_pairs_hook takes priority over the object_hook - self.assertEqual(json.loads(s, - object_pairs_hook = OrderedDict, - object_hook = lambda x: None), - OrderedDict(p)) - - 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.assertEqual(rval, {"key":"value", "k":"v"}) - - def check_keys_reuse(self, source, loads): - rval = loads(source) - (a, b), (c, d) = sorted(rval[0]), sorted(rval[1]) - self.assertIs(a, c) - self.assertIs(b, d) - - def test_keys_reuse(self): - s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]' - self.check_keys_reuse(s, json.loads) - # Disabled: the pure Python version of json simply doesn't work - with use_python_scanner(): - self.check_keys_reuse(s, json.decoder.JSONDecoder().decode) diff --git a/Lib/json/tests/test_default.py b/Lib/json/tests/test_default.py deleted file mode 100644 index 6a03eeb..0000000 --- a/Lib/json/tests/test_default.py +++ /dev/null @@ -1,9 +0,0 @@ -from unittest import TestCase - -import json - -class TestDefault(TestCase): - def test_default(self): - self.assertEqual( - json.dumps(type, default=repr), - json.dumps(repr(type))) diff --git a/Lib/json/tests/test_dump.py b/Lib/json/tests/test_dump.py deleted file mode 100644 index 8df234b..0000000 --- a/Lib/json/tests/test_dump.py +++ /dev/null @@ -1,21 +0,0 @@ -from unittest import TestCase -from io import StringIO - -import json - -class TestDump(TestCase): - def test_dump(self): - sio = StringIO() - json.dump({}, sio) - self.assertEqual(sio.getvalue(), '{}') - - def test_dumps(self): - self.assertEqual(json.dumps({}), '{}') - - def test_encode_truefalse(self): - self.assertEqual(json.dumps( - {True: False, False: True}, sort_keys=True), - '{"false": true, "true": false}') - self.assertEqual(json.dumps( - {2: 3.0, 4.0: 5, False: 1, 6: True}, sort_keys=True), - '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') diff --git a/Lib/json/tests/test_encode_basestring_ascii.py b/Lib/json/tests/test_encode_basestring_ascii.py deleted file mode 100644 index 4fddd12..0000000 --- a/Lib/json/tests/test_encode_basestring_ascii.py +++ /dev/null @@ -1,50 +0,0 @@ -from unittest import TestCase - -import json.encoder -from json import dumps -from collections import OrderedDict - -CASES = [ - ('/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'), - ('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), - ('controls', '"controls"'), - ('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'), - ('{"object with 1 member":["array with 1 element"]}', '"{\\"object with 1 member\\":[\\"array with 1 element\\"]}"'), - (' s p a c e d ', '" s p a c e d "'), - ('\U0001d120', '"\\ud834\\udd20"'), - ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), - ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), - ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), - ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), - ("`1~!@#$%^&*()_+-={':[,]}|;.?", '"`1~!@#$%^&*()_+-={\':[,]}|;.?"'), - ('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'), - ('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), -] - -class TestEncodeBaseStringAscii(TestCase): - def test_py_encode_basestring_ascii(self): - self._test_encode_basestring_ascii(json.encoder.py_encode_basestring_ascii) - - def test_c_encode_basestring_ascii(self): - if not json.encoder.c_encode_basestring_ascii: - return - self._test_encode_basestring_ascii(json.encoder.c_encode_basestring_ascii) - - def _test_encode_basestring_ascii(self, encode_basestring_ascii): - fname = encode_basestring_ascii.__name__ - for input_string, expect in CASES: - result = encode_basestring_ascii(input_string) - self.assertEqual(result, expect, - '{0!r} != {1!r} for {2}({3!r})'.format( - result, expect, fname, input_string)) - - def test_ordered_dict(self): - # See issue 6105 - items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] - s = json.dumps(OrderedDict(items)) - self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}') - - def test_sorted_dict(self): - items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] - s = json.dumps(dict(items), sort_keys=True) - self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}') diff --git a/Lib/json/tests/test_fail.py b/Lib/json/tests/test_fail.py deleted file mode 100644 index 9768edf..0000000 --- a/Lib/json/tests/test_fail.py +++ /dev/null @@ -1,85 +0,0 @@ -from unittest import TestCase - -import json - -# Fri Dec 30 18:57:26 2005 -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}', - # http://json.org/JSON_checker/test/fail4.json - '["extra comma",]', - # http://json.org/JSON_checker/test/fail5.json - '["double extra comma",,]', - # http://json.org/JSON_checker/test/fail6.json - '[ , "<-- missing value"]', - # http://json.org/JSON_checker/test/fail7.json - '["Comma after the close"],', - # http://json.org/JSON_checker/test/fail8.json - '["Extra close"]]', - # http://json.org/JSON_checker/test/fail9.json - '{"Extra comma": true,}', - # http://json.org/JSON_checker/test/fail10.json - '{"Extra value after close": true} "misplaced quoted value"', - # http://json.org/JSON_checker/test/fail11.json - '{"Illegal expression": 1 + 2}', - # http://json.org/JSON_checker/test/fail12.json - '{"Illegal invocation": alert()}', - # http://json.org/JSON_checker/test/fail13.json - '{"Numbers cannot have leading zeroes": 013}', - # http://json.org/JSON_checker/test/fail14.json - '{"Numbers cannot be hex": 0x14}', - # http://json.org/JSON_checker/test/fail15.json - '["Illegal backslash escape: \\x15"]', - # http://json.org/JSON_checker/test/fail16.json - '["Illegal backslash escape: \\\'"]', - # http://json.org/JSON_checker/test/fail17.json - '["Illegal backslash escape: \\017"]', - # http://json.org/JSON_checker/test/fail18.json - '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', - # http://json.org/JSON_checker/test/fail19.json - '{"Missing colon" null}', - # http://json.org/JSON_checker/test/fail20.json - '{"Double colon":: null}', - # http://json.org/JSON_checker/test/fail21.json - '{"Comma instead of colon", null}', - # http://json.org/JSON_checker/test/fail22.json - '["Colon instead of comma": false]', - # http://json.org/JSON_checker/test/fail23.json - '["Bad value", truth]', - # http://json.org/JSON_checker/test/fail24.json - "['single quote']", - # http://code.google.com/p/simplejson/issues/detail?id=3 - '["A\u001FZ control characters in string"]', -] - -SKIPS = { - 1: "why not have a string payload?", - 18: "spec doesn't specify any nesting limitations", -} - -class TestFail(TestCase): - def test_failures(self): - for idx, doc in enumerate(JSONDOCS): - idx = idx + 1 - if idx in SKIPS: - json.loads(doc) - continue - try: - json.loads(doc) - except ValueError: - pass - else: - self.fail("Expected failure for fail{0}.json: {1!r}".format(idx, doc)) - - def test_non_string_keys_dict(self): - data = {'a' : 1, (1, 2) : 2} - - #This is for c encoder - self.assertRaises(TypeError, json.dumps, data) - - #This is for python encoder - self.assertRaises(TypeError, json.dumps, data, indent=True) diff --git a/Lib/json/tests/test_float.py b/Lib/json/tests/test_float.py deleted file mode 100644 index ca4a506..0000000 --- a/Lib/json/tests/test_float.py +++ /dev/null @@ -1,15 +0,0 @@ -import math -from unittest import TestCase - -import json - -class TestFloat(TestCase): - def test_floats(self): - for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]: - self.assertEqual(float(json.dumps(num)), num) - self.assertEqual(json.loads(json.dumps(num)), num) - - def test_ints(self): - for num in [1, 1<<32, 1<<64]: - self.assertEqual(json.dumps(num), str(num)) - self.assertEqual(int(json.dumps(num)), num) diff --git a/Lib/json/tests/test_indent.py b/Lib/json/tests/test_indent.py deleted file mode 100644 index d8030aa..0000000 --- a/Lib/json/tests/test_indent.py +++ /dev/null @@ -1,45 +0,0 @@ -from unittest import TestCase - -import json -import textwrap - -class TestIndent(TestCase): - def test_indent(self): - h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', - {'nifty': 87}, {'field': 'yes', 'morefield': False} ] - - expect = textwrap.dedent("""\ - [ - \t[ - \t\t"blorpie" - \t], - \t[ - \t\t"whoops" - \t], - \t[], - \t"d-shtaeou", - \t"d-nthiouh", - \t"i-vhbjkhnth", - \t{ - \t\t"nifty": 87 - \t}, - \t{ - \t\t"field": "yes", - \t\t"morefield": false - \t} - ]""") - - - d1 = json.dumps(h) - d2 = json.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) - d3 = json.dumps(h, indent='\t', sort_keys=True, separators=(',', ': ')) - - h1 = json.loads(d1) - h2 = json.loads(d2) - h3 = json.loads(d3) - - self.assertEqual(h1, h) - self.assertEqual(h2, h) - self.assertEqual(h3, h) - self.assertEqual(d2, expect.expandtabs(2)) - self.assertEqual(d3, expect) diff --git a/Lib/json/tests/test_pass1.py b/Lib/json/tests/test_pass1.py deleted file mode 100644 index 719c113..0000000 --- a/Lib/json/tests/test_pass1.py +++ /dev/null @@ -1,76 +0,0 @@ -from unittest import TestCase - -import json - -# from http://json.org/JSON_checker/test/pass1.json -JSON = r''' -[ - "JSON Test Pattern pass1", - {"object with 1 member":["array with 1 element"]}, - {}, - [], - -42, - true, - false, - null, - { - "integer": 1234567890, - "real": -9876.543210, - "e": 0.123456789e-12, - "E": 1.234567890E+34, - "": 23456789012E666, - "zero": 0, - "one": 1, - "space": " ", - "quote": "\"", - "backslash": "\\", - "controls": "\b\f\n\r\t", - "slash": "/ & \/", - "alpha": "abcdefghijklmnopqrstuvwyz", - "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", - "digit": "0123456789", - "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", - "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", - "true": true, - "false": false, - "null": null, - "array":[ ], - "object":{ }, - "address": "50 St. James Street", - "url": "http://www.JSON.org/", - "comment": "// /* */": " ", - " s p a c e d " :[1,2 , 3 - -, - -4 , 5 , 6 ,7 ], - "compact": [1,2,3,4,5,6,7], - "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", - "quotes": "" \u0022 %22 0x22 034 "", - "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" -: "A key can be any string" - }, - 0.5 ,98.6 -, -99.44 -, - -1066 - - -,"rosebud"] -''' - -class TestPass1(TestCase): - def test_parse(self): - # test in/out equivalence and parsing - res = json.loads(JSON) - out = json.dumps(res) - self.assertEqual(res, json.loads(out)) - try: - json.dumps(res, allow_nan=False) - except ValueError: - pass - else: - self.fail("23456789012E666 should be out of range") diff --git a/Lib/json/tests/test_pass2.py b/Lib/json/tests/test_pass2.py deleted file mode 100644 index 379117e..0000000 --- a/Lib/json/tests/test_pass2.py +++ /dev/null @@ -1,14 +0,0 @@ -from unittest import TestCase -import json - -# from http://json.org/JSON_checker/test/pass2.json -JSON = r''' -[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] -''' - -class TestPass2(TestCase): - def test_parse(self): - # test in/out equivalence and parsing - res = json.loads(JSON) - out = json.dumps(res) - self.assertEqual(res, json.loads(out)) diff --git a/Lib/json/tests/test_pass3.py b/Lib/json/tests/test_pass3.py deleted file mode 100644 index 9151c43..0000000 --- a/Lib/json/tests/test_pass3.py +++ /dev/null @@ -1,20 +0,0 @@ -from unittest import TestCase - -import json - -# from http://json.org/JSON_checker/test/pass3.json -JSON = r''' -{ - "JSON Test Pattern pass3": { - "The outermost value": "must be an object or array.", - "In this test": "It is an object." - } -} -''' - -class TestPass3(TestCase): - def test_parse(self): - # test in/out equivalence and parsing - res = json.loads(JSON) - out = json.dumps(res) - self.assertEqual(res, json.loads(out)) diff --git a/Lib/json/tests/test_recursion.py b/Lib/json/tests/test_recursion.py deleted file mode 100644 index 1e9b8ab..0000000 --- a/Lib/json/tests/test_recursion.py +++ /dev/null @@ -1,67 +0,0 @@ -from unittest import TestCase - -import json - -class JSONTestObject: - pass - - -class RecursiveJSONEncoder(json.JSONEncoder): - recurse = False - def default(self, o): - if o is JSONTestObject: - if self.recurse: - return [JSONTestObject] - else: - return 'JSONTestObject' - return json.JSONEncoder.default(o) - - -class TestRecursion(TestCase): - def test_listrecursion(self): - x = [] - x.append(x) - try: - json.dumps(x) - except ValueError: - pass - else: - self.fail("didn't raise ValueError on list recursion") - x = [] - y = [x] - x.append(y) - try: - json.dumps(x) - except ValueError: - pass - else: - self.fail("didn't raise ValueError on alternating list recursion") - y = [] - x = [y, y] - # ensure that the marker is cleared - json.dumps(x) - - def test_dictrecursion(self): - x = {} - x["test"] = x - try: - json.dumps(x) - except ValueError: - pass - else: - self.fail("didn't raise ValueError on dict recursion") - x = {} - y = {"a": x, "b": x} - # ensure that the marker is cleared - json.dumps(x) - - def test_defaultrecursion(self): - enc = RecursiveJSONEncoder() - self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"') - enc.recurse = True - try: - enc.encode(JSONTestObject) - except ValueError: - pass - else: - self.fail("didn't raise ValueError on default recursion") diff --git a/Lib/json/tests/test_scanstring.py b/Lib/json/tests/test_scanstring.py deleted file mode 100644 index d503851..0000000 --- a/Lib/json/tests/test_scanstring.py +++ /dev/null @@ -1,107 +0,0 @@ -import sys -import decimal -from unittest import TestCase - -import json -import json.decoder - -class TestScanString(TestCase): - def test_py_scanstring(self): - self._test_scanstring(json.decoder.py_scanstring) - - def test_c_scanstring(self): - if json.decoder.c_scanstring is not None: - self._test_scanstring(json.decoder.c_scanstring) - - def _test_scanstring(self, scanstring): - self.assertEqual( - scanstring('"z\\ud834\\udd20x"', 1, True), - ('z\U0001d120x', 16)) - - if sys.maxunicode == 65535: - self.assertEqual( - scanstring('"z\U0001d120x"', 1, True), - ('z\U0001d120x', 6)) - else: - self.assertEqual( - scanstring('"z\U0001d120x"', 1, True), - ('z\U0001d120x', 5)) - - self.assertEqual( - scanstring('"\\u007b"', 1, True), - ('{', 8)) - - self.assertEqual( - scanstring('"A JSON payload should be an object or array, not a string."', 1, True), - ('A JSON payload should be an object or array, not a string.', 60)) - - self.assertEqual( - scanstring('["Unclosed array"', 2, True), - ('Unclosed array', 17)) - - self.assertEqual( - scanstring('["extra comma",]', 2, True), - ('extra comma', 14)) - - self.assertEqual( - scanstring('["double extra comma",,]', 2, True), - ('double extra comma', 21)) - - self.assertEqual( - scanstring('["Comma after the close"],', 2, True), - ('Comma after the close', 24)) - - self.assertEqual( - scanstring('["Extra close"]]', 2, True), - ('Extra close', 14)) - - self.assertEqual( - scanstring('{"Extra comma": true,}', 2, True), - ('Extra comma', 14)) - - self.assertEqual( - scanstring('{"Extra value after close": true} "misplaced quoted value"', 2, True), - ('Extra value after close', 26)) - - self.assertEqual( - scanstring('{"Illegal expression": 1 + 2}', 2, True), - ('Illegal expression', 21)) - - self.assertEqual( - scanstring('{"Illegal invocation": alert()}', 2, True), - ('Illegal invocation', 21)) - - self.assertEqual( - scanstring('{"Numbers cannot have leading zeroes": 013}', 2, True), - ('Numbers cannot have leading zeroes', 37)) - - self.assertEqual( - scanstring('{"Numbers cannot be hex": 0x14}', 2, True), - ('Numbers cannot be hex', 24)) - - self.assertEqual( - scanstring('[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', 21, True), - ('Too deep', 30)) - - self.assertEqual( - scanstring('{"Missing colon" null}', 2, True), - ('Missing colon', 16)) - - self.assertEqual( - scanstring('{"Double colon":: null}', 2, True), - ('Double colon', 15)) - - self.assertEqual( - scanstring('{"Comma instead of colon", null}', 2, True), - ('Comma instead of colon', 25)) - - self.assertEqual( - scanstring('["Colon instead of comma": false]', 2, True), - ('Colon instead of comma', 25)) - - self.assertEqual( - scanstring('["Bad value", truth]', 2, True), - ('Bad value', 12)) - - def test_overflow(self): - self.assertRaises(OverflowError, json.decoder.scanstring, b"xxx", sys.maxsize+1) diff --git a/Lib/json/tests/test_separators.py b/Lib/json/tests/test_separators.py deleted file mode 100644 index d5b92bd..0000000 --- a/Lib/json/tests/test_separators.py +++ /dev/null @@ -1,42 +0,0 @@ -import textwrap -from unittest import TestCase - -import json - - -class TestSeparators(TestCase): - def test_separators(self): - h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', - {'nifty': 87}, {'field': 'yes', 'morefield': False} ] - - expect = textwrap.dedent("""\ - [ - [ - "blorpie" - ] , - [ - "whoops" - ] , - [] , - "d-shtaeou" , - "d-nthiouh" , - "i-vhbjkhnth" , - { - "nifty" : 87 - } , - { - "field" : "yes" , - "morefield" : false - } - ]""") - - - d1 = json.dumps(h) - d2 = json.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : ')) - - h1 = json.loads(d1) - h2 = json.loads(d2) - - self.assertEqual(h1, h) - self.assertEqual(h2, h) - self.assertEqual(d2, expect) diff --git a/Lib/json/tests/test_speedups.py b/Lib/json/tests/test_speedups.py deleted file mode 100644 index 2718409..0000000 --- a/Lib/json/tests/test_speedups.py +++ /dev/null @@ -1,23 +0,0 @@ -from unittest import TestCase - -from json import decoder, encoder, scanner - -class TestSpeedups(TestCase): - def test_scanstring(self): - self.assertEqual(decoder.scanstring.__module__, "_json") - self.assertTrue(decoder.scanstring is decoder.c_scanstring) - - def test_encode_basestring_ascii(self): - self.assertEqual(encoder.encode_basestring_ascii.__module__, "_json") - self.assertTrue(encoder.encode_basestring_ascii is - encoder.c_encode_basestring_ascii) - -class TestDecode(TestCase): - def test_make_scanner(self): - self.assertRaises(AttributeError, scanner.c_make_scanner, 1) - - def test_make_encoder(self): - self.assertRaises(TypeError, encoder.c_make_encoder, - (True, False), - b"\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75", - None) diff --git a/Lib/json/tests/test_unicode.py b/Lib/json/tests/test_unicode.py deleted file mode 100644 index e336c91..0000000 --- a/Lib/json/tests/test_unicode.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest import TestCase - -import json -from collections import OrderedDict - -class TestUnicode(TestCase): - # test_encoding1 and test_encoding2 from 2.x are irrelevant (only str - # is supported as input, not bytes). - - def test_encoding3(self): - u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps(u) - self.assertEqual(j, '"\\u03b1\\u03a9"') - - def test_encoding4(self): - u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps([u]) - self.assertEqual(j, '["\\u03b1\\u03a9"]') - - def test_encoding5(self): - u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps(u, ensure_ascii=False) - self.assertEqual(j, '"{0}"'.format(u)) - - def test_encoding6(self): - u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps([u], ensure_ascii=False) - self.assertEqual(j, '["{0}"]'.format(u)) - - def test_big_unicode_encode(self): - u = '\U0001d120' - self.assertEqual(json.dumps(u), '"\\ud834\\udd20"') - self.assertEqual(json.dumps(u, ensure_ascii=False), '"\U0001d120"') - - def test_big_unicode_decode(self): - u = 'z\U0001d120x' - 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 = chr(i) - s = '"\\u{0:04x}"'.format(i) - self.assertEqual(json.loads(s), u) - - def test_unicode_preservation(self): - self.assertEqual(type(json.loads('""')), str) - self.assertEqual(type(json.loads('"a"')), str) - self.assertEqual(type(json.loads('["a"]')[0]), str) - - def test_bytes_encode(self): - self.assertRaises(TypeError, json.dumps, b"hi") - self.assertRaises(TypeError, json.dumps, [b"hi"]) - - def test_bytes_decode(self): - self.assertRaises(TypeError, json.loads, b'"hi"') - self.assertRaises(TypeError, json.loads, b'["hi"]') - - - def test_object_pairs_hook_with_unicode(self): - s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' - p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), - ("qrt", 5), ("pad", 6), ("hoy", 7)] - self.assertEqual(json.loads(s), eval(s)) - self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) - od = json.loads(s, object_pairs_hook = OrderedDict) - self.assertEqual(od, OrderedDict(p)) - self.assertEqual(type(od), OrderedDict) - # the object_pairs_hook takes priority over the object_hook - self.assertEqual(json.loads(s, - object_pairs_hook = OrderedDict, - object_hook = lambda x: None), - OrderedDict(p)) diff --git a/Lib/test/json_tests/__init__.py b/Lib/test/json_tests/__init__.py new file mode 100644 index 0000000..4977468 --- /dev/null +++ b/Lib/test/json_tests/__init__.py @@ -0,0 +1,35 @@ +import os +import sys +import unittest +import doctest + +here = os.path.dirname(__file__) + +def test_suite(): + suite = additional_tests() + loader = unittest.TestLoader() + for fn in os.listdir(here): + if fn.startswith("test") and fn.endswith(".py"): + modname = "test.json_tests." + fn[:-3] + __import__(modname) + module = sys.modules[modname] + suite.addTests(loader.loadTestsFromModule(module)) + return suite + +def additional_tests(): + import json + import json.encoder + import json.decoder + suite = unittest.TestSuite() + for mod in (json, json.encoder, json.decoder): + suite.addTest(doctest.DocTestSuite(mod)) + return suite + +def main(): + suite = test_suite() + runner = unittest.TextTestRunner() + runner.run(suite) + +if __name__ == '__main__': + sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + main() diff --git a/Lib/test/json_tests/test_decode.py b/Lib/test/json_tests/test_decode.py new file mode 100644 index 0000000..f41e5b7 --- /dev/null +++ b/Lib/test/json_tests/test_decode.py @@ -0,0 +1,69 @@ +import decimal +from unittest import TestCase +from io import StringIO +from contextlib import contextmanager + +import json +import json.decoder +import json.scanner +from collections import OrderedDict + + +@contextmanager +def use_python_scanner(): + py_scanner = json.scanner.py_make_scanner + old_scanner = json.decoder.make_scanner + json.decoder.make_scanner = py_scanner + try: + yield + finally: + json.decoder.make_scanner = old_scanner + + +class TestDecode(TestCase): + def test_decimal(self): + rval = json.loads('1.1', parse_float=decimal.Decimal) + self.assertTrue(isinstance(rval, decimal.Decimal)) + self.assertEqual(rval, decimal.Decimal('1.1')) + + def test_float(self): + rval = json.loads('1', parse_int=float) + self.assertTrue(isinstance(rval, float)) + self.assertEqual(rval, 1.0) + + def test_object_pairs_hook(self): + s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' + p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), + ("qrt", 5), ("pad", 6), ("hoy", 7)] + self.assertEqual(json.loads(s), eval(s)) + self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) + self.assertEqual(json.load(StringIO(s), + object_pairs_hook=lambda x: x), p) + od = json.loads(s, object_pairs_hook = OrderedDict) + self.assertEqual(od, OrderedDict(p)) + self.assertEqual(type(od), OrderedDict) + # the object_pairs_hook takes priority over the object_hook + self.assertEqual(json.loads(s, + object_pairs_hook = OrderedDict, + object_hook = lambda x: None), + OrderedDict(p)) + + 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.assertEqual(rval, {"key":"value", "k":"v"}) + + def check_keys_reuse(self, source, loads): + rval = loads(source) + (a, b), (c, d) = sorted(rval[0]), sorted(rval[1]) + self.assertIs(a, c) + self.assertIs(b, d) + + def test_keys_reuse(self): + s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]' + self.check_keys_reuse(s, json.loads) + # Disabled: the pure Python version of json simply doesn't work + with use_python_scanner(): + self.check_keys_reuse(s, json.decoder.JSONDecoder().decode) diff --git a/Lib/test/json_tests/test_default.py b/Lib/test/json_tests/test_default.py new file mode 100644 index 0000000..6a03eeb --- /dev/null +++ b/Lib/test/json_tests/test_default.py @@ -0,0 +1,9 @@ +from unittest import TestCase + +import json + +class TestDefault(TestCase): + def test_default(self): + self.assertEqual( + json.dumps(type, default=repr), + json.dumps(repr(type))) diff --git a/Lib/test/json_tests/test_dump.py b/Lib/test/json_tests/test_dump.py new file mode 100644 index 0000000..8df234b --- /dev/null +++ b/Lib/test/json_tests/test_dump.py @@ -0,0 +1,21 @@ +from unittest import TestCase +from io import StringIO + +import json + +class TestDump(TestCase): + def test_dump(self): + sio = StringIO() + json.dump({}, sio) + self.assertEqual(sio.getvalue(), '{}') + + def test_dumps(self): + self.assertEqual(json.dumps({}), '{}') + + def test_encode_truefalse(self): + self.assertEqual(json.dumps( + {True: False, False: True}, sort_keys=True), + '{"false": true, "true": false}') + self.assertEqual(json.dumps( + {2: 3.0, 4.0: 5, False: 1, 6: True}, sort_keys=True), + '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') diff --git a/Lib/test/json_tests/test_encode_basestring_ascii.py b/Lib/test/json_tests/test_encode_basestring_ascii.py new file mode 100644 index 0000000..4fddd12 --- /dev/null +++ b/Lib/test/json_tests/test_encode_basestring_ascii.py @@ -0,0 +1,50 @@ +from unittest import TestCase + +import json.encoder +from json import dumps +from collections import OrderedDict + +CASES = [ + ('/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'), + ('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), + ('controls', '"controls"'), + ('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'), + ('{"object with 1 member":["array with 1 element"]}', '"{\\"object with 1 member\\":[\\"array with 1 element\\"]}"'), + (' s p a c e d ', '" s p a c e d "'), + ('\U0001d120', '"\\ud834\\udd20"'), + ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), + ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), + ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), + ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), + ("`1~!@#$%^&*()_+-={':[,]}|;.?", '"`1~!@#$%^&*()_+-={\':[,]}|;.?"'), + ('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'), + ('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), +] + +class TestEncodeBaseStringAscii(TestCase): + def test_py_encode_basestring_ascii(self): + self._test_encode_basestring_ascii(json.encoder.py_encode_basestring_ascii) + + def test_c_encode_basestring_ascii(self): + if not json.encoder.c_encode_basestring_ascii: + return + self._test_encode_basestring_ascii(json.encoder.c_encode_basestring_ascii) + + def _test_encode_basestring_ascii(self, encode_basestring_ascii): + fname = encode_basestring_ascii.__name__ + for input_string, expect in CASES: + result = encode_basestring_ascii(input_string) + self.assertEqual(result, expect, + '{0!r} != {1!r} for {2}({3!r})'.format( + result, expect, fname, input_string)) + + def test_ordered_dict(self): + # See issue 6105 + items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] + s = json.dumps(OrderedDict(items)) + self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}') + + def test_sorted_dict(self): + items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] + s = json.dumps(dict(items), sort_keys=True) + self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}') diff --git a/Lib/test/json_tests/test_fail.py b/Lib/test/json_tests/test_fail.py new file mode 100644 index 0000000..9768edf --- /dev/null +++ b/Lib/test/json_tests/test_fail.py @@ -0,0 +1,85 @@ +from unittest import TestCase + +import json + +# Fri Dec 30 18:57:26 2005 +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}', + # http://json.org/JSON_checker/test/fail4.json + '["extra comma",]', + # http://json.org/JSON_checker/test/fail5.json + '["double extra comma",,]', + # http://json.org/JSON_checker/test/fail6.json + '[ , "<-- missing value"]', + # http://json.org/JSON_checker/test/fail7.json + '["Comma after the close"],', + # http://json.org/JSON_checker/test/fail8.json + '["Extra close"]]', + # http://json.org/JSON_checker/test/fail9.json + '{"Extra comma": true,}', + # http://json.org/JSON_checker/test/fail10.json + '{"Extra value after close": true} "misplaced quoted value"', + # http://json.org/JSON_checker/test/fail11.json + '{"Illegal expression": 1 + 2}', + # http://json.org/JSON_checker/test/fail12.json + '{"Illegal invocation": alert()}', + # http://json.org/JSON_checker/test/fail13.json + '{"Numbers cannot have leading zeroes": 013}', + # http://json.org/JSON_checker/test/fail14.json + '{"Numbers cannot be hex": 0x14}', + # http://json.org/JSON_checker/test/fail15.json + '["Illegal backslash escape: \\x15"]', + # http://json.org/JSON_checker/test/fail16.json + '["Illegal backslash escape: \\\'"]', + # http://json.org/JSON_checker/test/fail17.json + '["Illegal backslash escape: \\017"]', + # http://json.org/JSON_checker/test/fail18.json + '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', + # http://json.org/JSON_checker/test/fail19.json + '{"Missing colon" null}', + # http://json.org/JSON_checker/test/fail20.json + '{"Double colon":: null}', + # http://json.org/JSON_checker/test/fail21.json + '{"Comma instead of colon", null}', + # http://json.org/JSON_checker/test/fail22.json + '["Colon instead of comma": false]', + # http://json.org/JSON_checker/test/fail23.json + '["Bad value", truth]', + # http://json.org/JSON_checker/test/fail24.json + "['single quote']", + # http://code.google.com/p/simplejson/issues/detail?id=3 + '["A\u001FZ control characters in string"]', +] + +SKIPS = { + 1: "why not have a string payload?", + 18: "spec doesn't specify any nesting limitations", +} + +class TestFail(TestCase): + def test_failures(self): + for idx, doc in enumerate(JSONDOCS): + idx = idx + 1 + if idx in SKIPS: + json.loads(doc) + continue + try: + json.loads(doc) + except ValueError: + pass + else: + self.fail("Expected failure for fail{0}.json: {1!r}".format(idx, doc)) + + def test_non_string_keys_dict(self): + data = {'a' : 1, (1, 2) : 2} + + #This is for c encoder + self.assertRaises(TypeError, json.dumps, data) + + #This is for python encoder + self.assertRaises(TypeError, json.dumps, data, indent=True) diff --git a/Lib/test/json_tests/test_float.py b/Lib/test/json_tests/test_float.py new file mode 100644 index 0000000..ca4a506 --- /dev/null +++ b/Lib/test/json_tests/test_float.py @@ -0,0 +1,15 @@ +import math +from unittest import TestCase + +import json + +class TestFloat(TestCase): + def test_floats(self): + for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]: + self.assertEqual(float(json.dumps(num)), num) + self.assertEqual(json.loads(json.dumps(num)), num) + + def test_ints(self): + for num in [1, 1<<32, 1<<64]: + self.assertEqual(json.dumps(num), str(num)) + self.assertEqual(int(json.dumps(num)), num) diff --git a/Lib/test/json_tests/test_indent.py b/Lib/test/json_tests/test_indent.py new file mode 100644 index 0000000..d8030aa --- /dev/null +++ b/Lib/test/json_tests/test_indent.py @@ -0,0 +1,45 @@ +from unittest import TestCase + +import json +import textwrap + +class TestIndent(TestCase): + def test_indent(self): + h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', + {'nifty': 87}, {'field': 'yes', 'morefield': False} ] + + expect = textwrap.dedent("""\ + [ + \t[ + \t\t"blorpie" + \t], + \t[ + \t\t"whoops" + \t], + \t[], + \t"d-shtaeou", + \t"d-nthiouh", + \t"i-vhbjkhnth", + \t{ + \t\t"nifty": 87 + \t}, + \t{ + \t\t"field": "yes", + \t\t"morefield": false + \t} + ]""") + + + d1 = json.dumps(h) + d2 = json.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) + d3 = json.dumps(h, indent='\t', sort_keys=True, separators=(',', ': ')) + + h1 = json.loads(d1) + h2 = json.loads(d2) + h3 = json.loads(d3) + + self.assertEqual(h1, h) + self.assertEqual(h2, h) + self.assertEqual(h3, h) + self.assertEqual(d2, expect.expandtabs(2)) + self.assertEqual(d3, expect) diff --git a/Lib/test/json_tests/test_pass1.py b/Lib/test/json_tests/test_pass1.py new file mode 100644 index 0000000..719c113 --- /dev/null +++ b/Lib/test/json_tests/test_pass1.py @@ -0,0 +1,76 @@ +from unittest import TestCase + +import json + +# from http://json.org/JSON_checker/test/pass1.json +JSON = r''' +[ + "JSON Test Pattern pass1", + {"object with 1 member":["array with 1 element"]}, + {}, + [], + -42, + true, + false, + null, + { + "integer": 1234567890, + "real": -9876.543210, + "e": 0.123456789e-12, + "E": 1.234567890E+34, + "": 23456789012E666, + "zero": 0, + "one": 1, + "space": " ", + "quote": "\"", + "backslash": "\\", + "controls": "\b\f\n\r\t", + "slash": "/ & \/", + "alpha": "abcdefghijklmnopqrstuvwyz", + "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", + "digit": "0123456789", + "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", + "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", + "true": true, + "false": false, + "null": null, + "array":[ ], + "object":{ }, + "address": "50 St. James Street", + "url": "http://www.JSON.org/", + "comment": "// /* */": " ", + " s p a c e d " :[1,2 , 3 + +, + +4 , 5 , 6 ,7 ], + "compact": [1,2,3,4,5,6,7], + "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", + "quotes": "" \u0022 %22 0x22 034 "", + "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" +: "A key can be any string" + }, + 0.5 ,98.6 +, +99.44 +, + +1066 + + +,"rosebud"] +''' + +class TestPass1(TestCase): + def test_parse(self): + # test in/out equivalence and parsing + res = json.loads(JSON) + out = json.dumps(res) + self.assertEqual(res, json.loads(out)) + try: + json.dumps(res, allow_nan=False) + except ValueError: + pass + else: + self.fail("23456789012E666 should be out of range") diff --git a/Lib/test/json_tests/test_pass2.py b/Lib/test/json_tests/test_pass2.py new file mode 100644 index 0000000..379117e --- /dev/null +++ b/Lib/test/json_tests/test_pass2.py @@ -0,0 +1,14 @@ +from unittest import TestCase +import json + +# from http://json.org/JSON_checker/test/pass2.json +JSON = r''' +[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] +''' + +class TestPass2(TestCase): + def test_parse(self): + # test in/out equivalence and parsing + res = json.loads(JSON) + out = json.dumps(res) + self.assertEqual(res, json.loads(out)) diff --git a/Lib/test/json_tests/test_pass3.py b/Lib/test/json_tests/test_pass3.py new file mode 100644 index 0000000..9151c43 --- /dev/null +++ b/Lib/test/json_tests/test_pass3.py @@ -0,0 +1,20 @@ +from unittest import TestCase + +import json + +# from http://json.org/JSON_checker/test/pass3.json +JSON = r''' +{ + "JSON Test Pattern pass3": { + "The outermost value": "must be an object or array.", + "In this test": "It is an object." + } +} +''' + +class TestPass3(TestCase): + def test_parse(self): + # test in/out equivalence and parsing + res = json.loads(JSON) + out = json.dumps(res) + self.assertEqual(res, json.loads(out)) diff --git a/Lib/test/json_tests/test_recursion.py b/Lib/test/json_tests/test_recursion.py new file mode 100644 index 0000000..1e9b8ab --- /dev/null +++ b/Lib/test/json_tests/test_recursion.py @@ -0,0 +1,67 @@ +from unittest import TestCase + +import json + +class JSONTestObject: + pass + + +class RecursiveJSONEncoder(json.JSONEncoder): + recurse = False + def default(self, o): + if o is JSONTestObject: + if self.recurse: + return [JSONTestObject] + else: + return 'JSONTestObject' + return json.JSONEncoder.default(o) + + +class TestRecursion(TestCase): + def test_listrecursion(self): + x = [] + x.append(x) + try: + json.dumps(x) + except ValueError: + pass + else: + self.fail("didn't raise ValueError on list recursion") + x = [] + y = [x] + x.append(y) + try: + json.dumps(x) + except ValueError: + pass + else: + self.fail("didn't raise ValueError on alternating list recursion") + y = [] + x = [y, y] + # ensure that the marker is cleared + json.dumps(x) + + def test_dictrecursion(self): + x = {} + x["test"] = x + try: + json.dumps(x) + except ValueError: + pass + else: + self.fail("didn't raise ValueError on dict recursion") + x = {} + y = {"a": x, "b": x} + # ensure that the marker is cleared + json.dumps(x) + + def test_defaultrecursion(self): + enc = RecursiveJSONEncoder() + self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"') + enc.recurse = True + try: + enc.encode(JSONTestObject) + except ValueError: + pass + else: + self.fail("didn't raise ValueError on default recursion") diff --git a/Lib/test/json_tests/test_scanstring.py b/Lib/test/json_tests/test_scanstring.py new file mode 100644 index 0000000..d503851 --- /dev/null +++ b/Lib/test/json_tests/test_scanstring.py @@ -0,0 +1,107 @@ +import sys +import decimal +from unittest import TestCase + +import json +import json.decoder + +class TestScanString(TestCase): + def test_py_scanstring(self): + self._test_scanstring(json.decoder.py_scanstring) + + def test_c_scanstring(self): + if json.decoder.c_scanstring is not None: + self._test_scanstring(json.decoder.c_scanstring) + + def _test_scanstring(self, scanstring): + self.assertEqual( + scanstring('"z\\ud834\\udd20x"', 1, True), + ('z\U0001d120x', 16)) + + if sys.maxunicode == 65535: + self.assertEqual( + scanstring('"z\U0001d120x"', 1, True), + ('z\U0001d120x', 6)) + else: + self.assertEqual( + scanstring('"z\U0001d120x"', 1, True), + ('z\U0001d120x', 5)) + + self.assertEqual( + scanstring('"\\u007b"', 1, True), + ('{', 8)) + + self.assertEqual( + scanstring('"A JSON payload should be an object or array, not a string."', 1, True), + ('A JSON payload should be an object or array, not a string.', 60)) + + self.assertEqual( + scanstring('["Unclosed array"', 2, True), + ('Unclosed array', 17)) + + self.assertEqual( + scanstring('["extra comma",]', 2, True), + ('extra comma', 14)) + + self.assertEqual( + scanstring('["double extra comma",,]', 2, True), + ('double extra comma', 21)) + + self.assertEqual( + scanstring('["Comma after the close"],', 2, True), + ('Comma after the close', 24)) + + self.assertEqual( + scanstring('["Extra close"]]', 2, True), + ('Extra close', 14)) + + self.assertEqual( + scanstring('{"Extra comma": true,}', 2, True), + ('Extra comma', 14)) + + self.assertEqual( + scanstring('{"Extra value after close": true} "misplaced quoted value"', 2, True), + ('Extra value after close', 26)) + + self.assertEqual( + scanstring('{"Illegal expression": 1 + 2}', 2, True), + ('Illegal expression', 21)) + + self.assertEqual( + scanstring('{"Illegal invocation": alert()}', 2, True), + ('Illegal invocation', 21)) + + self.assertEqual( + scanstring('{"Numbers cannot have leading zeroes": 013}', 2, True), + ('Numbers cannot have leading zeroes', 37)) + + self.assertEqual( + scanstring('{"Numbers cannot be hex": 0x14}', 2, True), + ('Numbers cannot be hex', 24)) + + self.assertEqual( + scanstring('[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', 21, True), + ('Too deep', 30)) + + self.assertEqual( + scanstring('{"Missing colon" null}', 2, True), + ('Missing colon', 16)) + + self.assertEqual( + scanstring('{"Double colon":: null}', 2, True), + ('Double colon', 15)) + + self.assertEqual( + scanstring('{"Comma instead of colon", null}', 2, True), + ('Comma instead of colon', 25)) + + self.assertEqual( + scanstring('["Colon instead of comma": false]', 2, True), + ('Colon instead of comma', 25)) + + self.assertEqual( + scanstring('["Bad value", truth]', 2, True), + ('Bad value', 12)) + + def test_overflow(self): + self.assertRaises(OverflowError, json.decoder.scanstring, b"xxx", sys.maxsize+1) diff --git a/Lib/test/json_tests/test_separators.py b/Lib/test/json_tests/test_separators.py new file mode 100644 index 0000000..d5b92bd --- /dev/null +++ b/Lib/test/json_tests/test_separators.py @@ -0,0 +1,42 @@ +import textwrap +from unittest import TestCase + +import json + + +class TestSeparators(TestCase): + def test_separators(self): + h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', + {'nifty': 87}, {'field': 'yes', 'morefield': False} ] + + expect = textwrap.dedent("""\ + [ + [ + "blorpie" + ] , + [ + "whoops" + ] , + [] , + "d-shtaeou" , + "d-nthiouh" , + "i-vhbjkhnth" , + { + "nifty" : 87 + } , + { + "field" : "yes" , + "morefield" : false + } + ]""") + + + d1 = json.dumps(h) + d2 = json.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : ')) + + h1 = json.loads(d1) + h2 = json.loads(d2) + + self.assertEqual(h1, h) + self.assertEqual(h2, h) + self.assertEqual(d2, expect) diff --git a/Lib/test/json_tests/test_speedups.py b/Lib/test/json_tests/test_speedups.py new file mode 100644 index 0000000..2718409 --- /dev/null +++ b/Lib/test/json_tests/test_speedups.py @@ -0,0 +1,23 @@ +from unittest import TestCase + +from json import decoder, encoder, scanner + +class TestSpeedups(TestCase): + def test_scanstring(self): + self.assertEqual(decoder.scanstring.__module__, "_json") + self.assertTrue(decoder.scanstring is decoder.c_scanstring) + + def test_encode_basestring_ascii(self): + self.assertEqual(encoder.encode_basestring_ascii.__module__, "_json") + self.assertTrue(encoder.encode_basestring_ascii is + encoder.c_encode_basestring_ascii) + +class TestDecode(TestCase): + def test_make_scanner(self): + self.assertRaises(AttributeError, scanner.c_make_scanner, 1) + + def test_make_encoder(self): + self.assertRaises(TypeError, encoder.c_make_encoder, + (True, False), + b"\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75", + None) diff --git a/Lib/test/json_tests/test_unicode.py b/Lib/test/json_tests/test_unicode.py new file mode 100644 index 0000000..e336c91 --- /dev/null +++ b/Lib/test/json_tests/test_unicode.py @@ -0,0 +1,73 @@ +from unittest import TestCase + +import json +from collections import OrderedDict + +class TestUnicode(TestCase): + # test_encoding1 and test_encoding2 from 2.x are irrelevant (only str + # is supported as input, not bytes). + + def test_encoding3(self): + u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' + j = json.dumps(u) + self.assertEqual(j, '"\\u03b1\\u03a9"') + + def test_encoding4(self): + u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' + j = json.dumps([u]) + self.assertEqual(j, '["\\u03b1\\u03a9"]') + + def test_encoding5(self): + u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' + j = json.dumps(u, ensure_ascii=False) + self.assertEqual(j, '"{0}"'.format(u)) + + def test_encoding6(self): + u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' + j = json.dumps([u], ensure_ascii=False) + self.assertEqual(j, '["{0}"]'.format(u)) + + def test_big_unicode_encode(self): + u = '\U0001d120' + self.assertEqual(json.dumps(u), '"\\ud834\\udd20"') + self.assertEqual(json.dumps(u, ensure_ascii=False), '"\U0001d120"') + + def test_big_unicode_decode(self): + u = 'z\U0001d120x' + 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 = chr(i) + s = '"\\u{0:04x}"'.format(i) + self.assertEqual(json.loads(s), u) + + def test_unicode_preservation(self): + self.assertEqual(type(json.loads('""')), str) + self.assertEqual(type(json.loads('"a"')), str) + self.assertEqual(type(json.loads('["a"]')[0]), str) + + def test_bytes_encode(self): + self.assertRaises(TypeError, json.dumps, b"hi") + self.assertRaises(TypeError, json.dumps, [b"hi"]) + + def test_bytes_decode(self): + self.assertRaises(TypeError, json.loads, b'"hi"') + self.assertRaises(TypeError, json.loads, b'["hi"]') + + + def test_object_pairs_hook_with_unicode(self): + s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' + p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), + ("qrt", 5), ("pad", 6), ("hoy", 7)] + self.assertEqual(json.loads(s), eval(s)) + self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) + od = json.loads(s, object_pairs_hook = OrderedDict) + self.assertEqual(od, OrderedDict(p)) + self.assertEqual(type(od), OrderedDict) + # the object_pairs_hook takes priority over the object_hook + self.assertEqual(json.loads(s, + object_pairs_hook = OrderedDict, + object_hook = lambda x: None), + OrderedDict(p)) diff --git a/Lib/test/test_json.py b/Lib/test/test_json.py index a4b6e7a..41ff897 100644 --- a/Lib/test/test_json.py +++ b/Lib/test/test_json.py @@ -5,12 +5,12 @@ the test_suite() function there returns a test suite that's ready to be run. """ -import json.tests +from test import json_tests import test.support def test_main(): - test.support.run_unittest(json.tests.test_suite()) + test.support.run_unittest(json_tests.test_suite()) if __name__ == "__main__": diff --git a/Makefile.pre.in b/Makefile.pre.in index c605b21..28b3001 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -890,7 +890,7 @@ LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ test/tracedmodules test/encoded_modules \ concurrent concurrent/futures encodings \ email email/mime email/test email/test/data \ - html json json/tests http dbm xmlrpc \ + html json test/json_tests http dbm xmlrpc \ sqlite3 sqlite3/test \ logging csv wsgiref urllib \ lib2to3 lib2to3/fixes lib2to3/pgen2 lib2to3/tests \ -- cgit v0.12