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) """ with pytest.raises(Type5SolverException, match='i32 ~ f32'): 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) """ with pytest.raises(Type5SolverException, match='i32 ~ f32'): 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='i32 ~ f32'): 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.0 def action(applicable: Callable[i32, i32], left: i32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(double, 13) """ with pytest.raises(Type5SolverException, match='i32 ~ f32'): 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\[i32, i32\] ~ i32' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_too_many_args_use_0(): 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'\(\) ~ i32' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code(verbose=True) @pytest.mark.integration_test def test_sof_too_many_args_use_1(): code_py = """ def thirteen(x: i32) -> i32: return x def action(applicable: Callable[i32, i32], left: i32, right: i32) -> i32: return applicable(left, right) @exported def testEntry() -> i32: return action(thirteen, 13, 26) """ match = r'i32 ~ Callable\[i32, i32\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code(verbose=True) @pytest.mark.integration_test def test_sof_too_many_args_pass_0(): 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'\(\) ~ i32' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code() @pytest.mark.integration_test def test_sof_too_many_args_pass_1(): code_py = """ def double(left: i32, right: i32) -> i32: return left * right def action(applicable: Callable[i32, i32], left: i32, right: i32) -> i32: return applicable(left) @exported def testEntry() -> i32: return action(double, 13, 14) """ match = r'i32 ~ Callable\[i32, i32\]' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code()