from collections import Counter, deque import random import pickle import gc q = deque() q.append(1) q.append(2) q.appendleft(3) q.append(4) assert len(q) == 4 assert q == deque([3, 1, 2, 4]) assert q.popleft() == 3 assert q.pop() == 4 assert len(q) == 2 assert q == deque([1, 2]) ## ADDING TESTS FROM CPYTHON's test_deque.py file ############TEST basics############### def assertEqual(a, b): assert a == b BIG = 100000 def fail(): raise SyntaxError yield 1 d = deque(range(-5125, -5000)) d.__init__(range(200)) for i in range(200, 400): d.append(i) for i in reversed(range(-200, 0)): d.appendleft(i) assertEqual(list(d), list(range(-200, 400))) assertEqual(len(d), 600) left = [d.popleft() for i in range(250)] assertEqual(left, list(range(-200, 50))) assertEqual(list(d), list(range(50, 400))) right = [d.pop() for i in range(250)] right.reverse() assertEqual(right, list(range(150, 400))) assertEqual(list(d), list(range(50, 150))) #######TEST maxlen############### try: dq = deque() dq.maxlen = -1 except AttributeError: pass try: dq = deque() dq.maxlen = -2 except AttributeError: pass it = iter(range(10)) d = deque(it, maxlen=3) assertEqual(list(it), []) assertEqual(repr(d), 'deque([7, 8, 9], maxlen=3)') assertEqual(list(d), [7, 8, 9]) assertEqual(d, deque(range(10), 3)) d.append(10) assertEqual(list(d), [8, 9, 10]) d.appendleft(7) assertEqual(list(d), [7, 8, 9]) d.extend([10, 11]) assertEqual(list(d), [9, 10, 11]) d.extendleft([8, 7]) assertEqual(list(d), [7, 8, 9]) d = deque(range(200), maxlen=10) d.append(d) assertEqual(repr(d)[-30:], ', 198, 199, [...]], maxlen=10)') d = deque(range(10), maxlen=None) assertEqual(repr(d), 'deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])') #######TEST maxlen = 0############### it = iter(range(100)) deque(it, maxlen=0) assertEqual(list(it), []) it = iter(range(100)) d = deque(maxlen=0) d.extend(it) assertEqual(list(it), []) it = iter(range(100)) d = deque(maxlen=0) d.extendleft(it) assertEqual(list(it), []) #######TEST maxlen attribute ############# assertEqual(deque().maxlen, None) assertEqual(deque('abc').maxlen, None) assertEqual(deque('abc', maxlen=4).maxlen, 4) assertEqual(deque('abc', maxlen=2).maxlen, 2) assertEqual(deque('abc', maxlen=0).maxlen, 0) try: d = deque('abc') d.maxlen = 10 print("X Failed Tests!!") exit(1) except AttributeError: pass ######### TEST count()################# for s in ('', 'abracadabra', 'simsalabim'*500+'abc'): s = list(s) d = deque(s) for letter in 'abcdefghijklmnopqrstuvwxyz': assertEqual(s.count(letter), d.count(letter)) try: d.count() print("X Failed Tests!!") exit(1) except TypeError: pass try: d.count(1,2) print("X Failed Tests!!") exit(1) except TypeError: pass class BadCompare: def __eq__(self, other): raise ArithmeticError d = deque([1, 2, BadCompare(), 3]) try: d.count(2) print("X Failed Tests!!") exit(1) except ArithmeticError: pass d = deque([1, 2, 3]) try: d.count(BadCompare()) print("X Failed Tests!!") exit(1) except ArithmeticError: pass class MutatingCompare: def __eq__(self, other): d.pop() return True m = MutatingCompare() d = deque([1, 2, 3, m, 4, 5]) m.d = d try: d.count(3) print("X Failed Tests!") exit(1) except RuntimeError: pass d = deque([None]*16) for i in range(len(d)): d.rotate(-1) d.rotate(1) assertEqual(d.count(1), 0) assertEqual(d.count(None), 16) #### TEST comparisons == ##### d = deque('xabc') d.popleft() for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: assertEqual(d==e, type(d)==type(e) and list(d)==list(e)) assertEqual(d!=e, not(type(d)==type(e) and list(d)==list(e))) args = map(deque, ('', 'a', 'b', 'ab', 'ba', 'abc', 'xba', 'xabc', 'cba')) for x in args: for y in args: assertEqual(x == y, list(x) == list(y)) assertEqual(x != y, list(x) != list(y)) # assertEqual(x < y, list(x) < list(y)) # not currently supported # assertEqual(x <= y, list(x) <= list(y)) # not currently supported # assertEqual(x > y, list(x) > list(y)) # not currently supported # assertEqual(x >= y, list(x) >= list(y)) # not currently supported ###############TEST contains()################# n = 200 d = deque(range(n)) for i in range(n): assertEqual(i in d, True) assertEqual((n+1) not in d, True) class MutateCmp: def __init__(self, deque, result): self.deque = deque self.result = result def __eq__(self, other): self.deque.clear() return self.result # # Test detection of mutation during iteration d = deque(range(n)) d[n//2] = MutateCmp(d, False) try: n in d print("X Failed Tests!") exit(1) except RuntimeError: pass class BadCmp: def __eq__(self, other): raise RuntimeError # # Test detection of comparison exceptions d = deque(range(n)) d[n//2] = BadCmp() try: n in d print("X Failed Tests!") exit(1) except RuntimeError: pass #####test_contains_count_stop_crashes##### class A: def __eq__(self, other): d.clear() return NotImplemented d = deque([A(), A()]) try: _ = 3 in d print("X Failed Tests!") exit(1) except RuntimeError: pass d = deque([A(), A()]) try: _ = d.count(3) print("X Failed Tests!") exit(1) except RuntimeError: pass ########TEST extend()################ d = deque('a') try: d.extend(1) print("X Failed Tests!") exit(1) except TypeError: pass d.extend('bcd') assertEqual(list(d), list('abcd')) d.extend(d) assertEqual(list(d), list('abcdabcd')) ######TEST extend_left() ################ d = deque('a') try: d.extendleft(1) print("X Failed Tests!") exit(1) except TypeError: pass d.extendleft('bcd') assertEqual(list(d), list(reversed('abcd'))) d.extendleft(d) assertEqual(list(d), list('abcddcba')) d = deque() d.extendleft(range(1000)) assertEqual(list(d), list(reversed(range(1000)))) try: d.extendleft(fail()) print("X Failed Tests!") exit(1) except SyntaxError: pass ##### TEST get_item ################ n = 200 d = deque(range(n)) l = list(range(n)) for i in range(n): d.popleft() l.pop(0) if random.random() < 0.5: d.append(i) l.append(i) for j in range(1-len(l), len(l)): assert d[j] == l[j] d = deque('superman') assertEqual(d[0], 's') assertEqual(d[-1], 'n') d = deque() try: d.__getitem__(0) print("X Failed Tests!") exit(1) except IndexError: pass try: d.__getitem__(-1) print("X Failed Tests!") exit(1) except IndexError: pass #########TEST index()############### for n in 1, 2, 30, 40, 200: d = deque(range(n)) for i in range(n): assertEqual(d.index(i), i) try: d.index(n+1) print("X Failed Tests!") exit(1) except ValueError: pass # Test detection of mutation during iteration d = deque(range(n)) d[n//2] = MutateCmp(d, False) try: d.index(n) print("X Failed Tests!") exit(1) except RuntimeError: pass # Test detection of comparison exceptions d = deque(range(n)) d[n//2] = BadCmp() try: d.index(n) print("X Failed Tests!") exit(1) except RuntimeError: pass # Test start and stop arguments behavior matches list.index() #COMMENT: Current List behavior doesn't support start and stop arguments, so this test is not supported # elements = 'ABCDEFGHI' # nonelement = 'Z' # d = deque(elements * 2) # s = list(elements * 2) # for start in range(-5 - len(s)*2, 5 + len(s) * 2): # for stop in range(-5 - len(s)*2, 5 + len(s) * 2): # for element in elements + 'Z': # try: # print(element, start, stop) # target = s.index(element, start, stop) # except ValueError: # try: # d.index(element, start, stop) # print("X Failed Tests!") # exit(1) # except ValueError: # continue # # with assertRaises(ValueError): # # d.index(element, start, stop) # assertEqual(d.index(element, start, stop), target) # Test large start argument d = deque(range(0, 10000, 10)) for step in range(100): i = d.index(8500, 700) assertEqual(d[i], 8500) # Repeat test with a different internal offset d.rotate() ###########test_index_bug_24913############# d = deque('A' * 3) try: d.index('A', 1, 0) print("X Failed Tests!") exit(1) except ValueError: pass ###########test_insert############# # Test to make sure insert behaves like lists elements = 'ABCDEFGHI' for i in range(-5 - len(elements)*2, 5 + len(elements) * 2): d = deque('ABCDEFGHI') s = list('ABCDEFGHI') d.insert(i, 'Z') s.insert(i, 'Z') assertEqual(list(d), s) ###########test_insert_bug_26194############# data = 'ABC' d = deque(data, maxlen=len(data)) try: d.insert(0, 'Z') print("X Failed Tests!") exit(1) except IndexError: pass elements = 'ABCDEFGHI' for i in range(-len(elements), len(elements)): d = deque(elements, maxlen=len(elements)+1) d.insert(i, 'Z') if i >= 0: assertEqual(d[i], 'Z') else: assertEqual(d[i-1], 'Z') ######### test set_item ############# n = 200 d = deque(range(n)) for i in range(n): d[i] = 10 * i assertEqual(list(d), [10*i for i in range(n)]) l = list(d) for i in range(1-n, 0, -1): d[i] = 7*i l[i] = 7*i assertEqual(list(d), l) ########## test del_item ############# n = 500 # O(n**2) test, don't make this too big d = deque(range(n)) try: d.__delitem__(-n-1) print("X Failed Tests!") exit(1) except IndexError: pass try: d.__delitem__(n) print("X Failed Tests!") exit(1) except IndexError: pass for i in range(n): assertEqual(len(d), n-i) j = random.randint(0, len(d)-1) val = d[j] assertEqual(val in d, True) del d[j] assertEqual(val in d, False) assertEqual(len(d), 0) #########test reverse()############### n = 500 # O(n**2) test, don't make this too big data = [random.random() for i in range(n)] for i in range(n): d = deque(data[:i]) r = d.reverse() assertEqual(list(d), list(reversed(data[:i]))) assertEqual(r, None) d.reverse() assertEqual(list(d), data[:i]) try: d.reverse(1) print("X Failed Tests!") exit(1) except TypeError: pass ############test rotate############# s = tuple('abcde') n = len(s) d = deque(s) d.rotate(1) # verify rot(1) assertEqual(''.join(d), 'eabcd') d = deque(s) d.rotate(-1) # verify rot(-1) assertEqual(''.join(d), 'bcdea') d.rotate() # check default to 1 assertEqual(tuple(d), s) for i in range(n*3): d = deque(s) e = deque(d) d.rotate(i) # check vs. rot(1) n times for j in range(i): e.rotate(1) assertEqual(tuple(d), tuple(e)) d.rotate(-i) # check that it works in reverse assertEqual(tuple(d), s) e.rotate(n-i) # check that it wraps forward assertEqual(tuple(e), s) for i in range(n*3): d = deque(s) e = deque(d) d.rotate(-i) for j in range(i): e.rotate(-1) # check vs. rot(-1) n times assertEqual(tuple(d), tuple(e)) d.rotate(i) # check that it works in reverse assertEqual(tuple(d), s) e.rotate(i-n) # check that it wraps backaround assertEqual(tuple(e), s) d = deque(s) e = deque(s) e.rotate(BIG+17) # verify on long series of rotates dr = d.rotate for i in range(BIG+17): dr() assertEqual(tuple(d), tuple(e)) try: d.rotate(1, 2) print("X Failed Tests!") exit(1) except TypeError: pass try: d.rotate(1,10) print("X Failed Tests!") exit(1) except TypeError: pass d = deque() d.rotate() # rotate an empty deque assertEqual(d, deque()) ##########test len############# d = deque('ab') assertEqual(len(d), 2) d.popleft() assertEqual(len(d), 1) d.pop() assertEqual(len(d), 0) try: d.pop() print("X Failed Tests!") exit(1) except IndexError: pass assertEqual(len(d), 0) d.append('c') assertEqual(len(d), 1) d.appendleft('d') assertEqual(len(d), 2) d.clear() assertEqual(len(d), 0) ##############test underflow############# d = deque() try: d.pop() print("X Failed Tests!") exit(1) except IndexError: pass try: d.popleft() print("X Failed Tests!") exit(1) except IndexError: pass ##############test clear############# d = deque(range(100)) assertEqual(len(d), 100) d.clear() assertEqual(len(d), 0) assertEqual(list(d), []) d.clear() # clear an empty deque assertEqual(list(d), []) #############test remove############# d = deque('abcdefghcij') d.remove('c') assertEqual(d, deque('abdefghcij')) d.remove('c') assertEqual(d, deque('abdefghij')) try: d.remove('c') print("X Failed Tests!") exit(1) except ValueError: pass assertEqual(d, deque('abdefghij')) # Handle comparison errors d = deque(['a', 'b', BadCmp(), 'c']) e = deque(d) try: d.remove('c') print("X Failed Tests!") exit(1) except RuntimeError: pass for x, y in zip(d, e): # verify that original order and values are retained. assertEqual(x is y, True) # Handle evil mutator for match in (True, False): d = deque(['ab']) d.extend([MutateCmp(d, match), 'c']) try: d.remove('c') print("X Failed Tests!") exit(1) except IndexError: pass assertEqual(d, deque()) print('✓',"ALL TEST PASSED!!")