this repo has no description
1#!/usr/bin/env python3
2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
3# WARNING: This is a temporary copy of code from the cpython library to
4# facilitate bringup. Please file a task for anything you change!
5# flake8: noqa
6# fmt: off
7
8# tests common to dict and UserDict
9import collections
10import sys
11import unittest
12
13
14class BasicTestMappingProtocol(unittest.TestCase):
15 # This base class can be used to check that an object conforms to the
16 # mapping protocol
17
18 # Functions that can be useful to override to adapt to dictionary
19 # semantics
20 type2test = None # which class is being tested (overwrite in subclasses)
21
22 def _reference(self):
23 """Return a dictionary of values which are invariant by storage
24 in the object under test."""
25 return {"1": "2", "key1":"value1", "key2":(1,2,3)}
26 def _empty_mapping(self):
27 """Return an empty mapping object"""
28 return self.type2test()
29 def _full_mapping(self, data):
30 """Return a mapping object with the value contained in data
31 dictionary"""
32 x = self._empty_mapping()
33 for key, value in data.items():
34 x[key] = value
35 return x
36
37 def __init__(self, *args, **kw):
38 unittest.TestCase.__init__(self, *args, **kw)
39 self.reference = self._reference().copy()
40
41 # A (key, value) pair not in the mapping
42 key, value = self.reference.popitem()
43 self.other = {key:value}
44
45 # A (key, value) pair in the mapping
46 key, value = self.reference.popitem()
47 self.inmapping = {key:value}
48 self.reference[key] = value
49
50 def test_read(self):
51 # Test for read only operations on mapping
52 p = self._empty_mapping()
53 p1 = dict(p) #workaround for singleton objects
54 d = self._full_mapping(self.reference)
55 if d is p:
56 p = p1
57 #Indexing
58 for key, value in self.reference.items():
59 self.assertEqual(d[key], value)
60 knownkey = list(self.other.keys())[0]
61 self.assertRaises(KeyError, lambda:d[knownkey])
62 #len
63 self.assertEqual(len(p), 0)
64 self.assertEqual(len(d), len(self.reference))
65 #__contains__
66 for k in self.reference:
67 self.assertIn(k, d)
68 for k in self.other:
69 self.assertNotIn(k, d)
70 #cmp
71 self.assertEqual(p, p)
72 self.assertEqual(d, d)
73 self.assertNotEqual(p, d)
74 self.assertNotEqual(d, p)
75 #bool
76 if p: self.fail("Empty mapping must compare to False")
77 if not d: self.fail("Full mapping must compare to True")
78 # keys(), items(), iterkeys() ...
79 def check_iterandlist(iter, lst, ref):
80 self.assertTrue(hasattr(iter, '__next__'))
81 self.assertTrue(hasattr(iter, '__iter__'))
82 x = list(iter)
83 self.assertTrue(set(x)==set(lst)==set(ref))
84 check_iterandlist(iter(d.keys()), list(d.keys()),
85 self.reference.keys())
86 check_iterandlist(iter(d), list(d.keys()), self.reference.keys())
87 check_iterandlist(iter(d.values()), list(d.values()),
88 self.reference.values())
89 check_iterandlist(iter(d.items()), list(d.items()),
90 self.reference.items())
91 #get
92 key, value = next(iter(d.items()))
93 knownkey, knownvalue = next(iter(self.other.items()))
94 self.assertEqual(d.get(key, knownvalue), value)
95 self.assertEqual(d.get(knownkey, knownvalue), knownvalue)
96 self.assertNotIn(knownkey, d)
97
98 def test_write(self):
99 # Test for write operations on mapping
100 p = self._empty_mapping()
101 #Indexing
102 for key, value in self.reference.items():
103 p[key] = value
104 self.assertEqual(p[key], value)
105 for key in self.reference.keys():
106 del p[key]
107 self.assertRaises(KeyError, lambda:p[key])
108 p = self._empty_mapping()
109 #update
110 p.update(self.reference)
111 self.assertEqual(dict(p), self.reference)
112 items = list(p.items())
113 p = self._empty_mapping()
114 p.update(items)
115 self.assertEqual(dict(p), self.reference)
116 d = self._full_mapping(self.reference)
117 #setdefault
118 key, value = next(iter(d.items()))
119 knownkey, knownvalue = next(iter(self.other.items()))
120 self.assertEqual(d.setdefault(key, knownvalue), value)
121 self.assertEqual(d[key], value)
122 self.assertEqual(d.setdefault(knownkey, knownvalue), knownvalue)
123 self.assertEqual(d[knownkey], knownvalue)
124 #pop
125 self.assertEqual(d.pop(knownkey), knownvalue)
126 self.assertNotIn(knownkey, d)
127 self.assertRaises(KeyError, d.pop, knownkey)
128 default = 909
129 d[knownkey] = knownvalue
130 self.assertEqual(d.pop(knownkey, default), knownvalue)
131 self.assertNotIn(knownkey, d)
132 self.assertEqual(d.pop(knownkey, default), default)
133 #popitem
134 key, value = d.popitem()
135 self.assertNotIn(key, d)
136 self.assertEqual(value, self.reference[key])
137 p=self._empty_mapping()
138 self.assertRaises(KeyError, p.popitem)
139
140 def test_constructor(self):
141 self.assertEqual(self._empty_mapping(), self._empty_mapping())
142
143 def test_bool(self):
144 self.assertTrue(not self._empty_mapping())
145 self.assertTrue(self.reference)
146 self.assertTrue(bool(self._empty_mapping()) is False)
147 self.assertTrue(bool(self.reference) is True)
148
149 def test_keys(self):
150 d = self._empty_mapping()
151 self.assertEqual(list(d.keys()), [])
152 d = self.reference
153 self.assertIn(list(self.inmapping.keys())[0], d.keys())
154 self.assertNotIn(list(self.other.keys())[0], d.keys())
155 self.assertRaises(TypeError, d.keys, None)
156
157 def test_values(self):
158 d = self._empty_mapping()
159 self.assertEqual(list(d.values()), [])
160
161 self.assertRaises(TypeError, d.values, None)
162
163 def test_items(self):
164 d = self._empty_mapping()
165 self.assertEqual(list(d.items()), [])
166
167 self.assertRaises(TypeError, d.items, None)
168
169 def test_len(self):
170 d = self._empty_mapping()
171 self.assertEqual(len(d), 0)
172
173 def test_getitem(self):
174 d = self.reference
175 self.assertEqual(d[list(self.inmapping.keys())[0]],
176 list(self.inmapping.values())[0])
177
178 self.assertRaises(TypeError, d.__getitem__)
179
180 def test_update(self):
181 # mapping argument
182 d = self._empty_mapping()
183 d.update(self.other)
184 self.assertEqual(list(d.items()), list(self.other.items()))
185
186 # No argument
187 d = self._empty_mapping()
188 d.update()
189 self.assertEqual(d, self._empty_mapping())
190
191 # item sequence
192 d = self._empty_mapping()
193 d.update(self.other.items())
194 self.assertEqual(list(d.items()), list(self.other.items()))
195
196 # Iterator
197 d = self._empty_mapping()
198 d.update(self.other.items())
199 self.assertEqual(list(d.items()), list(self.other.items()))
200
201 # FIXME: Doesn't work with UserDict
202 # self.assertRaises((TypeError, AttributeError), d.update, None)
203 self.assertRaises((TypeError, AttributeError), d.update, 42)
204
205 outerself = self
206 class SimpleUserDict:
207 def __init__(self):
208 self.d = outerself.reference
209 def keys(self):
210 return self.d.keys()
211 def __getitem__(self, i):
212 return self.d[i]
213 d.clear()
214 d.update(SimpleUserDict())
215 i1 = sorted(d.items())
216 i2 = sorted(self.reference.items())
217 self.assertEqual(i1, i2)
218
219 class Exc(Exception): pass
220
221 d = self._empty_mapping()
222 class FailingUserDict:
223 def keys(self):
224 raise Exc
225 # TODO(T54143154): Throw Exception if the keys method throws Exception
226 # self.assertRaises(Exc, d.update, FailingUserDict())
227
228 d.clear()
229
230 class FailingUserDict:
231 def keys(self):
232 class BogonIter:
233 def __init__(self):
234 self.i = 1
235 def __iter__(self):
236 return self
237 def __next__(self):
238 if self.i:
239 self.i = 0
240 return 'a'
241 raise Exc
242 return BogonIter()
243 def __getitem__(self, key):
244 return key
245 self.assertRaises(Exc, d.update, FailingUserDict())
246
247 class FailingUserDict:
248 def keys(self):
249 class BogonIter:
250 def __init__(self):
251 self.i = ord('a')
252 def __iter__(self):
253 return self
254 def __next__(self):
255 if self.i <= ord('z'):
256 rtn = chr(self.i)
257 self.i += 1
258 return rtn
259 raise StopIteration
260 return BogonIter()
261 def __getitem__(self, key):
262 raise Exc
263 self.assertRaises(Exc, d.update, FailingUserDict())
264
265 d = self._empty_mapping()
266 class badseq(object):
267 def __iter__(self):
268 return self
269 def __next__(self):
270 raise Exc()
271
272 self.assertRaises(Exc, d.update, badseq())
273
274 self.assertRaises(ValueError, d.update, [(1, 2, 3)])
275
276 # no test_fromkeys or test_copy as both os.environ and selves don't support it
277
278 def test_get(self):
279 d = self._empty_mapping()
280 self.assertTrue(d.get(list(self.other.keys())[0]) is None)
281 self.assertEqual(d.get(list(self.other.keys())[0], 3), 3)
282 d = self.reference
283 self.assertTrue(d.get(list(self.other.keys())[0]) is None)
284 self.assertEqual(d.get(list(self.other.keys())[0], 3), 3)
285 self.assertEqual(d.get(list(self.inmapping.keys())[0]),
286 list(self.inmapping.values())[0])
287 self.assertEqual(d.get(list(self.inmapping.keys())[0], 3),
288 list(self.inmapping.values())[0])
289 self.assertRaises(TypeError, d.get)
290 self.assertRaises(TypeError, d.get, None, None, None)
291
292 def test_setdefault(self):
293 d = self._empty_mapping()
294 self.assertRaises(TypeError, d.setdefault)
295
296 def test_popitem(self):
297 d = self._empty_mapping()
298 self.assertRaises(KeyError, d.popitem)
299 self.assertRaises(TypeError, d.popitem, 42)
300
301 def test_pop(self):
302 d = self._empty_mapping()
303 k, v = list(self.inmapping.items())[0]
304 d[k] = v
305 self.assertRaises(KeyError, d.pop, list(self.other.keys())[0])
306
307 self.assertEqual(d.pop(k), v)
308 self.assertEqual(len(d), 0)
309
310 self.assertRaises(KeyError, d.pop, k)
311
312
313class TestMappingProtocol(BasicTestMappingProtocol):
314 def test_constructor(self):
315 BasicTestMappingProtocol.test_constructor(self)
316 self.assertTrue(self._empty_mapping() is not self._empty_mapping())
317 self.assertEqual(self.type2test(x=1, y=2), {"x": 1, "y": 2})
318
319 def test_bool(self):
320 BasicTestMappingProtocol.test_bool(self)
321 self.assertTrue(not self._empty_mapping())
322 self.assertTrue(self._full_mapping({"x": "y"}))
323 self.assertTrue(bool(self._empty_mapping()) is False)
324 self.assertTrue(bool(self._full_mapping({"x": "y"})) is True)
325
326 def test_keys(self):
327 BasicTestMappingProtocol.test_keys(self)
328 d = self._empty_mapping()
329 self.assertEqual(list(d.keys()), [])
330 d = self._full_mapping({'a': 1, 'b': 2})
331 k = d.keys()
332 self.assertIn('a', k)
333 self.assertIn('b', k)
334 self.assertNotIn('c', k)
335
336 def test_values(self):
337 BasicTestMappingProtocol.test_values(self)
338 d = self._full_mapping({1:2})
339 self.assertEqual(list(d.values()), [2])
340
341 def test_items(self):
342 BasicTestMappingProtocol.test_items(self)
343
344 d = self._full_mapping({1:2})
345 self.assertEqual(list(d.items()), [(1, 2)])
346
347 def test_contains(self):
348 d = self._empty_mapping()
349 self.assertNotIn('a', d)
350 self.assertTrue(not ('a' in d))
351 self.assertTrue('a' not in d)
352 d = self._full_mapping({'a': 1, 'b': 2})
353 self.assertIn('a', d)
354 self.assertIn('b', d)
355 self.assertNotIn('c', d)
356
357 self.assertRaises(TypeError, d.__contains__)
358
359 def test_len(self):
360 BasicTestMappingProtocol.test_len(self)
361 d = self._full_mapping({'a': 1, 'b': 2})
362 self.assertEqual(len(d), 2)
363
364 def test_getitem(self):
365 BasicTestMappingProtocol.test_getitem(self)
366 d = self._full_mapping({'a': 1, 'b': 2})
367 self.assertEqual(d['a'], 1)
368 self.assertEqual(d['b'], 2)
369 d['c'] = 3
370 d['a'] = 4
371 self.assertEqual(d['c'], 3)
372 self.assertEqual(d['a'], 4)
373 del d['b']
374 self.assertEqual(d, {'a': 4, 'c': 3})
375
376 self.assertRaises(TypeError, d.__getitem__)
377
378 def test_clear(self):
379 d = self._full_mapping({1:1, 2:2, 3:3})
380 d.clear()
381 self.assertEqual(d, {})
382
383 self.assertRaises(TypeError, d.clear, None)
384
385 def test_update(self):
386 BasicTestMappingProtocol.test_update(self)
387 # mapping argument
388 d = self._empty_mapping()
389 d.update({1:100})
390 d.update({2:20})
391 d.update({1:1, 2:2, 3:3})
392 self.assertEqual(d, {1:1, 2:2, 3:3})
393
394 # no argument
395 d.update()
396 self.assertEqual(d, {1:1, 2:2, 3:3})
397
398 # keyword arguments
399 d = self._empty_mapping()
400 d.update(x=100)
401 d.update(y=20)
402 d.update(x=1, y=2, z=3)
403 self.assertEqual(d, {"x":1, "y":2, "z":3})
404
405 # item sequence
406 d = self._empty_mapping()
407 d.update([("x", 100), ("y", 20)])
408 self.assertEqual(d, {"x":100, "y":20})
409
410 # Both item sequence and keyword arguments
411 d = self._empty_mapping()
412 d.update([("x", 100), ("y", 20)], x=1, y=2)
413 self.assertEqual(d, {"x":1, "y":2})
414
415 # iterator
416 d = self._full_mapping({1:3, 2:4})
417 d.update(self._full_mapping({1:2, 3:4, 5:6}).items())
418 self.assertEqual(d, {1:2, 2:4, 3:4, 5:6})
419
420 class SimpleUserDict:
421 def __init__(self):
422 self.d = {1:1, 2:2, 3:3}
423 def keys(self):
424 return self.d.keys()
425 def __getitem__(self, i):
426 return self.d[i]
427 d.clear()
428 d.update(SimpleUserDict())
429 self.assertEqual(d, {1:1, 2:2, 3:3})
430
431 def test_fromkeys(self):
432 self.assertEqual(self.type2test.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
433 d = self._empty_mapping()
434 self.assertTrue(not(d.fromkeys('abc') is d))
435 self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
436 self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
437 self.assertEqual(d.fromkeys([]), {})
438 def g():
439 yield 1
440 self.assertEqual(d.fromkeys(g()), {1:None})
441 self.assertRaises(TypeError, {}.fromkeys, 3)
442 class dictlike(self.type2test): pass
443 self.assertEqual(dictlike.fromkeys('a'), {'a':None})
444 self.assertEqual(dictlike().fromkeys('a'), {'a':None})
445 self.assertTrue(dictlike.fromkeys('a').__class__ is dictlike)
446 self.assertTrue(dictlike().fromkeys('a').__class__ is dictlike)
447 self.assertTrue(type(dictlike.fromkeys('a')) is dictlike)
448 class mydict(self.type2test):
449 def __new__(cls):
450 return collections.UserDict()
451 ud = mydict.fromkeys('ab')
452 self.assertEqual(ud, {'a':None, 'b':None})
453 self.assertIsInstance(ud, collections.UserDict)
454 self.assertRaises(TypeError, dict.fromkeys)
455
456 class Exc(Exception): pass
457
458 class baddict1(self.type2test):
459 def __init__(self):
460 raise Exc()
461
462 self.assertRaises(Exc, baddict1.fromkeys, [1])
463
464 class BadSeq(object):
465 def __iter__(self):
466 return self
467 def __next__(self):
468 raise Exc()
469
470 self.assertRaises(Exc, self.type2test.fromkeys, BadSeq())
471
472 class baddict2(self.type2test):
473 def __setitem__(self, key, value):
474 raise Exc()
475
476 self.assertRaises(Exc, baddict2.fromkeys, [1])
477
478 def test_copy(self):
479 d = self._full_mapping({1:1, 2:2, 3:3})
480 self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
481 d = self._empty_mapping()
482 self.assertEqual(d.copy(), d)
483 self.assertIsInstance(d.copy(), d.__class__)
484 self.assertRaises(TypeError, d.copy, None)
485
486 def test_get(self):
487 BasicTestMappingProtocol.test_get(self)
488 d = self._empty_mapping()
489 self.assertTrue(d.get('c') is None)
490 self.assertEqual(d.get('c', 3), 3)
491 d = self._full_mapping({'a' : 1, 'b' : 2})
492 self.assertTrue(d.get('c') is None)
493 self.assertEqual(d.get('c', 3), 3)
494 self.assertEqual(d.get('a'), 1)
495 self.assertEqual(d.get('a', 3), 1)
496
497 def test_setdefault(self):
498 BasicTestMappingProtocol.test_setdefault(self)
499 d = self._empty_mapping()
500 self.assertTrue(d.setdefault('key0') is None)
501 d.setdefault('key0', [])
502 self.assertTrue(d.setdefault('key0') is None)
503 d.setdefault('key', []).append(3)
504 self.assertEqual(d['key'][0], 3)
505 d.setdefault('key', []).append(4)
506 self.assertEqual(len(d['key']), 2)
507
508 def test_popitem(self):
509 BasicTestMappingProtocol.test_popitem(self)
510 for copymode in -1, +1:
511 # -1: b has same structure as a
512 # +1: b is a.copy()
513 for log2size in range(12):
514 size = 2**log2size
515 a = self._empty_mapping()
516 b = self._empty_mapping()
517 for i in range(size):
518 a[repr(i)] = i
519 if copymode < 0:
520 b[repr(i)] = i
521 if copymode > 0:
522 b = a.copy()
523 for i in range(size):
524 ka, va = ta = a.popitem()
525 self.assertEqual(va, int(ka))
526 kb, vb = tb = b.popitem()
527 self.assertEqual(vb, int(kb))
528 self.assertTrue(not(copymode < 0 and ta != tb))
529 self.assertTrue(not a)
530 self.assertTrue(not b)
531
532 def test_pop(self):
533 BasicTestMappingProtocol.test_pop(self)
534
535 # Tests for pop with specified key
536 d = self._empty_mapping()
537 k, v = 'abc', 'def'
538
539 self.assertEqual(d.pop(k, v), v)
540 d[k] = v
541 self.assertEqual(d.pop(k, 1), v)
542
543
544class TestHashMappingProtocol(TestMappingProtocol):
545
546 def test_getitem(self):
547 TestMappingProtocol.test_getitem(self)
548 class Exc(Exception): pass
549
550 class BadEq(object):
551 def __eq__(self, other):
552 raise Exc()
553 def __hash__(self):
554 return 24
555
556 d = self._empty_mapping()
557 d[BadEq()] = 42
558 self.assertRaises(KeyError, d.__getitem__, 23)
559
560 class BadHash(object):
561 fail = False
562 def __hash__(self):
563 if self.fail:
564 raise Exc()
565 else:
566 return 42
567
568 d = self._empty_mapping()
569 x = BadHash()
570 d[x] = 42
571 x.fail = True
572 self.assertRaises(Exc, d.__getitem__, x)
573
574 def test_fromkeys(self):
575 TestMappingProtocol.test_fromkeys(self)
576 class mydict(self.type2test):
577 def __new__(cls):
578 return collections.UserDict()
579 ud = mydict.fromkeys('ab')
580 self.assertEqual(ud, {'a':None, 'b':None})
581 self.assertIsInstance(ud, collections.UserDict)
582
583 def test_pop(self):
584 TestMappingProtocol.test_pop(self)
585
586 class Exc(Exception): pass
587
588 class BadHash(object):
589 fail = False
590 def __hash__(self):
591 if self.fail:
592 raise Exc()
593 else:
594 return 42
595
596 d = self._empty_mapping()
597 x = BadHash()
598 d[x] = 42
599 x.fail = True
600 self.assertRaises(Exc, d.pop, x)
601
602 def test_mutatingiteration(self):
603 d = self._empty_mapping()
604 d[1] = 1
605 try:
606 for i in d:
607 d[i+1] = 1
608 except RuntimeError:
609 pass
610 else:
611 self.fail("changing dict size during iteration doesn't raise Error")
612
613 def test_repr(self):
614 d = self._empty_mapping()
615 self.assertEqual(repr(d), '{}')
616 d[1] = 2
617 self.assertEqual(repr(d), '{1: 2}')
618 d = self._empty_mapping()
619 d[1] = d
620 self.assertEqual(repr(d), '{1: {...}}')
621
622 class Exc(Exception): pass
623
624 class BadRepr(object):
625 def __repr__(self):
626 raise Exc()
627
628 d = self._full_mapping({1: BadRepr()})
629 self.assertRaises(Exc, repr, d)
630
631 def test_repr_deep(self):
632 d = self._empty_mapping()
633 for i in range(sys.getrecursionlimit() + 100):
634 d0 = d
635 d = self._empty_mapping()
636 d[1] = d0
637 self.assertRaises(RecursionError, repr, d)
638
639 def test_eq(self):
640 self.assertEqual(self._empty_mapping(), self._empty_mapping())
641 self.assertEqual(self._full_mapping({1: 2}),
642 self._full_mapping({1: 2}))
643
644 class Exc(Exception): pass
645
646 class BadCmp(object):
647 def __eq__(self, other):
648 raise Exc()
649 def __hash__(self):
650 return 1
651
652 d1 = self._full_mapping({BadCmp(): 1})
653 d2 = self._full_mapping({1: 1})
654 self.assertRaises(Exc, lambda: BadCmp()==1)
655 self.assertRaises(Exc, lambda: d1==d2)
656
657 def test_setdefault(self):
658 TestMappingProtocol.test_setdefault(self)
659
660 class Exc(Exception): pass
661
662 class BadHash(object):
663 fail = False
664 def __hash__(self):
665 if self.fail:
666 raise Exc()
667 else:
668 return 42
669
670 d = self._empty_mapping()
671 x = BadHash()
672 d[x] = 42
673 x.fail = True
674 self.assertRaises(Exc, d.setdefault, x, [])