1import sys 2import time 3 4import unittest 5from unittest import mock 6from test import support 7from test.test_grammar import (VALID_UNDERSCORE_LITERALS, 8 INVALID_UNDERSCORE_LITERALS) 9 10try: 11 import _pylong 12except ImportError: 13 _pylong = None 14 15L = [ 16 ('0', 0), 17 ('1', 1), 18 ('9', 9), 19 ('10', 10), 20 ('99', 99), 21 ('100', 100), 22 ('314', 314), 23 (' 314', 314), 24 ('314 ', 314), 25 (' \t\t 314 \t\t ', 314), 26 (repr(sys.maxsize), sys.maxsize), 27 (' 1x', ValueError), 28 (' 1 ', 1), 29 (' 1\02 ', ValueError), 30 ('', ValueError), 31 (' ', ValueError), 32 (' \t\t ', ValueError), 33 ("\u0200", ValueError) 34] 35 36class IntSubclass(int): 37 pass 38 39class IntTestCases(unittest.TestCase): 40 41 def test_basic(self): 42 self.assertEqual(int(314), 314) 43 self.assertEqual(int(3.14), 3) 44 # Check that conversion from float truncates towards zero 45 self.assertEqual(int(-3.14), -3) 46 self.assertEqual(int(3.9), 3) 47 self.assertEqual(int(-3.9), -3) 48 self.assertEqual(int(3.5), 3) 49 self.assertEqual(int(-3.5), -3) 50 self.assertEqual(int("-3"), -3) 51 self.assertEqual(int(" -3 "), -3) 52 self.assertEqual(int("\N{EM SPACE}-3\N{EN SPACE}"), -3) 53 # Different base: 54 self.assertEqual(int("10",16), 16) 55 # Test conversion from strings and various anomalies 56 for s, v in L: 57 for sign in "", "+", "-": 58 for prefix in "", " ", "\t", " \t\t ": 59 ss = prefix + sign + s 60 vv = v 61 if sign == "-" and v is not ValueError: 62 vv = -v 63 try: 64 self.assertEqual(int(ss), vv) 65 except ValueError: 66 pass 67 68 s = repr(-1-sys.maxsize) 69 x = int(s) 70 self.assertEqual(x+1, -sys.maxsize) 71 self.assertIsInstance(x, int) 72 # should return int 73 self.assertEqual(int(s[1:]), sys.maxsize+1) 74 75 # should return int 76 x = int(1e100) 77 self.assertIsInstance(x, int) 78 x = int(-1e100) 79 self.assertIsInstance(x, int) 80 81 82 # SF bug 434186: 0x80000000/2 != 0x80000000>>1. 83 # Worked by accident in Windows release build, but failed in debug build. 84 # Failed in all Linux builds. 85 x = -1-sys.maxsize 86 self.assertEqual(x >> 1, x//2) 87 88 x = int('1' * 600) 89 self.assertIsInstance(x, int) 90 91 92 self.assertRaises(TypeError, int, 1, 12) 93 self.assertRaises(TypeError, int, "10", 2, 1) 94 95 self.assertEqual(int('0o123', 0), 83) 96 self.assertEqual(int('0x123', 16), 291) 97 98 # Bug 1679: "0x" is not a valid hex literal 99 self.assertRaises(ValueError, int, "0x", 16) 100 self.assertRaises(ValueError, int, "0x", 0) 101 102 self.assertRaises(ValueError, int, "0o", 8) 103 self.assertRaises(ValueError, int, "0o", 0) 104 105 self.assertRaises(ValueError, int, "0b", 2) 106 self.assertRaises(ValueError, int, "0b", 0) 107 108 # SF bug 1334662: int(string, base) wrong answers 109 # Various representations of 2**32 evaluated to 0 110 # rather than 2**32 in previous versions 111 112 self.assertEqual(int('100000000000000000000000000000000', 2), 4294967296) 113 self.assertEqual(int('102002022201221111211', 3), 4294967296) 114 self.assertEqual(int('10000000000000000', 4), 4294967296) 115 self.assertEqual(int('32244002423141', 5), 4294967296) 116 self.assertEqual(int('1550104015504', 6), 4294967296) 117 self.assertEqual(int('211301422354', 7), 4294967296) 118 self.assertEqual(int('40000000000', 8), 4294967296) 119 self.assertEqual(int('12068657454', 9), 4294967296) 120 self.assertEqual(int('4294967296', 10), 4294967296) 121 self.assertEqual(int('1904440554', 11), 4294967296) 122 self.assertEqual(int('9ba461594', 12), 4294967296) 123 self.assertEqual(int('535a79889', 13), 4294967296) 124 self.assertEqual(int('2ca5b7464', 14), 4294967296) 125 self.assertEqual(int('1a20dcd81', 15), 4294967296) 126 self.assertEqual(int('100000000', 16), 4294967296) 127 self.assertEqual(int('a7ffda91', 17), 4294967296) 128 self.assertEqual(int('704he7g4', 18), 4294967296) 129 self.assertEqual(int('4f5aff66', 19), 4294967296) 130 self.assertEqual(int('3723ai4g', 20), 4294967296) 131 self.assertEqual(int('281d55i4', 21), 4294967296) 132 self.assertEqual(int('1fj8b184', 22), 4294967296) 133 self.assertEqual(int('1606k7ic', 23), 4294967296) 134 self.assertEqual(int('mb994ag', 24), 4294967296) 135 self.assertEqual(int('hek2mgl', 25), 4294967296) 136 self.assertEqual(int('dnchbnm', 26), 4294967296) 137 self.assertEqual(int('b28jpdm', 27), 4294967296) 138 self.assertEqual(int('8pfgih4', 28), 4294967296) 139 self.assertEqual(int('76beigg', 29), 4294967296) 140 self.assertEqual(int('5qmcpqg', 30), 4294967296) 141 self.assertEqual(int('4q0jto4', 31), 4294967296) 142 self.assertEqual(int('4000000', 32), 4294967296) 143 self.assertEqual(int('3aokq94', 33), 4294967296) 144 self.assertEqual(int('2qhxjli', 34), 4294967296) 145 self.assertEqual(int('2br45qb', 35), 4294967296) 146 self.assertEqual(int('1z141z4', 36), 4294967296) 147 148 # tests with base 0 149 # this fails on 3.0, but in 2.x the old octal syntax is allowed 150 self.assertEqual(int(' 0o123 ', 0), 83) 151 self.assertEqual(int(' 0o123 ', 0), 83) 152 self.assertEqual(int('000', 0), 0) 153 self.assertEqual(int('0o123', 0), 83) 154 self.assertEqual(int('0x123', 0), 291) 155 self.assertEqual(int('0b100', 0), 4) 156 self.assertEqual(int(' 0O123 ', 0), 83) 157 self.assertEqual(int(' 0X123 ', 0), 291) 158 self.assertEqual(int(' 0B100 ', 0), 4) 159 with self.assertRaises(ValueError): 160 int('010', 0) 161 162 # without base still base 10 163 self.assertEqual(int('0123'), 123) 164 self.assertEqual(int('0123', 10), 123) 165 166 # tests with prefix and base != 0 167 self.assertEqual(int('0x123', 16), 291) 168 self.assertEqual(int('0o123', 8), 83) 169 self.assertEqual(int('0b100', 2), 4) 170 self.assertEqual(int('0X123', 16), 291) 171 self.assertEqual(int('0O123', 8), 83) 172 self.assertEqual(int('0B100', 2), 4) 173 174 # the code has special checks for the first character after the 175 # type prefix 176 self.assertRaises(ValueError, int, '0b2', 2) 177 self.assertRaises(ValueError, int, '0b02', 2) 178 self.assertRaises(ValueError, int, '0B2', 2) 179 self.assertRaises(ValueError, int, '0B02', 2) 180 self.assertRaises(ValueError, int, '0o8', 8) 181 self.assertRaises(ValueError, int, '0o08', 8) 182 self.assertRaises(ValueError, int, '0O8', 8) 183 self.assertRaises(ValueError, int, '0O08', 8) 184 self.assertRaises(ValueError, int, '0xg', 16) 185 self.assertRaises(ValueError, int, '0x0g', 16) 186 self.assertRaises(ValueError, int, '0Xg', 16) 187 self.assertRaises(ValueError, int, '0X0g', 16) 188 189 # SF bug 1334662: int(string, base) wrong answers 190 # Checks for proper evaluation of 2**32 + 1 191 self.assertEqual(int('100000000000000000000000000000001', 2), 4294967297) 192 self.assertEqual(int('102002022201221111212', 3), 4294967297) 193 self.assertEqual(int('10000000000000001', 4), 4294967297) 194 self.assertEqual(int('32244002423142', 5), 4294967297) 195 self.assertEqual(int('1550104015505', 6), 4294967297) 196 self.assertEqual(int('211301422355', 7), 4294967297) 197 self.assertEqual(int('40000000001', 8), 4294967297) 198 self.assertEqual(int('12068657455', 9), 4294967297) 199 self.assertEqual(int('4294967297', 10), 4294967297) 200 self.assertEqual(int('1904440555', 11), 4294967297) 201 self.assertEqual(int('9ba461595', 12), 4294967297) 202 self.assertEqual(int('535a7988a', 13), 4294967297) 203 self.assertEqual(int('2ca5b7465', 14), 4294967297) 204 self.assertEqual(int('1a20dcd82', 15), 4294967297) 205 self.assertEqual(int('100000001', 16), 4294967297) 206 self.assertEqual(int('a7ffda92', 17), 4294967297) 207 self.assertEqual(int('704he7g5', 18), 4294967297) 208 self.assertEqual(int('4f5aff67', 19), 4294967297) 209 self.assertEqual(int('3723ai4h', 20), 4294967297) 210 self.assertEqual(int('281d55i5', 21), 4294967297) 211 self.assertEqual(int('1fj8b185', 22), 4294967297) 212 self.assertEqual(int('1606k7id', 23), 4294967297) 213 self.assertEqual(int('mb994ah', 24), 4294967297) 214 self.assertEqual(int('hek2mgm', 25), 4294967297) 215 self.assertEqual(int('dnchbnn', 26), 4294967297) 216 self.assertEqual(int('b28jpdn', 27), 4294967297) 217 self.assertEqual(int('8pfgih5', 28), 4294967297) 218 self.assertEqual(int('76beigh', 29), 4294967297) 219 self.assertEqual(int('5qmcpqh', 30), 4294967297) 220 self.assertEqual(int('4q0jto5', 31), 4294967297) 221 self.assertEqual(int('4000001', 32), 4294967297) 222 self.assertEqual(int('3aokq95', 33), 4294967297) 223 self.assertEqual(int('2qhxjlj', 34), 4294967297) 224 self.assertEqual(int('2br45qc', 35), 4294967297) 225 self.assertEqual(int('1z141z5', 36), 4294967297) 226 227 def test_invalid_signs(self): 228 with self.assertRaises(ValueError): 229 int('+') 230 with self.assertRaises(ValueError): 231 int('-') 232 with self.assertRaises(ValueError): 233 int('- 1') 234 with self.assertRaises(ValueError): 235 int('+ 1') 236 with self.assertRaises(ValueError): 237 int(' + 1 ') 238 239 def test_unicode(self): 240 self.assertEqual(int("१२३४५६७८९०1234567890"), 12345678901234567890) 241 self.assertEqual(int('١٢٣٤٥٦٧٨٩٠'), 1234567890) 242 self.assertEqual(int("१२३४५६७८९०1234567890", 0), 12345678901234567890) 243 self.assertEqual(int('١٢٣٤٥٦٧٨٩٠', 0), 1234567890) 244 245 def test_underscores(self): 246 for lit in VALID_UNDERSCORE_LITERALS: 247 if any(ch in lit for ch in '.eEjJ'): 248 continue 249 self.assertEqual(int(lit, 0), eval(lit)) 250 self.assertEqual(int(lit, 0), int(lit.replace('_', ''), 0)) 251 for lit in INVALID_UNDERSCORE_LITERALS: 252 if any(ch in lit for ch in '.eEjJ'): 253 continue 254 self.assertRaises(ValueError, int, lit, 0) 255 # Additional test cases with bases != 0, only for the constructor: 256 self.assertEqual(int("1_00", 3), 9) 257 self.assertEqual(int("0_100"), 100) # not valid as a literal! 258 self.assertEqual(int(b"1_00"), 100) # byte underscore 259 self.assertRaises(ValueError, int, "_100") 260 self.assertRaises(ValueError, int, "+_100") 261 self.assertRaises(ValueError, int, "1__00") 262 self.assertRaises(ValueError, int, "100_") 263 264 @support.cpython_only 265 def test_small_ints(self): 266 # Bug #3236: Return small longs from PyLong_FromString 267 self.assertIs(int('10'), 10) 268 self.assertIs(int('-1'), -1) 269 self.assertIs(int(b'10'), 10) 270 self.assertIs(int(b'-1'), -1) 271 272 def test_no_args(self): 273 self.assertEqual(int(), 0) 274 275 def test_keyword_args(self): 276 # Test invoking int() using keyword arguments. 277 self.assertEqual(int('100', base=2), 4) 278 with self.assertRaisesRegex(TypeError, 'keyword argument'): 279 int(x=1.2) 280 with self.assertRaisesRegex(TypeError, 'keyword argument'): 281 int(x='100', base=2) 282 self.assertRaises(TypeError, int, base=10) 283 self.assertRaises(TypeError, int, base=0) 284 285 def test_int_base_limits(self): 286 """Testing the supported limits of the int() base parameter.""" 287 self.assertEqual(int('0', 5), 0) 288 with self.assertRaises(ValueError): 289 int('0', 1) 290 with self.assertRaises(ValueError): 291 int('0', 37) 292 with self.assertRaises(ValueError): 293 int('0', -909) # An old magic value base from Python 2. 294 with self.assertRaises(ValueError): 295 int('0', base=0-(2**234)) 296 with self.assertRaises(ValueError): 297 int('0', base=2**234) 298 # Bases 2 through 36 are supported. 299 for base in range(2,37): 300 self.assertEqual(int('0', base=base), 0) 301 302 def test_int_base_bad_types(self): 303 """Not integer types are not valid bases; issue16772.""" 304 with self.assertRaises(TypeError): 305 int('0', 5.5) 306 with self.assertRaises(TypeError): 307 int('0', 5.0) 308 309 def test_int_base_indexable(self): 310 class MyIndexable(object): 311 def __init__(self, value): 312 self.value = value 313 def __index__(self): 314 return self.value 315 316 # Check out of range bases. 317 for base in 2**100, -2**100, 1, 37: 318 with self.assertRaises(ValueError): 319 int('43', base) 320 321 # Check in-range bases. 322 self.assertEqual(int('101', base=MyIndexable(2)), 5) 323 self.assertEqual(int('101', base=MyIndexable(10)), 101) 324 self.assertEqual(int('101', base=MyIndexable(36)), 1 + 36**2) 325 326 def test_non_numeric_input_types(self): 327 # Test possible non-numeric types for the argument x, including 328 # subclasses of the explicitly documented accepted types. 329 class CustomStr(str): pass 330 class CustomBytes(bytes): pass 331 class CustomByteArray(bytearray): pass 332 333 factories = [ 334 bytes, 335 bytearray, 336 lambda b: CustomStr(b.decode()), 337 CustomBytes, 338 CustomByteArray, 339 memoryview, 340 ] 341 try: 342 from array import array 343 except ImportError: 344 pass 345 else: 346 factories.append(lambda b: array('B', b)) 347 348 for f in factories: 349 x = f(b'100') 350 with self.subTest(type(x)): 351 self.assertEqual(int(x), 100) 352 if isinstance(x, (str, bytes, bytearray)): 353 self.assertEqual(int(x, 2), 4) 354 else: 355 msg = "can't convert non-string" 356 with self.assertRaisesRegex(TypeError, msg): 357 int(x, 2) 358 with self.assertRaisesRegex(ValueError, 'invalid literal'): 359 int(f(b'A' * 0x10)) 360 361 def test_int_memoryview(self): 362 self.assertEqual(int(memoryview(b'123')[1:3]), 23) 363 self.assertEqual(int(memoryview(b'123\x00')[1:3]), 23) 364 self.assertEqual(int(memoryview(b'123 ')[1:3]), 23) 365 self.assertEqual(int(memoryview(b'123A')[1:3]), 23) 366 self.assertEqual(int(memoryview(b'1234')[1:3]), 23) 367 368 def test_string_float(self): 369 self.assertRaises(ValueError, int, '1.2') 370 371 def test_intconversion(self): 372 # Test __int__() 373 class ClassicMissingMethods: 374 pass 375 self.assertRaises(TypeError, int, ClassicMissingMethods()) 376 377 class MissingMethods(object): 378 pass 379 self.assertRaises(TypeError, int, MissingMethods()) 380 381 class Foo0: 382 def __int__(self): 383 return 42 384 385 self.assertEqual(int(Foo0()), 42) 386 387 class Classic: 388 pass 389 for base in (object, Classic): 390 class IntOverridesTrunc(base): 391 def __int__(self): 392 return 42 393 def __trunc__(self): 394 return -12 395 self.assertEqual(int(IntOverridesTrunc()), 42) 396 397 class JustTrunc(base): 398 def __trunc__(self): 399 return 42 400 with self.assertWarns(DeprecationWarning): 401 self.assertEqual(int(JustTrunc()), 42) 402 403 class ExceptionalTrunc(base): 404 def __trunc__(self): 405 1 / 0 406 with self.assertRaises(ZeroDivisionError), \ 407 self.assertWarns(DeprecationWarning): 408 int(ExceptionalTrunc()) 409 410 for trunc_result_base in (object, Classic): 411 class Index(trunc_result_base): 412 def __index__(self): 413 return 42 414 415 class TruncReturnsNonInt(base): 416 def __trunc__(self): 417 return Index() 418 with self.assertWarns(DeprecationWarning): 419 self.assertEqual(int(TruncReturnsNonInt()), 42) 420 421 class Intable(trunc_result_base): 422 def __int__(self): 423 return 42 424 425 class TruncReturnsNonIndex(base): 426 def __trunc__(self): 427 return Intable() 428 with self.assertWarns(DeprecationWarning): 429 self.assertEqual(int(TruncReturnsNonInt()), 42) 430 431 class NonIntegral(trunc_result_base): 432 def __trunc__(self): 433 # Check that we avoid infinite recursion. 434 return NonIntegral() 435 436 class TruncReturnsNonIntegral(base): 437 def __trunc__(self): 438 return NonIntegral() 439 try: 440 with self.assertWarns(DeprecationWarning): 441 int(TruncReturnsNonIntegral()) 442 except TypeError as e: 443 self.assertEqual(str(e), 444 "__trunc__ returned non-Integral" 445 " (type NonIntegral)") 446 else: 447 self.fail("Failed to raise TypeError with %s" % 448 ((base, trunc_result_base),)) 449 450 # Regression test for bugs.python.org/issue16060. 451 class BadInt(trunc_result_base): 452 def __int__(self): 453 return 42.0 454 455 class TruncReturnsBadInt(base): 456 def __trunc__(self): 457 return BadInt() 458 459 with self.assertRaises(TypeError), \ 460 self.assertWarns(DeprecationWarning): 461 int(TruncReturnsBadInt()) 462 463 def test_int_subclass_with_index(self): 464 class MyIndex(int): 465 def __index__(self): 466 return 42 467 468 class BadIndex(int): 469 def __index__(self): 470 return 42.0 471 472 my_int = MyIndex(7) 473 self.assertEqual(my_int, 7) 474 self.assertEqual(int(my_int), 7) 475 476 self.assertEqual(int(BadIndex()), 0) 477 478 def test_int_subclass_with_int(self): 479 class MyInt(int): 480 def __int__(self): 481 return 42 482 483 class BadInt(int): 484 def __int__(self): 485 return 42.0 486 487 my_int = MyInt(7) 488 self.assertEqual(my_int, 7) 489 self.assertEqual(int(my_int), 42) 490 491 my_int = BadInt(7) 492 self.assertEqual(my_int, 7) 493 self.assertRaises(TypeError, int, my_int) 494 495 def test_int_returns_int_subclass(self): 496 class BadIndex: 497 def __index__(self): 498 return True 499 500 class BadIndex2(int): 501 def __index__(self): 502 return True 503 504 class BadInt: 505 def __int__(self): 506 return True 507 508 class BadInt2(int): 509 def __int__(self): 510 return True 511 512 class TruncReturnsBadIndex: 513 def __trunc__(self): 514 return BadIndex() 515 516 class TruncReturnsBadInt: 517 def __trunc__(self): 518 return BadInt() 519 520 class TruncReturnsIntSubclass: 521 def __trunc__(self): 522 return True 523 524 bad_int = BadIndex() 525 with self.assertWarns(DeprecationWarning): 526 n = int(bad_int) 527 self.assertEqual(n, 1) 528 self.assertIs(type(n), int) 529 530 bad_int = BadIndex2() 531 n = int(bad_int) 532 self.assertEqual(n, 0) 533 self.assertIs(type(n), int) 534 535 bad_int = BadInt() 536 with self.assertWarns(DeprecationWarning): 537 n = int(bad_int) 538 self.assertEqual(n, 1) 539 self.assertIs(type(n), int) 540 541 bad_int = BadInt2() 542 with self.assertWarns(DeprecationWarning): 543 n = int(bad_int) 544 self.assertEqual(n, 1) 545 self.assertIs(type(n), int) 546 547 bad_int = TruncReturnsBadIndex() 548 with self.assertWarns(DeprecationWarning): 549 n = int(bad_int) 550 self.assertEqual(n, 1) 551 self.assertIs(type(n), int) 552 553 bad_int = TruncReturnsBadInt() 554 with self.assertWarns(DeprecationWarning): 555 self.assertRaises(TypeError, int, bad_int) 556 557 good_int = TruncReturnsIntSubclass() 558 with self.assertWarns(DeprecationWarning): 559 n = int(good_int) 560 self.assertEqual(n, 1) 561 self.assertIs(type(n), int) 562 with self.assertWarns(DeprecationWarning): 563 n = IntSubclass(good_int) 564 self.assertEqual(n, 1) 565 self.assertIs(type(n), IntSubclass) 566 567 def test_error_message(self): 568 def check(s, base=None): 569 with self.assertRaises(ValueError, 570 msg="int(%r, %r)" % (s, base)) as cm: 571 if base is None: 572 int(s) 573 else: 574 int(s, base) 575 self.assertEqual(cm.exception.args[0], 576 "invalid literal for int() with base %d: %r" % 577 (10 if base is None else base, s)) 578 579 check('\xbd') 580 check('123\xbd') 581 check(' 123 456 ') 582 583 check('123\x00') 584 # SF bug 1545497: embedded NULs were not detected with explicit base 585 check('123\x00', 10) 586 check('123\x00 245', 20) 587 check('123\x00 245', 16) 588 check('123\x00245', 20) 589 check('123\x00245', 16) 590 # byte string with embedded NUL 591 check(b'123\x00') 592 check(b'123\x00', 10) 593 # non-UTF-8 byte string 594 check(b'123\xbd') 595 check(b'123\xbd', 10) 596 # lone surrogate in Unicode string 597 check('123\ud800') 598 check('123\ud800', 10) 599 600 def test_issue31619(self): 601 self.assertEqual(int('1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1_0_1', 2), 602 0b1010101010101010101010101010101) 603 self.assertEqual(int('1_2_3_4_5_6_7_0_1_2_3', 8), 0o12345670123) 604 self.assertEqual(int('1_2_3_4_5_6_7_8_9', 16), 0x123456789) 605 self.assertEqual(int('1_2_3_4_5_6_7', 32), 1144132807) 606 607 608class IntStrDigitLimitsTests(unittest.TestCase): 609 610 int_class = int # Override this in subclasses to reuse the suite. 611 612 def setUp(self): 613 super().setUp() 614 self._previous_limit = sys.get_int_max_str_digits() 615 sys.set_int_max_str_digits(2048) 616 617 def tearDown(self): 618 sys.set_int_max_str_digits(self._previous_limit) 619 super().tearDown() 620 621 def test_disabled_limit(self): 622 self.assertGreater(sys.get_int_max_str_digits(), 0) 623 self.assertLess(sys.get_int_max_str_digits(), 20_000) 624 with support.adjust_int_max_str_digits(0): 625 self.assertEqual(sys.get_int_max_str_digits(), 0) 626 i = self.int_class('1' * 20_000) 627 str(i) 628 self.assertGreater(sys.get_int_max_str_digits(), 0) 629 630 def test_max_str_digits_edge_cases(self): 631 """Ignore the +/- sign and space padding.""" 632 int_class = self.int_class 633 maxdigits = sys.get_int_max_str_digits() 634 635 int_class('1' * maxdigits) 636 int_class(' ' + '1' * maxdigits) 637 int_class('1' * maxdigits + ' ') 638 int_class('+' + '1' * maxdigits) 639 int_class('-' + '1' * maxdigits) 640 self.assertEqual(len(str(10 ** (maxdigits - 1))), maxdigits) 641 642 def check(self, i, base=None): 643 with self.assertRaises(ValueError): 644 if base is None: 645 self.int_class(i) 646 else: 647 self.int_class(i, base) 648 649 def test_max_str_digits(self): 650 maxdigits = sys.get_int_max_str_digits() 651 652 self.check('1' * (maxdigits + 1)) 653 self.check(' ' + '1' * (maxdigits + 1)) 654 self.check('1' * (maxdigits + 1) + ' ') 655 self.check('+' + '1' * (maxdigits + 1)) 656 self.check('-' + '1' * (maxdigits + 1)) 657 self.check('1' * (maxdigits + 1)) 658 659 i = 10 ** maxdigits 660 with self.assertRaises(ValueError): 661 str(i) 662 663 def test_denial_of_service_prevented_int_to_str(self): 664 """Regression test: ensure we fail before performing O(N**2) work.""" 665 maxdigits = sys.get_int_max_str_digits() 666 assert maxdigits < 50_000, maxdigits # A test prerequisite. 667 668 huge_int = int(f'0x{"c"*65_000}', base=16) # 78268 decimal digits. 669 digits = 78_268 670 with ( 671 support.adjust_int_max_str_digits(digits), 672 support.CPUStopwatch() as sw_convert): 673 huge_decimal = str(huge_int) 674 self.assertEqual(len(huge_decimal), digits) 675 # Ensuring that we chose a slow enough conversion to measure. 676 # It takes 0.1 seconds on a Zen based cloud VM in an opt build. 677 # Some OSes have a low res 1/64s timer, skip if hard to measure. 678 if sw_convert.seconds < sw_convert.clock_info.resolution * 2: 679 raise unittest.SkipTest('"slow" conversion took only ' 680 f'{sw_convert.seconds} seconds.') 681 682 # We test with the limit almost at the size needed to check performance. 683 # The performant limit check is slightly fuzzy, give it a some room. 684 with support.adjust_int_max_str_digits(int(.995 * digits)): 685 with ( 686 self.assertRaises(ValueError) as err, 687 support.CPUStopwatch() as sw_fail_huge): 688 str(huge_int) 689 self.assertIn('conversion', str(err.exception)) 690 self.assertLessEqual(sw_fail_huge.seconds, sw_convert.seconds/2) 691 692 # Now we test that a conversion that would take 30x as long also fails 693 # in a similarly fast fashion. 694 extra_huge_int = int(f'0x{"c"*500_000}', base=16) # 602060 digits. 695 with ( 696 self.assertRaises(ValueError) as err, 697 support.CPUStopwatch() as sw_fail_extra_huge): 698 # If not limited, 8 seconds said Zen based cloud VM. 699 str(extra_huge_int) 700 self.assertIn('conversion', str(err.exception)) 701 self.assertLess(sw_fail_extra_huge.seconds, sw_convert.seconds/2) 702 703 def test_denial_of_service_prevented_str_to_int(self): 704 """Regression test: ensure we fail before performing O(N**2) work.""" 705 maxdigits = sys.get_int_max_str_digits() 706 assert maxdigits < 100_000, maxdigits # A test prerequisite. 707 708 digits = 133700 709 huge = '8'*digits 710 with ( 711 support.adjust_int_max_str_digits(digits), 712 support.CPUStopwatch() as sw_convert): 713 int(huge) 714 # Ensuring that we chose a slow enough conversion to measure. 715 # It takes 0.1 seconds on a Zen based cloud VM in an opt build. 716 # Some OSes have a low res 1/64s timer, skip if hard to measure. 717 if sw_convert.seconds < sw_convert.clock_info.resolution * 2: 718 raise unittest.SkipTest('"slow" conversion took only ' 719 f'{sw_convert.seconds} seconds.') 720 721 with support.adjust_int_max_str_digits(digits - 1): 722 with ( 723 self.assertRaises(ValueError) as err, 724 support.CPUStopwatch() as sw_fail_huge): 725 int(huge) 726 self.assertIn('conversion', str(err.exception)) 727 self.assertLessEqual(sw_fail_huge.seconds, sw_convert.seconds/2) 728 729 # Now we test that a conversion that would take 30x as long also fails 730 # in a similarly fast fashion. 731 extra_huge = '7'*1_200_000 732 with ( 733 self.assertRaises(ValueError) as err, 734 support.CPUStopwatch() as sw_fail_extra_huge): 735 # If not limited, 8 seconds in the Zen based cloud VM. 736 int(extra_huge) 737 self.assertIn('conversion', str(err.exception)) 738 self.assertLessEqual(sw_fail_extra_huge.seconds, sw_convert.seconds/2) 739 740 def test_power_of_two_bases_unlimited(self): 741 """The limit does not apply to power of 2 bases.""" 742 maxdigits = sys.get_int_max_str_digits() 743 744 for base in (2, 4, 8, 16, 32): 745 with self.subTest(base=base): 746 self.int_class('1' * (maxdigits + 1), base) 747 assert maxdigits < 100_000 748 self.int_class('1' * 100_000, base) 749 750 def test_underscores_ignored(self): 751 maxdigits = sys.get_int_max_str_digits() 752 753 triples = maxdigits // 3 754 s = '111' * triples 755 s_ = '1_11' * triples 756 self.int_class(s) # succeeds 757 self.int_class(s_) # succeeds 758 self.check(f'{s}111') 759 self.check(f'{s_}_111') 760 761 def test_sign_not_counted(self): 762 int_class = self.int_class 763 max_digits = sys.get_int_max_str_digits() 764 s = '5' * max_digits 765 i = int_class(s) 766 pos_i = int_class(f'+{s}') 767 assert i == pos_i 768 neg_i = int_class(f'-{s}') 769 assert -pos_i == neg_i 770 str(pos_i) 771 str(neg_i) 772 773 def _other_base_helper(self, base): 774 int_class = self.int_class 775 max_digits = sys.get_int_max_str_digits() 776 s = '2' * max_digits 777 i = int_class(s, base) 778 if base > 10: 779 with self.assertRaises(ValueError): 780 str(i) 781 elif base < 10: 782 str(i) 783 with self.assertRaises(ValueError) as err: 784 int_class(f'{s}1', base) 785 786 def test_int_from_other_bases(self): 787 base = 3 788 with self.subTest(base=base): 789 self._other_base_helper(base) 790 base = 36 791 with self.subTest(base=base): 792 self._other_base_helper(base) 793 794 def test_int_max_str_digits_is_per_interpreter(self): 795 # Changing the limit in one interpreter does not change others. 796 code = """if 1: 797 # Subinterpreters maintain and enforce their own limit 798 import sys 799 sys.set_int_max_str_digits(2323) 800 try: 801 int('3'*3333) 802 except ValueError: 803 pass 804 else: 805 raise AssertionError('Expected a int max str digits ValueError.') 806 """ 807 with support.adjust_int_max_str_digits(4000): 808 before_value = sys.get_int_max_str_digits() 809 self.assertEqual(support.run_in_subinterp(code), 0, 810 'subinterp code failure, check stderr.') 811 after_value = sys.get_int_max_str_digits() 812 self.assertEqual(before_value, after_value) 813 814 815class IntSubclassStrDigitLimitsTests(IntStrDigitLimitsTests): 816 int_class = IntSubclass 817 818 819class PyLongModuleTests(unittest.TestCase): 820 # Tests of the functions in _pylong.py. Those get used when the 821 # number of digits in the input values are large enough. 822 823 def setUp(self): 824 super().setUp() 825 self._previous_limit = sys.get_int_max_str_digits() 826 sys.set_int_max_str_digits(0) 827 828 def tearDown(self): 829 sys.set_int_max_str_digits(self._previous_limit) 830 super().tearDown() 831 832 def _test_pylong_int_to_decimal(self, n, suffix): 833 s = str(n) 834 self.assertEqual(s[-10:], suffix) 835 s2 = str(-n) 836 self.assertEqual(s2, '-' + s) 837 s3 = '%d' % n 838 self.assertEqual(s3, s) 839 s4 = b'%d' % n 840 self.assertEqual(s4, s.encode('ascii')) 841 842 def test_pylong_int_to_decimal(self): 843 self._test_pylong_int_to_decimal((1 << 100_000), '9883109376') 844 self._test_pylong_int_to_decimal((1 << 100_000) - 1, '9883109375') 845 self._test_pylong_int_to_decimal(10**30_000, '0000000000') 846 self._test_pylong_int_to_decimal(10**30_000 - 1, '9999999999') 847 self._test_pylong_int_to_decimal(3**60_000, '9313200001') 848 849 @support.requires_resource('cpu') 850 def test_pylong_int_to_decimal_2(self): 851 self._test_pylong_int_to_decimal(2**1_000_000, '2747109376') 852 self._test_pylong_int_to_decimal(10**300_000, '0000000000') 853 self._test_pylong_int_to_decimal(3**600_000, '3132000001') 854 855 def test_pylong_int_divmod(self): 856 n = (1 << 100_000) 857 a, b = divmod(n*3 + 1, n) 858 assert a == 3 and b == 1 859 860 def test_pylong_str_to_int(self): 861 v1 = 1 << 100_000 862 s = str(v1) 863 v2 = int(s) 864 assert v1 == v2 865 v3 = int(' -' + s) 866 assert -v1 == v3 867 v4 = int(' +' + s + ' ') 868 assert v1 == v4 869 with self.assertRaises(ValueError) as err: 870 int(s + 'z') 871 with self.assertRaises(ValueError) as err: 872 int(s + '_') 873 with self.assertRaises(ValueError) as err: 874 int('_' + s) 875 876 @support.cpython_only # tests implementation details of CPython. 877 @unittest.skipUnless(_pylong, "_pylong module required") 878 @mock.patch.object(_pylong, "int_to_decimal_string") 879 def test_pylong_misbehavior_error_path_to_str( 880 self, mock_int_to_str): 881 with support.adjust_int_max_str_digits(20_000): 882 big_value = int('7'*19_999) 883 mock_int_to_str.return_value = None # not a str 884 with self.assertRaises(TypeError) as ctx: 885 str(big_value) 886 self.assertIn('_pylong.int_to_decimal_string did not', 887 str(ctx.exception)) 888 mock_int_to_str.side_effect = RuntimeError("testABC") 889 with self.assertRaises(RuntimeError): 890 str(big_value) 891 892 @support.cpython_only # tests implementation details of CPython. 893 @unittest.skipUnless(_pylong, "_pylong module required") 894 @mock.patch.object(_pylong, "int_from_string") 895 def test_pylong_misbehavior_error_path_from_str( 896 self, mock_int_from_str): 897 big_value = '7'*19_999 898 with support.adjust_int_max_str_digits(20_000): 899 mock_int_from_str.return_value = b'not an int' 900 with self.assertRaises(TypeError) as ctx: 901 int(big_value) 902 self.assertIn('_pylong.int_from_string did not', 903 str(ctx.exception)) 904 905 mock_int_from_str.side_effect = RuntimeError("test123") 906 with self.assertRaises(RuntimeError): 907 int(big_value) 908 909 def test_pylong_roundtrip(self): 910 from random import randrange, getrandbits 911 bits = 5000 912 while bits <= 1_000_000: 913 bits += randrange(-100, 101) # break bitlength patterns 914 hibit = 1 << (bits - 1) 915 n = hibit | getrandbits(bits - 1) 916 assert n.bit_length() == bits 917 sn = str(n) 918 self.assertFalse(sn.startswith('0')) 919 self.assertEqual(n, int(sn)) 920 bits <<= 1 921 922if __name__ == "__main__": 923 unittest.main() 924