• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from json.tests import PyTest, CTest
2
3
4class JSONTestObject:
5    pass
6
7
8class TestRecursion(object):
9    def test_listrecursion(self):
10        x = []
11        x.append(x)
12        try:
13            self.dumps(x)
14        except ValueError:
15            pass
16        else:
17            self.fail("didn't raise ValueError on list recursion")
18        x = []
19        y = [x]
20        x.append(y)
21        try:
22            self.dumps(x)
23        except ValueError:
24            pass
25        else:
26            self.fail("didn't raise ValueError on alternating list recursion")
27        y = []
28        x = [y, y]
29        # ensure that the marker is cleared
30        self.dumps(x)
31
32    def test_dictrecursion(self):
33        x = {}
34        x["test"] = x
35        try:
36            self.dumps(x)
37        except ValueError:
38            pass
39        else:
40            self.fail("didn't raise ValueError on dict recursion")
41        x = {}
42        y = {"a": x, "b": x}
43        # ensure that the marker is cleared
44        self.dumps(x)
45
46    def test_defaultrecursion(self):
47        class RecursiveJSONEncoder(self.json.JSONEncoder):
48            recurse = False
49            def default(self, o):
50                if o is JSONTestObject:
51                    if self.recurse:
52                        return [JSONTestObject]
53                    else:
54                        return 'JSONTestObject'
55                return pyjson.JSONEncoder.default(o)
56
57        enc = RecursiveJSONEncoder()
58        self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"')
59        enc.recurse = True
60        try:
61            enc.encode(JSONTestObject)
62        except ValueError:
63            pass
64        else:
65            self.fail("didn't raise ValueError on default recursion")
66
67
68    def test_highly_nested_objects_decoding(self):
69        # test that loading highly-nested objects doesn't segfault when C
70        # accelerations are used. See #12017
71        # str
72        with self.assertRaises(RuntimeError):
73            self.loads('{"a":' * 100000 + '1' + '}' * 100000)
74        with self.assertRaises(RuntimeError):
75            self.loads('{"a":' * 100000 + '[1]' + '}' * 100000)
76        with self.assertRaises(RuntimeError):
77            self.loads('[' * 100000 + '1' + ']' * 100000)
78        # unicode
79        with self.assertRaises(RuntimeError):
80            self.loads(u'{"a":' * 100000 + u'1' + u'}' * 100000)
81        with self.assertRaises(RuntimeError):
82            self.loads(u'{"a":' * 100000 + u'[1]' + u'}' * 100000)
83        with self.assertRaises(RuntimeError):
84            self.loads(u'[' * 100000 + u'1' + u']' * 100000)
85
86    def test_highly_nested_objects_encoding(self):
87        # See #12051
88        l, d = [], {}
89        for x in xrange(100000):
90            l, d = [l], {'k':d}
91        with self.assertRaises(RuntimeError):
92            self.dumps(l)
93        with self.assertRaises(RuntimeError):
94            self.dumps(d)
95
96    def test_endless_recursion(self):
97        # See #12051
98        class EndlessJSONEncoder(self.json.JSONEncoder):
99            def default(self, o):
100                """If check_circular is False, this will keep adding another list."""
101                return [o]
102
103        with self.assertRaises(RuntimeError):
104            EndlessJSONEncoder(check_circular=False).encode(5j)
105
106
107class TestPyRecursion(TestRecursion, PyTest): pass
108class TestCRecursion(TestRecursion, CTest): pass
109