github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/stdlib/test/test_bisect.py (about) 1 import sys 2 import unittest 3 from test import test_support 4 #from UserList import UserList 5 import UserList as _UserList 6 UserList = _UserList.UserList 7 8 # We do a bit of trickery here to be able to test both the C implementation 9 # and the Python implementation of the module. 10 11 # Make it impossible to import the C implementation anymore. 12 sys.modules['_bisect'] = 0 13 # We must also handle the case that bisect was imported before. 14 if 'bisect' in sys.modules: 15 del sys.modules['bisect'] 16 17 # Now we can import the module and get the pure Python implementation. 18 import bisect as py_bisect 19 20 # Restore everything to normal. 21 del sys.modules['_bisect'] 22 del sys.modules['bisect'] 23 24 # This is now the module with the C implementation. 25 #import bisect as c_bisect 26 27 28 class Range(object): 29 """A trivial xrange()-like object without any integer width limitations.""" 30 def __init__(self, start, stop): 31 self.start = start 32 self.stop = stop 33 self.last_insert = None 34 35 def __len__(self): 36 return self.stop - self.start 37 38 def __getitem__(self, idx): 39 n = self.stop - self.start 40 if idx < 0: 41 idx += n 42 if idx >= n: 43 raise IndexError(idx) 44 return self.start + idx 45 46 def insert(self, idx, item): 47 self.last_insert = idx, item 48 49 50 class TestBisect(unittest.TestCase): 51 # module = None 52 module = py_bisect 53 54 def setUp(self): 55 self.precomputedCases = [ 56 (self.module.bisect_right, [], 1, 0), 57 (self.module.bisect_right, [1], 0, 0), 58 (self.module.bisect_right, [1], 1, 1), 59 (self.module.bisect_right, [1], 2, 1), 60 (self.module.bisect_right, [1, 1], 0, 0), 61 (self.module.bisect_right, [1, 1], 1, 2), 62 (self.module.bisect_right, [1, 1], 2, 2), 63 (self.module.bisect_right, [1, 1, 1], 0, 0), 64 (self.module.bisect_right, [1, 1, 1], 1, 3), 65 (self.module.bisect_right, [1, 1, 1], 2, 3), 66 (self.module.bisect_right, [1, 1, 1, 1], 0, 0), 67 (self.module.bisect_right, [1, 1, 1, 1], 1, 4), 68 (self.module.bisect_right, [1, 1, 1, 1], 2, 4), 69 (self.module.bisect_right, [1, 2], 0, 0), 70 (self.module.bisect_right, [1, 2], 1, 1), 71 (self.module.bisect_right, [1, 2], 1.5, 1), 72 (self.module.bisect_right, [1, 2], 2, 2), 73 (self.module.bisect_right, [1, 2], 3, 2), 74 (self.module.bisect_right, [1, 1, 2, 2], 0, 0), 75 (self.module.bisect_right, [1, 1, 2, 2], 1, 2), 76 (self.module.bisect_right, [1, 1, 2, 2], 1.5, 2), 77 (self.module.bisect_right, [1, 1, 2, 2], 2, 4), 78 (self.module.bisect_right, [1, 1, 2, 2], 3, 4), 79 (self.module.bisect_right, [1, 2, 3], 0, 0), 80 (self.module.bisect_right, [1, 2, 3], 1, 1), 81 (self.module.bisect_right, [1, 2, 3], 1.5, 1), 82 (self.module.bisect_right, [1, 2, 3], 2, 2), 83 (self.module.bisect_right, [1, 2, 3], 2.5, 2), 84 (self.module.bisect_right, [1, 2, 3], 3, 3), 85 (self.module.bisect_right, [1, 2, 3], 4, 3), 86 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 0, 0), 87 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1, 1), 88 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1.5, 1), 89 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2, 3), 90 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2.5, 3), 91 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3, 6), 92 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3.5, 6), 93 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 4, 10), 94 (self.module.bisect_right, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 5, 10), 95 96 (self.module.bisect_left, [], 1, 0), 97 (self.module.bisect_left, [1], 0, 0), 98 (self.module.bisect_left, [1], 1, 0), 99 (self.module.bisect_left, [1], 2, 1), 100 (self.module.bisect_left, [1, 1], 0, 0), 101 (self.module.bisect_left, [1, 1], 1, 0), 102 (self.module.bisect_left, [1, 1], 2, 2), 103 (self.module.bisect_left, [1, 1, 1], 0, 0), 104 (self.module.bisect_left, [1, 1, 1], 1, 0), 105 (self.module.bisect_left, [1, 1, 1], 2, 3), 106 (self.module.bisect_left, [1, 1, 1, 1], 0, 0), 107 (self.module.bisect_left, [1, 1, 1, 1], 1, 0), 108 (self.module.bisect_left, [1, 1, 1, 1], 2, 4), 109 (self.module.bisect_left, [1, 2], 0, 0), 110 (self.module.bisect_left, [1, 2], 1, 0), 111 (self.module.bisect_left, [1, 2], 1.5, 1), 112 (self.module.bisect_left, [1, 2], 2, 1), 113 (self.module.bisect_left, [1, 2], 3, 2), 114 (self.module.bisect_left, [1, 1, 2, 2], 0, 0), 115 (self.module.bisect_left, [1, 1, 2, 2], 1, 0), 116 (self.module.bisect_left, [1, 1, 2, 2], 1.5, 2), 117 (self.module.bisect_left, [1, 1, 2, 2], 2, 2), 118 (self.module.bisect_left, [1, 1, 2, 2], 3, 4), 119 (self.module.bisect_left, [1, 2, 3], 0, 0), 120 (self.module.bisect_left, [1, 2, 3], 1, 0), 121 (self.module.bisect_left, [1, 2, 3], 1.5, 1), 122 (self.module.bisect_left, [1, 2, 3], 2, 1), 123 (self.module.bisect_left, [1, 2, 3], 2.5, 2), 124 (self.module.bisect_left, [1, 2, 3], 3, 2), 125 (self.module.bisect_left, [1, 2, 3], 4, 3), 126 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 0, 0), 127 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1, 0), 128 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1.5, 1), 129 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2, 1), 130 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2.5, 3), 131 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3, 3), 132 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3.5, 6), 133 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 4, 6), 134 (self.module.bisect_left, [1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 5, 10) 135 ] 136 137 def test_precomputed(self): 138 for func, data, elem, expected in self.precomputedCases: 139 self.assertEqual(func(data, elem), expected) 140 self.assertEqual(func(UserList(data), elem), expected) 141 142 def test_negative_lo(self): 143 # Issue 3301 144 mod = self.module 145 self.assertRaises(ValueError, mod.bisect_left, [1, 2, 3], 5, -1, 3), 146 self.assertRaises(ValueError, mod.bisect_right, [1, 2, 3], 5, -1, 3), 147 self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3), 148 self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3), 149 150 def test_large_range(self): 151 # Issue 13496 152 mod = self.module 153 n = sys.maxsize 154 try: 155 data = xrange(n-1) 156 except OverflowError: 157 self.skipTest("can't create a xrange() object of size `sys.maxsize`") 158 self.assertEqual(mod.bisect_left(data, n-3), n-3) 159 self.assertEqual(mod.bisect_right(data, n-3), n-2) 160 self.assertEqual(mod.bisect_left(data, n-3, n-10, n), n-3) 161 self.assertEqual(mod.bisect_right(data, n-3, n-10, n), n-2) 162 163 def test_large_pyrange(self): 164 # Same as above, but without C-imposed limits on range() parameters 165 mod = self.module 166 n = sys.maxsize 167 data = Range(0, n-1) 168 self.assertEqual(mod.bisect_left(data, n-3), n-3) 169 self.assertEqual(mod.bisect_right(data, n-3), n-2) 170 self.assertEqual(mod.bisect_left(data, n-3, n-10, n), n-3) 171 self.assertEqual(mod.bisect_right(data, n-3, n-10, n), n-2) 172 x = n - 100 173 mod.insort_left(data, x, x - 50, x + 50) 174 self.assertEqual(data.last_insert, (x, x)) 175 x = n - 200 176 mod.insort_right(data, x, x - 50, x + 50) 177 self.assertEqual(data.last_insert, (x + 1, x)) 178 179 def test_random(self, n=25): 180 #from random import randrange 181 import random as _random 182 randrange = _random.randrange 183 184 for i in xrange(n): 185 data = [randrange(0, n, 2) for j in xrange(i)] 186 data.sort() 187 elem = randrange(-1, n+1) 188 ip = self.module.bisect_left(data, elem) 189 if ip < len(data): 190 self.assertTrue(elem <= data[ip]) 191 if ip > 0: 192 self.assertTrue(data[ip-1] < elem) 193 ip = self.module.bisect_right(data, elem) 194 if ip < len(data): 195 self.assertTrue(elem < data[ip]) 196 if ip > 0: 197 self.assertTrue(data[ip-1] <= elem) 198 199 def test_optionalSlicing(self): 200 for func, data, elem, expected in self.precomputedCases: 201 for lo in xrange(4): 202 lo = min(len(data), lo) 203 for hi in xrange(3,8): 204 hi = min(len(data), hi) 205 ip = func(data, elem, lo, hi) 206 self.assertTrue(lo <= ip <= hi) 207 if func is self.module.bisect_left and ip < hi: 208 self.assertTrue(elem <= data[ip]) 209 if func is self.module.bisect_left and ip > lo: 210 self.assertTrue(data[ip-1] < elem) 211 if func is self.module.bisect_right and ip < hi: 212 self.assertTrue(elem < data[ip]) 213 if func is self.module.bisect_right and ip > lo: 214 self.assertTrue(data[ip-1] <= elem) 215 self.assertEqual(ip, max(lo, min(hi, expected))) 216 217 def test_backcompatibility(self): 218 self.assertEqual(self.module.bisect, self.module.bisect_right) 219 220 def test_keyword_args(self): 221 data = [10, 20, 30, 40, 50] 222 self.assertEqual(self.module.bisect_left(a=data, x=25, lo=1, hi=3), 2) 223 self.assertEqual(self.module.bisect_right(a=data, x=25, lo=1, hi=3), 2) 224 self.assertEqual(self.module.bisect(a=data, x=25, lo=1, hi=3), 2) 225 self.module.insort_left(a=data, x=25, lo=1, hi=3) 226 self.module.insort_right(a=data, x=25, lo=1, hi=3) 227 self.module.insort(a=data, x=25, lo=1, hi=3) 228 self.assertEqual(data, [10, 20, 25, 25, 25, 30, 40, 50]) 229 230 # class TestBisectPython(TestBisect): 231 # module = py_bisect 232 233 # class TestBisectC(TestBisect): 234 # module = c_bisect 235 236 #============================================================================== 237 238 class TestInsort(unittest.TestCase): 239 # module = None 240 module = py_bisect 241 242 def test_vsBuiltinSort(self, n=500): 243 #from random import choice 244 import random as _random 245 choice = _random.choice 246 247 for insorted in (list(), UserList()): 248 for i in xrange(n): 249 digit = choice("0123456789") 250 if digit in "02468": 251 f = self.module.insort_left 252 else: 253 f = self.module.insort_right 254 f(insorted, digit) 255 self.assertEqual(sorted(insorted), insorted) 256 257 def test_backcompatibility(self): 258 self.assertEqual(self.module.insort, self.module.insort_right) 259 260 def test_listDerived(self): 261 class List(list): 262 data = [] 263 def insert(self, index, item): 264 self.data.insert(index, item) 265 266 lst = List() 267 self.module.insort_left(lst, 10) 268 self.module.insort_right(lst, 5) 269 self.assertEqual([5, 10], lst.data) 270 271 # class TestInsortPython(TestInsort): 272 # module = py_bisect 273 274 # class TestInsortC(TestInsort): 275 # module = c_bisect 276 277 #============================================================================== 278 279 280 class LenOnly(object): 281 "Dummy sequence class defining __len__ but not __getitem__." 282 def __len__(self): 283 return 10 284 285 # Have to define LenOnly as an object for the Grumpy runtime. Doing so will 286 # raise a TypeError instead of an AttributeError when accessing __getitem__, 287 # so we redefine __getitem__ to raise an AttributeError. 288 def __getitem__(self, ndx): 289 raise AttributeError 290 291 class GetOnly(object): 292 "Dummy sequence class defining __getitem__ but not __len__." 293 def __getitem__(self, ndx): 294 return 10 295 296 def __len__(self): 297 raise AttributeError 298 299 class CmpErr(object): 300 "Dummy element that always raises an error during comparison" 301 def __cmp__(self, other): 302 raise ZeroDivisionError 303 304 class TestErrorHandling(unittest.TestCase): 305 # module = None 306 module = py_bisect 307 308 def test_non_sequence(self): 309 for f in (self.module.bisect_left, self.module.bisect_right, 310 self.module.insort_left, self.module.insort_right): 311 self.assertRaises(TypeError, f, 10, 10) 312 313 def test_len_only(self): 314 for f in (self.module.bisect_left, self.module.bisect_right, 315 self.module.insort_left, self.module.insort_right): 316 self.assertRaises(AttributeError, f, LenOnly(), 10) 317 318 def test_get_only(self): 319 for f in (self.module.bisect_left, self.module.bisect_right, 320 self.module.insort_left, self.module.insort_right): 321 self.assertRaises(AttributeError, f, GetOnly(), 10) 322 323 def test_cmp_err(self): 324 seq = [CmpErr(), CmpErr(), CmpErr()] 325 for f in (self.module.bisect_left, self.module.bisect_right, 326 self.module.insort_left, self.module.insort_right): 327 self.assertRaises(ZeroDivisionError, f, seq, 10) 328 329 def test_arg_parsing(self): 330 for f in (self.module.bisect_left, self.module.bisect_right, 331 self.module.insort_left, self.module.insort_right): 332 self.assertRaises(TypeError, f, 10) 333 334 # class TestErrorHandlingPython(TestErrorHandling): 335 # module = py_bisect 336 337 # class TestErrorHandlingC(TestErrorHandling): 338 # module = c_bisect 339 340 #============================================================================== 341 342 libreftest = """ 343 Example from the Library Reference: Doc/library/bisect.rst 344 The bisect() function is generally useful for categorizing numeric data. 345 This example uses bisect() to look up a letter grade for an exam total 346 (say) based on a set of ordered numeric breakpoints: 85 and up is an `A', 347 75..84 is a `B', etc. 348 >>> grades = "FEDCBA" 349 >>> breakpoints = [30, 44, 66, 75, 85] 350 >>> from bisect import bisect 351 >>> def grade(total): 352 ... return grades[bisect(breakpoints, total)] 353 ... 354 >>> grade(66) 355 'C' 356 >>> map(grade, [33, 99, 77, 44, 12, 88]) 357 ['E', 'A', 'B', 'D', 'F', 'A'] 358 """ 359 360 #------------------------------------------------------------------------------ 361 362 __test__ = {'libreftest' : libreftest} 363 364 def test_main(verbose=None): 365 # from test import test_bisect 366 367 # test_classes = [TestBisectPython, TestBisectC, 368 # TestInsortPython, TestInsortC, 369 # TestErrorHandlingPython, TestErrorHandlingC] 370 test_classes = [TestBisect, TestInsort, TestErrorHandling] 371 372 test_support.run_unittest(*test_classes) 373 # test_support.run_doctest(test_bisect, verbose) 374 375 # verify reference counting 376 if verbose and hasattr(sys, "gettotalrefcount"): 377 #import gc 378 counts = [None] * 5 379 for i in xrange(len(counts)): 380 test_support.run_unittest(*test_classes) 381 #gc.collect() 382 counts[i] = sys.gettotalrefcount() 383 print counts 384 385 if __name__ == "__main__": 386 test_main(verbose=True)