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 self.json.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