summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_dict.py
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-09-10 02:28:36 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-09-10 02:28:36 (GMT)
commit78601a38c22ba1f09104e2562a10a94cbd36f5f0 (patch)
tree1abadfbcec51e16790781cbe045eaa6de6b91478 /Lib/test/test_dict.py
parenteb0dfa9251102e42bdabcb84de17cecb43537442 (diff)
downloadcpython-78601a38c22ba1f09104e2562a10a94cbd36f5f0.zip
cpython-78601a38c22ba1f09104e2562a10a94cbd36f5f0.tar.gz
cpython-78601a38c22ba1f09104e2562a10a94cbd36f5f0.tar.bz2
Fix SystemError in compact dict
Issue #28040: Fix _PyDict_DelItem_KnownHash() and _PyDict_Pop(): convert splitted table to combined table to be able to delete the item. Write an unit test for the issue. Patch by INADA Naoki.
Diffstat (limited to 'Lib/test/test_dict.py')
-rw-r--r--Lib/test/test_dict.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index 6c47066..fb954c8 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -4,6 +4,7 @@ import gc
import pickle
import random
import string
+import sys
import unittest
import weakref
from test import support
@@ -838,6 +839,74 @@ class DictTest(unittest.TestCase):
pass
self._tracked(MyDict())
+ def make_shared_key_dict(self, n):
+ class C:
+ pass
+
+ dicts = []
+ for i in range(n):
+ a = C()
+ a.x, a.y, a.z = 1, 2, 3
+ dicts.append(a.__dict__)
+
+ return dicts
+
+ @support.cpython_only
+ def test_splittable_del(self):
+ """split table must be combined when del d[k]"""
+ a, b = self.make_shared_key_dict(2)
+
+ orig_size = sys.getsizeof(a)
+
+ del a['y'] # split table is combined
+ with self.assertRaises(KeyError):
+ del a['y']
+
+ self.assertGreater(sys.getsizeof(a), orig_size)
+ self.assertEqual(list(a), ['x', 'z'])
+ self.assertEqual(list(b), ['x', 'y', 'z'])
+
+ # Two dicts have different insertion order.
+ a['y'] = 42
+ self.assertEqual(list(a), ['x', 'z', 'y'])
+ self.assertEqual(list(b), ['x', 'y', 'z'])
+
+ @support.cpython_only
+ def test_splittable_pop(self):
+ """split table must be combined when d.pop(k)"""
+ a, b = self.make_shared_key_dict(2)
+
+ orig_size = sys.getsizeof(a)
+
+ a.pop('y') # split table is combined
+ with self.assertRaises(KeyError):
+ a.pop('y')
+
+ self.assertGreater(sys.getsizeof(a), orig_size)
+ self.assertEqual(list(a), ['x', 'z'])
+ self.assertEqual(list(b), ['x', 'y', 'z'])
+
+ # Two dicts have different insertion order.
+ a['y'] = 42
+ self.assertEqual(list(a), ['x', 'z', 'y'])
+ self.assertEqual(list(b), ['x', 'y', 'z'])
+
+ @support.cpython_only
+ def test_splittable_popitem(self):
+ """split table must be combined when d.popitem()"""
+ a, b = self.make_shared_key_dict(2)
+
+ orig_size = sys.getsizeof(a)
+
+ item = a.popitem() # split table is combined
+ self.assertEqual(item, ('z', 3))
+ with self.assertRaises(KeyError):
+ del a['z']
+
+ self.assertGreater(sys.getsizeof(a), orig_size)
+ self.assertEqual(list(a), ['x', 'y'])
+ self.assertEqual(list(b), ['x', 'y', 'z'])
+
def test_iterator_pickling(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
data = {1:"a", 2:"b", 3:"c"}