import pytest import sys import os sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from slic.utils.eval import * # Valid expressions @pytest.mark.parametrize("expr, expected", [ ("1 + 2", 3), ("4 - 2", 2), ("3 * 5", 15), ("10 / 2", 5.0), ("10 % 3", 1), ("-5", -5), ("+7", 7), ("1 + 2 * 3", 7), ("(1 + 2) * 3", 9), ("-(-3)", 3), ("-2 + 4 * 2", 6), ("(4 + 5) * (6 - 1)", 45), ("(((3)))", 3), ("-(-(-2))", -2), ("3 + +4", 7), ("3 + -4", -1), ("True + 1", 2), ("'string'", 'string'), ("1e1000 * 1e1000", float("inf")), ("'a' + 'b'", "ab") # string concatenation supported !!! ]) def test_arithmetic_eval_valid(expr, expected): assert arithmetic_eval(expr) == expected # Expressions with unsupported operations or node types @pytest.mark.parametrize("expr, expected_message", [ # test ArithmeticEvalError of get_operator ("2 ** 3", "Unsupported BinOp Pow"), ("3 << 1", "Unsupported BinOp LShift"), # test ArithmeticEvalError of arithmetic_eval ("1 < 2", "Unsupported node type Compare"), ("abs(3)", "Unsupported node type Call"), ("a + 2", "Unsupported node type Name"), ("string", "Unsupported node type Name"), ("[1, 2] + [3]", "Unsupported node type List"), ("{1: 2}", "Unsupported node type Dict"), ]) def test_arithmetic_eval_raises_with_message(expr, expected_message): with pytest.raises(ArithmeticEvalError, match=expected_message): arithmetic_eval(expr) # Expressions that are syntactically valid but cause Python runtime errors @pytest.mark.parametrize("expr, exception", [ ("1 / 0", ZeroDivisionError), ("10 % 0", ZeroDivisionError), ]) def test_arithmetic_eval_runtime_errors(expr, exception): with pytest.raises(exception): arithmetic_eval(expr) # forgiving_eval: returns original expression string on error @pytest.mark.parametrize("expr, expected", [ ("1 + 2", 3), ("bad + 2", "bad + 2"), ("1 / 0", "1 / 0"), ("2 ** 10", "2 ** 10"), ]) def test_forgiving_eval(expr, expected): assert forgiving_eval(expr) == expected # defaulting_eval: returns provided default value on error @pytest.mark.parametrize("expr, default, expected", [ ("3 * 4", 0, 12), ("invalid + 1", 99, 99), ("1 / 0", -1, -1), ("2 ** 10", 42, 42), ]) def test_defaulting_eval(expr, default, expected): assert defaulting_eval(expr, default=default) == expected