1
from test.test_support import verbose
3
from UserList import UserList
7
def check(tag, expected, raw, compare=None):
11
print " checking", tag
13
orig = raw[:] # save input in case of error
19
if len(expected) != len(raw):
21
print "length mismatch;", len(expected), len(raw)
28
for i, good in enumerate(expected):
32
print "out of order at index", i, good, maybe
39
# Try a variety of sizes at and around powers of 2, and at powers of 10.
41
for power in range(1, 10):
43
sizes.extend(range(n-1, n+2))
44
sizes.extend([10, 100, 1000])
46
class Complains(object):
49
def __init__(self, i):
52
def __lt__(self, other):
53
if Complains.maybe_complain and random.random() < 0.001:
55
print " complaining at", self, other
57
return self.i < other.i
60
return "Complains(%d)" % self.i
63
def __init__(self, key, i):
67
def __cmp__(self, other):
68
return cmp(self.key, other.key)
71
return "Stable(%d, %d)" % (self.key, self.index)
76
print "Testing size", n
79
check("identity", x, s)
83
check("reversed", x, s)
87
check("random permutation", x, s)
92
check("reversed via function", y, s, lambda a, b: cmp(b, a))
95
print " Checking against an insane comparison function."
96
print " If the implementation isn't careful, this may segfault."
98
s.sort(lambda a, b: int(random.random() * 3) - 1)
99
check("an insane function left some permutation", x, s)
101
x = [Complains(i) for i in x]
104
Complains.maybe_complain = True
105
it_complained = False
111
Complains.maybe_complain = False
112
check("exception during sort left some permutation", x, s)
114
s = [Stable(random.randrange(10), i) for i in xrange(n)]
115
augmented = [(e, e.index) for e in s]
116
augmented.sort() # forced stable because ties broken by index
117
x = [e for e, i in augmented] # a stable sort of s
118
check("stability", x, s)
122
from test import test_support
125
#==============================================================================
127
class TestBugs(unittest.TestCase):
129
def test_bug453523(self):
130
# bug 453523 -- list.sort() crasher.
131
# If this fails, the most likely outcome is a core dump.
132
# Mutations during a list sort should raise a ValueError.
135
def __lt__(self, other):
136
if L and random.random() < 0.75:
140
return random.random() < 0.5
142
L = [C() for i in range(50)]
143
self.assertRaises(ValueError, L.sort)
145
def test_cmpNone(self):
146
# Testing None as a comparison function.
151
self.assertEqual(L, range(50))
153
def test_undetected_mutation(self):
154
# Python 2.4a1 did not always detect mutation
157
def mutating_cmp(x, y):
162
self.assertRaises(ValueError, L.sort, mutating_cmp)
163
def mutating_cmp(x, y):
167
self.assertRaises(ValueError, L.sort, mutating_cmp)
168
memorywaster = [memorywaster]
170
#==============================================================================
172
class TestDecorateSortUndecorate(unittest.TestCase):
174
def test_decorated(self):
175
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
178
data.sort(key=str.lower)
179
copy.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))
181
def test_baddecorator(self):
182
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
183
self.assertRaises(TypeError, data.sort, None, lambda x,y: 0)
185
def test_stability(self):
186
data = [(random.randrange(100), i) for i in xrange(200)]
188
data.sort(key=lambda (x,y): x) # sort on the random first field
189
copy.sort() # sort using both fields
190
self.assertEqual(data, copy) # should get the same result
192
def test_cmp_and_key_combination(self):
193
# Verify that the wrapper has been removed
195
self.assertEqual(type(x), str)
196
self.assertEqual(type(x), str)
198
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
199
data.sort(cmp=compare, key=str.lower)
201
def test_badcmp_with_key(self):
202
# Verify that the wrapper has been removed
203
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
204
self.assertRaises(TypeError, data.sort, "bad", str.lower)
206
def test_key_with_exception(self):
207
# Verify that the wrapper has been removed
210
self.assertRaises(ZeroDivisionError, data.sort, None, lambda x: 1/x)
211
self.assertEqual(data, dup)
213
def test_key_with_mutation(self):
219
self.assertRaises(ValueError, data.sort, key=k)
221
def test_key_with_mutating_del(self):
223
class SortKiller(object):
224
def __init__(self, x):
229
self.assertRaises(ValueError, data.sort, key=SortKiller)
231
def test_key_with_mutating_del_and_exception(self):
234
class SortKiller(object):
235
def __init__(self, x):
241
self.assertRaises(RuntimeError, data.sort, key=SortKiller)
242
## major honking subtlety: we *can't* do:
244
## self.assertEqual(data, dup)
246
## because there is a reference to a SortKiller in the
247
## traceback and by the time it dies we're outside the call to
248
## .sort() and so the list protection gimmicks are out of
249
## date (this cost some brain cells to figure out...).
251
def test_reverse(self):
254
data.sort(reverse=True)
255
self.assertEqual(data, range(99,-1,-1))
256
self.assertRaises(TypeError, data.sort, "wrong type")
258
def test_reverse_stability(self):
259
data = [(random.randrange(100), i) for i in xrange(200)]
262
data.sort(cmp=lambda x,y: cmp(x[0],y[0]), reverse=True)
263
copy1.sort(cmp=lambda x,y: cmp(y[0],x[0]))
264
self.assertEqual(data, copy1)
265
copy2.sort(key=lambda x: x[0], reverse=True)
266
self.assertEqual(data, copy2)
268
#==============================================================================
270
def test_main(verbose=None):
272
TestDecorateSortUndecorate,
276
test_support.run_unittest(*test_classes)
278
# verify reference counting
279
if verbose and hasattr(sys, "gettotalrefcount"):
282
for i in xrange(len(counts)):
283
test_support.run_unittest(*test_classes)
285
counts[i] = sys.gettotalrefcount()
288
if __name__ == "__main__":
289
test_main(verbose=True)