import pytest from .helpers import Suite TYPE_MAP = { 'u8': int, 'u32': int, 'u64': int, 'i32': int, 'i64': int, 'f32': float, 'f64': float, } COMPLETE_SIMPLE_TYPES = [ 'u32', 'u64', 'i32', 'i64', 'f32', 'f64', ] @pytest.mark.integration_test @pytest.mark.parametrize('type_', TYPE_MAP.keys()) def test_return(type_): code_py = f""" @exported def testEntry() -> {type_}: return 13 """ 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_', COMPLETE_SIMPLE_TYPES) def test_addition(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_', COMPLETE_SIMPLE_TYPES) def test_subtraction(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_', ['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_', ['u8', 'u32', 'u64']) def test_logical_right_shift(type_): code_py = f""" @exported def testEntry() -> {type_}: return 10 >> 3 """ result = Suite(code_py).run_code() assert 1 == 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_or(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 @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_', ['f32', 'f64']) def test_buildins_sqrt(type_): code_py = f""" @exported def testEntry() -> {type_}: return sqrt(25) """ result = Suite(code_py).run_code() assert 5 == result.returned_value assert TYPE_MAP[type_] == type(result.returned_value) @pytest.mark.integration_test @pytest.mark.parametrize('type_', TYPE_MAP.keys()) def test_arg(type_): code_py = f""" @exported def testEntry(a: {type_}) -> {type_}: return a """ result = Suite(code_py).run_code(125) assert 125 == result.returned_value assert TYPE_MAP[type_] == type(result.returned_value) @pytest.mark.integration_test @pytest.mark.skip('Do we want it to work like this?') def test_i32_to_i64(): code_py = """ @exported def testEntry(a: i32) -> i64: return a """ result = Suite(code_py).run_code(125) assert 125 == result.returned_value @pytest.mark.integration_test @pytest.mark.skip('Do we want it to work like this?') def test_i32_plus_i64(): code_py = """ @exported def testEntry(a: i32, b: i64) -> i64: return a + b """ result = Suite(code_py).run_code(125, 100) assert 225 == result.returned_value @pytest.mark.integration_test @pytest.mark.skip('Do we want it to work like this?') def test_f32_to_f64(): code_py = """ @exported def testEntry(a: f32) -> f64: return a """ result = Suite(code_py).run_code(125.5) assert 125.5 == result.returned_value @pytest.mark.integration_test @pytest.mark.skip('Do we want it to work like this?') def test_f32_plus_f64(): code_py = """ @exported def testEntry(a: f32, b: f64) -> f64: return a + b """ result = Suite(code_py).run_code(125.5, 100.25) assert 225.75 == result.returned_value @pytest.mark.integration_test @pytest.mark.skip('TODO') def test_uadd(): code_py = """ @exported def testEntry() -> i32: return +523 """ result = Suite(code_py).run_code() assert 523 == result.returned_value @pytest.mark.integration_test @pytest.mark.skip('TODO') def test_usub(): code_py = """ @exported def testEntry() -> i32: return -19 """ result = Suite(code_py).run_code() assert -19 == result.returned_value @pytest.mark.integration_test @pytest.mark.parametrize('inp', [9, 10, 11, 12]) def test_if_simple(inp): code_py = """ @exported def testEntry(a: i32) -> i32: if a > 10: return 15 return 3 """ exp_result = 15 if inp > 10 else 3 suite = Suite(code_py) result = suite.run_code(inp) assert exp_result == result.returned_value @pytest.mark.integration_test @pytest.mark.skip('Such a return is not how things should be') def test_if_complex(): code_py = """ @exported def testEntry(a: i32) -> i32: if a > 10: return 10 elif a > 0: return a else: return 0 return -1 # Required due to function type """ suite = Suite(code_py) assert 10 == suite.run_code(20).returned_value assert 10 == suite.run_code(10).returned_value assert 8 == suite.run_code(8).returned_value assert 0 == suite.run_code(0).returned_value assert 0 == suite.run_code(-1).returned_value @pytest.mark.integration_test def test_if_nested(): code_py = """ @exported def testEntry(a: i32, b: i32) -> i32: if a > 11: if b > 11: return 3 return 2 if b > 11: return 1 return 0 """ suite = Suite(code_py) assert 3 == suite.run_code(20, 20).returned_value assert 2 == suite.run_code(20, 10).returned_value assert 1 == suite.run_code(10, 20).returned_value assert 0 == suite.run_code(10, 10).returned_value @pytest.mark.integration_test def test_call_pre_defined(): code_py = """ def helper(left: i32, right: i32) -> i32: return left + right @exported def testEntry() -> i32: return helper(10, 3) """ 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_SIMPLE_TYPES) def test_call_with_expression(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.skip('Not yet implemented') def test_assign(): code_py = """ @exported def testEntry() -> i32: a: i32 = 8947 return a """ result = Suite(code_py).run_code() assert 8947 == result.returned_value @pytest.mark.integration_test @pytest.mark.parametrize('type_', TYPE_MAP.keys()) def test_struct_0(type_): code_py = f""" class CheckedValue: value: {type_} @exported def testEntry() -> {type_}: return helper(CheckedValue(23)) def helper(cv: CheckedValue) -> {type_}: return cv.value """ result = Suite(code_py).run_code() assert 23 == result.returned_value @pytest.mark.integration_test def test_struct_1(): code_py = """ class Rectangle: height: i32 width: i32 border: i32 @exported def testEntry() -> i32: return helper(Rectangle(100, 150, 2)) def helper(shape: Rectangle) -> i32: return shape.height + shape.width + shape.border """ result = Suite(code_py).run_code() assert 252 == result.returned_value @pytest.mark.integration_test def test_struct_2(): code_py = """ class Rectangle: height: i32 width: i32 border: i32 @exported def testEntry() -> i32: return helper(Rectangle(100, 150, 2), Rectangle(200, 90, 3)) def helper(shape1: Rectangle, shape2: Rectangle) -> i32: return shape1.height + shape1.width + shape1.border + shape2.height + shape2.width + shape2.border """ result = Suite(code_py).run_code() assert 545 == result.returned_value @pytest.mark.integration_test @pytest.mark.parametrize('type_', COMPLETE_SIMPLE_TYPES) def test_tuple_simple(type_): code_py = f""" @exported def testEntry() -> {type_}: return helper((24, 57, 80, )) def helper(vector: ({type_}, {type_}, {type_}, )) -> {type_}: return vector[0] + vector[1] + vector[2] """ result = Suite(code_py).run_code() assert 161 == result.returned_value assert TYPE_MAP[type_] == type(result.returned_value) @pytest.mark.integration_test def test_tuple_float(): code_py = """ @exported def testEntry() -> f32: return helper((1.0, 2.0, 3.0, )) def helper(v: (f32, f32, f32, )) -> f32: return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) """ result = Suite(code_py).run_code() assert 3.74 < result.returned_value < 3.75 @pytest.mark.integration_test def test_bytes_address(): code_py = """ @exported def testEntry(f: bytes) -> bytes: return f """ result = Suite(code_py).run_code(b'This is a test') # THIS DEPENDS ON THE ALLOCATOR # A different allocator will return a different value assert 20 == result.returned_value @pytest.mark.integration_test def test_bytes_length(): code_py = """ @exported def testEntry(f: bytes) -> i32: return len(f) """ result = Suite(code_py).run_code(b'This is another test') assert 20 == result.returned_value @pytest.mark.integration_test def test_bytes_index(): code_py = """ @exported def testEntry(f: bytes) -> u8: return f[8] """ result = Suite(code_py).run_code(b'This is another test') assert 0x61 == result.returned_value @pytest.mark.integration_test @pytest.mark.skip('SIMD support is but a dream') def test_tuple_i32x4(): code_py = """ @exported def testEntry() -> i32x4: return (51, 153, 204, 0, ) """ result = Suite(code_py).run_code() assert (1, 2, 3, 0) == result.returned_value @pytest.mark.integration_test def test_imported(): code_py = """ @imported def helper(mul: i32) -> i32: pass @exported def testEntry() -> i32: return helper(2) """ def helper(mul: int) -> int: return 4238 * mul result = Suite(code_py).run_code( runtime='wasmer', imports={ 'helper': helper, } ) assert 8476 == result.returned_value