blob: e98ce9208271823b243da76932ec0cfbaaf69dc5 [file] [log] [blame]
Neal Norwitz1c0423a2004-07-08 01:59:55 +00001# Python test set -- built-in functions
2
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003import test.support, unittest
Neal Norwitz1c0423a2004-07-08 01:59:55 +00004import sys
Alexandre Vassalotti75056072008-06-10 04:03:04 +00005import pickle
Mark Dickinsond550c9a2009-11-15 09:57:26 +00006import itertools
Neal Norwitz1c0423a2004-07-08 01:59:55 +00007
Mark Dickinsond550c9a2009-11-15 09:57:26 +00008# pure Python implementations (3 args only), for comparison
9def pyrange(start, stop, step):
10 if (start - stop) // step < 0:
11 # replace stop with next element in the sequence of integers
12 # that are congruent to start modulo step.
13 stop += (start - stop) % step
14 while start != stop:
15 yield start
16 start += step
17
18def pyrange_reversed(start, stop, step):
19 stop += (start - stop) % step
20 return pyrange(stop - step, start - step, -step)
21
22
Walter Dörwald4ad94212007-05-21 18:01:17 +000023class RangeTest(unittest.TestCase):
Mark Dickinsond550c9a2009-11-15 09:57:26 +000024 def assert_iterators_equal(self, xs, ys, test_id, limit=None):
25 # check that an iterator xs matches the expected results ys,
26 # up to a given limit.
27 if limit is not None:
28 xs = itertools.islice(xs, limit)
29 ys = itertools.islice(ys, limit)
30 sentinel = object()
31 pairs = itertools.zip_longest(xs, ys, fillvalue=sentinel)
32 for i, (x, y) in enumerate(pairs):
33 if x == y:
34 continue
35 elif x == sentinel:
36 self.fail('{}: iterator ended unexpectedly '
37 'at position {}; expected {}'.format(test_id, i, y))
38 elif y == sentinel:
39 self.fail('{}: unexpected excess element {} at '
40 'position {}'.format(test_id, x, i))
41 else:
42 self.fail('{}: wrong element at position {};'
43 'expected {}, got {}'.format(test_id, i, y, x))
44
Walter Dörwald4ad94212007-05-21 18:01:17 +000045 def test_range(self):
Guido van Rossum805365e2007-05-07 22:24:25 +000046 self.assertEqual(list(range(3)), [0, 1, 2])
47 self.assertEqual(list(range(1, 5)), [1, 2, 3, 4])
48 self.assertEqual(list(range(0)), [])
49 self.assertEqual(list(range(-3)), [])
50 self.assertEqual(list(range(1, 10, 3)), [1, 4, 7])
51 self.assertEqual(list(range(5, -5, -3)), [5, 2, -1, -4])
Neal Norwitz1c0423a2004-07-08 01:59:55 +000052
53 a = 10
54 b = 100
55 c = 50
56
Guido van Rossum805365e2007-05-07 22:24:25 +000057 self.assertEqual(list(range(a, a+2)), [a, a+1])
58 self.assertEqual(list(range(a+2, a, -1)), [a+2, a+1])
59 self.assertEqual(list(range(a+4, a, -2)), [a+4, a+2])
Neal Norwitz1c0423a2004-07-08 01:59:55 +000060
Guido van Rossum805365e2007-05-07 22:24:25 +000061 seq = list(range(a, b, c))
Benjamin Peterson577473f2010-01-19 00:09:57 +000062 self.assertIn(a, seq)
63 self.assertNotIn(b, seq)
Neal Norwitz1c0423a2004-07-08 01:59:55 +000064 self.assertEqual(len(seq), 2)
65
Guido van Rossum805365e2007-05-07 22:24:25 +000066 seq = list(range(b, a, -c))
Benjamin Peterson577473f2010-01-19 00:09:57 +000067 self.assertIn(b, seq)
68 self.assertNotIn(a, seq)
Neal Norwitz1c0423a2004-07-08 01:59:55 +000069 self.assertEqual(len(seq), 2)
70
Guido van Rossum805365e2007-05-07 22:24:25 +000071 seq = list(range(-a, -b, -c))
Benjamin Peterson577473f2010-01-19 00:09:57 +000072 self.assertIn(-a, seq)
73 self.assertNotIn(-b, seq)
Neal Norwitz1c0423a2004-07-08 01:59:55 +000074 self.assertEqual(len(seq), 2)
75
Guido van Rossum805365e2007-05-07 22:24:25 +000076 self.assertRaises(TypeError, range)
77 self.assertRaises(TypeError, range, 1, 2, 3, 4)
78 self.assertRaises(ValueError, range, 1, 2, 0)
Neal Norwitz1c0423a2004-07-08 01:59:55 +000079
Guido van Rossum805365e2007-05-07 22:24:25 +000080 self.assertRaises(TypeError, range, 0.0, 2, 1)
81 self.assertRaises(TypeError, range, 1, 2.0, 1)
82 self.assertRaises(TypeError, range, 1, 2, 1.0)
83 self.assertRaises(TypeError, range, 1e100, 1e101, 1e101)
Neal Norwitz1c0423a2004-07-08 01:59:55 +000084
Guido van Rossum805365e2007-05-07 22:24:25 +000085 self.assertRaises(TypeError, range, 0, "spam")
86 self.assertRaises(TypeError, range, 0, 42, "spam")
Neal Norwitz1c0423a2004-07-08 01:59:55 +000087
Christian Heimesa37d4c62007-12-04 23:02:19 +000088 self.assertEqual(len(range(0, sys.maxsize, sys.maxsize-1)), 2)
Tim Petersfeec4532004-08-08 07:17:39 +000089
Christian Heimesa37d4c62007-12-04 23:02:19 +000090 r = range(-sys.maxsize, sys.maxsize, 2)
91 self.assertEqual(len(r), sys.maxsize)
Tim Petersfeec4532004-08-08 07:17:39 +000092
Benjamin Peterson8d16ab32010-11-20 23:01:55 +000093 def test_large_operands(self):
94 x = range(10**20, 10**20+10, 3)
95 self.assertEqual(len(x), 4)
96 self.assertEqual(len(list(x)), 4)
97
98 x = range(10**20+10, 10**20, 3)
99 self.assertEqual(len(x), 0)
100 self.assertEqual(len(list(x)), 0)
101
102 x = range(10**20, 10**20+10, -3)
103 self.assertEqual(len(x), 0)
104 self.assertEqual(len(list(x)), 0)
105
106 x = range(10**20+10, 10**20, -3)
107 self.assertEqual(len(x), 4)
108 self.assertEqual(len(list(x)), 4)
109
110 # Now test range() with longs
111 self.assertEqual(list(range(-2**100)), [])
112 self.assertEqual(list(range(0, -2**100)), [])
113 self.assertEqual(list(range(0, 2**100, -1)), [])
114 self.assertEqual(list(range(0, 2**100, -1)), [])
115
116 a = int(10 * sys.maxsize)
117 b = int(100 * sys.maxsize)
118 c = int(50 * sys.maxsize)
119
120 self.assertEqual(list(range(a, a+2)), [a, a+1])
121 self.assertEqual(list(range(a+2, a, -1)), [a+2, a+1])
122 self.assertEqual(list(range(a+4, a, -2)), [a+4, a+2])
123
124 seq = list(range(a, b, c))
125 self.assertIn(a, seq)
126 self.assertNotIn(b, seq)
127 self.assertEqual(len(seq), 2)
128
129 seq = list(range(b, a, -c))
130 self.assertIn(b, seq)
131 self.assertNotIn(a, seq)
132 self.assertEqual(len(seq), 2)
133
134 seq = list(range(-a, -b, -c))
135 self.assertIn(-a, seq)
136 self.assertNotIn(-b, seq)
137 self.assertEqual(len(seq), 2)
138
139 self.assertRaises(OverflowError, len, range(0, sys.maxsize**10))
140
141 def test_invalid_invocation(self):
142 self.assertRaises(TypeError, range)
143 self.assertRaises(TypeError, range, 1, 2, 3, 4)
144 self.assertRaises(ValueError, range, 1, 2, 0)
145 self.assertRaises(ValueError, range, a, a + 1, int(0))
146 self.assertRaises(TypeError, range, 1., 1., 1.)
147 self.assertRaises(TypeError, range, 1e100, 1e101, 1e101)
148 self.assertRaises(TypeError, range, 0, "spam")
149 self.assertRaises(TypeError, range, 0, 42, "spam")
150 # Exercise various combinations of bad arguments, to check
151 # refcounting logic
152 self.assertRaises(TypeError, range, 0.0)
153 self.assertRaises(TypeError, range, 0, 0.0)
154 self.assertRaises(TypeError, range, 0.0, 0)
155 self.assertRaises(TypeError, range, 0.0, 0.0)
156 self.assertRaises(TypeError, range, 0, 0, 1.0)
157 self.assertRaises(TypeError, range, 0, 0.0, 1)
158 self.assertRaises(TypeError, range, 0, 0.0, 1.0)
159 self.assertRaises(TypeError, range, 0.0, 0, 1)
160 self.assertRaises(TypeError, range, 0.0, 0, 1.0)
161 self.assertRaises(TypeError, range, 0.0, 0.0, 1)
162 self.assertRaises(TypeError, range, 0.0, 0.0, 1.0)
163
164 def test_index(self):
165 u = range(2)
166 self.assertEqual(u.index(0), 0)
167 self.assertEqual(u.index(1), 1)
168 self.assertRaises(ValueError, u.index, 2)
169
170 u = range(-2, 3)
171 self.assertEqual(u.count(0), 1)
172 self.assertEqual(u.index(0), 2)
173 self.assertRaises(TypeError, u.index)
174
175 class BadExc(Exception):
176 pass
177
178 class BadCmp:
179 def __eq__(self, other):
180 if other == 2:
181 raise BadExc()
182 return False
183
184 a = range(4)
185 self.assertRaises(BadExc, a.index, BadCmp())
186
187 a = range(-2, 3)
188 self.assertEqual(a.index(0), 2)
189 self.assertEqual(range(1, 10, 3).index(4), 1)
190 self.assertEqual(range(1, -10, -3).index(-5), 2)
191
192 self.assertEqual(range(10**20).index(1), 1)
193 self.assertEqual(range(10**20).index(10**20 - 1), 10**20 - 1)
194
195 self.assertRaises(ValueError, range(1, 2**100, 2).index, 2**87)
196 self.assertEqual(range(1, 2**100, 2).index(2**87+1), 2**86)
197
198 class AlwaysEqual(object):
199 def __eq__(self, other):
200 return True
201 always_equal = AlwaysEqual()
202 self.assertEqual(range(10).index(always_equal), 10)
203
204 def test_user_index_method(self):
205 bignum = 2*sys.maxsize
206 smallnum = 42
207
208 # User-defined class with an __index__ method
209 class I:
210 def __init__(self, n):
211 self.n = int(n)
212 def __index__(self):
213 return self.n
214 self.assertEqual(list(range(I(bignum), I(bignum + 1))), [bignum])
215 self.assertEqual(list(range(I(smallnum), I(smallnum + 1))), [smallnum])
216
217 # User-defined class with a failing __index__ method
218 class IX:
219 def __index__(self):
220 raise RuntimeError
221 self.assertRaises(RuntimeError, range, IX())
222
223 # User-defined class with an invalid __index__ method
224 class IN:
225 def __index__(self):
226 return "not a number"
227
228 self.assertRaises(TypeError, range, IN())
229
230 def test_count(self):
231 self.assertEqual(range(3).count(-1), 0)
232 self.assertEqual(range(3).count(0), 1)
233 self.assertEqual(range(3).count(1), 1)
234 self.assertEqual(range(3).count(2), 1)
235 self.assertEqual(range(3).count(3), 0)
236 self.assertIs(type(range(3).count(-1)), int)
237 self.assertIs(type(range(3).count(1)), int)
238 self.assertEqual(range(10**20).count(1), 1)
239 self.assertEqual(range(10**20).count(10**20), 0)
240 self.assertEqual(range(3).index(1), 1)
241 self.assertEqual(range(1, 2**100, 2).count(2**87), 0)
242 self.assertEqual(range(1, 2**100, 2).count(2**87+1), 1)
243
244 class AlwaysEqual(object):
245 def __eq__(self, other):
246 return True
247 always_equal = AlwaysEqual()
248 self.assertEqual(range(10).count(always_equal), 10)
249
Walter Dörwald67d99932007-05-20 08:22:37 +0000250 def test_repr(self):
Walter Dörwald03b43d82007-05-21 10:43:34 +0000251 self.assertEqual(repr(range(1)), 'range(0, 1)')
Walter Dörwald67d99932007-05-20 08:22:37 +0000252 self.assertEqual(repr(range(1, 2)), 'range(1, 2)')
253 self.assertEqual(repr(range(1, 2, 3)), 'range(1, 2, 3)')
254
Alexandre Vassalotti75056072008-06-10 04:03:04 +0000255 def test_pickling(self):
256 testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1),
257 (13, 21, 3), (-2, 2, 2)]
Hirokazu Yamamotod0d0b652008-10-23 00:38:15 +0000258 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
Alexandre Vassalotti75056072008-06-10 04:03:04 +0000259 for t in testcases:
260 r = range(*t)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000261 self.assertEqual(list(pickle.loads(pickle.dumps(r, proto))),
262 list(r))
Alexandre Vassalotti75056072008-06-10 04:03:04 +0000263
Raymond Hettinger94f55832009-06-12 18:40:16 +0000264 def test_odd_bug(self):
265 # This used to raise a "SystemError: NULL result without error"
266 # because the range validation step was eating the exception
267 # before NULL was returned.
268 with self.assertRaises(TypeError):
269 range([], 1, -1)
270
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000271 def test_types(self):
272 # Non-integer objects *equal* to any of the range's items are supposed
273 # to be contained in the range.
Benjamin Peterson577473f2010-01-19 00:09:57 +0000274 self.assertIn(1.0, range(3))
275 self.assertIn(True, range(3))
276 self.assertIn(1+0j, range(3))
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000277
278 class C1:
279 def __eq__(self, other): return True
Benjamin Peterson577473f2010-01-19 00:09:57 +0000280 self.assertIn(C1(), range(3))
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000281
282 # Objects are never coerced into other types for comparison.
283 class C2:
284 def __int__(self): return 1
285 def __index__(self): return 1
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000286 self.assertNotIn(C2(), range(3))
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000287 # ..except if explicitly told so.
Benjamin Peterson577473f2010-01-19 00:09:57 +0000288 self.assertIn(int(C2()), range(3))
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000289
Mark Dickinson418f81d2009-09-24 20:04:23 +0000290 # Check that the range.__contains__ optimization is only
291 # used for ints, not for instances of subclasses of int.
292 class C3(int):
293 def __eq__(self, other): return True
Benjamin Peterson577473f2010-01-19 00:09:57 +0000294 self.assertIn(C3(11), range(10))
295 self.assertIn(C3(11), list(range(10)))
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000296
297 def test_strided_limits(self):
298 r = range(0, 101, 2)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000299 self.assertIn(0, r)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000300 self.assertNotIn(1, r)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000301 self.assertIn(2, r)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000302 self.assertNotIn(99, r)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000303 self.assertIn(100, r)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000304 self.assertNotIn(101, r)
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000305
306 r = range(0, -20, -1)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000307 self.assertIn(0, r)
308 self.assertIn(-1, r)
309 self.assertIn(-19, r)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000310 self.assertNotIn(-20, r)
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000311
312 r = range(0, -20, -2)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000313 self.assertIn(-18, r)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000314 self.assertNotIn(-19, r)
315 self.assertNotIn(-20, r)
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000316
317 def test_empty(self):
318 r = range(0)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000319 self.assertNotIn(0, r)
320 self.assertNotIn(1, r)
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000321
322 r = range(0, -10)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000323 self.assertNotIn(0, r)
324 self.assertNotIn(-1, r)
325 self.assertNotIn(1, r)
Mark Dickinson3e124ae2009-09-22 21:47:24 +0000326
Mark Dickinsond550c9a2009-11-15 09:57:26 +0000327 def test_range_iterators(self):
328 # exercise 'fast' iterators, that use a rangeiterobject internally.
329 # see issue 7298
330 limits = [base + jiggle
331 for M in (2**32, 2**64)
332 for base in (-M, -M//2, 0, M//2, M)
333 for jiggle in (-2, -1, 0, 1, 2)]
334 test_ranges = [(start, end, step)
335 for start in limits
336 for end in limits
337 for step in (-2**63, -2**31, -2, -1, 1, 2)]
338
339 for start, end, step in test_ranges:
340 iter1 = range(start, end, step)
341 iter2 = pyrange(start, end, step)
342 test_id = "range({}, {}, {})".format(start, end, step)
343 # check first 100 entries
344 self.assert_iterators_equal(iter1, iter2, test_id, limit=100)
345
346 iter1 = reversed(range(start, end, step))
347 iter2 = pyrange_reversed(start, end, step)
348 test_id = "reversed(range({}, {}, {}))".format(start, end, step)
349 self.assert_iterators_equal(iter1, iter2, test_id, limit=100)
350
Neal Norwitz1c0423a2004-07-08 01:59:55 +0000351def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000352 test.support.run_unittest(RangeTest)
Neal Norwitz1c0423a2004-07-08 01:59:55 +0000353
354if __name__ == "__main__":
355 test_main()