Large cleanup to the tests
They are now better organized and easier to extend, I hope.
This commit is contained in:
parent
07c0688d1b
commit
906b15c93c
16
tests/integration/constants.py
Normal file
16
tests/integration/constants.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
Constants for use in the tests
|
||||||
|
"""
|
||||||
|
|
||||||
|
ALL_INT_TYPES = ['u8', 'u32', 'u64', 'i32', 'i64']
|
||||||
|
COMPLETE_INT_TYPES = ['u32', 'u64', 'i32', 'i64']
|
||||||
|
|
||||||
|
ALL_FLOAT_TYPES = ['f32', 'f64']
|
||||||
|
COMPLETE_FLOAT_TYPES = ALL_FLOAT_TYPES
|
||||||
|
|
||||||
|
TYPE_MAP = {
|
||||||
|
**{x: int for x in ALL_INT_TYPES},
|
||||||
|
**{x: float for x in ALL_FLOAT_TYPES},
|
||||||
|
}
|
||||||
|
|
||||||
|
COMPLETE_PRIMITIVE_TYPES = COMPLETE_INT_TYPES + COMPLETE_FLOAT_TYPES
|
||||||
0
tests/integration/test_examples/__init__.py
Normal file
0
tests/integration/test_examples/__init__.py
Normal file
@ -3,9 +3,9 @@ import struct
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from .helpers import Suite
|
from ..helpers import Suite
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.slow_integration_test
|
||||||
def test_crc32():
|
def test_crc32():
|
||||||
# FIXME: Stub
|
# FIXME: Stub
|
||||||
# crc = 0xFFFFFFFF
|
# crc = 0xFFFFFFFF
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from .helpers import Suite
|
from ..helpers import Suite
|
||||||
|
|
||||||
@pytest.mark.slow_integration_test
|
@pytest.mark.slow_integration_test
|
||||||
def test_fib():
|
def test_fib():
|
||||||
@ -1,70 +0,0 @@
|
|||||||
import io
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from pywasm import binary
|
|
||||||
from pywasm import Runtime
|
|
||||||
|
|
||||||
from wasmer import wat2wasm
|
|
||||||
|
|
||||||
def run(code_wat):
|
|
||||||
code_wasm = wat2wasm(code_wat)
|
|
||||||
module = binary.Module.from_reader(io.BytesIO(code_wasm))
|
|
||||||
|
|
||||||
runtime = Runtime(module, {}, {})
|
|
||||||
|
|
||||||
out_put = runtime.exec('testEntry', [])
|
|
||||||
return (runtime, out_put)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('size,offset,exp_out_put', [
|
|
||||||
('32', 0, 0x3020100),
|
|
||||||
('32', 1, 0x4030201),
|
|
||||||
('64', 0, 0x706050403020100),
|
|
||||||
('64', 2, 0x908070605040302),
|
|
||||||
])
|
|
||||||
def test_i32_64_load(size, offset, exp_out_put):
|
|
||||||
code_wat = f"""
|
|
||||||
(module
|
|
||||||
(memory 1)
|
|
||||||
(data (memory 0) (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\10")
|
|
||||||
|
|
||||||
(func (export "testEntry") (result i{size})
|
|
||||||
i32.const {offset}
|
|
||||||
i{size}.load
|
|
||||||
return ))
|
|
||||||
"""
|
|
||||||
|
|
||||||
(_, out_put) = run(code_wat)
|
|
||||||
assert exp_out_put == out_put
|
|
||||||
|
|
||||||
def test_load_then_store():
|
|
||||||
code_wat = """
|
|
||||||
(module
|
|
||||||
(memory 1)
|
|
||||||
(data (memory 0) (i32.const 0) "\\04\\00\\00\\00")
|
|
||||||
|
|
||||||
(func (export "testEntry") (result i32) (local $my_memory_value i32)
|
|
||||||
;; Load i32 from address 0
|
|
||||||
i32.const 0
|
|
||||||
i32.load
|
|
||||||
|
|
||||||
;; Add 8 to the loaded value
|
|
||||||
i32.const 8
|
|
||||||
i32.add
|
|
||||||
|
|
||||||
local.set $my_memory_value
|
|
||||||
|
|
||||||
;; Store back to the memory
|
|
||||||
i32.const 0
|
|
||||||
local.get $my_memory_value
|
|
||||||
i32.store
|
|
||||||
|
|
||||||
;; Return something
|
|
||||||
i32.const 9
|
|
||||||
return ))
|
|
||||||
"""
|
|
||||||
(runtime, out_put) = run(code_wat)
|
|
||||||
|
|
||||||
assert 9 == out_put
|
|
||||||
|
|
||||||
assert (b'\x0c'+ b'\00' * 23) == runtime.store.mems[0].data[:24]
|
|
||||||
0
tests/integration/test_lang/__init__.py
Normal file
0
tests/integration/test_lang/__init__.py
Normal file
@ -2,8 +2,8 @@ import sys
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from .helpers import Suite, write_header
|
from ..helpers import Suite, write_header
|
||||||
from .runners import RunnerPywasm
|
from ..runners import RunnerPywasm
|
||||||
|
|
||||||
def setup_interpreter(phash_code: str) -> RunnerPywasm:
|
def setup_interpreter(phash_code: str) -> RunnerPywasm:
|
||||||
runner = RunnerPywasm(phash_code)
|
runner = RunnerPywasm(phash_code)
|
||||||
53
tests/integration/test_lang/test_bytes.py
Normal file
53
tests/integration/test_lang/test_bytes.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
@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
|
||||||
|
def test_bytes_index_out_of_bounds():
|
||||||
|
code_py = """
|
||||||
|
@exported
|
||||||
|
def testEntry(f: bytes) -> u8:
|
||||||
|
return f[50]
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code(b'Short', b'Long' * 100)
|
||||||
|
|
||||||
|
assert 0 == result.returned_value
|
||||||
71
tests/integration/test_lang/test_if.py
Normal file
71
tests/integration/test_lang/test_if.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
@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
|
||||||
27
tests/integration/test_lang/test_interface.py
Normal file
27
tests/integration/test_lang/test_interface.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
@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
|
||||||
324
tests/integration/test_lang/test_primitives.py
Normal file
324
tests/integration/test_lang/test_primitives.py
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
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_', ALL_INT_TYPES)
|
||||||
|
def test_expr_constant_int(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_', ALL_FLOAT_TYPES)
|
||||||
|
def test_expr_constant_float(type_):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return 32.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_', ALL_INT_TYPES)
|
||||||
|
def test_module_constant_int(type_):
|
||||||
|
code_py = f"""
|
||||||
|
CONSTANT: {type_} = 13
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return CONSTANT
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 13 == result.returned_value
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
||||||
|
def test_module_constant_float(type_):
|
||||||
|
code_py = f"""
|
||||||
|
CONSTANT: {type_} = 32.125
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return CONSTANT
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 32.125 == 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_', 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)
|
||||||
|
|
||||||
|
# TODO: Multiplication
|
||||||
|
# TODO: Division
|
||||||
|
|
||||||
|
@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.0)
|
||||||
|
"""
|
||||||
|
|
||||||
|
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_function_argument(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('TODO')
|
||||||
|
def test_explicit_positive_number():
|
||||||
|
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_explicit_negative_number():
|
||||||
|
code_py = """
|
||||||
|
@exported
|
||||||
|
def testEntry() -> i32:
|
||||||
|
return -19
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert -19 == result.returned_value
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_call_no_args():
|
||||||
|
code_py = """
|
||||||
|
def helper() -> i32:
|
||||||
|
return 19
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> i32:
|
||||||
|
return helper()
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 19 == result.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_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)
|
||||||
87
tests/integration/test_lang/test_static_array.py
Normal file
87
tests/integration/test_lang/test_static_array.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from phasm.exceptions import StaticError
|
||||||
|
|
||||||
|
from ..constants import COMPLETE_PRIMITIVE_TYPES, TYPE_MAP
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', COMPLETE_PRIMITIVE_TYPES)
|
||||||
|
def test_static_array_module_constant(type_):
|
||||||
|
code_py = f"""
|
||||||
|
CONSTANT: {type_}[3] = (24, 57, 80, )
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return helper(CONSTANT)
|
||||||
|
|
||||||
|
def helper(array: {type_}[3]) -> {type_}:
|
||||||
|
return array[0] + array[1] + array[2]
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 161 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_', COMPLETE_PRIMITIVE_TYPES)
|
||||||
|
def test_static_array_indexed(type_):
|
||||||
|
code_py = f"""
|
||||||
|
CONSTANT: {type_}[3] = (24, 57, 80, )
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return helper(CONSTANT, 0, 1, 2)
|
||||||
|
|
||||||
|
def helper(array: {type_}[3], i0: u32, i1: u32, i2: u32) -> {type_}:
|
||||||
|
return array[i0] + array[i1] + array[i2]
|
||||||
|
"""
|
||||||
|
|
||||||
|
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_static_array_constant_too_few_values():
|
||||||
|
code_py = """
|
||||||
|
CONSTANT: u8[3] = (24, 57, )
|
||||||
|
"""
|
||||||
|
|
||||||
|
with pytest.raises(StaticError, match='Static error on line 2: Invalid number of static array values'):
|
||||||
|
phasm_parse(code_py)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_static_array_constant_too_many_values():
|
||||||
|
code_py = """
|
||||||
|
CONSTANT: u8[3] = (24, 57, 1, 1, )
|
||||||
|
"""
|
||||||
|
|
||||||
|
with pytest.raises(StaticError, match='Static error on line 2: Invalid number of static array values'):
|
||||||
|
phasm_parse(code_py)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_static_array_constant_type_mismatch():
|
||||||
|
code_py = """
|
||||||
|
CONSTANT: u8[3] = (24, 4000, 1, )
|
||||||
|
"""
|
||||||
|
|
||||||
|
with pytest.raises(StaticError, match='Static error on line 2: Integer value out of range; expected 0..255, actual 4000'):
|
||||||
|
phasm_parse(code_py)
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_static_array_index_out_of_bounds():
|
||||||
|
code_py = """
|
||||||
|
CONSTANT0: u32[3] = (24, 57, 80, )
|
||||||
|
|
||||||
|
CONSTANT1: u32[16] = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, )
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> u32:
|
||||||
|
return CONSTANT0[16]
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 0 == result.returned_value
|
||||||
@ -1,18 +1,65 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from phasm.parser import phasm_parse
|
from ..helpers import Suite
|
||||||
from phasm.exceptions import StaticError
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@pytest.mark.parametrize('type_', ['i32', 'i64', 'f32', 'f64'])
|
@pytest.mark.parametrize('type_', ('i32', 'f64', ))
|
||||||
def test_type_mismatch_function_argument(type_):
|
def test_struct_0(type_):
|
||||||
code_py = f"""
|
code_py = f"""
|
||||||
def helper(a: {type_}) -> (i32, i32, ):
|
class CheckedValue:
|
||||||
return a
|
value: {type_}
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> {type_}:
|
||||||
|
return helper(CheckedValue(23))
|
||||||
|
|
||||||
|
def helper(cv: CheckedValue) -> {type_}:
|
||||||
|
return cv.value
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with pytest.raises(StaticError, match=f'Static error on line 3: Expected \\(i32, i32, \\), a is actually {type_}'):
|
result = Suite(code_py).run_code()
|
||||||
phasm_parse(code_py)
|
|
||||||
|
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.integration_test
|
||||||
@pytest.mark.parametrize('type_', ['i32', 'i64', 'f32', 'f64'])
|
@pytest.mark.parametrize('type_', ['i32', 'i64', 'f32', 'f64'])
|
||||||
@ -39,21 +86,6 @@ def testEntry(arg: ({type_}, )) -> (i32, i32, ):
|
|||||||
with pytest.raises(StaticError, match=f'Static error on line 3: Expected \\(i32, i32, \\), arg\\[0\\] is actually {type_}'):
|
with pytest.raises(StaticError, match=f'Static error on line 3: Expected \\(i32, i32, \\), arg\\[0\\] is actually {type_}'):
|
||||||
phasm_parse(code_py)
|
phasm_parse(code_py)
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ['i32', 'i64', 'f32', 'f64'])
|
|
||||||
def test_type_mismatch_function_result(type_):
|
|
||||||
code_py = f"""
|
|
||||||
def helper() -> {type_}:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> (i32, i32, ):
|
|
||||||
return helper()
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(StaticError, match=f'Static error on line 7: Expected \\(i32, i32, \\), helper actually returns {type_}'):
|
|
||||||
phasm_parse(code_py)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
def test_tuple_constant_too_few_values():
|
def test_tuple_constant_too_few_values():
|
||||||
code_py = """
|
code_py = """
|
||||||
@ -80,30 +112,3 @@ CONSTANT: (u32, u8, u8, ) = (24, 4000, 1, )
|
|||||||
|
|
||||||
with pytest.raises(StaticError, match='Static error on line 2: Integer value out of range; expected 0..255, actual 4000'):
|
with pytest.raises(StaticError, match='Static error on line 2: Integer value out of range; expected 0..255, actual 4000'):
|
||||||
phasm_parse(code_py)
|
phasm_parse(code_py)
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_static_array_constant_too_few_values():
|
|
||||||
code_py = """
|
|
||||||
CONSTANT: u8[3] = (24, 57, )
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(StaticError, match='Static error on line 2: Invalid number of static array values'):
|
|
||||||
phasm_parse(code_py)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_static_array_constant_too_many_values():
|
|
||||||
code_py = """
|
|
||||||
CONSTANT: u8[3] = (24, 57, 1, 1, )
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(StaticError, match='Static error on line 2: Invalid number of static array values'):
|
|
||||||
phasm_parse(code_py)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_static_array_constant_type_mismatch():
|
|
||||||
code_py = """
|
|
||||||
CONSTANT: u8[3] = (24, 4000, 1, )
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(StaticError, match='Static error on line 2: Integer value out of range; expected 0..255, actual 4000'):
|
|
||||||
phasm_parse(code_py)
|
|
||||||
@ -1,34 +1,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from .helpers import Suite
|
from ..constants import COMPLETE_PRIMITIVE_TYPES, TYPE_MAP
|
||||||
|
from ..helpers import Suite
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_i32_asis():
|
|
||||||
code_py = """
|
|
||||||
CONSTANT: i32 = 13
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> i32:
|
|
||||||
return CONSTANT
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 13 == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_i32_binop():
|
|
||||||
code_py = """
|
|
||||||
CONSTANT: i32 = 13
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> i32:
|
|
||||||
return CONSTANT * 5
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 65 == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64', ])
|
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64', ])
|
||||||
@ -66,36 +39,46 @@ def helper(vector: (u8, u8, u32, u32, u64, u64, )) -> u32:
|
|||||||
assert 3333 == result.returned_value
|
assert 3333 == result.returned_value
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@pytest.mark.parametrize('type_', ['u8', 'u32', 'u64', ])
|
@pytest.mark.parametrize('type_', COMPLETE_PRIMITIVE_TYPES)
|
||||||
def test_static_array_1(type_):
|
def test_tuple_simple_constructor(type_):
|
||||||
code_py = f"""
|
code_py = f"""
|
||||||
CONSTANT: {type_}[1] = (65, )
|
|
||||||
|
|
||||||
@exported
|
@exported
|
||||||
def testEntry() -> {type_}:
|
def testEntry() -> {type_}:
|
||||||
return helper(CONSTANT)
|
return helper((24, 57, 80, ))
|
||||||
|
|
||||||
def helper(vector: {type_}[1]) -> {type_}:
|
def helper(vector: ({type_}, {type_}, {type_}, )) -> {type_}:
|
||||||
return vector[0]
|
return vector[0] + vector[1] + vector[2]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
assert 65 == result.returned_value
|
assert 161 == result.returned_value
|
||||||
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
def test_static_array_6():
|
def test_tuple_float():
|
||||||
code_py = """
|
code_py = """
|
||||||
CONSTANT: u32[6] = (11, 22, 3333, 4444, 555555, 666666, )
|
|
||||||
|
|
||||||
@exported
|
@exported
|
||||||
def testEntry() -> u32:
|
def testEntry() -> f32:
|
||||||
return helper(CONSTANT)
|
return helper((1.0, 2.0, 3.0, ))
|
||||||
|
|
||||||
def helper(vector: u32[6]) -> u32:
|
def helper(v: (f32, f32, f32, )) -> f32:
|
||||||
return vector[2]
|
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
assert 3333 == result.returned_value
|
assert 3.74 < result.returned_value < 3.75
|
||||||
|
|
||||||
|
@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
|
||||||
@ -1,31 +0,0 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from .helpers import Suite
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_bytes_index_out_of_bounds():
|
|
||||||
code_py = """
|
|
||||||
@exported
|
|
||||||
def testEntry(f: bytes) -> u8:
|
|
||||||
return f[50]
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code(b'Short', b'Long' * 100)
|
|
||||||
|
|
||||||
assert 0 == result.returned_value
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_static_array_index_out_of_bounds():
|
|
||||||
code_py = """
|
|
||||||
CONSTANT0: u32[3] = (24, 57, 80, )
|
|
||||||
|
|
||||||
CONSTANT1: u32[16] = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, )
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> u32:
|
|
||||||
return CONSTANT0[16]
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 0 == result.returned_value
|
|
||||||
@ -1,644 +0,0 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from .helpers import Suite
|
|
||||||
|
|
||||||
ALL_INT_TYPES = ['u8', 'u32', 'u64', 'i32', 'i64']
|
|
||||||
COMLETE_INT_TYPES = ['u32', 'u64', 'i32', 'i64']
|
|
||||||
ALL_FLOAT_TYPES = ['f32', 'f64']
|
|
||||||
|
|
||||||
TYPE_MAP = {
|
|
||||||
**{x: int for x in ALL_INT_TYPES},
|
|
||||||
**{x: float for x in ALL_FLOAT_TYPES},
|
|
||||||
}
|
|
||||||
|
|
||||||
COMPLETE_SIMPLE_TYPES = [
|
|
||||||
'u32', 'u64',
|
|
||||||
'i32', 'i64',
|
|
||||||
'f32', 'f64',
|
|
||||||
]
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', ALL_INT_TYPES)
|
|
||||||
def test_return_int(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_', ALL_FLOAT_TYPES)
|
|
||||||
def test_return_float(type_):
|
|
||||||
code_py = f"""
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return 32.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_', COMLETE_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_', COMLETE_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(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.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.0)
|
|
||||||
"""
|
|
||||||
|
|
||||||
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_no_args():
|
|
||||||
code_py = """
|
|
||||||
def helper() -> i32:
|
|
||||||
return 19
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> i32:
|
|
||||||
return helper()
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 19 == result.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_', COMLETE_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
|
|
||||||
@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_constructor(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
|
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_SIMPLE_TYPES)
|
|
||||||
def test_static_array_module_constant(type_):
|
|
||||||
code_py = f"""
|
|
||||||
CONSTANT: {type_}[3] = (24, 57, 80, )
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return helper(CONSTANT)
|
|
||||||
|
|
||||||
def helper(array: {type_}[3]) -> {type_}:
|
|
||||||
return array[0] + array[1] + array[2]
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
|
||||||
|
|
||||||
assert 161 == result.returned_value
|
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_SIMPLE_TYPES)
|
|
||||||
def test_static_array_indexed(type_):
|
|
||||||
code_py = f"""
|
|
||||||
CONSTANT: {type_}[3] = (24, 57, 80, )
|
|
||||||
|
|
||||||
@exported
|
|
||||||
def testEntry() -> {type_}:
|
|
||||||
return helper(CONSTANT, 0, 1, 2)
|
|
||||||
|
|
||||||
def helper(array: {type_}[3], i0: u32, i1: u32, i2: u32) -> {type_}:
|
|
||||||
return array[i0] + array[i1] + array[i2]
|
|
||||||
"""
|
|
||||||
|
|
||||||
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_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
|
|
||||||
0
tests/integration/test_stdlib/__init__.py
Normal file
0
tests/integration/test_stdlib/__init__.py
Normal file
@ -2,8 +2,8 @@ import sys
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from .helpers import write_header
|
from ..helpers import write_header
|
||||||
from .runners import RunnerPywasm3 as Runner
|
from ..runners import RunnerPywasm3 as Runner
|
||||||
|
|
||||||
def setup_interpreter(phash_code: str) -> Runner:
|
def setup_interpreter(phash_code: str) -> Runner:
|
||||||
runner = Runner(phash_code)
|
runner = Runner(phash_code)
|
||||||
Loading…
x
Reference in New Issue
Block a user