From d6350c672a3277af8b1c07363809659d80e24a8b Mon Sep 17 00:00:00 2001 From: Andrey Maltsev Date: Tue, 4 Apr 2023 10:00:24 +0000 Subject: [PATCH] Update test_long.py from Cpython v3.11.2 --- Lib/test/test_long.py | 226 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 221 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 20dab209e3..a25eff5b06 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -378,6 +378,8 @@ def test_long(self): self.assertRaises(ValueError, int, '\u3053\u3093\u306b\u3061\u306f') + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_conversion(self): class JustLong: @@ -392,7 +394,8 @@ def __long__(self): return 42 def __trunc__(self): return 1729 - self.assertEqual(int(LongTrunc()), 1729) + with self.assertWarns(DeprecationWarning): + self.assertEqual(int(LongTrunc()), 1729) def check_float_conversion(self, n): # Check that int -> float conversion behaviour matches @@ -952,8 +955,13 @@ def test_huge_lshift(self, size): self.assertEqual(1 << (sys.maxsize + 1000), 1 << 1000 << sys.maxsize) def test_huge_rshift(self): - self.assertEqual(42 >> (1 << 1000), 0) - self.assertEqual((-42) >> (1 << 1000), -1) + huge_shift = 1 << 1000 + self.assertEqual(42 >> huge_shift, 0) + self.assertEqual((-42) >> huge_shift, -1) + self.assertEqual(1123 >> huge_shift, 0) + self.assertEqual((-1123) >> huge_shift, -1) + self.assertEqual(2**128 >> huge_shift, 0) + self.assertEqual(-2**128 >> huge_shift, -1) @support.cpython_only @support.bigmemtest(sys.maxsize + 500, memuse=2/15, dry_run=False) @@ -962,6 +970,64 @@ def test_huge_rshift_of_huge(self, size): self.assertEqual(huge >> (sys.maxsize + 1), (1 << 499) + 5) self.assertEqual(huge >> (sys.maxsize + 1000), 0) + def test_small_rshift(self): + self.assertEqual(42 >> 1, 21) + self.assertEqual((-42) >> 1, -21) + self.assertEqual(43 >> 1, 21) + self.assertEqual((-43) >> 1, -22) + + self.assertEqual(1122 >> 1, 561) + self.assertEqual((-1122) >> 1, -561) + self.assertEqual(1123 >> 1, 561) + self.assertEqual((-1123) >> 1, -562) + + self.assertEqual(2**128 >> 1, 2**127) + self.assertEqual(-2**128 >> 1, -2**127) + self.assertEqual((2**128 + 1) >> 1, 2**127) + self.assertEqual(-(2**128 + 1) >> 1, -2**127 - 1) + + def test_medium_rshift(self): + self.assertEqual(42 >> 9, 0) + self.assertEqual((-42) >> 9, -1) + self.assertEqual(1122 >> 9, 2) + self.assertEqual((-1122) >> 9, -3) + self.assertEqual(2**128 >> 9, 2**119) + self.assertEqual(-2**128 >> 9, -2**119) + # Exercise corner case of the current algorithm, where the result of + # shifting a two-limb int by the limb size still has two limbs. + self.assertEqual((1 - BASE*BASE) >> SHIFT, -BASE) + self.assertEqual((BASE - 1 - BASE*BASE) >> SHIFT, -BASE) + + def test_big_rshift(self): + self.assertEqual(42 >> 32, 0) + self.assertEqual((-42) >> 32, -1) + self.assertEqual(1122 >> 32, 0) + self.assertEqual((-1122) >> 32, -1) + self.assertEqual(2**128 >> 32, 2**96) + self.assertEqual(-2**128 >> 32, -2**96) + + def test_small_lshift(self): + self.assertEqual(42 << 1, 84) + self.assertEqual((-42) << 1, -84) + self.assertEqual(561 << 1, 1122) + self.assertEqual((-561) << 1, -1122) + self.assertEqual(2**127 << 1, 2**128) + self.assertEqual(-2**127 << 1, -2**128) + + def test_medium_lshift(self): + self.assertEqual(42 << 9, 21504) + self.assertEqual((-42) << 9, -21504) + self.assertEqual(1122 << 9, 574464) + self.assertEqual((-1122) << 9, -574464) + + def test_big_lshift(self): + self.assertEqual(42 << 32, 42 * 2**32) + self.assertEqual((-42) << 32, -42 * 2**32) + self.assertEqual(1122 << 32, 1122 * 2**32) + self.assertEqual((-1122) << 32, -1122 * 2**32) + self.assertEqual(2**128 << 32, 2**160) + self.assertEqual(-2**128 << 32, -2**160) + @support.cpython_only def test_small_ints_in_huge_calculation(self): a = 2 ** 100 @@ -970,6 +1036,48 @@ def test_small_ints_in_huge_calculation(self): self.assertIs(a + b, 1) self.assertIs(c - a, 1) + @support.cpython_only + def test_pow_uses_cached_small_ints(self): + self.assertIs(pow(10, 3, 998), 2) + self.assertIs(10 ** 3 % 998, 2) + a, p, m = 10, 3, 998 + self.assertIs(a ** p % m, 2) + + self.assertIs(pow(2, 31, 2 ** 31 - 1), 1) + self.assertIs(2 ** 31 % (2 ** 31 - 1), 1) + a, p, m = 2, 31, 2 ** 31 - 1 + self.assertIs(a ** p % m, 1) + + self.assertIs(pow(2, 100, 2**100 - 3), 3) + self.assertIs(2 ** 100 % (2 ** 100 - 3), 3) + a, p, m = 2, 100, 2**100 - 3 + self.assertIs(a ** p % m, 3) + + @support.cpython_only + def test_divmod_uses_cached_small_ints(self): + big = 10 ** 100 + + self.assertIs((big + 1) % big, 1) + self.assertIs((big + 1) // big, 1) + self.assertIs(big // (big // 2), 2) + self.assertIs(big // (big // -4), -4) + + q, r = divmod(2 * big + 3, big) + self.assertIs(q, 2) + self.assertIs(r, 3) + + q, r = divmod(-4 * big + 100, big) + self.assertIs(q, -4) + self.assertIs(r, 100) + + q, r = divmod(3 * (-big) - 1, -big) + self.assertIs(q, 3) + self.assertIs(r, -1) + + q, r = divmod(3 * big - 1, -big) + self.assertIs(q, -3) + self.assertIs(r, -1) + def test_small_ints(self): for i in range(-5, 257): self.assertIs(i, i + 0) @@ -1111,6 +1219,13 @@ def test_round(self): def test_to_bytes(self): def check(tests, byteorder, signed=False): + def equivalent_python(n, length, byteorder, signed=False): + if byteorder == 'little': + order = range(length) + elif byteorder == 'big': + order = reversed(range(length)) + return bytes((n >> i*8) & 0xff for i in order) + for test, expected in tests.items(): try: self.assertEqual( @@ -1118,9 +1233,30 @@ def check(tests, byteorder, signed=False): expected) except Exception as err: raise AssertionError( - "failed to convert {0} with byteorder={1} and signed={2}" + "failed to convert {} with byteorder={} and signed={}" .format(test, byteorder, signed)) from err + # Test for all default arguments. + if len(expected) == 1 and byteorder == 'big' and not signed: + try: + self.assertEqual(test.to_bytes(), expected) + except Exception as err: + raise AssertionError( + "failed to convert {} with default arguments" + .format(test)) from err + + try: + self.assertEqual( + equivalent_python( + test, len(expected), byteorder, signed=signed), + expected + ) + except Exception as err: + raise AssertionError( + "Code equivalent from docs is not equivalent for " + "conversion of {0} with byteorder byteorder={1} and " + "signed={2}".format(test, byteorder, signed)) from err + # Convert integers to signed big-endian byte arrays. tests1 = { 0: b'\x00', @@ -1208,10 +1344,28 @@ def check(tests, byteorder, signed=False): b'\xff\xff\xff\xff\xff') self.assertRaises(OverflowError, (1).to_bytes, 0, 'big') + # gh-98783 + class SubStr(str): + pass + self.assertEqual((0).to_bytes(1, SubStr('big')), b'\x00') + self.assertEqual((0).to_bytes(0, SubStr('little')), b'') + # TODO: RUSTPYTHON @unittest.expectedFailure def test_from_bytes(self): def check(tests, byteorder, signed=False): + def equivalent_python(byte_array, byteorder, signed=False): + if byteorder == 'little': + little_ordered = list(byte_array) + elif byteorder == 'big': + little_ordered = list(reversed(byte_array)) + + n = sum(b << i*8 for i, b in enumerate(little_ordered)) + if signed and little_ordered and (little_ordered[-1] & 0x80): + n -= 1 << 8*len(little_ordered) + + return n + for test, expected in tests.items(): try: self.assertEqual( @@ -1219,7 +1373,29 @@ def check(tests, byteorder, signed=False): expected) except Exception as err: raise AssertionError( - "failed to convert {0} with byteorder={1!r} and signed={2}" + "failed to convert {} with byteorder={!r} and signed={}" + .format(test, byteorder, signed)) from err + + # Test for all default arguments. + if byteorder == 'big' and not signed: + try: + self.assertEqual( + int.from_bytes(test), + expected) + except Exception as err: + raise AssertionError( + "failed to convert {} with default arguments" + .format(test)) from err + + try: + self.assertEqual( + equivalent_python(test, byteorder, signed=signed), + expected + ) + except Exception as err: + raise AssertionError( + "Code equivalent from docs is not equivalent for " + "conversion of {0} with byteorder={1!r} and signed={2}" .format(test, byteorder, signed)) from err # Convert signed big-endian byte arrays to integers. @@ -1360,6 +1536,35 @@ def __init__(self, value): self.assertEqual(i, 1) self.assertEqual(getattr(i, 'foo', 'none'), 'bar') + class ValidBytes: + def __bytes__(self): + return b'\x01' + class InvalidBytes: + def __bytes__(self): + return 'abc' + class MissingBytes: ... + class RaisingBytes: + def __bytes__(self): + 1 / 0 + + self.assertEqual(int.from_bytes(ValidBytes()), 1) + self.assertRaises(TypeError, int.from_bytes, InvalidBytes()) + self.assertRaises(TypeError, int.from_bytes, MissingBytes()) + self.assertRaises(ZeroDivisionError, int.from_bytes, RaisingBytes()) + + # gh-98783 + class SubStr(str): + pass + self.assertEqual(int.from_bytes(b'', SubStr('big')), 0) + self.assertEqual(int.from_bytes(b'\x00', SubStr('little')), 0) + + @support.cpython_only + def test_from_bytes_small(self): + # bpo-46361 + for i in range(-5, 257): + b = i.to_bytes(2, signed=True) + self.assertIs(int.from_bytes(b, signed=True), i) + def test_access_to_nonexistent_digit_0(self): # http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that # ob_digit[0] was being incorrectly accessed for instances of a @@ -1391,6 +1596,17 @@ class myint(int): self.assertEqual(type(numerator), int) self.assertEqual(type(denominator), int) + def test_square(self): + # Multiplication makes a special case of multiplying an int with + # itself, using a special, faster algorithm. This test is mostly + # to ensure that no asserts in the implementation trigger, in + # cases with a maximal amount of carries. + for bitlen in range(1, 400): + n = (1 << bitlen) - 1 # solid string of 1 bits + with self.subTest(bitlen=bitlen, n=n): + # (2**i - 1)**2 = 2**(2*i) - 2*2**i + 1 + self.assertEqual(n**2, + (1 << (2 * bitlen)) - (1 << (bitlen + 1)) + 1) if __name__ == "__main__": unittest.main()