BuddyMath / tests /test_validation_robustness.py
dotandru's picture
V280.0: Robust Math Validation Fixes & Model Lockdown (RCE Protection, Multiline Regex, Soft Fail)
5230898
Raw
History Blame Contribute Delete
3.12 kB
import pytest
import asyncio
from domain.math_validator import MathPolygraph, _latex_to_sympy_str
import sympy
@pytest.mark.asyncio
async def test_blind_stripping_and_regex():
# Test that mixed text is preserved and math is extracted
text = "ื ืฆื™ื‘ $x=5$ ื•ื ืงื‘ืœ $y=2$. ื”ืชื•ืฆืื” ื”ื™ื $$z=7$$."
# _validate_single should return True because all math segments are valid
ok, reason = await MathPolygraph._validate_single(text, 1)
assert ok, f"Failed mixed text: {reason}"
@pytest.mark.asyncio
async def test_multiline_display_math():
# Test re.DOTALL with multi-line display math
text = """ื”ื ื” ืžืฉื•ื•ืื”:
$$
x = 5 + 3
y = 10
$$
ืกื•ืฃ."""
ok, reason = await MathPolygraph._validate_single(text, 1)
assert ok, f"Failed multiline display math: {reason}"
@pytest.mark.asyncio
async def test_multi_equal_guard():
# x=y=5 should not crash unpacking
text = "ื ืชื•ืŸ $x = y = 5$."
ok, reason = await MathPolygraph._validate_single(text, 1)
assert ok, f"Failed multi-equal check: {reason}"
@pytest.mark.asyncio
async def test_empty_string_guard():
# $$$$ should be ignored
text = "ืจื™ืง $$$$ ื•ื’ื $ $."
ok, reason = await MathPolygraph._validate_single(text, 1)
assert ok, f"Failed empty string guard: {reason}"
@pytest.mark.asyncio
async def test_arithmetic_exception_handling():
# $1/0$ should not crash the server
text = "ื—ืœื•ืงื” ื‘ืืคืก $1/0$."
ok, reason = await MathPolygraph._validate_single(text, 1)
assert not ok
assert "SYMPY_PARSE_ERROR" in reason
@pytest.mark.asyncio
async def test_variable_trap_in_equivalence():
# Algebraic equivalence should pass syntax check but skip numerical identity
# x=5 is validated segment by segment (LHS: x, RHS: 5)
# are_equivalent for x=5 and x=5 should return True
res = MathPolygraph.are_equivalent("x=5", "x=5")
assert res is True
@pytest.mark.asyncio
async def test_numerical_identity_check():
# Valid identity
assert MathPolygraph.are_equivalent("2+3", "5") is True
# Hallucination
assert MathPolygraph.are_equivalent("2+3", "6") is False
@pytest.mark.asyncio
async def test_inequality_guard():
# x > 0 should not crash simplify(LHS - RHS)
# It should skip identity check and return True because strings are same
assert MathPolygraph.are_equivalent("x > 0", "x > 0") is True
@pytest.mark.asyncio
async def test_rce_protection():
# Malicious string that would execute if sympify was used without evaluate=False
# However, parse_expr(evaluate=False) just builds the tree.
# We just want to ensure it doesn't crash or execute.
# Note: testing "exec" in a string is hard without side effects,
# but we can verify it doesn't crash on standard malicious patterns.
text = "__import__('os').system('echo hello')"
# This should definitely fail parsing or at least not execute
ok, reason = await MathPolygraph._check_segment(text, 1)
assert not ok
assert "SYMPY_PARSE_ERROR" in reason
if __name__ == "__main__":
import pytest
pytest.main([__file__])