"""ASV benchmarks for SEC1 config security scanner. Measures performance of the security scanner across varying content sizes and numbers of violations to establish a baseline for config parsing performance. """ from __future__ import annotations import contextlib import sys from pathlib import Path try: from cleveragents.config.security_scanner import ( scan_content, scan_file, validate_config_safety, ) except ModuleNotFoundError: sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) from cleveragents.config.security_scanner import ( scan_content, scan_file, validate_config_safety, ) # --------------------------------------------------------------------------- # Fixtures # --------------------------------------------------------------------------- _CLEAN_SMALL = "name: project\nversion: 1.0.0\ndescription: safe\n" _CLEAN_LARGE = "\n".join(f"key_{i}: value_{i}" for i in range(500)) _DIRTY_SMALL = "safe: true\ntransform: eval('1+1')\nrunner: exec('import os')\n" _DIRTY_LARGE = "\n".join( f"item_{i}: eval('x')" if i % 50 == 0 else f"item_{i}: safe" for i in range(500) ) # --------------------------------------------------------------------------- # Benchmark suites # --------------------------------------------------------------------------- class TimeScanContent: """Benchmark scan_content on in-memory strings.""" def time_clean_small(self) -> None: """Scan a small clean config string.""" scan_content(_CLEAN_SMALL, "") def time_clean_large(self) -> None: """Scan a large clean config string (500 lines).""" scan_content(_CLEAN_LARGE, "") def time_dirty_small(self) -> None: """Scan a small config with violations.""" scan_content(_DIRTY_SMALL, "") def time_dirty_large(self) -> None: """Scan a large config with scattered violations.""" scan_content(_DIRTY_LARGE, "") class TimeValidateConfigSafety: """Benchmark validate_config_safety (raises on violations).""" def time_clean_content(self) -> None: """Validate clean content (no exception).""" validate_config_safety(_CLEAN_SMALL, "") def time_dirty_content_caught(self) -> None: """Validate dirty content (exception caught).""" with contextlib.suppress(Exception): validate_config_safety(_DIRTY_SMALL, "") class TimeScanFile: """Benchmark scan_file on actual project files.""" def setup(self) -> None: """Locate a real config file for benchmarking.""" self.pyproject_path = Path("pyproject.toml") if not self.pyproject_path.exists(): self.pyproject_path = Path(__file__).resolve().parents[1] / "pyproject.toml" if not self.pyproject_path.exists(): raise FileNotFoundError( "pyproject.toml not found — TimeScanFile benchmark cannot run" ) def time_scan_pyproject_toml(self) -> None: """Scan pyproject.toml for violations.""" scan_file(self.pyproject_path)