import pytest from phasm.type5.solver import Type5SolverException from ..helpers import Suite @pytest.mark.integration_test def test_sof_in_code_0_arg(): code_py = """ def thirteen() -> i32: return 13 def action(applicable: Callable[i32]) -> i32: return applicable() @exported def testEntry() -> i32: return action(thirteen) """ result = Suite(code_py).run_code() assert 13 == result.returned_value @pytest.mark.integration_test def test_sof_in_code_1_arg(): code_py = """ def double(left: i32) -> i32: return left * 2 def action(applicable: Callable[i32, i32], left: i32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(double, 13) """ result = Suite(code_py).run_code() assert 26 == result.returned_value @pytest.mark.integration_test def test_sof_in_code_2_arg(): code_py = """ def add(left: i32, right: i32) -> i32: return left + right def action(applicable: Callable[i32, i32, i32], left: i32, right: i32) -> i32: return applicable(left, right) @exported def testEntry() -> i32: return action(add, 13, 14) """ result = Suite(code_py).run_code() assert 27 == result.returned_value @pytest.mark.integration_test def test_sof_in_code_3_arg(): code_py = """ def add(left: i32, mid: i32, right: i32) -> i32: return left + mid + right def action(applicable: Callable[i32, i32, i32, i32], left: i32, mid: i32, right: i32) -> i32: return applicable(left, mid, right) @exported def testEntry() -> i32: return action(add, 13, 14, 15) """ result = Suite(code_py).run_code() assert 42 == result.returned_value @pytest.mark.integration_test def test_sof_function_with_wrong_argument_type_use(): code_py = """ def double(left: i32) -> i32: return left * 2 def action(applicable: Callable[i32, i32], left: f32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(double, 13.0) """ match = r'Callable\[i32, i32\] ~ Callable\[f32, [^]]+\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_function_with_wrong_argument_type_pass(): code_py = """ def double(left: f32) -> i32: return truncate(left) * 2 def action(applicable: Callable[i32, i32], left: i32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(double, 13) """ match = r'Callable\[Callable\[i32, i32\], i32, i32\] ~ Callable\[Callable\[f32, i32\], p_[0-9]+, [^]]+\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_function_with_wrong_return_type_use(): code_py = """ def double(left: i32) -> i32: return left * 2 def action(applicable: Callable[i32, i32], left: i32) -> f32: return applicable(left) @exported def testEntry() -> f32: return action(double, 13) """ with pytest.raises(Type5SolverException, match='f32 ~ i32'): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_function_with_wrong_return_type_pass(): code_py = """ def double(left: i32) -> f32: return convert(left) * 2 def action(applicable: Callable[i32, i32], left: i32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(double, 13) """ match = r'Callable\[Callable\[i32, i32\], i32, i32\] ~ Callable\[Callable\[i32, f32\], p_[0-9]+, [^]]+\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_not_enough_args_use(): code_py = """ def add(left: i32, right: i32) -> i32: return left + right def action(applicable: Callable[i32, i32, i32], left: i32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(add, 13) """ with pytest.raises(Type5SolverException, match='Not the same type'): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_not_enough_args_pass(): code_py = """ def double(left: i32) -> i32: return left * 2 def action(applicable: Callable[i32, i32, i32], left: i32, right: i32) -> i32: return applicable(left, right) @exported def testEntry() -> i32: return action(double, 13, 14) """ match = r'Callable\[Callable\[i32, i32, i32\], i32, i32, i32\] ~ Callable\[Callable\[i32, i32\], p_[0-9]+, p_[0-9]+, p_[0-9]+\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_too_many_args_use(): code_py = """ def thirteen() -> i32: return 13 def action(applicable: Callable[i32], left: i32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(thirteen, 13) """ match = r'Callable\[i32\] ~ Callable\[i32, p_[0-9]+\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code(verbose=True) @pytest.mark.integration_test def test_sof_too_many_args_pass(): code_py = """ def double(left: i32) -> i32: return left * 2 def action(applicable: Callable[i32], left: i32, right: i32) -> i32: return applicable() @exported def testEntry() -> i32: return action(double, 13, 14) """ match = r'Callable\[Callable\[i32\], i32, i32, i32\] ~ Callable\[Callable\[i32, i32\], p_[0-9]+, p_[0-9]+, p_[0-9]+\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code()