"""Tests for code fixers.""" import pytest from pathlib import Path from src.analyzers.base import SeverityLevel, FindingCategory from src.fixers import ( SQLInjectionFixer, EvalUsageFixer, ExceptionSwallowFixer, MagicNumberFixer, RedundantOperationFixer, ) class TestSQLInjectionFixer: """Tests for SQL injection fixer.""" def setup_method(self): self.fixer = SQLInjectionFixer() def test_fixes_sql_injection(self): code = 'cursor.execute("SELECT * FROM users WHERE name = \'" + user_input + "\'")' finding = self._create_finding() tree = self._parse_code(code) result = self.fixer.fix(code, finding, tree) assert "?" in result or '"' in result def _create_finding(self): from src.analyzers.base import Finding return Finding( rule_id="security.sql_injection", rule_name="SQL Injection Detection", severity=SeverityLevel.CRITICAL, category=FindingCategory.SECURITY, message="SQL injection detected", suggestion="Use parameterized queries", file_path=Path("test.py"), line_number=1, column=0, ) def _parse_code(self, code): from src.analyzers import PythonParser parser = PythonParser() return parser.parse(code) class TestEvalUsageFixer: """Tests for eval/exec fixer.""" def setup_method(self): self.fixer = EvalUsageFixer() def test_comments_out_eval(self): code = 'result = eval(user_input)' finding = self._create_finding() tree = self._parse_code(code) result = self.fixer.fix(code, finding, tree) assert "# eval(" in result def _create_finding(self): from src.analyzers.base import Finding return Finding( rule_id="security.eval_usage", rule_name="Eval Usage Detection", severity=SeverityLevel.CRITICAL, category=FindingCategory.SECURITY, message="eval detected", suggestion="Avoid eval", file_path=Path("test.py"), line_number=1, column=0, ) def _parse_code(self, code): from src.analyzers import PythonParser parser = PythonParser() return parser.parse(code) class TestExceptionSwallowFixer: """Tests for exception swallowing fixer.""" def setup_method(self): self.fixer = ExceptionSwallowFixer() def test_adds_exception_logging(self): code = """try: dangerous() except: pass """ finding = self._create_finding() tree = self._parse_code(code) result = self.fixer.fix(code, finding, tree) assert "logger.error" in result or "Exception as e" in result def _create_finding(self): from src.analyzers.base import Finding return Finding( rule_id="antipattern.exception_swallow", rule_name="Exception Swallow Detection", severity=SeverityLevel.MEDIUM, category=FindingCategory.ANTIPATTERN, message="Exception swallowing detected", suggestion="Log the exception", file_path=Path("test.py"), line_number=2, column=0, ) def _parse_code(self, code): from src.analyzers import PythonParser parser = PythonParser() return parser.parse(code) class TestMagicNumberFixer: """Tests for magic number fixer.""" def setup_method(self): self.fixer = MagicNumberFixer() def test_replaces_magic_number(self): code = "result = 42" finding = self._create_finding() tree = self._parse_code(code) result = self.fixer.fix(code, finding, tree) assert "MAGIC_NUMBER_42" in result def _create_finding(self): from src.analyzers.base import Finding return Finding( rule_id="antipattern.magic_number", rule_name="Magic Number Detection", severity=SeverityLevel.LOW, category=FindingCategory.ANTIPATTERN, message="Magic number detected", suggestion="Define as constant", file_path=Path("test.py"), line_number=1, column=0, ) def _parse_code(self, code): from src.analyzers import PythonParser parser = PythonParser() return parser.parse(code) class TestRedundantOperationFixer: """Tests for redundant operation fixer.""" def setup_method(self): self.fixer = RedundantOperationFixer() def test_removes_redundant_list_call(self): code = "result = list(list(my_list))" finding = self._create_finding() tree = self._parse_code(code) result = self.fixer.fix(code, finding, tree) assert "list(list(" not in result def _create_finding(self): from src.analyzers.base import Finding return Finding( rule_id="performance.redundant_operation", rule_name="Redundant Operation Detection", severity=SeverityLevel.LOW, category=FindingCategory.PERFORMANCE, message="Redundant operation detected", suggestion="Remove redundant call", file_path=Path("test.py"), line_number=1, column=0, ) def _parse_code(self, code): from src.analyzers import PythonParser parser = PythonParser() return parser.parse(code) class TestFixerRegistry: """Tests for fixer registry.""" def test_get_fixer_returns_correct_fixer(self): from src.fixers import FixerRegistry registry = FixerRegistry() fixer = registry.get_fixer("security.sql_injection") assert fixer is not None assert isinstance(fixer, SQLInjectionFixer) def test_get_fixer_returns_none_for_unknown_rule(self): from src.fixers import FixerRegistry registry = FixerRegistry() fixer = registry.get_fixer("unknown.rule_id") assert fixer is None def test_can_fix_checks_correctly(self): from src.fixers import FixerRegistry from src.analyzers.base import Finding registry = FixerRegistry() finding = Finding( rule_id="security.sql_injection", rule_name="Test", severity=SeverityLevel.CRITICAL, category=FindingCategory.SECURITY, message="Test", suggestion="Test", file_path=Path("test.py"), line_number=1, column=0, ) assert registry.can_fix(finding) is True finding.rule_id = "unknown.rule" assert registry.can_fix(finding) is False