Organized tests in type classes, removed some redundant ones
This commit is contained in:
parent
4a4c62c728
commit
4236340ff6
115
tests/integration/test_lang/test_bits.py
Normal file
115
tests/integration/test_lang/test_bits.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from phasm.type3.entry import Type3Exception
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
from ..constants import ALL_INT_TYPES, ALL_FLOAT_TYPES, COMPLETE_INT_TYPES, TYPE_MAP
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ['u32', 'u64']) # FIXME: Support u8, requires an extra AND operation
|
||||||
|
def test_logical_left_shift(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 << 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 80 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ['u32', 'u64'])
|
||||||
|
def test_logical_right_shift_left_bit_zero(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 >> 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check with wasmtime, as other engines don't mind if the type
|
||||||
|
# doesn't match. They'll complain when: (>>) : u32 -> u64 -> u32
|
||||||
|
result = Suite(code_py).run_code(runtime='wasmtime')
|
||||||
|
|
||||||
|
assert 1 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_logical_right_shift_left_bit_one():
|
||||||
|
code_py = """
|
||||||
|
@exported
|
||||||
|
def testEntry() -> u32:
|
||||||
|
return 4294967295 >> 16
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 0xFFFF == result.returned_value
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
||||||
|
def test_bitwise_or_uint(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 | 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 11 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_bitwise_or_inv_type():
|
||||||
|
code_py = """
|
||||||
|
@exported
|
||||||
|
def testEntry() -> f64:
|
||||||
|
return 10.0 | 3.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
with pytest.raises(Type3Exception, match='f64 does not implement the BitWiseOperation type class'):
|
||||||
|
Suite(code_py).run_code()
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_bitwise_or_type_mismatch():
|
||||||
|
code_py = """
|
||||||
|
CONSTANT1: u32 = 3
|
||||||
|
CONSTANT2: u64 = 3
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> u64:
|
||||||
|
return CONSTANT1 | CONSTANT2
|
||||||
|
"""
|
||||||
|
|
||||||
|
with pytest.raises(Type3Exception, match='u64 must be u32 instead'):
|
||||||
|
Suite(code_py).run_code()
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
||||||
|
def test_bitwise_xor(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 ^ 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 9 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
||||||
|
def test_bitwise_and(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 & 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 2 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
@ -17,7 +17,7 @@ def testEntry(f: bytes) -> u32:
|
|||||||
assert 24 == result.returned_value
|
assert 24 == result.returned_value
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
def test_bytes_index():
|
def test_bytes_index_ok():
|
||||||
code_py = """
|
code_py = """
|
||||||
@exported
|
@exported
|
||||||
def testEntry(f: bytes) -> u8:
|
def testEntry(f: bytes) -> u8:
|
||||||
@ -41,30 +41,12 @@ def testEntry(f: bytes, g: bytes) -> u8:
|
|||||||
assert 0 == result.returned_value
|
assert 0 == result.returned_value
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
def test_function_call_element_ok():
|
def test_bytes_index_invalid_type():
|
||||||
code_py = """
|
code_py = """
|
||||||
@exported
|
@exported
|
||||||
def testEntry(f: bytes) -> u8:
|
def testEntry(f: bytes, g: bytes) -> u64:
|
||||||
return helper(f[0])
|
return f[50]
|
||||||
|
|
||||||
def helper(x: u8) -> u8:
|
|
||||||
return x
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code(b'Short')
|
|
||||||
|
|
||||||
assert 83 == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_function_call_element_type_mismatch():
|
|
||||||
code_py = """
|
|
||||||
@exported
|
|
||||||
def testEntry(f: bytes) -> u64:
|
|
||||||
return helper(f[0])
|
|
||||||
|
|
||||||
def helper(x: u64) -> u64:
|
|
||||||
return x
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match=r'u64 must be u8 instead'):
|
with pytest.raises(Type3Exception, match=r'u64 must be u8 instead'):
|
||||||
Suite(code_py).run_code()
|
Suite(code_py).run_code(b'Short', b'Long' * 100)
|
||||||
|
|||||||
17
tests/integration/test_lang/test_floating.py
Normal file
17
tests/integration/test_lang/test_floating.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ['f32', 'f64'])
|
||||||
|
def test_builtins_sqrt(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return sqrt(25.0)
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 5 == result.returned_value
|
||||||
|
assert isinstance(result.returned_value, float)
|
||||||
33
tests/integration/test_lang/test_fractional.py
Normal file
33
tests/integration/test_lang/test_fractional.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
TYPE_LIST = ['f32', 'f64']
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', TYPE_LIST)
|
||||||
|
def test_division_float(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10.0 / 8.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 1.25 == result.returned_value
|
||||||
|
assert isinstance(result.returned_value, float)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', TYPE_LIST)
|
||||||
|
def test_division_zero_let_it_crash_float(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10.0 / 0.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
# WebAssembly dictates that float division follows the IEEE rules
|
||||||
|
# https://www.w3.org/TR/wasm-core-1/#-hrefop-fdivmathrmfdiv_n-z_1-z_2
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
assert float('+inf') == result.returned_value
|
||||||
33
tests/integration/test_lang/test_function_calls.py
Normal file
33
tests/integration/test_lang/test_function_calls.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_call_pre_defined():
|
||||||
|
code_py = """
|
||||||
|
def helper(left: i32) -> i32:
|
||||||
|
return left
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> i32:
|
||||||
|
return helper(13)
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 13 == result.returned_value
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_call_post_defined():
|
||||||
|
code_py = """
|
||||||
|
@exported
|
||||||
|
def testEntry() -> i32:
|
||||||
|
return helper(10, 3)
|
||||||
|
|
||||||
|
def helper(left: i32, right: i32) -> i32:
|
||||||
|
return left - right
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 7 == result.returned_value
|
||||||
33
tests/integration/test_lang/test_integral.py
Normal file
33
tests/integration/test_lang/test_integral.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
TYPE_LIST = ['u32', 'u64', 'i32', 'i64']
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', TYPE_LIST)
|
||||||
|
def test_division_int(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 / 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 3 == result.returned_value
|
||||||
|
assert isinstance(result.returned_value, int)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', TYPE_LIST)
|
||||||
|
def test_division_zero_let_it_crash_int(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 / 0
|
||||||
|
"""
|
||||||
|
|
||||||
|
# WebAssembly dictates that integer division is a partial operator (e.g. unreachable for 0)
|
||||||
|
# https://www.w3.org/TR/wasm-core-1/#-hrefop-idiv-umathrmidiv_u_n-i_1-i_2
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
Suite(code_py).run_code()
|
||||||
17
tests/integration/test_lang/test_literals.py
Normal file
17
tests/integration/test_lang/test_literals.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from phasm.type3.entry import Type3Exception
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
from ..constants import ALL_INT_TYPES, ALL_FLOAT_TYPES, COMPLETE_INT_TYPES, TYPE_MAP
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_expr_constant_literal_does_not_fit():
|
||||||
|
code_py = """
|
||||||
|
@exported
|
||||||
|
def testEntry() -> u8:
|
||||||
|
return 1000
|
||||||
|
"""
|
||||||
|
|
||||||
|
with pytest.raises(Type3Exception, match=r'Must fit in 1 byte\(s\)'):
|
||||||
|
Suite(code_py).run_code()
|
||||||
112
tests/integration/test_lang/test_num.py
Normal file
112
tests/integration/test_lang/test_num.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from phasm.type3.entry import Type3Exception
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
from ..constants import ALL_INT_TYPES, ALL_FLOAT_TYPES, COMPLETE_INT_TYPES, TYPE_MAP
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
||||||
|
def test_addition_int(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 + 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 13 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
||||||
|
def test_addition_float(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 32.0 + 0.125
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 32.125 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
||||||
|
def test_subtraction_int(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 - 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 7 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
||||||
|
def test_subtraction_float(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 100.0 - 67.875
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 32.125 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.skip('TODO: Runtimes return a signed value, which is difficult to test')
|
||||||
|
@pytest.mark.parametrize('type_', ('u32', 'u64')) # FIXME: u8
|
||||||
|
def test_subtraction_underflow(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 10 - 11
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 0 < result.returned_value
|
||||||
|
|
||||||
|
# TODO: Multiplication
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
||||||
|
def test_call_with_expression_int(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return helper(10 + 20, 3 + 5)
|
||||||
|
|
||||||
|
def helper(left: {type_}, right: {type_}) -> {type_}:
|
||||||
|
return left - right
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 22 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
||||||
|
def test_call_with_expression_float(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return helper(10.078125 + 90.046875, 63.0 + 5.0)
|
||||||
|
|
||||||
|
def helper(left: {type_}, right: {type_}) -> {type_}:
|
||||||
|
return left - right
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 32.125 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
@ -1,360 +0,0 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from phasm.type3.entry import Type3Exception
|
|
||||||
|
|
||||||
from ..helpers import Suite
|
|
||||||
from ..constants import ALL_INT_TYPES, ALL_FLOAT_TYPES, COMPLETE_INT_TYPES, TYPE_MAP
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_expr_constant_literal_does_not_fit():
|
|
||||||
code_py = """
|
|
||||||
@exported
|
|
||||||
def testEntry() -> u8:
|
|
||||||
return 1000
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match=r'Must fit in 1 byte\(s\)'):
|
|
||||||
Suite(code_py).run_code()
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ['u32', 'u64']) # FIXME: Support u8, requires an extra AND operation
|
|
||||||
def test_logical_left_shift(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 << 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 80 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ['u32', 'u64'])
|
|
||||||
def test_logical_right_shift_left_bit_zero(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 >> 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Check with wasmtime, as other engines don't mind if the type
|
|
||||||
# doesn't match. They'll complain when: (>>) : u32 -> u64 -> u32
|
|
||||||
result = Suite(code_py).run_code(runtime='wasmtime')
|
|
||||||
|
|
||||||
assert 1 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_logical_right_shift_left_bit_one():
|
|
||||||
code_py = """
|
|
||||||
@exported
|
|
||||||
def testEntry() -> u32:
|
|
||||||
return 4294967295 >> 16
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 0xFFFF == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
|
||||||
def test_bitwise_or_uint(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 | 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 11 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_bitwise_or_inv_type():
|
|
||||||
code_py = """
|
|
||||||
@exported
|
|
||||||
def testEntry() -> f64:
|
|
||||||
return 10.0 | 3.0
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match='f64 does not implement the BitWiseOperation type class'):
|
|
||||||
Suite(code_py).run_code()
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_bitwise_or_type_mismatch():
|
|
||||||
code_py = """
|
|
||||||
CONSTANT1: u32 = 3
|
|
||||||
CONSTANT2: u64 = 3
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> u64:
|
|
||||||
return CONSTANT1 | CONSTANT2
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match='u64 must be u32 instead'):
|
|
||||||
Suite(code_py).run_code()
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
|
||||||
def test_bitwise_xor(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 ^ 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 9 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64'])
|
|
||||||
def test_bitwise_and(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 & 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 2 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
|
||||||
def test_addition_int(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 + 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 13 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
|
||||||
def test_addition_float(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 32.0 + 0.125
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 32.125 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
|
||||||
def test_subtraction_int(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 - 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 7 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
|
||||||
def test_subtraction_float(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 100.0 - 67.875
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 32.125 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.skip('TODO: Runtimes return a signed value, which is difficult to test')
|
|
||||||
@pytest.mark.parametrize('type_', ('u32', 'u64')) # FIXME: u8
|
|
||||||
def test_subtraction_underflow(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 - 11
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 0 < result.returned_value
|
|
||||||
|
|
||||||
# TODO: Multiplication
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
|
||||||
def test_division_int(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 / 3
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 3 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
|
||||||
def test_division_float(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10.0 / 8.0
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 1.25 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
|
||||||
def test_division_zero_let_it_crash_int(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10 / 0
|
|
||||||
"""
|
|
||||||
|
|
||||||
# WebAssembly dictates that integer division is a partial operator (e.g. unreachable for 0)
|
|
||||||
# https://www.w3.org/TR/wasm-core-1/#-hrefop-idiv-umathrmidiv_u_n-i_1-i_2
|
|
||||||
with pytest.raises(Exception):
|
|
||||||
Suite(code_py).run_code()
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
|
||||||
def test_division_zero_let_it_crash_float(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 10.0 / 0.0
|
|
||||||
"""
|
|
||||||
|
|
||||||
# WebAssembly dictates that float division follows the IEEE rules
|
|
||||||
# https://www.w3.org/TR/wasm-core-1/#-hrefop-fdivmathrmfdiv_n-z_1-z_2
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
assert float('+inf') == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ['f32', 'f64'])
|
|
||||||
def test_builtins_sqrt(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return sqrt(25.0)
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 5 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_call_pre_defined():
|
|
||||||
code_py = """
|
|
||||||
def helper(left: i32) -> i32:
|
|
||||||
return left
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> i32:
|
|
||||||
return helper(13)
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 13 == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_call_post_defined():
|
|
||||||
code_py = """
|
|
||||||
@exported
|
|
||||||
def testEntry() -> i32:
|
|
||||||
return helper(10, 3)
|
|
||||||
|
|
||||||
def helper(left: i32, right: i32) -> i32:
|
|
||||||
return left - right
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 7 == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
|
|
||||||
def test_call_with_expression_int(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return helper(10 + 20, 3 + 5)
|
|
||||||
|
|
||||||
def helper(left: {type_}, right: {type_}) -> {type_}:
|
|
||||||
return left - right
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 22 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
|
||||||
def test_call_with_expression_float(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return helper(10.078125 + 90.046875, 63.0 + 5.0)
|
|
||||||
|
|
||||||
def helper(left: {type_}, right: {type_}) -> {type_}:
|
|
||||||
return left - right
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 32.125 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_call_invalid_return_type():
|
|
||||||
code_py = """
|
|
||||||
def helper() -> i64:
|
|
||||||
return 19
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> i32:
|
|
||||||
return helper()
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match=r'i64 must be i32 instead'):
|
|
||||||
Suite(code_py).run_code()
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_call_invalid_arg_type():
|
|
||||||
code_py = """
|
|
||||||
def helper(left: u8) -> u8:
|
|
||||||
return left
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> u8:
|
|
||||||
return helper(500)
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match=r'Must fit in 1 byte\(s\)'):
|
|
||||||
Suite(code_py).run_code()
|
|
||||||
Loading…
x
Reference in New Issue
Block a user