""" Simple test to verify attack path generation logic works correctly. Run with: python test_attack_paths.py """ import asyncio import sys import os import json sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from app.models.models import Finding, FindingSeverity, FindingCategory from app.services.ai_translator import _generate_mock_attack_path async def test_attack_path_generation(): """Test that attack path generation creates valid node/edge structure.""" # Create a mock finding finding = Finding( id="test-finding-1", tenant_id="test-tenant", title="Test vulnerability", severity=FindingSeverity.high, category=FindingCategory.external_exposure, technical_description="A test security issue", affected_component="test-component", ) # Generate mock attack path result = _generate_mock_attack_path(finding) data = json.loads(result) # Verify structure assert "narrative" in data, "Missing narrative" assert "nodes" in data, "Missing nodes" assert "edges" in data, "Missing edges" nodes = data["nodes"] edges = data["edges"] # Verify nodes have required fields assert len(nodes) > 0, "No nodes generated" for node in nodes: assert "id" in node, f"Node missing 'id': {node}" assert "label" in node, f"Node missing 'label': {node}" assert "type" in node, f"Node missing 'type': {node}" assert "risk_level" in node, f"Node missing 'risk_level': {node}" assert node["type"] in ["attacker", "entry_point", "pivot", "target"], f"Invalid node type: {node['type']}" assert node["risk_level"] in ["none", "low", "medium", "high", "critical"], f"Invalid risk_level: {node['risk_level']}" # Verify edges have required fields assert len(edges) > 0, "No edges generated" for edge in edges: assert "source" in edge, f"Edge missing 'source': {edge}" assert "target" in edge, f"Edge missing 'target': {edge}" # Verify source and target reference valid nodes node_ids = {n["id"] for n in nodes} assert edge["source"] in node_ids, f"Edge source '{edge['source']}' doesn't reference valid node" assert edge["target"] in node_ids, f"Edge target '{edge['target']}' doesn't reference valid node" # Verify narrative assert isinstance(data["narrative"], str), "Narrative should be a string" assert len(data["narrative"]) > 0, "Narrative should not be empty" print("āœ“ Attack path structure validation passed") print(f" - Generated {len(nodes)} nodes") print(f" - Generated {len(edges)} edges") print(f" - Narrative: {data['narrative'][:80]}...") return True if __name__ == "__main__": try: result = asyncio.run(test_attack_path_generation()) print("\nāœ“ All tests passed!") sys.exit(0) except AssertionError as e: print(f"\nāœ— Test failed: {e}", file=sys.stderr) sys.exit(1) except Exception as e: print(f"\nāœ— Unexpected error: {e}", file=sys.stderr) import traceback traceback.print_exc() sys.exit(1)