home *** CD-ROM | disk | FTP | other *** search
- from test.test_support import verbose
- import random
-
- nerrors = 0
-
- def check(tag, expected, raw, compare=None):
- global nerrors
-
- if verbose:
- print " checking", tag
-
- orig = raw[:] # save input in case of error
- if compare:
- raw.sort(compare)
- else:
- raw.sort()
-
- if len(expected) != len(raw):
- print "error in", tag
- print "length mismatch;", len(expected), len(raw)
- print expected
- print orig
- print raw
- nerrors += 1
- return
-
- for i, good in enumerate(expected):
- maybe = raw[i]
- if good is not maybe:
- print "error in", tag
- print "out of order at index", i, good, maybe
- print expected
- print orig
- print raw
- nerrors += 1
- return
-
- # Try a variety of sizes at and around powers of 2, and at powers of 10.
- sizes = [0]
- for power in range(1, 10):
- n = 2 ** power
- sizes.extend(range(n-1, n+2))
- sizes.extend([10, 100, 1000])
-
- class Complains(object):
- maybe_complain = True
-
- def __init__(self, i):
- self.i = i
-
- def __lt__(self, other):
- if Complains.maybe_complain and random.random() < 0.001:
- if verbose:
- print " complaining at", self, other
- raise RuntimeError
- return self.i < other.i
-
- def __repr__(self):
- return "Complains(%d)" % self.i
-
- class Stable(object):
- def __init__(self, key, i):
- self.key = key
- self.index = i
-
- def __cmp__(self, other):
- return cmp(self.key, other.key)
-
- def __repr__(self):
- return "Stable(%d, %d)" % (self.key, self.index)
-
- for n in sizes:
- x = range(n)
- if verbose:
- print "Testing size", n
-
- s = x[:]
- check("identity", x, s)
-
- s = x[:]
- s.reverse()
- check("reversed", x, s)
-
- s = x[:]
- random.shuffle(s)
- check("random permutation", x, s)
-
- y = x[:]
- y.reverse()
- s = x[:]
- check("reversed via function", y, s, lambda a, b: cmp(b, a))
-
- if verbose:
- print " Checking against an insane comparison function."
- print " If the implementation isn't careful, this may segfault."
- s = x[:]
- s.sort(lambda a, b: int(random.random() * 3) - 1)
- check("an insane function left some permutation", x, s)
-
- x = [Complains(i) for i in x]
- s = x[:]
- random.shuffle(s)
- Complains.maybe_complain = True
- it_complained = False
- try:
- s.sort()
- except RuntimeError:
- it_complained = True
- if it_complained:
- Complains.maybe_complain = False
- check("exception during sort left some permutation", x, s)
-
- s = [Stable(random.randrange(10), i) for i in xrange(n)]
- augmented = [(e, e.index) for e in s]
- augmented.sort() # forced stable because ties broken by index
- x = [e for e, i in augmented] # a stable sort of s
- check("stability", x, s)
-
- def bug453523():
- global nerrors
- from random import random
-
- # If this fails, the most likely outcome is a core dump.
- if verbose:
- print "Testing bug 453523 -- list.sort() crasher."
-
- class C:
- def __lt__(self, other):
- if L and random() < 0.75:
- pop()
- else:
- push(3)
- return random() < 0.5
-
- L = [C() for i in range(50)]
- pop = L.pop
- push = L.append
- try:
- L.sort()
- except ValueError:
- pass
- else:
- print " Mutation during list.sort() wasn't caught."
- nerrors += 1
-
- bug453523()
-
- def cmpNone():
- global nerrors
-
- if verbose:
- print "Testing None as a comparison function."
-
- L = range(50)
- random.shuffle(L)
- try:
- L.sort(None)
- except TypeError:
- print " Passing None as cmpfunc failed."
- nerrors += 1
- else:
- if L != range(50):
- print " Passing None as cmpfunc failed."
- nerrors += 1
-
- cmpNone()
-
- if nerrors:
- print "Test failed", nerrors
- elif verbose:
- print "Test passed -- no errors."
-