497 lines
13 KiB
Plaintext
497 lines
13 KiB
Plaintext
# Test cases for integers (compile and run)
|
|
|
|
[case testInc]
|
|
def inc(x: int) -> int:
|
|
return x + 1
|
|
[file driver.py]
|
|
from native import inc
|
|
print(inc(3))
|
|
print(inc(-5))
|
|
print(inc(10**20))
|
|
[out]
|
|
4
|
|
-4
|
|
100000000000000000001
|
|
|
|
[case testCount]
|
|
def count(n: int) -> int:
|
|
i = 1
|
|
while i <= n:
|
|
i = i + 1
|
|
return i
|
|
[file driver.py]
|
|
from native import count
|
|
print(count(0))
|
|
print(count(1))
|
|
print(count(5))
|
|
[out]
|
|
1
|
|
2
|
|
6
|
|
|
|
[case testIntMathOps]
|
|
# This tests integer math things that are either easier to test in Python than
|
|
# in our C tests or are tested here because (for annoying reasons) we don't run
|
|
# the C unit tests in our 32-bit CI.
|
|
def multiply(x: int, y: int) -> int:
|
|
return x * y
|
|
|
|
# these stringify their outputs because that will catch if exceptions are mishandled
|
|
def floor_div(x: int, y: int) -> str:
|
|
return str(x // y)
|
|
def remainder(x: int, y: int) -> str:
|
|
return str(x % y)
|
|
|
|
[file driver.py]
|
|
from native import multiply, floor_div, remainder
|
|
|
|
def test_multiply(x, y):
|
|
assert multiply(x, y) == x * y
|
|
def test_floor_div(x, y):
|
|
assert floor_div(x, y) == str(x // y)
|
|
def test_remainder(x, y):
|
|
assert remainder(x, y) == str(x % y)
|
|
|
|
test_multiply(10**6, 10**6)
|
|
test_multiply(2**15, 2**15-1)
|
|
test_multiply(2**14, 2**14)
|
|
|
|
test_multiply(10**12, 10**12)
|
|
test_multiply(2**30, 2**30-1)
|
|
test_multiply(2**29, 2**29)
|
|
|
|
test_floor_div(-2**62, -1)
|
|
test_floor_div(-2**30, -1)
|
|
try:
|
|
floor_div(10, 0)
|
|
except ZeroDivisionError:
|
|
pass
|
|
else:
|
|
assert False, "Expected ZeroDivisionError"
|
|
|
|
test_remainder(-2**62, -1)
|
|
test_remainder(-2**30, -1)
|
|
try:
|
|
remainder(10, 0)
|
|
except ZeroDivisionError:
|
|
pass
|
|
else:
|
|
assert False, "Expected ZeroDivisionError"
|
|
|
|
[case testBigIntLiteral]
|
|
def big_int() -> None:
|
|
a_62_bit = 4611686018427387902
|
|
max_62_bit = 4611686018427387903
|
|
b_63_bit = 4611686018427387904
|
|
c_63_bit = 9223372036854775806
|
|
max_63_bit = 9223372036854775807
|
|
d_64_bit = 9223372036854775808
|
|
max_32_bit = 2147483647
|
|
max_32_bit_plus1 = 2147483648
|
|
max_31_bit = 1073741823
|
|
max_31_bit_plus1 = 1073741824
|
|
neg = -1234567
|
|
min_signed_63_bit = -4611686018427387904
|
|
underflow = -4611686018427387905
|
|
min_signed_64_bit = -9223372036854775808
|
|
min_signed_31_bit = -1073741824
|
|
min_signed_31_bit_plus1 = -1073741823
|
|
min_signed_31_bit_minus1 = -1073741825
|
|
min_signed_32_bit = -2147483648
|
|
print(a_62_bit)
|
|
print(max_62_bit)
|
|
print(b_63_bit)
|
|
print(c_63_bit)
|
|
print(max_63_bit)
|
|
print(d_64_bit)
|
|
print('==')
|
|
print(max_32_bit)
|
|
print(max_32_bit_plus1)
|
|
print(max_31_bit)
|
|
print(max_31_bit_plus1)
|
|
print(neg)
|
|
print(min_signed_63_bit)
|
|
print(underflow)
|
|
print(min_signed_64_bit)
|
|
print(min_signed_31_bit)
|
|
print(min_signed_31_bit_plus1)
|
|
print(min_signed_31_bit_minus1)
|
|
print(min_signed_32_bit)
|
|
[file driver.py]
|
|
from native import big_int
|
|
big_int()
|
|
[out]
|
|
4611686018427387902
|
|
4611686018427387903
|
|
4611686018427387904
|
|
9223372036854775806
|
|
9223372036854775807
|
|
9223372036854775808
|
|
==
|
|
2147483647
|
|
2147483648
|
|
1073741823
|
|
1073741824
|
|
-1234567
|
|
-4611686018427387904
|
|
-4611686018427387905
|
|
-9223372036854775808
|
|
-1073741824
|
|
-1073741823
|
|
-1073741825
|
|
-2147483648
|
|
|
|
[case testNeg]
|
|
def neg(x: int) -> int:
|
|
return -x
|
|
[file driver.py]
|
|
from native import neg
|
|
assert neg(5) == -5
|
|
assert neg(-5) == 5
|
|
assert neg(1073741823) == -1073741823
|
|
assert neg(-1073741823) == 1073741823
|
|
assert neg(1073741824) == -1073741824
|
|
assert neg(-1073741824) == 1073741824
|
|
assert neg(2147483647) == -2147483647
|
|
assert neg(-2147483647) == 2147483647
|
|
assert neg(2147483648) == -2147483648
|
|
assert neg(-2147483648) == 2147483648
|
|
assert neg(4611686018427387904) == -4611686018427387904
|
|
assert neg(-4611686018427387904) == 4611686018427387904
|
|
assert neg(9223372036854775807) == -9223372036854775807
|
|
assert neg(-9223372036854775807) == 9223372036854775807
|
|
assert neg(9223372036854775808) == -9223372036854775808
|
|
assert neg(-9223372036854775808) == 9223372036854775808
|
|
|
|
[case testIsinstanceIntAndNotBool]
|
|
def test_isinstance_int_and_not_bool(value: object) -> bool:
|
|
return isinstance(value, int) and not isinstance(value, bool)
|
|
[file driver.py]
|
|
from native import test_isinstance_int_and_not_bool
|
|
assert test_isinstance_int_and_not_bool(True) == False
|
|
assert test_isinstance_int_and_not_bool(1) == True
|
|
|
|
[case testIntOps]
|
|
from typing import Any
|
|
|
|
def check_and(x: int, y: int) -> None:
|
|
# eval() can be trusted to calculate expected result
|
|
expected = eval('{} & {}'.format(x, y))
|
|
actual = x & y
|
|
assert actual == expected, '{} & {}: got {}, expected {}'.format(x, y, actual, expected)
|
|
|
|
def check_or(x: int, y: int) -> None:
|
|
# eval() can be trusted to calculate expected result
|
|
expected = eval('{} | {}'.format(x, y))
|
|
actual = x | y
|
|
assert actual == expected, '{} | {}: got {}, expected {}'.format(x, y, actual, expected)
|
|
|
|
def check_xor(x: int, y: int) -> None:
|
|
# eval() can be trusted to calculate expected result
|
|
expected = eval('{} ^ {}'.format(x, y))
|
|
actual = x ^ y
|
|
assert actual == expected, '{} ^ {}: got {}, expected {}'.format(x, y, actual, expected)
|
|
|
|
def check_bitwise(x: int, y: int) -> None:
|
|
for l, r in (x, y), (y, x):
|
|
for ll, rr in (l, r), (-l, r), (l, -r), (-l, -r):
|
|
check_and(ll, rr)
|
|
check_or(ll, rr)
|
|
check_xor(ll, rr)
|
|
|
|
SHIFT = 30
|
|
DIGIT0a = 615729753
|
|
DIGIT0b = 832796681
|
|
DIGIT1a = 744342356 << SHIFT
|
|
DIGIT1b = 321006080 << SHIFT
|
|
DIGIT2a = 643582106 << (SHIFT * 2)
|
|
DIGIT2b = 656420725 << (SHIFT * 2)
|
|
DIGIT50 = 315723472 << (SHIFT * 50)
|
|
DIGIT100a = 1020652627 << (SHIFT * 100)
|
|
DIGIT100b = 923752451 << (SHIFT * 100)
|
|
BIG_SHORT = 3491190729721336556
|
|
MAX_SHORT = (1 << 62) - 1
|
|
MIN_SHORT = -(1 << 62)
|
|
MAX_SHORT_32 = (1 << 30) - 1
|
|
MIN_SHORT_32 = -(1 << 30)
|
|
|
|
def test_and_or_xor() -> None:
|
|
check_bitwise(0, 0)
|
|
check_bitwise(0, 1)
|
|
check_bitwise(1, 1)
|
|
check_bitwise(DIGIT0a, DIGIT0b)
|
|
check_bitwise(DIGIT1a, DIGIT1b)
|
|
check_bitwise(DIGIT2a, DIGIT2b)
|
|
check_bitwise(DIGIT100a, DIGIT100b)
|
|
check_bitwise(DIGIT0a, DIGIT0b + DIGIT2a)
|
|
check_bitwise(DIGIT0a, DIGIT0b + DIGIT50)
|
|
check_bitwise(DIGIT50 + DIGIT1a, DIGIT100a + DIGIT2b)
|
|
check_bitwise(BIG_SHORT, DIGIT0a)
|
|
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a)
|
|
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a)
|
|
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a + DIGIT50)
|
|
|
|
for x in range(-25, 25):
|
|
for y in range(-25, 25):
|
|
check_bitwise(x, y)
|
|
|
|
def test_bitwise_inplace() -> None:
|
|
# Basic sanity checks; these should use the same code as the non-in-place variants
|
|
for x, y in (DIGIT0a, DIGIT1a), (DIGIT2a, DIGIT0a + DIGIT2b):
|
|
n = x
|
|
n &= y
|
|
assert n == x & y
|
|
n = x
|
|
n |= y
|
|
assert n == x | y
|
|
n = x
|
|
n ^= y
|
|
assert n == x ^ y
|
|
|
|
def check_invert(x: int) -> None:
|
|
# Use eval() as the source of truth
|
|
assert ~x == eval('~{}'.format(x))
|
|
assert ~(-x) == eval('~({})'.format(-x))
|
|
|
|
def test_invert() -> None:
|
|
check_invert(0)
|
|
check_invert(1)
|
|
check_invert(DIGIT0a)
|
|
check_invert(DIGIT0a + DIGIT1a)
|
|
check_invert(DIGIT0a + DIGIT1a + DIGIT2a)
|
|
check_invert(DIGIT0a + DIGIT1a + DIGIT2a + DIGIT50)
|
|
check_invert(BIG_SHORT)
|
|
for delta in -1, 0, 1:
|
|
check_invert(MAX_SHORT + delta)
|
|
check_invert(MIN_SHORT + delta)
|
|
check_invert(MAX_SHORT_32 + delta)
|
|
check_invert(MIN_SHORT_32 + delta)
|
|
|
|
def check_right_shift(x: int, n: int) -> None:
|
|
if n < 0:
|
|
try:
|
|
x >> n
|
|
except ValueError:
|
|
return
|
|
assert False, "no exception raised"
|
|
# Use eval() as the source of truth
|
|
expected = eval('{} >> {}'.format(x, n))
|
|
actual = x >> n
|
|
assert actual == expected, "{} >> {}: got {}, expected {}".format(x, n, actual, expected)
|
|
|
|
def test_right_shift() -> None:
|
|
for x in 0, 1, 1235, DIGIT0a, DIGIT0a + DIGIT1a, DIGIT0a + DIGIT50:
|
|
for n in 0, 1, 2, 3, 4, 10, 40, 10000, DIGIT1a, -1, -1334444, -DIGIT1a:
|
|
check_right_shift(x, n)
|
|
check_right_shift(-x, n)
|
|
x = DIGIT0a
|
|
x >>= 1
|
|
assert x == DIGIT0a >> 1
|
|
x = DIGIT50
|
|
x >>= 5
|
|
assert x == DIGIT50 >> 5
|
|
for i in range(256):
|
|
check_right_shift(1, i)
|
|
check_right_shift(137, i)
|
|
check_right_shift(MAX_SHORT, i)
|
|
check_right_shift(MAX_SHORT_32, i)
|
|
check_right_shift(MAX_SHORT + 1, i)
|
|
check_right_shift(MAX_SHORT_32 + 1, i)
|
|
for x in 1, DIGIT50:
|
|
try:
|
|
# It's okay if this raises an exception
|
|
assert x >> DIGIT2a == 0
|
|
except Exception:
|
|
pass
|
|
try:
|
|
x >> -DIGIT2a
|
|
assert False
|
|
except Exception:
|
|
pass
|
|
|
|
def check_left_shift(x: int, n: int) -> None:
|
|
if n < 0:
|
|
try:
|
|
x << n
|
|
except ValueError:
|
|
return
|
|
assert False, "no exception raised"
|
|
# Use eval() as the source of truth
|
|
expected = eval('{} << {}'.format(x, n))
|
|
actual = x << n
|
|
assert actual == expected, "{} << {}: got {}, expected {}".format(x, n, actual, expected)
|
|
|
|
def test_left_shift() -> None:
|
|
for x in 0, 1, 1235, DIGIT0a, DIGIT0a + DIGIT1a, DIGIT0a + DIGIT50:
|
|
for n in 0, 1, 2, 10, 40, 10000, -1, -1334444:
|
|
check_left_shift(x, n)
|
|
check_left_shift(-x, n)
|
|
x = DIGIT0a
|
|
x <<= 1
|
|
assert x == DIGIT0a << 1
|
|
x = DIGIT50
|
|
x <<= 5
|
|
assert x == DIGIT50 << 5
|
|
for shift in range(256):
|
|
check_left_shift(1, shift)
|
|
check_left_shift(137, shift)
|
|
for x in 1, DIGIT50:
|
|
try:
|
|
x << DIGIT50
|
|
assert False
|
|
except Exception:
|
|
pass
|
|
try:
|
|
x << -DIGIT50
|
|
assert False
|
|
except Exception:
|
|
pass
|
|
|
|
def is_true(x: int) -> bool:
|
|
if x:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def is_false(x: int) -> bool:
|
|
if not x:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def test_int_as_bool() -> None:
|
|
assert not is_true(0)
|
|
assert is_false(0)
|
|
for x in 1, 55, -1, -7, 1 << 50, 1 << 101, -(1 << 50), -(1 << 101):
|
|
assert is_true(x)
|
|
assert not is_false(x)
|
|
|
|
def test_divide() -> None:
|
|
for x in range(-100, 100):
|
|
for y in range(-100, 100):
|
|
if y != 0:
|
|
assert x // y == getattr(x, "__floordiv__")(y)
|
|
|
|
def test_mod() -> None:
|
|
for x in range(-100, 100):
|
|
for y in range(-100, 100):
|
|
if y != 0:
|
|
assert x % y == getattr(x, "__mod__")(y)
|
|
|
|
def test_constant_fold() -> None:
|
|
assert str(-5 + 3) == "-2"
|
|
assert str(15 - 3) == "12"
|
|
assert str(1000 * 1000) == "1000000"
|
|
assert str(12325 // 12 ) == "1027"
|
|
assert str(87645 % 321) == "12"
|
|
assert str(674253 | 76544) == "748493"
|
|
assert str(765 ^ 82) == "687"
|
|
assert str(6546 << 3) == "52368"
|
|
assert str(6546 >> 7) == "51"
|
|
assert str(3**5) == "243"
|
|
assert str(~76) == "-77"
|
|
try:
|
|
2 / 0
|
|
except ZeroDivisionError:
|
|
pass
|
|
else:
|
|
assert False, "no exception raised"
|
|
|
|
x = int()
|
|
y = int() - 1
|
|
assert x == -1 or y != -3
|
|
assert -1 <= x
|
|
assert -1 == y
|
|
|
|
# Use int() to avoid constant propagation
|
|
i30 = (1 << 30) + int()
|
|
assert i30 == 1 << 30
|
|
i31 = (1 << 31) + int()
|
|
assert i31 == 1 << 31
|
|
i32 = (1 << 32) + int()
|
|
assert i32 == 1 << 32
|
|
i62 = (1 << 62) + int()
|
|
assert i62 == 1 << 62
|
|
i63 = (1 << 63) + int()
|
|
assert i63 == 1 << 63
|
|
i64 = (1 << 64) + int()
|
|
assert i64 == 1 << 64
|
|
|
|
n30 = -(1 << 30) + int()
|
|
assert n30 == -(1 << 30)
|
|
n31 = -(1 << 31) + int()
|
|
assert n31 == -(1 << 31)
|
|
n32 = -(1 << 32) + int()
|
|
assert n32 == -(1 << 32)
|
|
n62 = -(1 << 62) + int()
|
|
assert n62 == -(1 << 62)
|
|
n63 = -(1 << 63) + int()
|
|
assert n63 == -(1 << 63)
|
|
n64 = -(1 << 64) + int()
|
|
assert n64 == -(1 << 64)
|
|
|
|
def div_by_2(x: int) -> int:
|
|
return x // 2
|
|
|
|
def div_by_3(x: int) -> int:
|
|
return x // 3
|
|
|
|
def div_by_4(x: int) -> int:
|
|
return x // 4
|
|
|
|
def test_floor_divide_by_literal() -> None:
|
|
for i in range(-100, 100):
|
|
i_boxed: Any = i
|
|
assert div_by_2(i) == i_boxed // int('2')
|
|
assert div_by_3(i) == i_boxed // int('3')
|
|
assert div_by_4(i) == i_boxed // int('4')
|
|
|
|
[case testIntMinMax]
|
|
def test_int_min_max() -> None:
|
|
x: int = 200
|
|
y: int = 30
|
|
assert min(x, y) == 30
|
|
assert max(x, y) == 200
|
|
assert min(y, x) == 30
|
|
assert max(y, x) == 200
|
|
|
|
def test_int_hybrid_min_max() -> None:
|
|
from typing import Any
|
|
|
|
x: object = 30
|
|
y: Any = 20.0
|
|
assert min(x, y) == 20.0
|
|
assert max(x, y) == 30
|
|
|
|
u: object = 20
|
|
v: float = 30.0
|
|
assert min(u, v) == 20
|
|
assert max(u, v) == 30.0
|
|
|
|
def test_int_incompatible_min_max() -> None:
|
|
x: int = 2
|
|
y: str = 'aaa'
|
|
try:
|
|
print(min(x, y))
|
|
except TypeError as e:
|
|
assert str(e) == "'<' not supported between instances of 'str' and 'int'"
|
|
try:
|
|
print(max(x, y))
|
|
except TypeError as e:
|
|
assert str(e) == "'>' not supported between instances of 'str' and 'int'"
|
|
|
|
def test_int_bool_min_max() -> None:
|
|
x: int = 2
|
|
y: bool = False
|
|
z: bool = True
|
|
assert min(x, y) == False
|
|
assert min(x, z) == True
|
|
assert max(x, y) == 2
|
|
assert max(x, z) == 2
|
|
|
|
u: int = -10
|
|
assert min(u, y) == -10
|
|
assert min(u, z) == -10
|
|
assert max(u, y) == False
|
|
assert max(u, z) == True
|