blob: b518a0bb02b7320f7da0c9f6975f367b105e5a4a [file] [log] [blame]
Walter Dörwald59b23e82004-09-30 13:46:00 +00001import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002from test import support
Walter Dörwald59b23e82004-09-30 13:46:00 +00003
Raymond Hettingerf80680d2008-02-06 00:07:11 +00004import sys, collections, random, string
Walter Dörwald59b23e82004-09-30 13:46:00 +00005
6
7class DictTest(unittest.TestCase):
Guido van Rossum47b9ff62006-08-24 00:41:19 +00008
Walter Dörwald59b23e82004-09-30 13:46:00 +00009 def test_constructor(self):
10 # calling built-in types without argument must return empty
11 self.assertEqual(dict(), {})
12 self.assert_(dict() is not {})
13
Christian Heimes99170a52007-12-19 02:07:34 +000014 def test_literal_constructor(self):
15 # check literal constructor for different sized dicts (to exercise the BUILD_MAP oparg
Christian Heimesb186d002008-03-18 15:15:01 +000016 for n in (0, 1, 6, 256, 400):
17 items = [(''.join([random.choice(string.ascii_letters)
18 for j in range(8)]),
19 i)
20 for i in range(n)]
21 random.shuffle(items)
Christian Heimes99170a52007-12-19 02:07:34 +000022 dictliteral = '{' + ', '.join('%r: %d' % item for item in items) + '}'
23 self.assertEqual(eval(dictliteral), dict(items))
Christian Heimes99170a52007-12-19 02:07:34 +000024
Walter Dörwald59b23e82004-09-30 13:46:00 +000025 def test_bool(self):
26 self.assert_(not {})
27 self.assert_({1: 2})
28 self.assert_(bool({}) is False)
29 self.assert_(bool({1: 2}) is True)
30
31 def test_keys(self):
32 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000033 self.assertEqual(set(d.keys()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000034 d = {'a': 1, 'b': 2}
35 k = d.keys()
Guido van Rossume2b70bc2006-08-18 22:13:04 +000036 self.assert_('a' in d)
37 self.assert_('b' in d)
Walter Dörwald59b23e82004-09-30 13:46:00 +000038
39 self.assertRaises(TypeError, d.keys, None)
40
41 def test_values(self):
42 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000043 self.assertEqual(set(d.values()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000044 d = {1:2}
Guido van Rossume34cdd12007-02-14 17:49:04 +000045 self.assertEqual(set(d.values()), {2})
Walter Dörwald59b23e82004-09-30 13:46:00 +000046
47 self.assertRaises(TypeError, d.values, None)
48
49 def test_items(self):
50 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000051 self.assertEqual(set(d.items()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000052
53 d = {1:2}
Guido van Rossume34cdd12007-02-14 17:49:04 +000054 self.assertEqual(set(d.items()), {(1, 2)})
Walter Dörwald59b23e82004-09-30 13:46:00 +000055
56 self.assertRaises(TypeError, d.items, None)
57
Walter Dörwald59b23e82004-09-30 13:46:00 +000058 def test_contains(self):
59 d = {}
60 self.assert_(not ('a' in d))
61 self.assert_('a' not in d)
62 d = {'a': 1, 'b': 2}
63 self.assert_('a' in d)
64 self.assert_('b' in d)
65 self.assert_('c' not in d)
66
67 self.assertRaises(TypeError, d.__contains__)
68
69 def test_len(self):
70 d = {}
71 self.assertEqual(len(d), 0)
72 d = {'a': 1, 'b': 2}
73 self.assertEqual(len(d), 2)
74
75 def test_getitem(self):
76 d = {'a': 1, 'b': 2}
77 self.assertEqual(d['a'], 1)
78 self.assertEqual(d['b'], 2)
79 d['c'] = 3
80 d['a'] = 4
81 self.assertEqual(d['c'], 3)
82 self.assertEqual(d['a'], 4)
83 del d['b']
84 self.assertEqual(d, {'a': 4, 'c': 3})
85
86 self.assertRaises(TypeError, d.__getitem__)
87
88 class BadEq(object):
89 def __eq__(self, other):
90 raise Exc()
Guido van Rossum38938152006-08-21 23:36:26 +000091 def __hash__(self):
92 return 24
Walter Dörwald59b23e82004-09-30 13:46:00 +000093
94 d = {}
95 d[BadEq()] = 42
96 self.assertRaises(KeyError, d.__getitem__, 23)
97
98 class Exc(Exception): pass
99
100 class BadHash(object):
101 fail = False
102 def __hash__(self):
103 if self.fail:
104 raise Exc()
105 else:
106 return 42
107
108 x = BadHash()
109 d[x] = 42
110 x.fail = True
111 self.assertRaises(Exc, d.__getitem__, x)
112
113 def test_clear(self):
114 d = {1:1, 2:2, 3:3}
115 d.clear()
116 self.assertEqual(d, {})
117
118 self.assertRaises(TypeError, d.clear, None)
119
120 def test_update(self):
121 d = {}
122 d.update({1:100})
123 d.update({2:20})
124 d.update({1:1, 2:2, 3:3})
125 self.assertEqual(d, {1:1, 2:2, 3:3})
126
127 d.update()
128 self.assertEqual(d, {1:1, 2:2, 3:3})
129
130 self.assertRaises((TypeError, AttributeError), d.update, None)
131
132 class SimpleUserDict:
133 def __init__(self):
134 self.d = {1:1, 2:2, 3:3}
135 def keys(self):
136 return self.d.keys()
137 def __getitem__(self, i):
138 return self.d[i]
139 d.clear()
140 d.update(SimpleUserDict())
141 self.assertEqual(d, {1:1, 2:2, 3:3})
142
143 class Exc(Exception): pass
144
145 d.clear()
146 class FailingUserDict:
147 def keys(self):
148 raise Exc
149 self.assertRaises(Exc, d.update, FailingUserDict())
150
151 class FailingUserDict:
152 def keys(self):
153 class BogonIter:
154 def __init__(self):
155 self.i = 1
156 def __iter__(self):
157 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000158 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000159 if self.i:
160 self.i = 0
161 return 'a'
162 raise Exc
163 return BogonIter()
164 def __getitem__(self, key):
165 return key
166 self.assertRaises(Exc, d.update, FailingUserDict())
167
168 class FailingUserDict:
169 def keys(self):
170 class BogonIter:
171 def __init__(self):
172 self.i = ord('a')
173 def __iter__(self):
174 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000175 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000176 if self.i <= ord('z'):
177 rtn = chr(self.i)
178 self.i += 1
179 return rtn
180 raise StopIteration
181 return BogonIter()
182 def __getitem__(self, key):
183 raise Exc
184 self.assertRaises(Exc, d.update, FailingUserDict())
185
186 class badseq(object):
187 def __iter__(self):
188 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000189 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000190 raise Exc()
191
192 self.assertRaises(Exc, {}.update, badseq())
193
194 self.assertRaises(ValueError, {}.update, [(1, 2, 3)])
195
196 def test_fromkeys(self):
197 self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
198 d = {}
199 self.assert_(not(d.fromkeys('abc') is d))
200 self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
201 self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
202 self.assertEqual(d.fromkeys([]), {})
203 def g():
204 yield 1
205 self.assertEqual(d.fromkeys(g()), {1:None})
206 self.assertRaises(TypeError, {}.fromkeys, 3)
207 class dictlike(dict): pass
208 self.assertEqual(dictlike.fromkeys('a'), {'a':None})
209 self.assertEqual(dictlike().fromkeys('a'), {'a':None})
210 self.assert_(type(dictlike.fromkeys('a')) is dictlike)
211 self.assert_(type(dictlike().fromkeys('a')) is dictlike)
212 class mydict(dict):
213 def __new__(cls):
Raymond Hettingerf80680d2008-02-06 00:07:11 +0000214 return collections.UserDict()
Walter Dörwald59b23e82004-09-30 13:46:00 +0000215 ud = mydict.fromkeys('ab')
216 self.assertEqual(ud, {'a':None, 'b':None})
Raymond Hettingerf80680d2008-02-06 00:07:11 +0000217 self.assert_(isinstance(ud, collections.UserDict))
Walter Dörwald59b23e82004-09-30 13:46:00 +0000218 self.assertRaises(TypeError, dict.fromkeys)
219
220 class Exc(Exception): pass
221
222 class baddict1(dict):
223 def __init__(self):
224 raise Exc()
225
226 self.assertRaises(Exc, baddict1.fromkeys, [1])
227
228 class BadSeq(object):
229 def __iter__(self):
230 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000231 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000232 raise Exc()
233
234 self.assertRaises(Exc, dict.fromkeys, BadSeq())
235
236 class baddict2(dict):
237 def __setitem__(self, key, value):
238 raise Exc()
239
240 self.assertRaises(Exc, baddict2.fromkeys, [1])
241
Guido van Rossum58da9312007-11-10 23:39:45 +0000242 # test fast path for dictionary inputs
243 d = dict(zip(range(6), range(6)))
244 self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
245
Walter Dörwald59b23e82004-09-30 13:46:00 +0000246 def test_copy(self):
247 d = {1:1, 2:2, 3:3}
248 self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
249 self.assertEqual({}.copy(), {})
250 self.assertRaises(TypeError, d.copy, None)
251
252 def test_get(self):
253 d = {}
254 self.assert_(d.get('c') is None)
255 self.assertEqual(d.get('c', 3), 3)
256 d = {'a' : 1, 'b' : 2}
257 self.assert_(d.get('c') is None)
258 self.assertEqual(d.get('c', 3), 3)
259 self.assertEqual(d.get('a'), 1)
260 self.assertEqual(d.get('a', 3), 1)
261 self.assertRaises(TypeError, d.get)
262 self.assertRaises(TypeError, d.get, None, None, None)
263
264 def test_setdefault(self):
265 # dict.setdefault()
266 d = {}
267 self.assert_(d.setdefault('key0') is None)
268 d.setdefault('key0', [])
269 self.assert_(d.setdefault('key0') is None)
270 d.setdefault('key', []).append(3)
271 self.assertEqual(d['key'][0], 3)
272 d.setdefault('key', []).append(4)
273 self.assertEqual(len(d['key']), 2)
274 self.assertRaises(TypeError, d.setdefault)
275
276 class Exc(Exception): pass
277
278 class BadHash(object):
279 fail = False
280 def __hash__(self):
281 if self.fail:
282 raise Exc()
283 else:
284 return 42
285
286 x = BadHash()
287 d[x] = 42
288 x.fail = True
289 self.assertRaises(Exc, d.setdefault, x, [])
290
291 def test_popitem(self):
292 # dict.popitem()
293 for copymode in -1, +1:
294 # -1: b has same structure as a
295 # +1: b is a.copy()
296 for log2size in range(12):
297 size = 2**log2size
298 a = {}
299 b = {}
300 for i in range(size):
301 a[repr(i)] = i
302 if copymode < 0:
303 b[repr(i)] = i
304 if copymode > 0:
305 b = a.copy()
306 for i in range(size):
307 ka, va = ta = a.popitem()
308 self.assertEqual(va, int(ka))
309 kb, vb = tb = b.popitem()
310 self.assertEqual(vb, int(kb))
311 self.assert_(not(copymode < 0 and ta != tb))
312 self.assert_(not a)
313 self.assert_(not b)
314
315 d = {}
316 self.assertRaises(KeyError, d.popitem)
317
318 def test_pop(self):
319 # Tests for pop with specified key
320 d = {}
321 k, v = 'abc', 'def'
322 d[k] = v
323 self.assertRaises(KeyError, d.pop, 'ghi')
324
325 self.assertEqual(d.pop(k), v)
326 self.assertEqual(len(d), 0)
327
328 self.assertRaises(KeyError, d.pop, k)
329
330 # verify longs/ints get same value when key > 32 bits (for 64-bit archs)
331 # see SF bug #689659
Guido van Rossume2a383d2007-01-15 16:59:06 +0000332 x = 4503599627370496
Walter Dörwald59b23e82004-09-30 13:46:00 +0000333 y = 4503599627370496
334 h = {x: 'anything', y: 'something else'}
335 self.assertEqual(h[x], h[y])
336
337 self.assertEqual(d.pop(k, v), v)
338 d[k] = v
339 self.assertEqual(d.pop(k, 1), v)
340
341 self.assertRaises(TypeError, d.pop)
342
343 class Exc(Exception): pass
344
345 class BadHash(object):
346 fail = False
347 def __hash__(self):
348 if self.fail:
349 raise Exc()
350 else:
351 return 42
352
353 x = BadHash()
354 d[x] = 42
355 x.fail = True
356 self.assertRaises(Exc, d.pop, x)
357
358 def test_mutatingiteration(self):
359 d = {}
360 d[1] = 1
361 try:
362 for i in d:
363 d[i+1] = 1
364 except RuntimeError:
365 pass
366 else:
367 self.fail("changing dict size during iteration doesn't raise Error")
368
369 def test_repr(self):
370 d = {}
371 self.assertEqual(repr(d), '{}')
372 d[1] = 2
373 self.assertEqual(repr(d), '{1: 2}')
374 d = {}
375 d[1] = d
376 self.assertEqual(repr(d), '{1: {...}}')
377
378 class Exc(Exception): pass
379
380 class BadRepr(object):
381 def __repr__(self):
382 raise Exc()
383
384 d = {1: BadRepr()}
385 self.assertRaises(Exc, repr, d)
386
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000387 def test_eq(self):
388 self.assertEqual({}, {})
Guido van Rossume2a383d2007-01-15 16:59:06 +0000389 self.assertEqual({1: 2}, {1: 2})
Walter Dörwald59b23e82004-09-30 13:46:00 +0000390
391 class Exc(Exception): pass
392
393 class BadCmp(object):
394 def __eq__(self, other):
395 raise Exc()
Guido van Rossum38938152006-08-21 23:36:26 +0000396 def __hash__(self):
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000397 return 1
Walter Dörwald59b23e82004-09-30 13:46:00 +0000398
399 d1 = {BadCmp(): 1}
400 d2 = {1: 1}
401 try:
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000402 d1 == d2
Walter Dörwald59b23e82004-09-30 13:46:00 +0000403 except Exc:
404 pass
405 else:
406 self.fail("< didn't raise Exc")
407
Guido van Rossumaac530c2007-08-24 22:33:45 +0000408 def test_keys_contained(self):
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000409 self.helper_keys_contained(lambda x: x.keys())
410 self.helper_keys_contained(lambda x: x.items())
411
412 def helper_keys_contained(self, fn):
Guido van Rossumaac530c2007-08-24 22:33:45 +0000413 # Test rich comparisons against dict key views, which should behave the
414 # same as sets.
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000415 empty = fn(dict())
416 empty2 = fn(dict())
417 smaller = fn({1:1, 2:2})
418 larger = fn({1:1, 2:2, 3:3})
419 larger2 = fn({1:1, 2:2, 3:3})
420 larger3 = fn({4:1, 2:2, 3:3})
Guido van Rossumaac530c2007-08-24 22:33:45 +0000421
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000422 self.assertTrue(smaller < larger)
423 self.assertTrue(smaller <= larger)
424 self.assertTrue(larger > smaller)
425 self.assertTrue(larger >= smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000426
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000427 self.assertFalse(smaller >= larger)
428 self.assertFalse(smaller > larger)
429 self.assertFalse(larger <= smaller)
430 self.assertFalse(larger < smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000431
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000432 self.assertFalse(smaller < larger3)
433 self.assertFalse(smaller <= larger3)
434 self.assertFalse(larger3 > smaller)
435 self.assertFalse(larger3 >= smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000436
437 # Inequality strictness
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000438 self.assertTrue(larger2 >= larger)
439 self.assertTrue(larger2 <= larger)
440 self.assertFalse(larger2 > larger)
441 self.assertFalse(larger2 < larger)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000442
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000443 self.assertTrue(larger == larger2)
444 self.assertTrue(smaller != larger)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000445
446 # There is an optimization on the zero-element case.
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000447 self.assertTrue(empty == empty2)
448 self.assertFalse(empty != empty2)
449 self.assertFalse(empty == smaller)
450 self.assertTrue(empty != smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000451
452 # With the same size, an elementwise compare happens
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000453 self.assertTrue(larger != larger3)
454 self.assertFalse(larger == larger3)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000455
456 def test_errors_in_view_containment_check(self):
457 class C:
458 def __eq__(self, other):
459 raise RuntimeError
460 d1 = {1: C()}
461 d2 = {1: C()}
462 self.assertRaises(RuntimeError, lambda: d1.items() == d2.items())
463 self.assertRaises(RuntimeError, lambda: d1.items() != d2.items())
464 self.assertRaises(RuntimeError, lambda: d1.items() <= d2.items())
465 self.assertRaises(RuntimeError, lambda: d1.items() >= d2.items())
466 d3 = {1: C(), 2: C()}
467 self.assertRaises(RuntimeError, lambda: d2.items() < d3.items())
468 self.assertRaises(RuntimeError, lambda: d3.items() > d2.items())
469
Guido van Rossumbe534712007-08-24 23:43:52 +0000470 def test_dictview_set_operations_on_keys(self):
Guido van Rossum523259b2007-08-24 23:41:22 +0000471 k1 = {1:1, 2:2}.keys()
472 k2 = {1:1, 2:2, 3:3}.keys()
473 k3 = {4:4}.keys()
474
475 self.assertEquals(k1 - k2, set())
476 self.assertEquals(k1 - k3, {1,2})
477 self.assertEquals(k2 - k1, {3})
478 self.assertEquals(k3 - k1, {4})
479 self.assertEquals(k1 & k2, {1,2})
480 self.assertEquals(k1 & k3, set())
481 self.assertEquals(k1 | k2, {1,2,3})
482 self.assertEquals(k1 ^ k2, {3})
483 self.assertEquals(k1 ^ k3, {1,2,4})
484
Guido van Rossumbe534712007-08-24 23:43:52 +0000485 def test_dictview_set_operations_on_items(self):
486 k1 = {1:1, 2:2}.items()
487 k2 = {1:1, 2:2, 3:3}.items()
488 k3 = {4:4}.items()
489
490 self.assertEquals(k1 - k2, set())
491 self.assertEquals(k1 - k3, {(1,1), (2,2)})
492 self.assertEquals(k2 - k1, {(3,3)})
493 self.assertEquals(k3 - k1, {(4,4)})
494 self.assertEquals(k1 & k2, {(1,1), (2,2)})
495 self.assertEquals(k1 & k3, set())
496 self.assertEquals(k1 | k2, {(1,1), (2,2), (3,3)})
497 self.assertEquals(k1 ^ k2, {(3,3)})
498 self.assertEquals(k1 ^ k3, {(1,1), (2,2), (4,4)})
Guido van Rossum523259b2007-08-24 23:41:22 +0000499
Guido van Rossum1d719962007-08-24 23:47:30 +0000500 def test_dictview_mixed_set_operations(self):
501 # Just a few for .keys()
Guido van Rossuma401bbe2007-08-24 23:51:55 +0000502 self.assertTrue({1:1}.keys() == {1})
503 self.assertTrue({1} == {1:1}.keys())
Guido van Rossum1d719962007-08-24 23:47:30 +0000504 self.assertEquals({1:1}.keys() | {2}, {1, 2})
505 self.assertEquals({2} | {1:1}.keys(), {1, 2})
506 # And a few for .items()
Guido van Rossuma401bbe2007-08-24 23:51:55 +0000507 self.assertTrue({1:1}.items() == {(1,1)})
508 self.assertTrue({(1,1)} == {1:1}.items())
Guido van Rossum1d719962007-08-24 23:47:30 +0000509 self.assertEquals({1:1}.items() | {2}, {(1,1), 2})
510 self.assertEquals({2} | {1:1}.items(), {(1,1), 2})
511
Guido van Rossum1968ad32006-02-25 22:38:04 +0000512 def test_missing(self):
513 # Make sure dict doesn't have a __missing__ method
514 self.assertEqual(hasattr(dict, "__missing__"), False)
515 self.assertEqual(hasattr({}, "__missing__"), False)
516 # Test several cases:
517 # (D) subclass defines __missing__ method returning a value
518 # (E) subclass defines __missing__ method raising RuntimeError
519 # (F) subclass sets __missing__ instance variable (no effect)
520 # (G) subclass doesn't define __missing__ at a all
521 class D(dict):
522 def __missing__(self, key):
523 return 42
524 d = D({1: 2, 3: 4})
525 self.assertEqual(d[1], 2)
526 self.assertEqual(d[3], 4)
527 self.assert_(2 not in d)
528 self.assert_(2 not in d.keys())
529 self.assertEqual(d[2], 42)
530 class E(dict):
531 def __missing__(self, key):
532 raise RuntimeError(key)
533 e = E()
534 try:
535 e[42]
Guido van Rossumb940e112007-01-10 16:19:56 +0000536 except RuntimeError as err:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000537 self.assertEqual(err.args, (42,))
538 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000539 self.fail("e[42] didn't raise RuntimeError")
Guido van Rossum1968ad32006-02-25 22:38:04 +0000540 class F(dict):
541 def __init__(self):
542 # An instance variable __missing__ should have no effect
543 self.__missing__ = lambda key: None
544 f = F()
545 try:
546 f[42]
Guido van Rossumb940e112007-01-10 16:19:56 +0000547 except KeyError as err:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000548 self.assertEqual(err.args, (42,))
549 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000550 self.fail("f[42] didn't raise KeyError")
Guido van Rossum1968ad32006-02-25 22:38:04 +0000551 class G(dict):
552 pass
553 g = G()
554 try:
555 g[42]
Guido van Rossumb940e112007-01-10 16:19:56 +0000556 except KeyError as err:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000557 self.assertEqual(err.args, (42,))
558 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000559 self.fail("g[42] didn't raise KeyError")
Guido van Rossum1968ad32006-02-25 22:38:04 +0000560
Thomas Wouters89f507f2006-12-13 04:49:30 +0000561 def test_tuple_keyerror(self):
562 # SF #1576657
563 d = {}
564 try:
565 d[(1,)]
Guido van Rossumb940e112007-01-10 16:19:56 +0000566 except KeyError as e:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000567 self.assertEqual(e.args, ((1,),))
568 else:
569 self.fail("missing KeyError")
570
Guido van Rossumd8faa362007-04-27 19:54:29 +0000571 def test_bad_key(self):
572 # Dictionary lookups should fail if __cmp__() raises an exception.
573 class CustomException(Exception):
574 pass
575
576 class BadDictKey:
577 def __hash__(self):
578 return hash(self.__class__)
579
580 def __eq__(self, other):
581 if isinstance(other, self.__class__):
582 raise CustomException
583 return other
584
585 d = {}
586 x1 = BadDictKey()
587 x2 = BadDictKey()
588 d[x1] = 1
589 for stmt in ['d[x2] = 2',
590 'z = d[x2]',
591 'x2 in d',
592 'd.get(x2)',
593 'd.setdefault(x2, 42)',
594 'd.pop(x2)',
595 'd.update({x2: 2})']:
596 try:
597 exec(stmt, locals())
598 except CustomException:
599 pass
600 else:
601 self.fail("Statement %r didn't raise exception" % stmt)
602
603 def test_resize1(self):
604 # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
605 # This version got an assert failure in debug build, infinite loop in
606 # release build. Unfortunately, provoking this kind of stuff requires
607 # a mix of inserts and deletes hitting exactly the right hash codes in
608 # exactly the right order, and I can't think of a randomized approach
609 # that would be *likely* to hit a failing case in reasonable time.
610
611 d = {}
612 for i in range(5):
613 d[i] = i
614 for i in range(5):
615 del d[i]
616 for i in range(5, 9): # i==8 was the problem
617 d[i] = i
618
619 def test_resize2(self):
620 # Another dict resizing bug (SF bug #1456209).
621 # This caused Segmentation faults or Illegal instructions.
622
623 class X(object):
624 def __hash__(self):
625 return 5
626 def __eq__(self, other):
627 if resizing:
628 d.clear()
629 return False
630 d = {}
631 resizing = False
632 d[X()] = 1
633 d[X()] = 2
634 d[X()] = 3
635 d[X()] = 4
636 d[X()] = 5
637 # now trigger a resize
638 resizing = True
639 d[9] = 6
640
Guido van Rossum1968ad32006-02-25 22:38:04 +0000641
Neal Norwitzc3e54b82006-03-24 07:38:37 +0000642from test import mapping_tests
Raymond Hettinger49c522b2004-09-30 15:07:29 +0000643
644class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
645 type2test = dict
646
647class Dict(dict):
648 pass
649
650class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
651 type2test = Dict
652
Walter Dörwald59b23e82004-09-30 13:46:00 +0000653def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000654 support.run_unittest(
Walter Dörwald59b23e82004-09-30 13:46:00 +0000655 DictTest,
Raymond Hettinger49c522b2004-09-30 15:07:29 +0000656 GeneralMappingTests,
657 SubclassMappingTests,
Walter Dörwald59b23e82004-09-30 13:46:00 +0000658 )
659
660if __name__ == "__main__":
661 test_main()