from json.tests import PyTest, CTest | |
class JSONTestObject: | |
pass | |
class TestRecursion(object): | |
def test_listrecursion(self): | |
x = [] | |
x.append(x) | |
try: | |
self.dumps(x) | |
except ValueError: | |
pass | |
else: | |
self.fail("didn't raise ValueError on list recursion") | |
x = [] | |
y = [x] | |
x.append(y) | |
try: | |
self.dumps(x) | |
except ValueError: | |
pass | |
else: | |
self.fail("didn't raise ValueError on alternating list recursion") | |
y = [] | |
x = [y, y] | |
# ensure that the marker is cleared | |
self.dumps(x) | |
def test_dictrecursion(self): | |
x = {} | |
x["test"] = x | |
try: | |
self.dumps(x) | |
except ValueError: | |
pass | |
else: | |
self.fail("didn't raise ValueError on dict recursion") | |
x = {} | |
y = {"a": x, "b": x} | |
# ensure that the marker is cleared | |
self.dumps(x) | |
def test_defaultrecursion(self): | |
class RecursiveJSONEncoder(self.json.JSONEncoder): | |
recurse = False | |
def default(self, o): | |
if o is JSONTestObject: | |
if self.recurse: | |
return [JSONTestObject] | |
else: | |
return 'JSONTestObject' | |
return pyjson.JSONEncoder.default(o) | |
enc = RecursiveJSONEncoder() | |
self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"') | |
enc.recurse = True | |
try: | |
enc.encode(JSONTestObject) | |
except ValueError: | |
pass | |
else: | |
self.fail("didn't raise ValueError on default recursion") | |
def test_highly_nested_objects_decoding(self): | |
# test that loading highly-nested objects doesn't segfault when C | |
# accelerations are used. See #12017 | |
# str | |
with self.assertRaises(RuntimeError): | |
self.loads('{"a":' * 100000 + '1' + '}' * 100000) | |
with self.assertRaises(RuntimeError): | |
self.loads('{"a":' * 100000 + '[1]' + '}' * 100000) | |
with self.assertRaises(RuntimeError): | |
self.loads('[' * 100000 + '1' + ']' * 100000) | |
# unicode | |
with self.assertRaises(RuntimeError): | |
self.loads(u'{"a":' * 100000 + u'1' + u'}' * 100000) | |
with self.assertRaises(RuntimeError): | |
self.loads(u'{"a":' * 100000 + u'[1]' + u'}' * 100000) | |
with self.assertRaises(RuntimeError): | |
self.loads(u'[' * 100000 + u'1' + u']' * 100000) | |
def test_highly_nested_objects_encoding(self): | |
# See #12051 | |
l, d = [], {} | |
for x in xrange(100000): | |
l, d = [l], {'k':d} | |
with self.assertRaises(RuntimeError): | |
self.dumps(l) | |
with self.assertRaises(RuntimeError): | |
self.dumps(d) | |
def test_endless_recursion(self): | |
# See #12051 | |
class EndlessJSONEncoder(self.json.JSONEncoder): | |
def default(self, o): | |
"""If check_circular is False, this will keep adding another list.""" | |
return [o] | |
with self.assertRaises(RuntimeError): | |
EndlessJSONEncoder(check_circular=False).encode(5j) | |
class TestPyRecursion(TestRecursion, PyTest): pass | |
class TestCRecursion(TestRecursion, CTest): pass |