Issue #892902: Added new tests for pickling recursive collections.

This commit is contained in:
Serhiy Storchaka 2015-11-07 11:16:10 +02:00
parent eeb896c411
commit 608c213530

View File

@ -103,6 +103,15 @@ class E(C):
class H(object): class H(object):
pass pass
# Hashable mutable key
class K(object):
def __init__(self, value):
self.value = value
def __reduce__(self):
# Shouldn't support the recursion itself
return K, (self.value,)
import __main__ import __main__
__main__.C = C __main__.C = C
C.__module__ = "__main__" C.__module__ = "__main__"
@ -112,6 +121,8 @@ __main__.E = E
E.__module__ = "__main__" E.__module__ = "__main__"
__main__.H = H __main__.H = H
H.__module__ = "__main__" H.__module__ = "__main__"
__main__.K = K
K.__module__ = "__main__"
class myint(int): class myint(int):
def __init__(self, x): def __init__(self, x):
@ -1041,9 +1052,9 @@ class AbstractPickleTests(unittest.TestCase):
x = self.loads(s) x = self.loads(s)
self.assertIsInstance(x, list) self.assertIsInstance(x, list)
self.assertEqual(len(x), 1) self.assertEqual(len(x), 1)
self.assertTrue(x is x[0]) self.assertIs(x[0], x)
def test_recursive_tuple(self): def test_recursive_tuple_and_list(self):
t = ([],) t = ([],)
t[0].append(t) t[0].append(t)
for proto in protocols: for proto in protocols:
@ -1051,8 +1062,9 @@ class AbstractPickleTests(unittest.TestCase):
x = self.loads(s) x = self.loads(s)
self.assertIsInstance(x, tuple) self.assertIsInstance(x, tuple)
self.assertEqual(len(x), 1) self.assertEqual(len(x), 1)
self.assertIsInstance(x[0], list)
self.assertEqual(len(x[0]), 1) self.assertEqual(len(x[0]), 1)
self.assertTrue(x is x[0][0]) self.assertIs(x[0][0], x)
def test_recursive_dict(self): def test_recursive_dict(self):
d = {} d = {}
@ -1062,29 +1074,63 @@ class AbstractPickleTests(unittest.TestCase):
x = self.loads(s) x = self.loads(s)
self.assertIsInstance(x, dict) self.assertIsInstance(x, dict)
self.assertEqual(list(x.keys()), [1]) self.assertEqual(list(x.keys()), [1])
self.assertTrue(x[1] is x) self.assertIs(x[1], x)
def test_recursive_dict_key(self):
d = {}
k = K(d)
d[k] = 1
for proto in protocols:
s = self.dumps(d, proto)
x = self.loads(s)
self.assertIsInstance(x, dict)
self.assertEqual(len(x.keys()), 1)
self.assertIsInstance(list(x.keys())[0], K)
self.assertIs(list(x.keys())[0].value, x)
def test_recursive_set(self): def test_recursive_set(self):
h = H() y = set()
y = set({h}) k = K(y)
h.attr = y y.add(k)
for proto in protocols: for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
s = self.dumps(y, proto) s = self.dumps(y, proto)
x = self.loads(s) x = self.loads(s)
self.assertIsInstance(x, set) self.assertIsInstance(x, set)
self.assertIs(list(x)[0].attr, x)
self.assertEqual(len(x), 1) self.assertEqual(len(x), 1)
self.assertIsInstance(list(x)[0], K)
self.assertIs(list(x)[0].value, x)
def test_recursive_frozenset(self): def test_recursive_list_subclass(self):
h = H() y = MyList()
y = frozenset({h}) y.append(y)
h.attr = y for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
for proto in protocols:
s = self.dumps(y, proto) s = self.dumps(y, proto)
x = self.loads(s) x = self.loads(s)
self.assertIsInstance(x, frozenset) self.assertIsInstance(x, MyList)
self.assertIs(list(x)[0].attr, x)
self.assertEqual(len(x), 1) self.assertEqual(len(x), 1)
self.assertIs(x[0], x)
def test_recursive_dict_subclass(self):
d = MyDict()
d[1] = d
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
s = self.dumps(d, proto)
x = self.loads(s)
self.assertIsInstance(x, MyDict)
self.assertEqual(list(x.keys()), [1])
self.assertIs(x[1], x)
def test_recursive_dict_subclass_key(self):
d = MyDict()
k = K(d)
d[k] = 1
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
s = self.dumps(d, proto)
x = self.loads(s)
self.assertIsInstance(x, MyDict)
self.assertEqual(len(list(x.keys())), 1)
self.assertIsInstance(list(x.keys())[0], K)
self.assertIs(list(x.keys())[0].value, x)
def test_recursive_inst(self): def test_recursive_inst(self):
i = C() i = C()
@ -1111,6 +1157,48 @@ class AbstractPickleTests(unittest.TestCase):
self.assertEqual(list(x[0].attr.keys()), [1]) self.assertEqual(list(x[0].attr.keys()), [1])
self.assertTrue(x[0].attr[1] is x) self.assertTrue(x[0].attr[1] is x)
def check_recursive_collection_and_inst(self, factory):
h = H()
y = factory([h])
h.attr = y
for proto in protocols:
s = self.dumps(y, proto)
x = self.loads(s)
self.assertIsInstance(x, type(y))
self.assertEqual(len(x), 1)
self.assertIsInstance(list(x)[0], H)
self.assertIs(list(x)[0].attr, x)
def test_recursive_list_and_inst(self):
self.check_recursive_collection_and_inst(list)
def test_recursive_tuple_and_inst(self):
self.check_recursive_collection_and_inst(tuple)
def test_recursive_dict_and_inst(self):
self.check_recursive_collection_and_inst(dict.fromkeys)
def test_recursive_set_and_inst(self):
self.check_recursive_collection_and_inst(set)
def test_recursive_frozenset_and_inst(self):
self.check_recursive_collection_and_inst(frozenset)
def test_recursive_list_subclass_and_inst(self):
self.check_recursive_collection_and_inst(MyList)
def test_recursive_tuple_subclass_and_inst(self):
self.check_recursive_collection_and_inst(MyTuple)
def test_recursive_dict_subclass_and_inst(self):
self.check_recursive_collection_and_inst(MyDict.fromkeys)
def test_recursive_set_subclass_and_inst(self):
self.check_recursive_collection_and_inst(MySet)
def test_recursive_frozenset_subclass_and_inst(self):
self.check_recursive_collection_and_inst(MyFrozenSet)
def test_unicode(self): def test_unicode(self):
endcases = ['', '<\\u>', '<\\\u1234>', '<\n>', endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
'<\\>', '<\\\U00012345>', '<\\>', '<\\\U00012345>',