test_xrange.py 5.13 KB
Newer Older
Neal Norwitz's avatar
Neal Norwitz committed
1 2 3 4
# Python test set -- built-in functions

import test.test_support, unittest
import sys
5
import pickle
6
import itertools
Neal Norwitz's avatar
Neal Norwitz committed
7 8 9 10 11

import warnings
warnings.filterwarnings("ignore", "integer argument expected",
                        DeprecationWarning, "unittest")

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
# pure Python implementations (3 args only), for comparison
def pyrange(start, stop, step):
    if (start - stop) // step < 0:
        # replace stop with next element in the sequence of integers
        # that are congruent to start modulo step.
        stop += (start - stop) % step
        while start != stop:
            yield start
            start += step

def pyrange_reversed(start, stop, step):
    stop += (start - stop) % step
    return pyrange(stop - step, start - step, -step)


Neal Norwitz's avatar
Neal Norwitz committed
27
class XrangeTest(unittest.TestCase):
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    def assert_iterators_equal(self, xs, ys, test_id, limit=None):
        # check that an iterator xs matches the expected results ys,
        # up to a given limit.
        if limit is not None:
            xs = itertools.islice(xs, limit)
            ys = itertools.islice(ys, limit)
        sentinel = object()
        pairs = itertools.izip_longest(xs, ys, fillvalue=sentinel)
        for i, (x, y) in enumerate(pairs):
            if x == y:
                continue
            elif x == sentinel:
                self.fail('{0}: iterator ended unexpectedly '
                          'at position {1}; expected {2}'.format(test_id, i, y))
            elif y == sentinel:
                self.fail('{0}: unexpected excess element {1} at '
                          'position {2}'.format(test_id, x, i))
            else:
                self.fail('{0}: wrong element at position {1};'
                          'expected {2}, got {3}'.format(test_id, i, y, x))

Neal Norwitz's avatar
Neal Norwitz committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
    def test_xrange(self):
        self.assertEqual(list(xrange(3)), [0, 1, 2])
        self.assertEqual(list(xrange(1, 5)), [1, 2, 3, 4])
        self.assertEqual(list(xrange(0)), [])
        self.assertEqual(list(xrange(-3)), [])
        self.assertEqual(list(xrange(1, 10, 3)), [1, 4, 7])
        self.assertEqual(list(xrange(5, -5, -3)), [5, 2, -1, -4])

        a = 10
        b = 100
        c = 50

        self.assertEqual(list(xrange(a, a+2)), [a, a+1])
        self.assertEqual(list(xrange(a+2, a, -1L)), [a+2, a+1])
        self.assertEqual(list(xrange(a+4, a, -2)), [a+4, a+2])

        seq = list(xrange(a, b, c))
        self.assert_(a in seq)
        self.assert_(b not in seq)
        self.assertEqual(len(seq), 2)

        seq = list(xrange(b, a, -c))
        self.assert_(b in seq)
        self.assert_(a not in seq)
        self.assertEqual(len(seq), 2)

        seq = list(xrange(-a, -b, -c))
        self.assert_(-a in seq)
        self.assert_(-b not in seq)
        self.assertEqual(len(seq), 2)

        self.assertRaises(TypeError, xrange)
        self.assertRaises(TypeError, xrange, 1, 2, 3, 4)
        self.assertRaises(ValueError, xrange, 1, 2, 0)

        self.assertRaises(OverflowError, xrange, 1e100, 1e101, 1e101)

        self.assertRaises(TypeError, xrange, 0, "spam")
        self.assertRaises(TypeError, xrange, 0, 42, "spam")

Tim Peters's avatar
Tim Peters committed
89 90
        self.assertEqual(len(xrange(0, sys.maxint, sys.maxint-1)), 2)

Neal Norwitz's avatar
Neal Norwitz committed
91 92 93
        self.assertRaises(OverflowError, xrange, -sys.maxint, sys.maxint)
        self.assertRaises(OverflowError, xrange, 0, 2*sys.maxint)

94
        r = xrange(-sys.maxint, sys.maxint, 2)
95
        self.assertEqual(len(r), sys.maxint)
Tim Peters's avatar
Tim Peters committed
96 97
        self.assertRaises(OverflowError, xrange, -sys.maxint-1, sys.maxint, 2)

98 99 100
    def test_pickling(self):
        testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1),
                     (13, 21, 3), (-2, 2, 2)]
Georg Brandl's avatar
Georg Brandl committed
101
        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
102 103 104 105 106
            for t in testcases:
                r = xrange(*t)
                self.assertEquals(list(pickle.loads(pickle.dumps(r, proto))),
                                  list(r))

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
    def test_range_iterators(self):
        # see issue 7298
        limits = [base + jiggle
                  for M in (2**32, 2**64)
                  for base in (-M, -M//2, 0, M//2, M)
                  for jiggle in (-2, -1, 0, 1, 2)]
        test_ranges = [(start, end, step)
                       for start in limits
                       for end in limits
                       for step in (-2**63, -2**31, -2, -1, 1, 2)]

        for start, end, step in test_ranges:
            try:
                iter1 = xrange(start, end, step)
            except OverflowError:
                pass
            else:
                iter2 = pyrange(start, end, step)
                test_id = "xrange({0}, {1}, {2})".format(start, end, step)
                # check first 100 entries
                self.assert_iterators_equal(iter1, iter2, test_id, limit=100)

            try:
                iter1 = reversed(xrange(start, end, step))
            except OverflowError:
                pass
            else:
                iter2 = pyrange_reversed(start, end, step)
                test_id = "reversed(xrange({0}, {1}, {2}))".format(
                    start, end, step)
                self.assert_iterators_equal(iter1, iter2, test_id, limit=100)

139

Neal Norwitz's avatar
Neal Norwitz committed
140 141 142 143 144
def test_main():
    test.test_support.run_unittest(XrangeTest)

if __name__ == "__main__":
    test_main()