/Lib/test/test_deque.py
Python | 705 lines | 675 code | 25 blank | 5 comment | 25 complexity | 9524415fd11032f7d520bbe2be28b563 MD5 | raw file
1from collections import deque 2import unittest 3from test import test_support, seq_tests 4import gc 5import weakref 6import copy 7import cPickle as pickle 8import random 9import os 10 11BIG = 100000 12 13def fail(): 14 raise SyntaxError 15 yield 1 16 17class BadCmp: 18 def __eq__(self, other): 19 raise RuntimeError 20 21class MutateCmp: 22 def __init__(self, deque, result): 23 self.deque = deque 24 self.result = result 25 def __eq__(self, other): 26 self.deque.clear() 27 return self.result 28 29class TestBasic(unittest.TestCase): 30 31 def test_basics(self): 32 d = deque(xrange(-5125, -5000)) 33 d.__init__(xrange(200)) 34 for i in xrange(200, 400): 35 d.append(i) 36 for i in reversed(xrange(-200, 0)): 37 d.appendleft(i) 38 self.assertEqual(list(d), range(-200, 400)) 39 self.assertEqual(len(d), 600) 40 41 left = [d.popleft() for i in xrange(250)] 42 self.assertEqual(left, range(-200, 50)) 43 self.assertEqual(list(d), range(50, 400)) 44 45 right = [d.pop() for i in xrange(250)] 46 right.reverse() 47 self.assertEqual(right, range(150, 400)) 48 self.assertEqual(list(d), range(50, 150)) 49 50 def test_maxlen(self): 51 self.assertRaises(ValueError, deque, 'abc', -1) 52 self.assertRaises(ValueError, deque, 'abc', -2) 53 d = deque(range(10), maxlen=3) 54 self.assertEqual(repr(d), 'deque([7, 8, 9], maxlen=3)') 55 self.assertEqual(list(d), range(7, 10)) 56 self.assertEqual(d, deque(range(10), 3)) 57 d.append(10) 58 self.assertEqual(list(d), range(8, 11)) 59 d.appendleft(7) 60 self.assertEqual(list(d), range(7, 10)) 61 d.extend([10, 11]) 62 self.assertEqual(list(d), range(9, 12)) 63 d.extendleft([8, 7]) 64 self.assertEqual(list(d), range(7, 10)) 65 d = deque(xrange(200), maxlen=10) 66 d.append(d) 67 test_support.unlink(test_support.TESTFN) 68 fo = open(test_support.TESTFN, "wb") 69 try: 70 print >> fo, d, 71 fo.close() 72 fo = open(test_support.TESTFN, "rb") 73 self.assertEqual(fo.read(), repr(d)) 74 finally: 75 fo.close() 76 test_support.unlink(test_support.TESTFN) 77 78 d = deque(range(10), maxlen=None) 79 self.assertEqual(repr(d), 'deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])') 80 fo = open(test_support.TESTFN, "wb") 81 try: 82 print >> fo, d, 83 fo.close() 84 fo = open(test_support.TESTFN, "rb") 85 self.assertEqual(fo.read(), repr(d)) 86 finally: 87 fo.close() 88 test_support.unlink(test_support.TESTFN) 89 90 def test_comparisons(self): 91 d = deque('xabc'); d.popleft() 92 for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: 93 self.assertEqual(d==e, type(d)==type(e) and list(d)==list(e)) 94 self.assertEqual(d!=e, not(type(d)==type(e) and list(d)==list(e))) 95 96 args = map(deque, ('', 'a', 'b', 'ab', 'ba', 'abc', 'xba', 'xabc', 'cba')) 97 for x in args: 98 for y in args: 99 self.assertEqual(x == y, list(x) == list(y), (x,y)) 100 self.assertEqual(x != y, list(x) != list(y), (x,y)) 101 self.assertEqual(x < y, list(x) < list(y), (x,y)) 102 self.assertEqual(x <= y, list(x) <= list(y), (x,y)) 103 self.assertEqual(x > y, list(x) > list(y), (x,y)) 104 self.assertEqual(x >= y, list(x) >= list(y), (x,y)) 105 self.assertEqual(cmp(x,y), cmp(list(x),list(y)), (x,y)) 106 107 def test_extend(self): 108 d = deque('a') 109 self.assertRaises(TypeError, d.extend, 1) 110 d.extend('bcd') 111 self.assertEqual(list(d), list('abcd')) 112 113 def test_extendleft(self): 114 d = deque('a') 115 self.assertRaises(TypeError, d.extendleft, 1) 116 d.extendleft('bcd') 117 self.assertEqual(list(d), list(reversed('abcd'))) 118 d = deque() 119 d.extendleft(range(1000)) 120 self.assertEqual(list(d), list(reversed(range(1000)))) 121 self.assertRaises(SyntaxError, d.extendleft, fail()) 122 123 def test_getitem(self): 124 n = 200 125 d = deque(xrange(n)) 126 l = range(n) 127 for i in xrange(n): 128 d.popleft() 129 l.pop(0) 130 if random.random() < 0.5: 131 d.append(i) 132 l.append(i) 133 for j in xrange(1-len(l), len(l)): 134 assert d[j] == l[j] 135 136 d = deque('superman') 137 self.assertEqual(d[0], 's') 138 self.assertEqual(d[-1], 'n') 139 d = deque() 140 self.assertRaises(IndexError, d.__getitem__, 0) 141 self.assertRaises(IndexError, d.__getitem__, -1) 142 143 def test_setitem(self): 144 n = 200 145 d = deque(xrange(n)) 146 for i in xrange(n): 147 d[i] = 10 * i 148 self.assertEqual(list(d), [10*i for i in xrange(n)]) 149 l = list(d) 150 for i in xrange(1-n, 0, -1): 151 d[i] = 7*i 152 l[i] = 7*i 153 self.assertEqual(list(d), l) 154 155 def test_delitem(self): 156 n = 500 # O(n**2) test, don't make this too big 157 d = deque(xrange(n)) 158 self.assertRaises(IndexError, d.__delitem__, -n-1) 159 self.assertRaises(IndexError, d.__delitem__, n) 160 for i in xrange(n): 161 self.assertEqual(len(d), n-i) 162 j = random.randrange(-len(d), len(d)) 163 val = d[j] 164 self.assert_(val in d) 165 del d[j] 166 self.assert_(val not in d) 167 self.assertEqual(len(d), 0) 168 169 def test_rotate(self): 170 s = tuple('abcde') 171 n = len(s) 172 173 d = deque(s) 174 d.rotate(1) # verify rot(1) 175 self.assertEqual(''.join(d), 'eabcd') 176 177 d = deque(s) 178 d.rotate(-1) # verify rot(-1) 179 self.assertEqual(''.join(d), 'bcdea') 180 d.rotate() # check default to 1 181 self.assertEqual(tuple(d), s) 182 183 for i in xrange(n*3): 184 d = deque(s) 185 e = deque(d) 186 d.rotate(i) # check vs. rot(1) n times 187 for j in xrange(i): 188 e.rotate(1) 189 self.assertEqual(tuple(d), tuple(e)) 190 d.rotate(-i) # check that it works in reverse 191 self.assertEqual(tuple(d), s) 192 e.rotate(n-i) # check that it wraps forward 193 self.assertEqual(tuple(e), s) 194 195 for i in xrange(n*3): 196 d = deque(s) 197 e = deque(d) 198 d.rotate(-i) 199 for j in xrange(i): 200 e.rotate(-1) # check vs. rot(-1) n times 201 self.assertEqual(tuple(d), tuple(e)) 202 d.rotate(i) # check that it works in reverse 203 self.assertEqual(tuple(d), s) 204 e.rotate(i-n) # check that it wraps backaround 205 self.assertEqual(tuple(e), s) 206 207 d = deque(s) 208 e = deque(s) 209 e.rotate(BIG+17) # verify on long series of rotates 210 dr = d.rotate 211 for i in xrange(BIG+17): 212 dr() 213 self.assertEqual(tuple(d), tuple(e)) 214 215 self.assertRaises(TypeError, d.rotate, 'x') # Wrong arg type 216 self.assertRaises(TypeError, d.rotate, 1, 10) # Too many args 217 218 d = deque() 219 d.rotate() # rotate an empty deque 220 self.assertEqual(d, deque()) 221 222 def test_len(self): 223 d = deque('ab') 224 self.assertEqual(len(d), 2) 225 d.popleft() 226 self.assertEqual(len(d), 1) 227 d.pop() 228 self.assertEqual(len(d), 0) 229 self.assertRaises(IndexError, d.pop) 230 self.assertEqual(len(d), 0) 231 d.append('c') 232 self.assertEqual(len(d), 1) 233 d.appendleft('d') 234 self.assertEqual(len(d), 2) 235 d.clear() 236 self.assertEqual(len(d), 0) 237 238 def test_underflow(self): 239 d = deque() 240 self.assertRaises(IndexError, d.pop) 241 self.assertRaises(IndexError, d.popleft) 242 243 def test_clear(self): 244 d = deque(xrange(100)) 245 self.assertEqual(len(d), 100) 246 d.clear() 247 self.assertEqual(len(d), 0) 248 self.assertEqual(list(d), []) 249 d.clear() # clear an emtpy deque 250 self.assertEqual(list(d), []) 251 252 def test_remove(self): 253 d = deque('abcdefghcij') 254 d.remove('c') 255 self.assertEqual(d, deque('abdefghcij')) 256 d.remove('c') 257 self.assertEqual(d, deque('abdefghij')) 258 self.assertRaises(ValueError, d.remove, 'c') 259 self.assertEqual(d, deque('abdefghij')) 260 261 # Handle comparison errors 262 d = deque(['a', 'b', BadCmp(), 'c']) 263 e = deque(d) 264 self.assertRaises(RuntimeError, d.remove, 'c') 265 for x, y in zip(d, e): 266 # verify that original order and values are retained. 267 self.assert_(x is y) 268 269 # Handle evil mutator 270 for match in (True, False): 271 d = deque(['ab']) 272 d.extend([MutateCmp(d, match), 'c']) 273 self.assertRaises(IndexError, d.remove, 'c') 274 self.assertEqual(d, deque()) 275 276 def test_repr(self): 277 d = deque(xrange(200)) 278 e = eval(repr(d)) 279 self.assertEqual(list(d), list(e)) 280 d.append(d) 281 self.assert_('...' in repr(d)) 282 283 def test_print(self): 284 d = deque(xrange(200)) 285 d.append(d) 286 test_support.unlink(test_support.TESTFN) 287 fo = open(test_support.TESTFN, "wb") 288 try: 289 print >> fo, d, 290 fo.close() 291 fo = open(test_support.TESTFN, "rb") 292 self.assertEqual(fo.read(), repr(d)) 293 finally: 294 fo.close() 295 test_support.unlink(test_support.TESTFN) 296 297 def test_init(self): 298 self.assertRaises(TypeError, deque, 'abc', 2, 3); 299 self.assertRaises(TypeError, deque, 1); 300 301 def test_hash(self): 302 self.assertRaises(TypeError, hash, deque('abc')) 303 304 def test_long_steadystate_queue_popleft(self): 305 for size in (0, 1, 2, 100, 1000): 306 d = deque(xrange(size)) 307 append, pop = d.append, d.popleft 308 for i in xrange(size, BIG): 309 append(i) 310 x = pop() 311 if x != i - size: 312 self.assertEqual(x, i-size) 313 self.assertEqual(list(d), range(BIG-size, BIG)) 314 315 def test_long_steadystate_queue_popright(self): 316 for size in (0, 1, 2, 100, 1000): 317 d = deque(reversed(xrange(size))) 318 append, pop = d.appendleft, d.pop 319 for i in xrange(size, BIG): 320 append(i) 321 x = pop() 322 if x != i - size: 323 self.assertEqual(x, i-size) 324 self.assertEqual(list(reversed(list(d))), range(BIG-size, BIG)) 325 326 def test_big_queue_popleft(self): 327 pass 328 d = deque() 329 append, pop = d.append, d.popleft 330 for i in xrange(BIG): 331 append(i) 332 for i in xrange(BIG): 333 x = pop() 334 if x != i: 335 self.assertEqual(x, i) 336 337 def test_big_queue_popright(self): 338 d = deque() 339 append, pop = d.appendleft, d.pop 340 for i in xrange(BIG): 341 append(i) 342 for i in xrange(BIG): 343 x = pop() 344 if x != i: 345 self.assertEqual(x, i) 346 347 def test_big_stack_right(self): 348 d = deque() 349 append, pop = d.append, d.pop 350 for i in xrange(BIG): 351 append(i) 352 for i in reversed(xrange(BIG)): 353 x = pop() 354 if x != i: 355 self.assertEqual(x, i) 356 self.assertEqual(len(d), 0) 357 358 def test_big_stack_left(self): 359 d = deque() 360 append, pop = d.appendleft, d.popleft 361 for i in xrange(BIG): 362 append(i) 363 for i in reversed(xrange(BIG)): 364 x = pop() 365 if x != i: 366 self.assertEqual(x, i) 367 self.assertEqual(len(d), 0) 368 369 def test_roundtrip_iter_init(self): 370 d = deque(xrange(200)) 371 e = deque(d) 372 self.assertNotEqual(id(d), id(e)) 373 self.assertEqual(list(d), list(e)) 374 375 def test_pickle(self): 376 d = deque(xrange(200)) 377 for i in range(pickle.HIGHEST_PROTOCOL + 1): 378 s = pickle.dumps(d, i) 379 e = pickle.loads(s) 380 self.assertNotEqual(id(d), id(e)) 381 self.assertEqual(list(d), list(e)) 382 383## def test_pickle_recursive(self): 384## d = deque('abc') 385## d.append(d) 386## for i in range(pickle.HIGHEST_PROTOCOL + 1): 387## e = pickle.loads(pickle.dumps(d, i)) 388## self.assertNotEqual(id(d), id(e)) 389## self.assertEqual(id(e), id(e[-1])) 390 391 def test_deepcopy(self): 392 mut = [10] 393 d = deque([mut]) 394 e = copy.deepcopy(d) 395 self.assertEqual(list(d), list(e)) 396 mut[0] = 11 397 self.assertNotEqual(id(d), id(e)) 398 self.assertNotEqual(list(d), list(e)) 399 400 def test_copy(self): 401 mut = [10] 402 d = deque([mut]) 403 e = copy.copy(d) 404 self.assertEqual(list(d), list(e)) 405 mut[0] = 11 406 self.assertNotEqual(id(d), id(e)) 407 self.assertEqual(list(d), list(e)) 408 409 def test_reversed(self): 410 for s in ('abcd', xrange(2000)): 411 self.assertEqual(list(reversed(deque(s))), list(reversed(s))) 412 413 def test_gc_doesnt_blowup(self): 414 import gc 415 # This used to assert-fail in deque_traverse() under a debug 416 # build, or run wild with a NULL pointer in a release build. 417 d = deque() 418 for i in xrange(100): 419 d.append(1) 420 gc.collect() 421 422 def test_container_iterator(self): 423 # Bug #3680: tp_traverse was not implemented for deque iterator objects 424 class C(object): 425 pass 426 for i in range(2): 427 obj = C() 428 ref = weakref.ref(obj) 429 if i == 0: 430 container = deque([obj, 1]) 431 else: 432 container = reversed(deque([obj, 1])) 433 obj.x = iter(container) 434 del obj, container 435 gc.collect() 436 self.assert_(ref() is None, "Cycle was not collected") 437 438class TestVariousIteratorArgs(unittest.TestCase): 439 440 def test_constructor(self): 441 for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): 442 for g in (seq_tests.Sequence, seq_tests.IterFunc, 443 seq_tests.IterGen, seq_tests.IterFuncStop, 444 seq_tests.itermulti, seq_tests.iterfunc): 445 self.assertEqual(list(deque(g(s))), list(g(s))) 446 self.assertRaises(TypeError, deque, seq_tests.IterNextOnly(s)) 447 self.assertRaises(TypeError, deque, seq_tests.IterNoNext(s)) 448 self.assertRaises(ZeroDivisionError, deque, seq_tests.IterGenExc(s)) 449 450 def test_iter_with_altered_data(self): 451 d = deque('abcdefg') 452 it = iter(d) 453 d.pop() 454 self.assertRaises(RuntimeError, it.next) 455 456 def test_runtime_error_on_empty_deque(self): 457 d = deque() 458 it = iter(d) 459 d.append(10) 460 self.assertRaises(RuntimeError, it.next) 461 462class Deque(deque): 463 pass 464 465class DequeWithBadIter(deque): 466 def __iter__(self): 467 raise TypeError 468 469class TestSubclass(unittest.TestCase): 470 471 def test_basics(self): 472 d = Deque(xrange(25)) 473 d.__init__(xrange(200)) 474 for i in xrange(200, 400): 475 d.append(i) 476 for i in reversed(xrange(-200, 0)): 477 d.appendleft(i) 478 self.assertEqual(list(d), range(-200, 400)) 479 self.assertEqual(len(d), 600) 480 481 left = [d.popleft() for i in xrange(250)] 482 self.assertEqual(left, range(-200, 50)) 483 self.assertEqual(list(d), range(50, 400)) 484 485 right = [d.pop() for i in xrange(250)] 486 right.reverse() 487 self.assertEqual(right, range(150, 400)) 488 self.assertEqual(list(d), range(50, 150)) 489 490 d.clear() 491 self.assertEqual(len(d), 0) 492 493 def test_copy_pickle(self): 494 495 d = Deque('abc') 496 497 e = d.__copy__() 498 self.assertEqual(type(d), type(e)) 499 self.assertEqual(list(d), list(e)) 500 501 e = Deque(d) 502 self.assertEqual(type(d), type(e)) 503 self.assertEqual(list(d), list(e)) 504 505 s = pickle.dumps(d) 506 e = pickle.loads(s) 507 self.assertNotEqual(id(d), id(e)) 508 self.assertEqual(type(d), type(e)) 509 self.assertEqual(list(d), list(e)) 510 511 d = Deque('abcde', maxlen=4) 512 513 e = d.__copy__() 514 self.assertEqual(type(d), type(e)) 515 self.assertEqual(list(d), list(e)) 516 517 e = Deque(d) 518 self.assertEqual(type(d), type(e)) 519 self.assertEqual(list(d), list(e)) 520 521 s = pickle.dumps(d) 522 e = pickle.loads(s) 523 self.assertNotEqual(id(d), id(e)) 524 self.assertEqual(type(d), type(e)) 525 self.assertEqual(list(d), list(e)) 526 527## def test_pickle(self): 528## d = Deque('abc') 529## d.append(d) 530## 531## e = pickle.loads(pickle.dumps(d)) 532## self.assertNotEqual(id(d), id(e)) 533## self.assertEqual(type(d), type(e)) 534## dd = d.pop() 535## ee = e.pop() 536## self.assertEqual(id(e), id(ee)) 537## self.assertEqual(d, e) 538## 539## d.x = d 540## e = pickle.loads(pickle.dumps(d)) 541## self.assertEqual(id(e), id(e.x)) 542## 543## d = DequeWithBadIter('abc') 544## self.assertRaises(TypeError, pickle.dumps, d) 545 546 def test_weakref(self): 547 d = deque('gallahad') 548 p = weakref.proxy(d) 549 self.assertEqual(str(p), str(d)) 550 d = None 551 self.assertRaises(ReferenceError, str, p) 552 553 def test_strange_subclass(self): 554 class X(deque): 555 def __iter__(self): 556 return iter([]) 557 d1 = X([1,2,3]) 558 d2 = X([4,5,6]) 559 d1 == d2 # not clear if this is supposed to be True or False, 560 # but it used to give a SystemError 561 562 563class SubclassWithKwargs(deque): 564 def __init__(self, newarg=1): 565 deque.__init__(self) 566 567class TestSubclassWithKwargs(unittest.TestCase): 568 def test_subclass_with_kwargs(self): 569 # SF bug #1486663 -- this used to erroneously raise a TypeError 570 SubclassWithKwargs(newarg=1) 571 572#============================================================================== 573 574libreftest = """ 575Example from the Library Reference: Doc/lib/libcollections.tex 576 577>>> from collections import deque 578>>> d = deque('ghi') # make a new deque with three items 579>>> for elem in d: # iterate over the deque's elements 580... print elem.upper() 581G 582H 583I 584>>> d.append('j') # add a new entry to the right side 585>>> d.appendleft('f') # add a new entry to the left side 586>>> d # show the representation of the deque 587deque(['f', 'g', 'h', 'i', 'j']) 588>>> d.pop() # return and remove the rightmost item 589'j' 590>>> d.popleft() # return and remove the leftmost item 591'f' 592>>> list(d) # list the contents of the deque 593['g', 'h', 'i'] 594>>> d[0] # peek at leftmost item 595'g' 596>>> d[-1] # peek at rightmost item 597'i' 598>>> list(reversed(d)) # list the contents of a deque in reverse 599['i', 'h', 'g'] 600>>> 'h' in d # search the deque 601True 602>>> d.extend('jkl') # add multiple elements at once 603>>> d 604deque(['g', 'h', 'i', 'j', 'k', 'l']) 605>>> d.rotate(1) # right rotation 606>>> d 607deque(['l', 'g', 'h', 'i', 'j', 'k']) 608>>> d.rotate(-1) # left rotation 609>>> d 610deque(['g', 'h', 'i', 'j', 'k', 'l']) 611>>> deque(reversed(d)) # make a new deque in reverse order 612deque(['l', 'k', 'j', 'i', 'h', 'g']) 613>>> d.clear() # empty the deque 614>>> d.pop() # cannot pop from an empty deque 615Traceback (most recent call last): 616 File "<pyshell#6>", line 1, in -toplevel- 617 d.pop() 618IndexError: pop from an empty deque 619 620>>> d.extendleft('abc') # extendleft() reverses the input order 621>>> d 622deque(['c', 'b', 'a']) 623 624 625 626>>> def delete_nth(d, n): 627... d.rotate(-n) 628... d.popleft() 629... d.rotate(n) 630... 631>>> d = deque('abcdef') 632>>> delete_nth(d, 2) # remove the entry at d[2] 633>>> d 634deque(['a', 'b', 'd', 'e', 'f']) 635 636 637 638>>> def roundrobin(*iterables): 639... pending = deque(iter(i) for i in iterables) 640... while pending: 641... task = pending.popleft() 642... try: 643... yield task.next() 644... except StopIteration: 645... continue 646... pending.append(task) 647... 648 649>>> for value in roundrobin('abc', 'd', 'efgh'): 650... print value 651... 652a 653d 654e 655b 656f 657c 658g 659h 660 661 662>>> def maketree(iterable): 663... d = deque(iterable) 664... while len(d) > 1: 665... pair = [d.popleft(), d.popleft()] 666... d.append(pair) 667... return list(d) 668... 669>>> print maketree('abcdefgh') 670[[[['a', 'b'], ['c', 'd']], [['e', 'f'], ['g', 'h']]]] 671 672""" 673 674 675#============================================================================== 676 677__test__ = {'libreftest' : libreftest} 678 679def test_main(verbose=None): 680 import sys 681 test_classes = ( 682 TestBasic, 683 TestVariousIteratorArgs, 684 TestSubclass, 685 TestSubclassWithKwargs, 686 ) 687 688 test_support.run_unittest(*test_classes) 689 690 # verify reference counting 691 if verbose and hasattr(sys, "gettotalrefcount"): 692 import gc 693 counts = [None] * 5 694 for i in xrange(len(counts)): 695 test_support.run_unittest(*test_classes) 696 gc.collect() 697 counts[i] = sys.gettotalrefcount() 698 print counts 699 700 # doctests 701 from test import test_deque 702 test_support.run_doctest(test_deque, verbose) 703 704if __name__ == "__main__": 705 test_main(verbose=True)