test_int.py revision 6156560e4b40ae81304d80b5a932fd90e6b4ba80
1import sys
2
3import unittest
4from test import test_support
5from test.test_support import run_unittest, have_unicode
6import math
7
8L = [
9        ('0', 0),
10        ('1', 1),
11        ('9', 9),
12        ('10', 10),
13        ('99', 99),
14        ('100', 100),
15        ('314', 314),
16        (' 314', 314),
17        ('314 ', 314),
18        ('  \t\t  314  \t\t  ', 314),
19        (repr(sys.maxint), sys.maxint),
20        ('  1x', ValueError),
21        ('  1  ', 1),
22        ('  1\02  ', ValueError),
23        ('', ValueError),
24        (' ', ValueError),
25        ('  \t\t  ', ValueError)
26]
27if have_unicode:
28    L += [
29        (unicode('0'), 0),
30        (unicode('1'), 1),
31        (unicode('9'), 9),
32        (unicode('10'), 10),
33        (unicode('99'), 99),
34        (unicode('100'), 100),
35        (unicode('314'), 314),
36        (unicode(' 314'), 314),
37        (unicode('\u0663\u0661\u0664 ','raw-unicode-escape'), 314),
38        (unicode('  \t\t  314  \t\t  '), 314),
39        (unicode('  1x'), ValueError),
40        (unicode('  1  '), 1),
41        (unicode('  1\02  '), ValueError),
42        (unicode(''), ValueError),
43        (unicode(' '), ValueError),
44        (unicode('  \t\t  '), ValueError),
45        (unichr(0x200), ValueError),
46]
47
48class IntLongCommonTests(object):
49
50    """Mixin of test cases to share between both test_int and test_long."""
51
52    # Change to int or long in the TestCase subclass.
53    ntype = None
54
55    def test_no_args(self):
56        self.assertEqual(self.ntype(), 0)
57
58    def test_keyword_args(self):
59        # Test invoking constructor using keyword arguments.
60        self.assertEqual(self.ntype(x=1.2), 1)
61        self.assertEqual(self.ntype('100', base=2), 4)
62        self.assertEqual(self.ntype(x='100', base=2), 4)
63        self.assertRaises(TypeError, self.ntype, base=10)
64        self.assertRaises(TypeError, self.ntype, base=0)
65
66class IntTestCases(IntLongCommonTests, unittest.TestCase):
67
68    ntype = int
69
70    def test_basic(self):
71        self.assertEqual(int(314), 314)
72        self.assertEqual(int(3.14), 3)
73        self.assertEqual(int(314L), 314)
74        # Check that conversion from float truncates towards zero
75        self.assertEqual(int(-3.14), -3)
76        self.assertEqual(int(3.9), 3)
77        self.assertEqual(int(-3.9), -3)
78        self.assertEqual(int(3.5), 3)
79        self.assertEqual(int(-3.5), -3)
80        # Different base:
81        self.assertEqual(int("10",16), 16L)
82        if have_unicode:
83            self.assertEqual(int(unicode("10"),16), 16L)
84        # Test conversion from strings and various anomalies
85        for s, v in L:
86            for sign in "", "+", "-":
87                for prefix in "", " ", "\t", "  \t\t  ":
88                    ss = prefix + sign + s
89                    vv = v
90                    if sign == "-" and v is not ValueError:
91                        vv = -v
92                    try:
93                        self.assertEqual(int(ss), vv)
94                    except v:
95                        pass
96
97        s = repr(-1-sys.maxint)
98        x = int(s)
99        self.assertEqual(x+1, -sys.maxint)
100        self.assertIsInstance(x, int)
101        # should return long
102        self.assertEqual(int(s[1:]), sys.maxint+1)
103
104        # should return long
105        x = int(1e100)
106        self.assertIsInstance(x, long)
107        x = int(-1e100)
108        self.assertIsInstance(x, long)
109
110
111        # SF bug 434186:  0x80000000/2 != 0x80000000>>1.
112        # Worked by accident in Windows release build, but failed in debug build.
113        # Failed in all Linux builds.
114        x = -1-sys.maxint
115        self.assertEqual(x >> 1, x//2)
116
117        self.assertRaises(ValueError, int, '123\0')
118        self.assertRaises(ValueError, int, '53', 40)
119
120        # SF bug 1545497: embedded NULs were not detected with
121        # explicit base
122        self.assertRaises(ValueError, int, '123\0', 10)
123        self.assertRaises(ValueError, int, '123\x00 245', 20)
124
125        x = int('1' * 600)
126        self.assertIsInstance(x, long)
127
128        if have_unicode:
129            x = int(unichr(0x661) * 600)
130            self.assertIsInstance(x, long)
131
132        self.assertRaises(TypeError, int, 1, 12)
133
134        self.assertEqual(int('0123', 0), 83)
135        self.assertEqual(int('0x123', 16), 291)
136
137        # Bug 1679: "0x" is not a valid hex literal
138        self.assertRaises(ValueError, int, "0x", 16)
139        self.assertRaises(ValueError, int, "0x", 0)
140
141        self.assertRaises(ValueError, int, "0o", 8)
142        self.assertRaises(ValueError, int, "0o", 0)
143
144        self.assertRaises(ValueError, int, "0b", 2)
145        self.assertRaises(ValueError, int, "0b", 0)
146
147
148        # SF bug 1334662: int(string, base) wrong answers
149        # Various representations of 2**32 evaluated to 0
150        # rather than 2**32 in previous versions
151
152        self.assertEqual(int('100000000000000000000000000000000', 2), 4294967296L)
153        self.assertEqual(int('102002022201221111211', 3), 4294967296L)
154        self.assertEqual(int('10000000000000000', 4), 4294967296L)
155        self.assertEqual(int('32244002423141', 5), 4294967296L)
156        self.assertEqual(int('1550104015504', 6), 4294967296L)
157        self.assertEqual(int('211301422354', 7), 4294967296L)
158        self.assertEqual(int('40000000000', 8), 4294967296L)
159        self.assertEqual(int('12068657454', 9), 4294967296L)
160        self.assertEqual(int('4294967296', 10), 4294967296L)
161        self.assertEqual(int('1904440554', 11), 4294967296L)
162        self.assertEqual(int('9ba461594', 12), 4294967296L)
163        self.assertEqual(int('535a79889', 13), 4294967296L)
164        self.assertEqual(int('2ca5b7464', 14), 4294967296L)
165        self.assertEqual(int('1a20dcd81', 15), 4294967296L)
166        self.assertEqual(int('100000000', 16), 4294967296L)
167        self.assertEqual(int('a7ffda91', 17), 4294967296L)
168        self.assertEqual(int('704he7g4', 18), 4294967296L)
169        self.assertEqual(int('4f5aff66', 19), 4294967296L)
170        self.assertEqual(int('3723ai4g', 20), 4294967296L)
171        self.assertEqual(int('281d55i4', 21), 4294967296L)
172        self.assertEqual(int('1fj8b184', 22), 4294967296L)
173        self.assertEqual(int('1606k7ic', 23), 4294967296L)
174        self.assertEqual(int('mb994ag', 24), 4294967296L)
175        self.assertEqual(int('hek2mgl', 25), 4294967296L)
176        self.assertEqual(int('dnchbnm', 26), 4294967296L)
177        self.assertEqual(int('b28jpdm', 27), 4294967296L)
178        self.assertEqual(int('8pfgih4', 28), 4294967296L)
179        self.assertEqual(int('76beigg', 29), 4294967296L)
180        self.assertEqual(int('5qmcpqg', 30), 4294967296L)
181        self.assertEqual(int('4q0jto4', 31), 4294967296L)
182        self.assertEqual(int('4000000', 32), 4294967296L)
183        self.assertEqual(int('3aokq94', 33), 4294967296L)
184        self.assertEqual(int('2qhxjli', 34), 4294967296L)
185        self.assertEqual(int('2br45qb', 35), 4294967296L)
186        self.assertEqual(int('1z141z4', 36), 4294967296L)
187
188        # tests with base 0
189        # this fails on 3.0, but in 2.x the old octal syntax is allowed
190        self.assertEqual(int(' 0123  ', 0), 83)
191        self.assertEqual(int(' 0123  ', 0), 83)
192        self.assertEqual(int('000', 0), 0)
193        self.assertEqual(int('0o123', 0), 83)
194        self.assertEqual(int('0x123', 0), 291)
195        self.assertEqual(int('0b100', 0), 4)
196        self.assertEqual(int(' 0O123   ', 0), 83)
197        self.assertEqual(int(' 0X123  ', 0), 291)
198        self.assertEqual(int(' 0B100 ', 0), 4)
199        self.assertEqual(int('0', 0), 0)
200        self.assertEqual(int('+0', 0), 0)
201        self.assertEqual(int('-0', 0), 0)
202        self.assertEqual(int('00', 0), 0)
203        self.assertRaises(ValueError, int, '08', 0)
204        self.assertRaises(ValueError, int, '-012395', 0)
205
206        # without base still base 10
207        self.assertEqual(int('0123'), 123)
208        self.assertEqual(int('0123', 10), 123)
209
210        # tests with prefix and base != 0
211        self.assertEqual(int('0x123', 16), 291)
212        self.assertEqual(int('0o123', 8), 83)
213        self.assertEqual(int('0b100', 2), 4)
214        self.assertEqual(int('0X123', 16), 291)
215        self.assertEqual(int('0O123', 8), 83)
216        self.assertEqual(int('0B100', 2), 4)
217
218        # the code has special checks for the first character after the
219        #  type prefix
220        self.assertRaises(ValueError, int, '0b2', 2)
221        self.assertRaises(ValueError, int, '0b02', 2)
222        self.assertRaises(ValueError, int, '0B2', 2)
223        self.assertRaises(ValueError, int, '0B02', 2)
224        self.assertRaises(ValueError, int, '0o8', 8)
225        self.assertRaises(ValueError, int, '0o08', 8)
226        self.assertRaises(ValueError, int, '0O8', 8)
227        self.assertRaises(ValueError, int, '0O08', 8)
228        self.assertRaises(ValueError, int, '0xg', 16)
229        self.assertRaises(ValueError, int, '0x0g', 16)
230        self.assertRaises(ValueError, int, '0Xg', 16)
231        self.assertRaises(ValueError, int, '0X0g', 16)
232
233        # SF bug 1334662: int(string, base) wrong answers
234        # Checks for proper evaluation of 2**32 + 1
235        self.assertEqual(int('100000000000000000000000000000001', 2), 4294967297L)
236        self.assertEqual(int('102002022201221111212', 3), 4294967297L)
237        self.assertEqual(int('10000000000000001', 4), 4294967297L)
238        self.assertEqual(int('32244002423142', 5), 4294967297L)
239        self.assertEqual(int('1550104015505', 6), 4294967297L)
240        self.assertEqual(int('211301422355', 7), 4294967297L)
241        self.assertEqual(int('40000000001', 8), 4294967297L)
242        self.assertEqual(int('12068657455', 9), 4294967297L)
243        self.assertEqual(int('4294967297', 10), 4294967297L)
244        self.assertEqual(int('1904440555', 11), 4294967297L)
245        self.assertEqual(int('9ba461595', 12), 4294967297L)
246        self.assertEqual(int('535a7988a', 13), 4294967297L)
247        self.assertEqual(int('2ca5b7465', 14), 4294967297L)
248        self.assertEqual(int('1a20dcd82', 15), 4294967297L)
249        self.assertEqual(int('100000001', 16), 4294967297L)
250        self.assertEqual(int('a7ffda92', 17), 4294967297L)
251        self.assertEqual(int('704he7g5', 18), 4294967297L)
252        self.assertEqual(int('4f5aff67', 19), 4294967297L)
253        self.assertEqual(int('3723ai4h', 20), 4294967297L)
254        self.assertEqual(int('281d55i5', 21), 4294967297L)
255        self.assertEqual(int('1fj8b185', 22), 4294967297L)
256        self.assertEqual(int('1606k7id', 23), 4294967297L)
257        self.assertEqual(int('mb994ah', 24), 4294967297L)
258        self.assertEqual(int('hek2mgm', 25), 4294967297L)
259        self.assertEqual(int('dnchbnn', 26), 4294967297L)
260        self.assertEqual(int('b28jpdn', 27), 4294967297L)
261        self.assertEqual(int('8pfgih5', 28), 4294967297L)
262        self.assertEqual(int('76beigh', 29), 4294967297L)
263        self.assertEqual(int('5qmcpqh', 30), 4294967297L)
264        self.assertEqual(int('4q0jto5', 31), 4294967297L)
265        self.assertEqual(int('4000001', 32), 4294967297L)
266        self.assertEqual(int('3aokq95', 33), 4294967297L)
267        self.assertEqual(int('2qhxjlj', 34), 4294967297L)
268        self.assertEqual(int('2br45qc', 35), 4294967297L)
269        self.assertEqual(int('1z141z5', 36), 4294967297L)
270
271    def test_bit_length(self):
272        tiny = 1e-10
273        for x in xrange(-65000, 65000):
274            k = x.bit_length()
275            # Check equivalence with Python version
276            self.assertEqual(k, len(bin(x).lstrip('-0b')))
277            # Behaviour as specified in the docs
278            if x != 0:
279                self.assertTrue(2**(k-1) <= abs(x) < 2**k)
280            else:
281                self.assertEqual(k, 0)
282            # Alternative definition: x.bit_length() == 1 + floor(log_2(x))
283            if x != 0:
284                # When x is an exact power of 2, numeric errors can
285                # cause floor(log(x)/log(2)) to be one too small; for
286                # small x this can be fixed by adding a small quantity
287                # to the quotient before taking the floor.
288                self.assertEqual(k, 1 + math.floor(
289                        math.log(abs(x))/math.log(2) + tiny))
290
291        self.assertEqual((0).bit_length(), 0)
292        self.assertEqual((1).bit_length(), 1)
293        self.assertEqual((-1).bit_length(), 1)
294        self.assertEqual((2).bit_length(), 2)
295        self.assertEqual((-2).bit_length(), 2)
296        for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64]:
297            a = 2**i
298            self.assertEqual((a-1).bit_length(), i)
299            self.assertEqual((1-a).bit_length(), i)
300            self.assertEqual((a).bit_length(), i+1)
301            self.assertEqual((-a).bit_length(), i+1)
302            self.assertEqual((a+1).bit_length(), i+1)
303            self.assertEqual((-a-1).bit_length(), i+1)
304
305    @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
306                         "test requires IEEE 754 doubles")
307    def test_float_conversion(self):
308        # values exactly representable as floats
309        exact_values = [-2, -1, 0, 1, 2, 2**52, 2**53-1, 2**53, 2**53+2,
310                         2**53+4, 2**54-4, 2**54-2, 2**63, -2**63, 2**64,
311                         -2**64, 10**20, 10**21, 10**22]
312        for value in exact_values:
313            self.assertEqual(int(float(int(value))), value)
314
315        # test round-half-to-even
316        self.assertEqual(int(float(2**53+1)), 2**53)
317        self.assertEqual(int(float(2**53+2)), 2**53+2)
318        self.assertEqual(int(float(2**53+3)), 2**53+4)
319        self.assertEqual(int(float(2**53+5)), 2**53+4)
320        self.assertEqual(int(float(2**53+6)), 2**53+6)
321        self.assertEqual(int(float(2**53+7)), 2**53+8)
322
323        self.assertEqual(int(float(-2**53-1)), -2**53)
324        self.assertEqual(int(float(-2**53-2)), -2**53-2)
325        self.assertEqual(int(float(-2**53-3)), -2**53-4)
326        self.assertEqual(int(float(-2**53-5)), -2**53-4)
327        self.assertEqual(int(float(-2**53-6)), -2**53-6)
328        self.assertEqual(int(float(-2**53-7)), -2**53-8)
329
330        self.assertEqual(int(float(2**54-2)), 2**54-2)
331        self.assertEqual(int(float(2**54-1)), 2**54)
332        self.assertEqual(int(float(2**54+2)), 2**54)
333        self.assertEqual(int(float(2**54+3)), 2**54+4)
334        self.assertEqual(int(float(2**54+5)), 2**54+4)
335        self.assertEqual(int(float(2**54+6)), 2**54+8)
336        self.assertEqual(int(float(2**54+10)), 2**54+8)
337        self.assertEqual(int(float(2**54+11)), 2**54+12)
338
339    def test_valid_non_numeric_input_types_for_x(self):
340        # Test possible valid non-numeric types for x, including subclasses
341        # of the allowed built-in types.
342        class CustomStr(str): pass
343        class CustomByteArray(bytearray): pass
344        factories = [str, bytearray, CustomStr, CustomByteArray, buffer]
345
346        if have_unicode:
347            class CustomUnicode(unicode): pass
348            factories += [unicode, CustomUnicode]
349
350        for f in factories:
351            x = f('100')
352            msg = 'x has value %s and type %s' % (x, type(x).__name__)
353            try:
354                self.assertEqual(int(x), 100, msg=msg)
355                if isinstance(x, basestring):
356                    self.assertEqual(int(x, 2), 4, msg=msg)
357            except TypeError, err:
358                raise AssertionError('For %s got TypeError: %s' %
359                                     (type(x).__name__, err))
360            if not isinstance(x, basestring):
361                errmsg = "can't convert non-string"
362                with self.assertRaisesRegexp(TypeError, errmsg, msg=msg):
363                    int(x, 2)
364            errmsg = 'invalid literal'
365            with self.assertRaisesRegexp(ValueError, errmsg, msg=msg):
366                int(f('A' * 0x10))
367
368    def test_int_buffer(self):
369        self.assertEqual(int(buffer('123', 1, 2)), 23)
370        self.assertEqual(int(buffer('123\x00', 1, 2)), 23)
371        self.assertEqual(int(buffer('123 ', 1, 2)), 23)
372        self.assertEqual(int(buffer('123A', 1, 2)), 23)
373        self.assertEqual(int(buffer('1234', 1, 2)), 23)
374
375    def test_error_on_string_float_for_x(self):
376        self.assertRaises(ValueError, int, '1.2')
377
378    def test_error_on_bytearray_for_x(self):
379        self.assertRaises(TypeError, int, bytearray('100'), 2)
380
381    def test_error_on_invalid_int_bases(self):
382        for base in [-1, 1, 1000]:
383            self.assertRaises(ValueError, int, '100', base)
384
385    def test_error_on_string_base(self):
386        self.assertRaises(TypeError, int, 100, base='foo')
387
388    @test_support.cpython_only
389    def test_small_ints(self):
390        self.assertIs(int('10'), 10)
391        self.assertIs(int('-1'), -1)
392        if have_unicode:
393            self.assertIs(int(u'10'), 10)
394            self.assertIs(int(u'-1'), -1)
395
396    def test_intconversion(self):
397        # Test __int__()
398        class ClassicMissingMethods:
399            pass
400        self.assertRaises(AttributeError, int, ClassicMissingMethods())
401
402        class MissingMethods(object):
403            pass
404        self.assertRaises(TypeError, int, MissingMethods())
405
406        class Foo0:
407            def __int__(self):
408                return 42
409
410        class Foo1(object):
411            def __int__(self):
412                return 42
413
414        class Foo2(int):
415            def __int__(self):
416                return 42
417
418        class Foo3(int):
419            def __int__(self):
420                return self
421
422        class Foo4(int):
423            def __int__(self):
424                return 42L
425
426        class Foo5(int):
427            def __int__(self):
428                return 42.
429
430        self.assertEqual(int(Foo0()), 42)
431        self.assertEqual(int(Foo1()), 42)
432        self.assertEqual(int(Foo2()), 42)
433        self.assertEqual(int(Foo3()), 0)
434        self.assertEqual(int(Foo4()), 42L)
435        self.assertRaises(TypeError, int, Foo5())
436
437        class Classic:
438            pass
439        for base in (object, Classic):
440            class IntOverridesTrunc(base):
441                def __int__(self):
442                    return 42
443                def __trunc__(self):
444                    return -12
445            self.assertEqual(int(IntOverridesTrunc()), 42)
446
447            class JustTrunc(base):
448                def __trunc__(self):
449                    return 42
450            self.assertEqual(int(JustTrunc()), 42)
451
452            for trunc_result_base in (object, Classic):
453                class Integral(trunc_result_base):
454                    def __int__(self):
455                        return 42
456
457                class TruncReturnsNonInt(base):
458                    def __trunc__(self):
459                        return Integral()
460                self.assertEqual(int(TruncReturnsNonInt()), 42)
461
462                class NonIntegral(trunc_result_base):
463                    def __trunc__(self):
464                        # Check that we avoid infinite recursion.
465                        return NonIntegral()
466
467                class TruncReturnsNonIntegral(base):
468                    def __trunc__(self):
469                        return NonIntegral()
470                try:
471                    int(TruncReturnsNonIntegral())
472                except TypeError as e:
473                    self.assertEqual(str(e),
474                                      "__trunc__ returned non-Integral"
475                                      " (type NonIntegral)")
476                else:
477                    self.fail("Failed to raise TypeError with %s" %
478                              ((base, trunc_result_base),))
479
480def test_main():
481    run_unittest(IntTestCases)
482
483if __name__ == "__main__":
484    test_main()
485