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)