summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_sort.py124
1 files changed, 124 insertions, 0 deletions
diff --git a/Lib/test/test_sort.py b/Lib/test/test_sort.py
new file mode 100644
index 0000000..1a069c2
--- /dev/null
+++ b/Lib/test/test_sort.py
@@ -0,0 +1,124 @@
+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):
+ maybe_complain = True
+
+ 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)
+
+if nerrors:
+ print "Test failed", nerrors
+elif verbose:
+ print "Test passed -- no errors."