mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			171 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
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."
 |