this repo has no description
at trunk 674 lines 23 kB view raw
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, [])