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