80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
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
|