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