1 | from json.tests import PyTest, CTest
|
---|
2 |
|
---|
3 |
|
---|
4 | class JSONTestObject:
|
---|
5 | pass
|
---|
6 |
|
---|
7 |
|
---|
8 | class 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 |
|
---|
107 | class TestPyRecursion(TestRecursion, PyTest): pass
|
---|
108 | class TestCRecursion(TestRecursion, CTest): pass
|
---|