import pytest
from coreason_meta_engineering.topological_validator import (
TopologicalBoundaryViolation,
TopologicalValidator,
)
def test_topological_boundary_violation_exception() -> None:
exc = TopologicalBoundaryViolation(node_type="Call:eval", line=42, details="eval is bad")
assert exc.node_type == "Call:eval"
assert exc.line == 42
assert exc.details == "eval is bad"
assert "TopologicalBoundaryViolation at line 42: Forbidden node 'Call:eval' detected. eval is bad" in str(exc)
def test_topological_validator_syntax_error() -> None:
validator = TopologicalValidator()
code = "def func("
report = validator.validate(code)
assert report.valid is False
assert len(report.violations) == 1
assert report.violations[0]["type"] == "SyntaxError"
assert report.violations[0]["line"] == 1
assert len(report.violations[0]["details"]) > 0
def test_topological_validator_valid_code() -> None:
validator = TopologicalValidator()
code = "def hello_world():\n print('Hello World')\n return 42\n"
report = validator.validate(code)
assert report.valid is True
assert len(report.violations) == 0
assert report.nodes_scanned > 0
def test_topological_validator_forbidden_import_statement() -> None:
validator = TopologicalValidator()
code_import = "import subprocess"
report = validator.validate(code_import)
assert report.valid is False
assert any(v["type"] == "Import:subprocess" for v in report.violations)
code_import_from = "from subprocess import Popen"
report_from = validator.validate(code_import_from)
assert report_from.valid is False
assert any(v["type"] == "Import:subprocess" for v in report_from.violations)
def test_topological_validator_forbidden_calls() -> None:
validator = TopologicalValidator()
code_eval = "eval('1 + 1')"
report_eval = validator.validate(code_eval)
assert report_eval.valid is False
assert any(v["type"] == "Call:eval" for v in report_eval.violations)
code_exec = "exec('x = 1')"
report_exec = validator.validate(code_exec)
assert report_exec.valid is False
assert any(v["type"] == "Call:exec" for v in report_exec.violations)
code_compile = "compile('x = 1', 'file.py', 'exec')"
report_compile = validator.validate(code_compile)
assert report_compile.valid is False
assert any(v["type"] == "Call:compile" for v in report_compile.violations)
code_import_func = "__import__('os')"
report_import = validator.validate(code_import_func)
assert report_import.valid is False
assert any(v["type"] == "Call:__import__" for v in report_import.violations)
code_open = "open('file.txt', 'r')"
report_open = validator.validate(code_open)
assert report_open.valid is False
assert any(v["type"] == "Call:open" for v in report_open.violations)
def test_topological_validator_forbidden_attributes() -> None:
validator = TopologicalValidator()
code_write = "f.write('hello')"
report_write = validator.validate(code_write)
assert report_write.valid is False
assert any(v["type"] == "Attribute:write" for v in report_write.violations)
code_writelines = "f.writelines(['hello'])"
report_writelines = validator.validate(code_writelines)
assert report_writelines.valid is False
assert any(v["type"] == "Attribute:writelines" for v in report_writelines.violations)
def test_topological_validator_strict_validation() -> None:
validator = TopologicalValidator()
valid_code = "x = 5"
report = validator.validate_strict(valid_code)
assert report.valid is True
invalid_code = "import subprocess"
with pytest.raises(TopologicalBoundaryViolation) as exc_info:
validator.validate_strict(invalid_code)
assert exc_info.value.node_type == "Import:subprocess"
assert exc_info.value.line == 1