• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from test.test_json import PyTest, CTest
2
3
4class JSONTestObject:
5    pass
6
7
8class TestRecursion:
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        with self.assertRaises(RecursionError):
72            self.loads('{"a":' * 100000 + '1' + '}' * 100000)
73        with self.assertRaises(RecursionError):
74            self.loads('{"a":' * 100000 + '[1]' + '}' * 100000)
75        with self.assertRaises(RecursionError):
76            self.loads('[' * 100000 + '1' + ']' * 100000)
77
78    def test_highly_nested_objects_encoding(self):
79        # See #12051
80        l, d = [], {}
81        for x in range(100000):
82            l, d = [l], {'k':d}
83        with self.assertRaises(RecursionError):
84            self.dumps(l)
85        with self.assertRaises(RecursionError):
86            self.dumps(d)
87
88    def test_endless_recursion(self):
89        # See #12051
90        class EndlessJSONEncoder(self.json.JSONEncoder):
91            def default(self, o):
92                """If check_circular is False, this will keep adding another list."""
93                return [o]
94
95        with self.assertRaises(RecursionError):
96            EndlessJSONEncoder(check_circular=False).encode(5j)
97
98
99class TestPyRecursion(TestRecursion, PyTest): pass
100class TestCRecursion(TestRecursion, CTest): pass
101