blob: 9bed28e058c95634aa4c1b6382615cdb4abca39e [file] [log] [blame]
Victor Stinner30509872017-07-05 09:16:47 +02001from __future__ import absolute_import
Georg Brandl0bb85672008-02-23 22:35:33 +00002import sys
Raymond Hettingerd2305502003-01-16 12:02:35 +00003import unittest
4from test import test_support
Raymond Hettinger0c410272004-01-05 10:13:35 +00005from UserList import UserList
Tim Peters36cdad12000-12-29 02:06:45 +00006
Georg Brandl0bb85672008-02-23 22:35:33 +00007# We do a bit of trickery here to be able to test both the C implementation
8# and the Python implementation of the module.
9
10# Make it impossible to import the C implementation anymore.
11sys.modules['_bisect'] = 0
12# We must also handle the case that bisect was imported before.
13if 'bisect' in sys.modules:
14 del sys.modules['bisect']
15
16# Now we can import the module and get the pure Python implementation.
17import bisect as py_bisect
18
19# Restore everything to normal.
20del sys.modules['_bisect']
21del sys.modules['bisect']
22
23# This is now the module with the C implementation.
24import bisect as c_bisect
25
26
Antoine Pitrou38fbd792012-05-16 15:01:40 +020027class Range(object):
28 """A trivial xrange()-like object without any integer width limitations."""
29 def __init__(self, start, stop):
30 self.start = start
31 self.stop = stop
32 self.last_insert = None
33
34 def __len__(self):
35 return self.stop - self.start
36
37 def __getitem__(self, idx):
38 n = self.stop - self.start
39 if idx < 0:
40 idx += n
41 if idx >= n:
42 raise IndexError(idx)
43 return self.start + idx
44
45 def insert(self, idx, item):
46 self.last_insert = idx, item
47
48
Raymond Hettingerd2305502003-01-16 12:02:35 +000049class TestBisect(unittest.TestCase):
Georg Brandl0bb85672008-02-23 22:35:33 +000050 module = None
Tim Peters36cdad12000-12-29 02:06:45 +000051
Georg Brandl0bb85672008-02-23 22:35:33 +000052 def setUp(self):
53 self.precomputedCases = [
54 (self.module.bisect_right, [], 1, 0),
55 (self.module.bisect_right, [1], 0, 0),
56 (self.module.bisect_right, [1], 1, 1),
57 (self.module.bisect_right, [1], 2, 1),
58 (self.module.bisect_right, [1, 1], 0, 0),
59 (self.module.bisect_right, [1, 1], 1, 2),
60 (self.module.bisect_right, [1, 1], 2, 2),
61 (self.module.bisect_right, [1, 1, 1], 0, 0),
62 (self.module.bisect_right, [1, 1, 1], 1, 3),
63 (self.module.bisect_right, [1, 1, 1], 2, 3),
64 (self.module.bisect_right, [1, 1, 1, 1], 0, 0),
65 (self.module.bisect_right, [1, 1, 1, 1], 1, 4),
66 (self.module.bisect_right, [1, 1, 1, 1], 2, 4),
67 (self.module.bisect_right, [1, 2], 0, 0),
68 (self.module.bisect_right, [1, 2], 1, 1),
69 (self.module.bisect_right, [1, 2], 1.5, 1),
70 (self.module.bisect_right, [1, 2], 2, 2),
71 (self.module.bisect_right, [1, 2], 3, 2),
72 (self.module.bisect_right, [1, 1, 2, 2], 0, 0),
73 (self.module.bisect_right, [1, 1, 2, 2], 1, 2),
74 (self.module.bisect_right, [1, 1, 2, 2], 1.5, 2),
75 (self.module.bisect_right, [1, 1, 2, 2], 2, 4),
76 (self.module.bisect_right, [1, 1, 2, 2], 3, 4),
77 (self.module.bisect_right, [1, 2, 3], 0, 0),
78 (self.module.bisect_right, [1, 2, 3], 1, 1),
79 (self.module.bisect_right, [1, 2, 3], 1.5, 1),
80 (self.module.bisect_right, [1, 2, 3], 2, 2),
81 (self.module.bisect_right, [1, 2, 3], 2.5, 2),
82 (self.module.bisect_right, [1, 2, 3], 3, 3),
83 (self.module.bisect_right, [1, 2, 3], 4, 3),
84 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 0, 0),
85 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1, 1),
86 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1.5, 1),
87 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2, 3),
88 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2.5, 3),
89 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3, 6),
90 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3.5, 6),
91 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 4, 10),
92 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 5, 10),
Tim Peters36cdad12000-12-29 02:06:45 +000093
Georg Brandl0bb85672008-02-23 22:35:33 +000094 (self.module.bisect_left, [], 1, 0),
95 (self.module.bisect_left, [1], 0, 0),
96 (self.module.bisect_left, [1], 1, 0),
97 (self.module.bisect_left, [1], 2, 1),
98 (self.module.bisect_left, [1, 1], 0, 0),
99 (self.module.bisect_left, [1, 1], 1, 0),
100 (self.module.bisect_left, [1, 1], 2, 2),
101 (self.module.bisect_left, [1, 1, 1], 0, 0),
102 (self.module.bisect_left, [1, 1, 1], 1, 0),
103 (self.module.bisect_left, [1, 1, 1], 2, 3),
104 (self.module.bisect_left, [1, 1, 1, 1], 0, 0),
105 (self.module.bisect_left, [1, 1, 1, 1], 1, 0),
106 (self.module.bisect_left, [1, 1, 1, 1], 2, 4),
107 (self.module.bisect_left, [1, 2], 0, 0),
108 (self.module.bisect_left, [1, 2], 1, 0),
109 (self.module.bisect_left, [1, 2], 1.5, 1),
110 (self.module.bisect_left, [1, 2], 2, 1),
111 (self.module.bisect_left, [1, 2], 3, 2),
112 (self.module.bisect_left, [1, 1, 2, 2], 0, 0),
113 (self.module.bisect_left, [1, 1, 2, 2], 1, 0),
114 (self.module.bisect_left, [1, 1, 2, 2], 1.5, 2),
115 (self.module.bisect_left, [1, 1, 2, 2], 2, 2),
116 (self.module.bisect_left, [1, 1, 2, 2], 3, 4),
117 (self.module.bisect_left, [1, 2, 3], 0, 0),
118 (self.module.bisect_left, [1, 2, 3], 1, 0),
119 (self.module.bisect_left, [1, 2, 3], 1.5, 1),
120 (self.module.bisect_left, [1, 2, 3], 2, 1),
121 (self.module.bisect_left, [1, 2, 3], 2.5, 2),
122 (self.module.bisect_left, [1, 2, 3], 3, 2),
123 (self.module.bisect_left, [1, 2, 3], 4, 3),
124 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 0, 0),
125 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1, 0),
126 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1.5, 1),
127 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2, 1),
128 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2.5, 3),
129 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3, 3),
130 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3.5, 6),
131 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 4, 6),
132 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 5, 10)
133 ]
Tim Peters36cdad12000-12-29 02:06:45 +0000134
Raymond Hettingerd2305502003-01-16 12:02:35 +0000135 def test_precomputed(self):
Raymond Hettinger6aa1c3f2003-01-16 14:00:15 +0000136 for func, data, elem, expected in self.precomputedCases:
137 self.assertEqual(func(data, elem), expected)
Raymond Hettinger0c410272004-01-05 10:13:35 +0000138 self.assertEqual(func(UserList(data), elem), expected)
Raymond Hettingerd2305502003-01-16 12:02:35 +0000139
Raymond Hettinger3cd1e422008-07-10 14:03:19 +0000140 def test_negative_lo(self):
141 # Issue 3301
142 mod = self.module
143 self.assertRaises(ValueError, mod.bisect_left, [1, 2, 3], 5, -1, 3),
144 self.assertRaises(ValueError, mod.bisect_right, [1, 2, 3], 5, -1, 3),
145 self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3),
146 self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3),
147
Mark Dickinson0407e962012-04-15 16:43:19 +0100148 def test_large_range(self):
149 # Issue 13496
150 mod = self.module
Antoine Pitrou38fbd792012-05-16 15:01:40 +0200151 n = sys.maxsize
Antoine Pitrou4cf3f692012-05-16 14:50:25 +0200152 try:
Antoine Pitrou38fbd792012-05-16 15:01:40 +0200153 data = xrange(n-1)
Antoine Pitrou4cf3f692012-05-16 14:50:25 +0200154 except OverflowError:
155 self.skipTest("can't create a xrange() object of size `sys.maxsize`")
Antoine Pitrou38fbd792012-05-16 15:01:40 +0200156 self.assertEqual(mod.bisect_left(data, n-3), n-3)
157 self.assertEqual(mod.bisect_right(data, n-3), n-2)
158 self.assertEqual(mod.bisect_left(data, n-3, n-10, n), n-3)
159 self.assertEqual(mod.bisect_right(data, n-3, n-10, n), n-2)
160
161 def test_large_pyrange(self):
162 # Same as above, but without C-imposed limits on range() parameters
163 mod = self.module
164 n = sys.maxsize
165 data = Range(0, n-1)
166 self.assertEqual(mod.bisect_left(data, n-3), n-3)
167 self.assertEqual(mod.bisect_right(data, n-3), n-2)
168 self.assertEqual(mod.bisect_left(data, n-3, n-10, n), n-3)
169 self.assertEqual(mod.bisect_right(data, n-3, n-10, n), n-2)
170 x = n - 100
171 mod.insort_left(data, x, x - 50, x + 50)
172 self.assertEqual(data.last_insert, (x, x))
173 x = n - 200
174 mod.insort_right(data, x, x - 50, x + 50)
175 self.assertEqual(data.last_insert, (x + 1, x))
Mark Dickinson0407e962012-04-15 16:43:19 +0100176
Raymond Hettinger6aa1c3f2003-01-16 14:00:15 +0000177 def test_random(self, n=25):
Raymond Hettinger44223752003-01-16 12:31:36 +0000178 from random import randrange
179 for i in xrange(n):
180 data = [randrange(0, n, 2) for j in xrange(i)]
181 data.sort()
Raymond Hettinger6aa1c3f2003-01-16 14:00:15 +0000182 elem = randrange(-1, n+1)
Georg Brandl0bb85672008-02-23 22:35:33 +0000183 ip = self.module.bisect_left(data, elem)
Raymond Hettinger44223752003-01-16 12:31:36 +0000184 if ip < len(data):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000185 self.assertTrue(elem <= data[ip])
Raymond Hettinger44223752003-01-16 12:31:36 +0000186 if ip > 0:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000187 self.assertTrue(data[ip-1] < elem)
Georg Brandl0bb85672008-02-23 22:35:33 +0000188 ip = self.module.bisect_right(data, elem)
Raymond Hettinger44223752003-01-16 12:31:36 +0000189 if ip < len(data):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000190 self.assertTrue(elem < data[ip])
Raymond Hettinger44223752003-01-16 12:31:36 +0000191 if ip > 0:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000192 self.assertTrue(data[ip-1] <= elem)
Raymond Hettinger44223752003-01-16 12:31:36 +0000193
Raymond Hettingera9f18dc2003-01-16 13:02:25 +0000194 def test_optionalSlicing(self):
Raymond Hettinger6aa1c3f2003-01-16 14:00:15 +0000195 for func, data, elem, expected in self.precomputedCases:
196 for lo in xrange(4):
197 lo = min(len(data), lo)
198 for hi in xrange(3,8):
199 hi = min(len(data), hi)
200 ip = func(data, elem, lo, hi)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000201 self.assertTrue(lo <= ip <= hi)
Georg Brandl0bb85672008-02-23 22:35:33 +0000202 if func is self.module.bisect_left and ip < hi:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000203 self.assertTrue(elem <= data[ip])
Georg Brandl0bb85672008-02-23 22:35:33 +0000204 if func is self.module.bisect_left and ip > lo:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000205 self.assertTrue(data[ip-1] < elem)
Georg Brandl0bb85672008-02-23 22:35:33 +0000206 if func is self.module.bisect_right and ip < hi:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000207 self.assertTrue(elem < data[ip])
Georg Brandl0bb85672008-02-23 22:35:33 +0000208 if func is self.module.bisect_right and ip > lo:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000209 self.assertTrue(data[ip-1] <= elem)
Raymond Hettinger6aa1c3f2003-01-16 14:00:15 +0000210 self.assertEqual(ip, max(lo, min(hi, expected)))
Raymond Hettingera9f18dc2003-01-16 13:02:25 +0000211
212 def test_backcompatibility(self):
Georg Brandl0bb85672008-02-23 22:35:33 +0000213 self.assertEqual(self.module.bisect, self.module.bisect_right)
Raymond Hettingera9f18dc2003-01-16 13:02:25 +0000214
Raymond Hettingercc9a9512005-10-05 11:39:12 +0000215 def test_keyword_args(self):
216 data = [10, 20, 30, 40, 50]
Georg Brandl0bb85672008-02-23 22:35:33 +0000217 self.assertEqual(self.module.bisect_left(a=data, x=25, lo=1, hi=3), 2)
218 self.assertEqual(self.module.bisect_right(a=data, x=25, lo=1, hi=3), 2)
219 self.assertEqual(self.module.bisect(a=data, x=25, lo=1, hi=3), 2)
220 self.module.insort_left(a=data, x=25, lo=1, hi=3)
221 self.module.insort_right(a=data, x=25, lo=1, hi=3)
222 self.module.insort(a=data, x=25, lo=1, hi=3)
Raymond Hettingercc9a9512005-10-05 11:39:12 +0000223 self.assertEqual(data, [10, 20, 25, 25, 25, 30, 40, 50])
224
Georg Brandl0bb85672008-02-23 22:35:33 +0000225class TestBisectPython(TestBisect):
226 module = py_bisect
227
228class TestBisectC(TestBisect):
229 module = c_bisect
230
Raymond Hettingerd2305502003-01-16 12:02:35 +0000231#==============================================================================
232
233class TestInsort(unittest.TestCase):
Georg Brandl0bb85672008-02-23 22:35:33 +0000234 module = None
Raymond Hettingerd2305502003-01-16 12:02:35 +0000235
Raymond Hettinger0c410272004-01-05 10:13:35 +0000236 def test_vsBuiltinSort(self, n=500):
Raymond Hettingerd2305502003-01-16 12:02:35 +0000237 from random import choice
Raymond Hettinger0c410272004-01-05 10:13:35 +0000238 for insorted in (list(), UserList()):
239 for i in xrange(n):
240 digit = choice("0123456789")
241 if digit in "02468":
Georg Brandl0bb85672008-02-23 22:35:33 +0000242 f = self.module.insort_left
Raymond Hettinger0c410272004-01-05 10:13:35 +0000243 else:
Georg Brandl0bb85672008-02-23 22:35:33 +0000244 f = self.module.insort_right
Raymond Hettinger0c410272004-01-05 10:13:35 +0000245 f(insorted, digit)
Mark Dickinson4ca83ec2012-10-31 20:38:52 +0000246 self.assertEqual(sorted(insorted), insorted)
Raymond Hettingerd2305502003-01-16 12:02:35 +0000247
Raymond Hettingera9f18dc2003-01-16 13:02:25 +0000248 def test_backcompatibility(self):
Georg Brandl0bb85672008-02-23 22:35:33 +0000249 self.assertEqual(self.module.insort, self.module.insort_right)
250
Georg Brandlf3776a12008-10-08 18:47:17 +0000251 def test_listDerived(self):
252 class List(list):
253 data = []
254 def insert(self, index, item):
255 self.data.insert(index, item)
256
257 lst = List()
258 self.module.insort_left(lst, 10)
259 self.module.insort_right(lst, 5)
260 self.assertEqual([5, 10], lst.data)
261
Georg Brandl0bb85672008-02-23 22:35:33 +0000262class TestInsortPython(TestInsort):
263 module = py_bisect
264
265class TestInsortC(TestInsort):
266 module = c_bisect
Raymond Hettingera9f18dc2003-01-16 13:02:25 +0000267
Raymond Hettingerd2305502003-01-16 12:02:35 +0000268#==============================================================================
269
Raymond Hettinger63251782004-09-27 22:48:40 +0000270
271class LenOnly:
272 "Dummy sequence class defining __len__ but not __getitem__."
273 def __len__(self):
274 return 10
275
276class GetOnly:
277 "Dummy sequence class defining __getitem__ but not __len__."
278 def __getitem__(self, ndx):
279 return 10
280
281class CmpErr:
282 "Dummy element that always raises an error during comparison"
283 def __cmp__(self, other):
284 raise ZeroDivisionError
285
286class TestErrorHandling(unittest.TestCase):
Georg Brandl0bb85672008-02-23 22:35:33 +0000287 module = None
Raymond Hettinger63251782004-09-27 22:48:40 +0000288
289 def test_non_sequence(self):
Georg Brandl0bb85672008-02-23 22:35:33 +0000290 for f in (self.module.bisect_left, self.module.bisect_right,
291 self.module.insort_left, self.module.insort_right):
Raymond Hettinger63251782004-09-27 22:48:40 +0000292 self.assertRaises(TypeError, f, 10, 10)
293
294 def test_len_only(self):
Georg Brandl0bb85672008-02-23 22:35:33 +0000295 for f in (self.module.bisect_left, self.module.bisect_right,
296 self.module.insort_left, self.module.insort_right):
Raymond Hettinger63251782004-09-27 22:48:40 +0000297 self.assertRaises(AttributeError, f, LenOnly(), 10)
298
299 def test_get_only(self):
Georg Brandl0bb85672008-02-23 22:35:33 +0000300 for f in (self.module.bisect_left, self.module.bisect_right,
301 self.module.insort_left, self.module.insort_right):
Raymond Hettinger63251782004-09-27 22:48:40 +0000302 self.assertRaises(AttributeError, f, GetOnly(), 10)
303
Raymond Hettinger630e5352004-09-27 23:11:35 +0000304 def test_cmp_err(self):
Raymond Hettinger63251782004-09-27 22:48:40 +0000305 seq = [CmpErr(), CmpErr(), CmpErr()]
Georg Brandl0bb85672008-02-23 22:35:33 +0000306 for f in (self.module.bisect_left, self.module.bisect_right,
307 self.module.insort_left, self.module.insort_right):
Raymond Hettinger63251782004-09-27 22:48:40 +0000308 self.assertRaises(ZeroDivisionError, f, seq, 10)
309
310 def test_arg_parsing(self):
Georg Brandl0bb85672008-02-23 22:35:33 +0000311 for f in (self.module.bisect_left, self.module.bisect_right,
312 self.module.insort_left, self.module.insort_right):
Raymond Hettinger63251782004-09-27 22:48:40 +0000313 self.assertRaises(TypeError, f, 10)
314
Georg Brandl0bb85672008-02-23 22:35:33 +0000315class TestErrorHandlingPython(TestErrorHandling):
316 module = py_bisect
317
318class TestErrorHandlingC(TestErrorHandling):
319 module = c_bisect
320
Raymond Hettinger63251782004-09-27 22:48:40 +0000321#==============================================================================
322
Raymond Hettinger44223752003-01-16 12:31:36 +0000323libreftest = """
Georg Brandl0bb85672008-02-23 22:35:33 +0000324Example from the Library Reference: Doc/library/bisect.rst
Raymond Hettinger44223752003-01-16 12:31:36 +0000325
326The bisect() function is generally useful for categorizing numeric data.
327This example uses bisect() to look up a letter grade for an exam total
328(say) based on a set of ordered numeric breakpoints: 85 and up is an `A',
32975..84 is a `B', etc.
330
331 >>> grades = "FEDCBA"
332 >>> breakpoints = [30, 44, 66, 75, 85]
333 >>> from bisect import bisect
334 >>> def grade(total):
335 ... return grades[bisect(breakpoints, total)]
336 ...
337 >>> grade(66)
338 'C'
339 >>> map(grade, [33, 99, 77, 44, 12, 88])
340 ['E', 'A', 'B', 'D', 'F', 'A']
341
Raymond Hettinger44223752003-01-16 12:31:36 +0000342"""
343
Raymond Hettingerd2305502003-01-16 12:02:35 +0000344#------------------------------------------------------------------------------
345
Raymond Hettinger44223752003-01-16 12:31:36 +0000346__test__ = {'libreftest' : libreftest}
347
Raymond Hettingerd2305502003-01-16 12:02:35 +0000348def test_main(verbose=None):
349 from test import test_bisect
Raymond Hettinger63251782004-09-27 22:48:40 +0000350
Georg Brandl0bb85672008-02-23 22:35:33 +0000351 test_classes = [TestBisectPython, TestBisectC,
352 TestInsortPython, TestInsortC,
353 TestErrorHandlingPython, TestErrorHandlingC]
Raymond Hettinger63251782004-09-27 22:48:40 +0000354
355 test_support.run_unittest(*test_classes)
Raymond Hettinger44223752003-01-16 12:31:36 +0000356 test_support.run_doctest(test_bisect, verbose)
Raymond Hettingerd2305502003-01-16 12:02:35 +0000357
Raymond Hettinger63251782004-09-27 22:48:40 +0000358 # verify reference counting
359 if verbose and hasattr(sys, "gettotalrefcount"):
360 import gc
361 counts = [None] * 5
362 for i in xrange(len(counts)):
363 test_support.run_unittest(*test_classes)
364 gc.collect()
365 counts[i] = sys.gettotalrefcount()
366 print counts
367
Raymond Hettingerd2305502003-01-16 12:02:35 +0000368if __name__ == "__main__":
369 test_main(verbose=True)