mirror of
https://github.com/micropython/micropython.git
synced 2025-07-20 20:41:10 +02:00
tests: Add specific tests for "long long" 64-bit bigints.
These will run on all ports which support them, but importantly they'll also run on ports that don't support arbitrary precision but do support 64-bit long ints. Includes some test workarounds to account for things which will overflow once "long long" big integers overflow (added in follow-up commit): - uctypes_array_load_store test was failing already, now won't parse. - all the ffi_int tests contain 64-bit unsigned values, that won't parse as long long. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
committed by
Damien George
parent
c72a3e528d
commit
2d8d64059f
126
tests/basics/int_64_basics.py
Normal file
126
tests/basics/int_64_basics.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# test support for 64-bit long integers
|
||||
# (some ports don't support arbitrary precision but do support these)
|
||||
|
||||
# this test is adapted from int_big1.py with numbers kept within 64-bit signed range
|
||||
|
||||
# to test arbitrary precision integers
|
||||
|
||||
x = 1000000000000000000
|
||||
xn = -1000000000000000000
|
||||
y = 2000000000000000000
|
||||
|
||||
# printing
|
||||
print(x)
|
||||
print(y)
|
||||
print('%#X' % (x - x)) # print prefix
|
||||
print('{:#,}'.format(x)) # print with commas
|
||||
|
||||
# construction
|
||||
print(int(x))
|
||||
|
||||
# addition
|
||||
print(x + 1)
|
||||
print(x + y)
|
||||
print(x + xn == 0)
|
||||
print(bool(x + xn))
|
||||
|
||||
# subtraction
|
||||
print(x - 1)
|
||||
print(x - y)
|
||||
print(y - x)
|
||||
print(x - x == 0)
|
||||
print(bool(x - x))
|
||||
|
||||
# multiplication
|
||||
print(x * 2)
|
||||
print(1090511627776 * 1048500)
|
||||
|
||||
# integer division
|
||||
print(x // 2)
|
||||
print(y // x)
|
||||
|
||||
# bit inversion
|
||||
print(~x)
|
||||
print(~(-x))
|
||||
|
||||
# left shift
|
||||
print("left shift positive")
|
||||
x = 0x40000000
|
||||
for i in range(32):
|
||||
x = x << 1
|
||||
print(x)
|
||||
|
||||
# right shift
|
||||
print("right shift positive")
|
||||
x = 0x2000000000000000 # TODO: why can't second-tip bit be set?
|
||||
for i in range(64):
|
||||
x = x >> 1
|
||||
print(x)
|
||||
|
||||
# left shift of a negative number
|
||||
print("left shift negative")
|
||||
for i in range(8):
|
||||
print(-10000000000000000 << i)
|
||||
print(-10000000000000001 << i)
|
||||
print(-10000000000000002 << i)
|
||||
print(-10000000000000003 << i)
|
||||
print(-10000000000000004 << i)
|
||||
|
||||
|
||||
# right shift of a negative number
|
||||
print("right shift negative")
|
||||
for i in range(8):
|
||||
print(-1000000000000000000 >> i)
|
||||
print(-1000000000000000001 >> i)
|
||||
print(-1000000000000000002 >> i)
|
||||
print(-1000000000000000003 >> i)
|
||||
print(-1000000000000000004 >> i)
|
||||
|
||||
# conversion from string
|
||||
print(int("1234567890123456789"))
|
||||
print(int("-1234567890123456789"))
|
||||
print(int("1234567890abcdef", 16))
|
||||
print(int("1234567890ABCDEF", 16))
|
||||
print(int("-1234567890ABCDEF", 16))
|
||||
print(int("ijklmnopqrsz", 36))
|
||||
|
||||
# numbers close to 64-bit limits
|
||||
print(int("-9111222333444555666"))
|
||||
print(int("9111222333444555666"))
|
||||
|
||||
# numbers with preceding 0s
|
||||
print(int("-00000000000000000000009111222333444555666"))
|
||||
print(int("0000000000000000000000009111222333444555666"))
|
||||
|
||||
# invalid characters in string
|
||||
try:
|
||||
print(int("1234567890abcdef"))
|
||||
except ValueError:
|
||||
print('ValueError');
|
||||
try:
|
||||
print(int("123456789\x01"))
|
||||
except ValueError:
|
||||
print('ValueError');
|
||||
|
||||
# test parsing ints just on threshold of small to big
|
||||
# for 32 bit archs
|
||||
x = 1073741823 # small
|
||||
x = -1073741823 # small
|
||||
x = 1073741824 # big
|
||||
x = -1073741824 # big
|
||||
# for 64 bit archs
|
||||
x = 4611686018427387903 # small
|
||||
x = -4611686018427387903 # small
|
||||
x = 4611686018427387904 # big
|
||||
x = -4611686018427387904 # big
|
||||
|
||||
# sys.maxsize is a constant bigint, so test it's compatible with dynamic ones
|
||||
import sys
|
||||
if hasattr(sys, "maxsize"):
|
||||
print(sys.maxsize + 1 - 1 == sys.maxsize)
|
||||
else:
|
||||
print(True) # No maxsize property in this config
|
||||
|
||||
# test extraction of big int value via mp_obj_get_int_maybe
|
||||
x = 1 << 62
|
||||
print('a' * (x + 4 - x))
|
@@ -6,6 +6,13 @@ except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
# 'int' needs to be able to represent UINT64 for this test
|
||||
try:
|
||||
int("FF" * 8, 16)
|
||||
except OverflowError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
N = 5
|
||||
|
||||
for endian in ("NATIVE", "LITTLE_ENDIAN", "BIG_ENDIAN"):
|
||||
|
2
tests/feature_check/int_64.py
Normal file
2
tests/feature_check/int_64.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# Check whether 64-bit long integers are supported
|
||||
print(1 << 62)
|
1
tests/feature_check/int_64.py.exp
Normal file
1
tests/feature_check/int_64.py.exp
Normal file
@@ -0,0 +1 @@
|
||||
4611686018427387904
|
@@ -628,6 +628,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
|
||||
skip_tests = set()
|
||||
skip_native = False
|
||||
skip_int_big = False
|
||||
skip_int_64 = False
|
||||
skip_bytearray = False
|
||||
skip_set_type = False
|
||||
skip_slice = False
|
||||
@@ -658,6 +659,11 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
|
||||
if output != b"1000000000000000000000000000000000000000000000\n":
|
||||
skip_int_big = True
|
||||
|
||||
# Check if 'long long' precision integers are supported, even if arbitrary precision is not
|
||||
output = run_feature_check(pyb, args, "int_64.py")
|
||||
if output != b"4611686018427387904\n":
|
||||
skip_int_64 = True
|
||||
|
||||
# Check if bytearray is supported, and skip such tests if it's not
|
||||
output = run_feature_check(pyb, args, "bytearray.py")
|
||||
if output != b"bytearray\n":
|
||||
@@ -885,7 +891,12 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
|
||||
test_name = os.path.splitext(os.path.basename(test_file))[0]
|
||||
is_native = test_name.startswith("native_") or test_name.startswith("viper_")
|
||||
is_endian = test_name.endswith("_endian")
|
||||
is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig")
|
||||
is_int_big = (
|
||||
test_name.startswith("int_big")
|
||||
or test_name.endswith("_intbig")
|
||||
or test_name.startswith("ffi_int") # these tests contain large integer literals
|
||||
)
|
||||
is_int_64 = test_name.startswith("int_64") or test_name.endswith("_int64")
|
||||
is_bytearray = test_name.startswith("bytearray") or test_name.endswith("_bytearray")
|
||||
is_set_type = test_name.startswith(("set_", "frozenset")) or test_name.endswith("_set")
|
||||
is_slice = test_name.find("slice") != -1 or test_name in misc_slice_tests
|
||||
@@ -899,6 +910,7 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
|
||||
skip_it |= skip_native and is_native
|
||||
skip_it |= skip_endian and is_endian
|
||||
skip_it |= skip_int_big and is_int_big
|
||||
skip_it |= skip_int_64 and is_int_64
|
||||
skip_it |= skip_bytearray and is_bytearray
|
||||
skip_it |= skip_set_type and is_set_type
|
||||
skip_it |= skip_slice and is_slice
|
||||
|
Reference in New Issue
Block a user