#18273: move the tests in Lib/test/json_tests to Lib/test/test_json and make them discoverable by unittest.  Patch by Zachary Ware.
diff --git a/Lib/test/test_json/__init__.py b/Lib/test/test_json/__init__.py
new file mode 100644
index 0000000..f994f9b
--- /dev/null
+++ b/Lib/test/test_json/__init__.py
@@ -0,0 +1,64 @@
+import os
+import sys
+import json
+import doctest
+import unittest
+
+from test import support
+
+# import json with and without accelerations
+cjson = support.import_fresh_module('json', fresh=['_json'])
+pyjson = support.import_fresh_module('json', blocked=['_json'])
+
+# create two base classes that will be used by the other tests
+class PyTest(unittest.TestCase):
+    json = pyjson
+    loads = staticmethod(pyjson.loads)
+    dumps = staticmethod(pyjson.dumps)
+
+@unittest.skipUnless(cjson, 'requires _json')
+class CTest(unittest.TestCase):
+    if cjson is not None:
+        json = cjson
+        loads = staticmethod(cjson.loads)
+        dumps = staticmethod(cjson.dumps)
+
+# test PyTest and CTest checking if the functions come from the right module
+class TestPyTest(PyTest):
+    def test_pyjson(self):
+        self.assertEqual(self.json.scanner.make_scanner.__module__,
+                         'json.scanner')
+        self.assertEqual(self.json.decoder.scanstring.__module__,
+                         'json.decoder')
+        self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__,
+                         'json.encoder')
+
+class TestCTest(CTest):
+    def test_cjson(self):
+        self.assertEqual(self.json.scanner.make_scanner.__module__, '_json')
+        self.assertEqual(self.json.decoder.scanstring.__module__, '_json')
+        self.assertEqual(self.json.encoder.c_make_encoder.__module__, '_json')
+        self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__,
+                         '_json')
+
+
+here = os.path.dirname(__file__)
+
+def load_tests(*args):
+    suite = additional_tests()
+    loader = unittest.TestLoader()
+    for fn in os.listdir(here):
+        if fn.startswith("test") and fn.endswith(".py"):
+            modname = "test.test_json." + fn[:-3]
+            __import__(modname)
+            module = sys.modules[modname]
+            suite.addTests(loader.loadTestsFromModule(module))
+    return suite
+
+def additional_tests():
+    suite = unittest.TestSuite()
+    for mod in (json, json.encoder, json.decoder):
+        suite.addTest(doctest.DocTestSuite(mod))
+    suite.addTest(TestPyTest('test_pyjson'))
+    suite.addTest(TestCTest('test_cjson'))
+    return suite
diff --git a/Lib/test/test_json/__main__.py b/Lib/test/test_json/__main__.py
new file mode 100644
index 0000000..e756afb
--- /dev/null
+++ b/Lib/test/test_json/__main__.py
@@ -0,0 +1,4 @@
+import unittest
+from test.test_json import load_tests
+
+unittest.main()
diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py
new file mode 100644
index 0000000..d23e285
--- /dev/null
+++ b/Lib/test/test_json/test_decode.py
@@ -0,0 +1,74 @@
+import decimal
+from io import StringIO
+from collections import OrderedDict
+from test.test_json import PyTest, CTest
+
+
+class TestDecode:
+    def test_decimal(self):
+        rval = self.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 = self.loads('1', parse_int=float)
+        self.assertTrue(isinstance(rval, float))
+        self.assertEqual(rval, 1.0)
+
+    def test_empty_objects(self):
+        self.assertEqual(self.loads('{}'), {})
+        self.assertEqual(self.loads('[]'), [])
+        self.assertEqual(self.loads('""'), "")
+
+    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(self.loads(s), eval(s))
+        self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p)
+        self.assertEqual(self.json.load(StringIO(s),
+                                        object_pairs_hook=lambda x: x), p)
+        od = self.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(self.loads(s, object_pairs_hook=OrderedDict,
+                                    object_hook=lambda x: None),
+                         OrderedDict(p))
+        # check that empty objects literals work (see #17368)
+        self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict),
+                         OrderedDict())
+        self.assertEqual(self.loads('{"empty": {}}',
+                                    object_pairs_hook=OrderedDict),
+                         OrderedDict([('empty', OrderedDict())]))
+
+    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 = self.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, self.loads)
+        self.check_keys_reuse(s, self.json.decoder.JSONDecoder().decode)
+
+    def test_extra_data(self):
+        s = '[1, 2, 3]5'
+        msg = 'Extra data'
+        self.assertRaisesRegex(ValueError, msg, self.loads, s)
+
+    def test_invalid_escape(self):
+        s = '["abc\\y"]'
+        msg = 'escape'
+        self.assertRaisesRegex(ValueError, msg, self.loads, s)
+
+class TestPyDecode(TestDecode, PyTest): pass
+class TestCDecode(TestDecode, CTest): pass
diff --git a/Lib/test/test_json/test_default.py b/Lib/test/test_json/test_default.py
new file mode 100644
index 0000000..9b8325e
--- /dev/null
+++ b/Lib/test/test_json/test_default.py
@@ -0,0 +1,12 @@
+from test.test_json import PyTest, CTest
+
+
+class TestDefault:
+    def test_default(self):
+        self.assertEqual(
+            self.dumps(type, default=repr),
+            self.dumps(repr(type)))
+
+
+class TestPyDefault(TestDefault, PyTest): pass
+class TestCDefault(TestDefault, CTest): pass
diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py
new file mode 100644
index 0000000..af19258
--- /dev/null
+++ b/Lib/test/test_json/test_dump.py
@@ -0,0 +1,49 @@
+from io import StringIO
+from test.test_json import PyTest, CTest
+
+from test.support import bigmemtest, _1G
+
+class TestDump:
+    def test_dump(self):
+        sio = StringIO()
+        self.json.dump({}, sio)
+        self.assertEqual(sio.getvalue(), '{}')
+
+    def test_dumps(self):
+        self.assertEqual(self.dumps({}), '{}')
+
+    def test_encode_truefalse(self):
+        self.assertEqual(self.dumps(
+                 {True: False, False: True}, sort_keys=True),
+                 '{"false": true, "true": false}')
+        self.assertEqual(self.dumps(
+                {2: 3.0, 4.0: 5, False: 1, 6: True}, sort_keys=True),
+                '{"false": 1, "2": 3.0, "4.0": 5, "6": true}')
+
+    # Issue 16228: Crash on encoding resized list
+    def test_encode_mutated(self):
+        a = [object()] * 10
+        def crasher(obj):
+            del a[-1]
+        self.assertEqual(self.dumps(a, default=crasher),
+                 '[null, null, null, null, null]')
+
+
+class TestPyDump(TestDump, PyTest): pass
+
+class TestCDump(TestDump, CTest):
+
+    # The size requirement here is hopefully over-estimated (actual
+    # memory consumption depending on implementation details, and also
+    # system memory management, since this may allocate a lot of
+    # small objects).
+
+    @bigmemtest(size=_1G, memuse=1)
+    def test_large_list(self, size):
+        N = int(30 * 1024 * 1024 * (size / _1G))
+        l = [1] * N
+        encoded = self.dumps(l)
+        self.assertEqual(len(encoded), N * 3)
+        self.assertEqual(encoded[:1], "[")
+        self.assertEqual(encoded[-2:], "1]")
+        self.assertEqual(encoded[1:-2], "1, " * (N - 1))
diff --git a/Lib/test/test_json/test_encode_basestring_ascii.py b/Lib/test/test_json/test_encode_basestring_ascii.py
new file mode 100644
index 0000000..480afd6
--- /dev/null
+++ b/Lib/test/test_json/test_encode_basestring_ascii.py
@@ -0,0 +1,44 @@
+from collections import OrderedDict
+from test.test_json import PyTest, CTest
+
+
+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:
+    def test_encode_basestring_ascii(self):
+        fname = self.json.encoder.encode_basestring_ascii.__name__
+        for input_string, expect in CASES:
+            result = self.json.encoder.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 = self.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 = self.dumps(dict(items), sort_keys=True)
+        self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}')
+
+
+class TestPyEncodeBasestringAscii(TestEncodeBasestringAscii, PyTest): pass
+class TestCEncodeBasestringAscii(TestEncodeBasestringAscii, CTest): pass
diff --git a/Lib/test/test_json/test_fail.py b/Lib/test/test_json/test_fail.py
new file mode 100644
index 0000000..3dd877a
--- /dev/null
+++ b/Lib/test/test_json/test_fail.py
@@ -0,0 +1,105 @@
+from test.test_json import PyTest, CTest
+
+# 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"}',
+    # 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
+    '[\\naked]',
+    # 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://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
+    '["A\u001FZ control characters in string"]',
+]
+
+SKIPS = {
+    1: "why not have a string payload?",
+    18: "spec doesn't specify any nesting limitations",
+}
+
+class TestFail:
+    def test_failures(self):
+        for idx, doc in enumerate(JSONDOCS):
+            idx = idx + 1
+            if idx in SKIPS:
+                self.loads(doc)
+                continue
+            try:
+                self.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, self.dumps, data)
+
+        #This is for python encoder
+        self.assertRaises(TypeError, self.dumps, data, indent=True)
+
+
+class TestPyFail(TestFail, PyTest): pass
+class TestCFail(TestFail, CTest): pass
diff --git a/Lib/test/test_json/test_float.py b/Lib/test/test_json/test_float.py
new file mode 100644
index 0000000..d0c7214
--- /dev/null
+++ b/Lib/test/test_json/test_float.py
@@ -0,0 +1,33 @@
+import math
+from test.test_json import PyTest, CTest
+
+
+class TestFloat:
+    def test_floats(self):
+        for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]:
+            self.assertEqual(float(self.dumps(num)), num)
+            self.assertEqual(self.loads(self.dumps(num)), num)
+
+    def test_ints(self):
+        for num in [1, 1<<32, 1<<64]:
+            self.assertEqual(self.dumps(num), str(num))
+            self.assertEqual(int(self.dumps(num)), num)
+
+    def test_out_of_range(self):
+        self.assertEqual(self.loads('[23456789012E666]'), [float('inf')])
+        self.assertEqual(self.loads('[-23456789012E666]'), [float('-inf')])
+
+    def test_allow_nan(self):
+        for val in (float('inf'), float('-inf'), float('nan')):
+            out = self.dumps([val])
+            if val == val:  # inf
+                self.assertEqual(self.loads(out), [val])
+            else:  # nan
+                res = self.loads(out)
+                self.assertEqual(len(res), 1)
+                self.assertNotEqual(res[0], res[0])
+            self.assertRaises(ValueError, self.dumps, [val], allow_nan=False)
+
+
+class TestPyFloat(TestFloat, PyTest): pass
+class TestCFloat(TestFloat, CTest): pass
diff --git a/Lib/test/test_json/test_indent.py b/Lib/test/test_json/test_indent.py
new file mode 100644
index 0000000..a4d4d20
--- /dev/null
+++ b/Lib/test/test_json/test_indent.py
@@ -0,0 +1,63 @@
+import textwrap
+from io import StringIO
+from test.test_json import PyTest, CTest
+
+
+class TestIndent:
+    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 = self.dumps(h)
+        d2 = self.dumps(h, indent=2, sort_keys=True, separators=(',', ': '))
+        d3 = self.dumps(h, indent='\t', sort_keys=True, separators=(',', ': '))
+
+        h1 = self.loads(d1)
+        h2 = self.loads(d2)
+        h3 = self.loads(d3)
+
+        self.assertEqual(h1, h)
+        self.assertEqual(h2, h)
+        self.assertEqual(h3, h)
+        self.assertEqual(d2, expect.expandtabs(2))
+        self.assertEqual(d3, expect)
+
+    def test_indent0(self):
+        h = {3: 1}
+        def check(indent, expected):
+            d1 = self.dumps(h, indent=indent)
+            self.assertEqual(d1, expected)
+
+            sio = StringIO()
+            self.json.dump(h, sio, indent=indent)
+            self.assertEqual(sio.getvalue(), expected)
+
+        # indent=0 should emit newlines
+        check(0, '{\n"3": 1\n}')
+        # indent=None is more compact
+        check(None, '{"3": 1}')
+
+
+class TestPyIndent(TestIndent, PyTest): pass
+class TestCIndent(TestIndent, CTest): pass
diff --git a/Lib/test/test_json/test_pass1.py b/Lib/test/test_json/test_pass1.py
new file mode 100644
index 0000000..15e64b0
--- /dev/null
+++ b/Lib/test/test_json/test_pass1.py
@@ -0,0 +1,75 @@
+from test.test_json import PyTest, CTest
+
+
+# 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,
+        "":  23456789012E66,
+        "zero": 0,
+        "one": 1,
+        "space": " ",
+        "quote": "\"",
+        "backslash": "\\",
+        "controls": "\b\f\n\r\t",
+        "slash": "/ & \/",
+        "alpha": "abcdefghijklmnopqrstuvwyz",
+        "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+        "digit": "0123456789",
+        "0123456789": "digit",
+        "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": "&#34; \u0022 %22 0x22 034 &#x22;",
+        "\/\\\"\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,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
+,"rosebud"]
+'''
+
+class TestPass1:
+    def test_parse(self):
+        # test in/out equivalence and parsing
+        res = self.loads(JSON)
+        out = self.dumps(res)
+        self.assertEqual(res, self.loads(out))
+
+
+class TestPyPass1(TestPass1, PyTest): pass
+class TestCPass1(TestPass1, CTest): pass
diff --git a/Lib/test/test_json/test_pass2.py b/Lib/test/test_json/test_pass2.py
new file mode 100644
index 0000000..3507524
--- /dev/null
+++ b/Lib/test/test_json/test_pass2.py
@@ -0,0 +1,18 @@
+from test.test_json import PyTest, CTest
+
+
+# from http://json.org/JSON_checker/test/pass2.json
+JSON = r'''
+[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
+'''
+
+class TestPass2:
+    def test_parse(self):
+        # test in/out equivalence and parsing
+        res = self.loads(JSON)
+        out = self.dumps(res)
+        self.assertEqual(res, self.loads(out))
+
+
+class TestPyPass2(TestPass2, PyTest): pass
+class TestCPass2(TestPass2, CTest): pass
diff --git a/Lib/test/test_json/test_pass3.py b/Lib/test/test_json/test_pass3.py
new file mode 100644
index 0000000..cd0cf17
--- /dev/null
+++ b/Lib/test/test_json/test_pass3.py
@@ -0,0 +1,24 @@
+from test.test_json import PyTest, CTest
+
+
+# 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:
+    def test_parse(self):
+        # test in/out equivalence and parsing
+        res = self.loads(JSON)
+        out = self.dumps(res)
+        self.assertEqual(res, self.loads(out))
+
+
+class TestPyPass3(TestPass3, PyTest): pass
+class TestCPass3(TestPass3, CTest): pass
diff --git a/Lib/test/test_json/test_recursion.py b/Lib/test/test_json/test_recursion.py
new file mode 100644
index 0000000..1a76254
--- /dev/null
+++ b/Lib/test/test_json/test_recursion.py
@@ -0,0 +1,100 @@
+from test.test_json import PyTest, CTest
+
+
+class JSONTestObject:
+    pass
+
+
+class TestRecursion:
+    def test_listrecursion(self):
+        x = []
+        x.append(x)
+        try:
+            self.dumps(x)
+        except ValueError:
+            pass
+        else:
+            self.fail("didn't raise ValueError on list recursion")
+        x = []
+        y = [x]
+        x.append(y)
+        try:
+            self.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
+        self.dumps(x)
+
+    def test_dictrecursion(self):
+        x = {}
+        x["test"] = x
+        try:
+            self.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
+        self.dumps(x)
+
+    def test_defaultrecursion(self):
+        class RecursiveJSONEncoder(self.json.JSONEncoder):
+            recurse = False
+            def default(self, o):
+                if o is JSONTestObject:
+                    if self.recurse:
+                        return [JSONTestObject]
+                    else:
+                        return 'JSONTestObject'
+                return pyjson.JSONEncoder.default(o)
+
+        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")
+
+
+    def test_highly_nested_objects_decoding(self):
+        # test that loading highly-nested objects doesn't segfault when C
+        # accelerations are used. See #12017
+        with self.assertRaises(RuntimeError):
+            self.loads('{"a":' * 100000 + '1' + '}' * 100000)
+        with self.assertRaises(RuntimeError):
+            self.loads('{"a":' * 100000 + '[1]' + '}' * 100000)
+        with self.assertRaises(RuntimeError):
+            self.loads('[' * 100000 + '1' + ']' * 100000)
+
+    def test_highly_nested_objects_encoding(self):
+        # See #12051
+        l, d = [], {}
+        for x in range(100000):
+            l, d = [l], {'k':d}
+        with self.assertRaises(RuntimeError):
+            self.dumps(l)
+        with self.assertRaises(RuntimeError):
+            self.dumps(d)
+
+    def test_endless_recursion(self):
+        # See #12051
+        class EndlessJSONEncoder(self.json.JSONEncoder):
+            def default(self, o):
+                """If check_circular is False, this will keep adding another list."""
+                return [o]
+
+        with self.assertRaises(RuntimeError):
+            EndlessJSONEncoder(check_circular=False).encode(5j)
+
+
+class TestPyRecursion(TestRecursion, PyTest): pass
+class TestCRecursion(TestRecursion, CTest): pass
diff --git a/Lib/test/test_json/test_scanstring.py b/Lib/test/test_json/test_scanstring.py
new file mode 100644
index 0000000..2e3a291
--- /dev/null
+++ b/Lib/test/test_json/test_scanstring.py
@@ -0,0 +1,98 @@
+import sys
+from test.test_json import PyTest, CTest
+
+
+class TestScanstring:
+    def test_scanstring(self):
+        scanstring = self.json.decoder.scanstring
+        self.assertEqual(
+            scanstring('"z\\ud834\\udd20x"', 1, True),
+            ('z\U0001d120x', 16))
+
+        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):
+        with self.assertRaises(OverflowError):
+            self.json.decoder.scanstring(b"xxx", sys.maxsize+1)
+
+
+class TestPyScanstring(TestScanstring, PyTest): pass
+class TestCScanstring(TestScanstring, CTest): pass
diff --git a/Lib/test/test_json/test_separators.py b/Lib/test/test_json/test_separators.py
new file mode 100644
index 0000000..84a2be9
--- /dev/null
+++ b/Lib/test/test_json/test_separators.py
@@ -0,0 +1,44 @@
+import textwrap
+from test.test_json import PyTest, CTest
+
+
+class TestSeparators:
+    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 = self.dumps(h)
+        d2 = self.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : '))
+
+        h1 = self.loads(d1)
+        h2 = self.loads(d2)
+
+        self.assertEqual(h1, h)
+        self.assertEqual(h2, h)
+        self.assertEqual(d2, expect)
+
+
+class TestPySeparators(TestSeparators, PyTest): pass
+class TestCSeparators(TestSeparators, CTest): pass
diff --git a/Lib/test/test_json/test_speedups.py b/Lib/test/test_json/test_speedups.py
new file mode 100644
index 0000000..109a246
--- /dev/null
+++ b/Lib/test/test_json/test_speedups.py
@@ -0,0 +1,24 @@
+from test.test_json import CTest
+
+
+class TestSpeedups(CTest):
+    def test_scanstring(self):
+        self.assertEqual(self.json.decoder.scanstring.__module__, "_json")
+        self.assertIs(self.json.decoder.scanstring, self.json.decoder.c_scanstring)
+
+    def test_encode_basestring_ascii(self):
+        self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__,
+                         "_json")
+        self.assertIs(self.json.encoder.encode_basestring_ascii,
+                      self.json.encoder.c_encode_basestring_ascii)
+
+
+class TestDecode(CTest):
+    def test_make_scanner(self):
+        self.assertRaises(AttributeError, self.json.scanner.c_make_scanner, 1)
+
+    def test_make_encoder(self):
+        self.assertRaises(TypeError, self.json.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/test_json/test_tool.py b/Lib/test/test_json/test_tool.py
new file mode 100644
index 0000000..0c39e56
--- /dev/null
+++ b/Lib/test/test_json/test_tool.py
@@ -0,0 +1,69 @@
+import os
+import sys
+import textwrap
+import unittest
+import subprocess
+from test import support
+from test.script_helper import assert_python_ok
+
+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 test_stdin_stdout(self):
+        with subprocess.Popen(
+                (sys.executable, '-m', 'json.tool'),
+                stdin=subprocess.PIPE, stdout=subprocess.PIPE) as proc:
+            out, err = proc.communicate(self.data.encode())
+        self.assertEqual(out.splitlines(), self.expect.encode().splitlines())
+        self.assertEqual(err, None)
+
+    def _create_infile(self):
+        infile = support.TESTFN
+        with open(infile, "w") as fp:
+            self.addCleanup(os.remove, infile)
+            fp.write(self.data)
+        return infile
+
+    def test_infile_stdout(self):
+        infile = self._create_infile()
+        rc, out, err = assert_python_ok('-m', 'json.tool', infile)
+        self.assertEqual(out.splitlines(), self.expect.encode().splitlines())
+        self.assertEqual(err, b'')
+
+    def test_infile_outfile(self):
+        infile = self._create_infile()
+        outfile = support.TESTFN + '.out'
+        rc, out, err = assert_python_ok('-m', 'json.tool', infile, outfile)
+        self.addCleanup(os.remove, outfile)
+        with open(outfile, "r") as fp:
+            self.assertEqual(fp.read(), self.expect)
+        self.assertEqual(out, b'')
+        self.assertEqual(err, b'')
diff --git a/Lib/test/test_json/test_unicode.py b/Lib/test/test_json/test_unicode.py
new file mode 100644
index 0000000..c7cc8a7
--- /dev/null
+++ b/Lib/test/test_json/test_unicode.py
@@ -0,0 +1,75 @@
+from collections import OrderedDict
+from test.test_json import PyTest, CTest
+
+
+class TestUnicode:
+    # 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 = self.dumps(u)
+        self.assertEqual(j, '"\\u03b1\\u03a9"')
+
+    def test_encoding4(self):
+        u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
+        j = self.dumps([u])
+        self.assertEqual(j, '["\\u03b1\\u03a9"]')
+
+    def test_encoding5(self):
+        u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
+        j = self.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 = self.dumps([u], ensure_ascii=False)
+        self.assertEqual(j, '["{0}"]'.format(u))
+
+    def test_big_unicode_encode(self):
+        u = '\U0001d120'
+        self.assertEqual(self.dumps(u), '"\\ud834\\udd20"')
+        self.assertEqual(self.dumps(u, ensure_ascii=False), '"\U0001d120"')
+
+    def test_big_unicode_decode(self):
+        u = 'z\U0001d120x'
+        self.assertEqual(self.loads('"' + u + '"'), u)
+        self.assertEqual(self.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(self.loads(s), u)
+
+    def test_unicode_preservation(self):
+        self.assertEqual(type(self.loads('""')), str)
+        self.assertEqual(type(self.loads('"a"')), str)
+        self.assertEqual(type(self.loads('["a"]')[0]), str)
+
+    def test_bytes_encode(self):
+        self.assertRaises(TypeError, self.dumps, b"hi")
+        self.assertRaises(TypeError, self.dumps, [b"hi"])
+
+    def test_bytes_decode(self):
+        self.assertRaises(TypeError, self.loads, b'"hi"')
+        self.assertRaises(TypeError, self.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(self.loads(s), eval(s))
+        self.assertEqual(self.loads(s, object_pairs_hook = lambda x: x), p)
+        od = self.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(self.loads(s, object_pairs_hook = OrderedDict,
+                                    object_hook = lambda x: None),
+                         OrderedDict(p))
+
+
+class TestPyUnicode(TestUnicode, PyTest): pass
+class TestCUnicode(TestUnicode, CTest): pass