| from __future__ import annotations |
|
|
| import importlib.util |
| from pathlib import Path |
|
|
|
|
| def _load_module(): |
| script_path = Path(__file__).resolve().parents[1] / "scripts" / "compare_runs.py" |
| spec = importlib.util.spec_from_file_location("compare_runs", script_path) |
| module = importlib.util.module_from_spec(spec) |
| assert spec.loader is not None |
| spec.loader.exec_module(module) |
| return module |
|
|
|
|
| def test_compare_summaries_includes_breakdowns_and_markdown() -> None: |
| module = _load_module() |
|
|
| baseline = { |
| "run_id": "base", |
| "experiment_name": "baseline_exp", |
| "aggregate_metrics": { |
| "attack_success_rate": 0.6, |
| "successful_attacks": 6, |
| "prompt_leakage_cases": 1, |
| "refusals": 0, |
| "manual_review_cases": 1, |
| "benign_utility_rate": 0.5, |
| "false_positive_rate": 0.0, |
| "by_attack_category": { |
| "instruction_override": { |
| "successful_attacks": 4, |
| "total_cases": 5, |
| "attack_success_rate": 0.8, |
| } |
| }, |
| "by_attack_surface": { |
| "direct": { |
| "successful_attacks": 6, |
| "total_cases": 10, |
| "attack_success_rate": 0.6, |
| } |
| }, |
| "by_source": { |
| "HackAPrompt": { |
| "successful_attacks": 6, |
| "total_cases": 10, |
| "attack_success_rate": 0.6, |
| } |
| }, |
| }, |
| } |
| defended = { |
| "run_id": "def", |
| "experiment_name": "defended_exp", |
| "aggregate_metrics": { |
| "attack_success_rate": 0.3, |
| "successful_attacks": 3, |
| "prompt_leakage_cases": 0, |
| "refusals": 1, |
| "manual_review_cases": 0, |
| "benign_utility_rate": 0.5, |
| "false_positive_rate": 0.1, |
| "by_attack_category": { |
| "instruction_override": { |
| "successful_attacks": 1, |
| "total_cases": 5, |
| "attack_success_rate": 0.2, |
| } |
| }, |
| "by_attack_surface": { |
| "direct": { |
| "successful_attacks": 3, |
| "total_cases": 10, |
| "attack_success_rate": 0.3, |
| } |
| }, |
| "by_source": { |
| "HackAPrompt": { |
| "successful_attacks": 3, |
| "total_cases": 10, |
| "attack_success_rate": 0.3, |
| } |
| }, |
| }, |
| "mitigation_metrics": {"strategy": "surface_aligned", "transformed_cases": 10}, |
| } |
|
|
| comparison = module.compare_summaries(baseline, defended) |
|
|
| assert comparison["metric_diffs"][0]["metric"] == "attack_success_rate" |
| assert comparison["by_attack_category"][0]["label"] == "instruction_override" |
| assert comparison["by_attack_category"][0]["attack_success_rate_delta"] == -0.6000000000000001 |
|
|
| markdown = module.render_markdown_summary(comparison) |
| assert "# Phase 7 Comparison Summary" in markdown |
| assert "## By Attack Category" in markdown |
| assert "instruction_override" in markdown |
|
|