"""Tests for dashboard store.""" import threading import pytest from ayn_antivirus.dashboard.store import DashboardStore @pytest.fixture def store(tmp_path): s = DashboardStore(str(tmp_path / "test_dashboard.db")) yield s s.close() def test_record_and_get_metrics(store): store.record_metric( cpu=50.0, mem_pct=60.0, mem_used=4000, mem_total=8000, disk_usage=[{"mount": "/", "percent": 50}], load_avg=[1.0, 0.5, 0.3], net_conns=10, ) latest = store.get_latest_metrics() assert latest is not None assert latest["cpu_percent"] == 50.0 assert latest["mem_percent"] == 60.0 assert latest["disk_usage"] == [{"mount": "/", "percent": 50}] assert latest["load_avg"] == [1.0, 0.5, 0.3] def test_record_and_get_threats(store): store.record_threat( "/tmp/evil", "TestVirus", "malware", "HIGH", "test_det", "abc", "quarantined", "test detail", ) threats = store.get_recent_threats(10) assert len(threats) == 1 assert threats[0]["threat_name"] == "TestVirus" assert threats[0]["action_taken"] == "quarantined" def test_threat_stats(store): store.record_threat("/a", "V1", "malware", "CRITICAL", "d", "", "detected", "") store.record_threat("/b", "V2", "miner", "HIGH", "d", "", "killed", "") store.record_threat("/c", "V3", "spyware", "MEDIUM", "d", "", "detected", "") stats = store.get_threat_stats() assert stats["total"] == 3 assert stats["by_severity"]["CRITICAL"] == 1 assert stats["by_severity"]["HIGH"] == 1 assert stats["by_severity"]["MEDIUM"] == 1 assert stats["last_24h"] == 3 assert stats["last_7d"] == 3 def test_record_and_get_scans(store): store.record_scan("full", "/", 1000, 50, 2, 10.5) scans = store.get_recent_scans(10) assert len(scans) == 1 assert scans[0]["files_scanned"] == 1000 assert scans[0]["scan_type"] == "full" assert scans[0]["status"] == "completed" def test_scan_chart_data(store): store.record_scan("full", "/", 100, 5, 1, 5.0) data = store.get_scan_chart_data(30) assert len(data) >= 1 row = data[0] assert "day" in row assert "scans" in row assert "threats" in row def test_sig_updates(store): store.record_sig_update("malwarebazaar", hashes=100, ips=50, domains=20, urls=10) updates = store.get_recent_sig_updates(10) assert len(updates) == 1 assert updates[0]["feed_name"] == "malwarebazaar" stats = store.get_sig_stats() assert stats["total_hashes"] == 100 assert stats["total_ips"] == 50 assert stats["total_domains"] == 20 assert stats["total_urls"] == 10 def test_activity_log(store): store.log_activity("Test message", "INFO", "test") logs = store.get_recent_logs(10) assert len(logs) == 1 assert logs[0]["message"] == "Test message" assert logs[0]["level"] == "INFO" assert logs[0]["source"] == "test" def test_metrics_history(store): store.record_metric( cpu=10, mem_pct=20, mem_used=1000, mem_total=8000, disk_usage=[], load_avg=[0.1], net_conns=5, ) store.record_metric( cpu=20, mem_pct=30, mem_used=2000, mem_total=8000, disk_usage=[], load_avg=[0.2], net_conns=10, ) history = store.get_metrics_history(hours=1) assert len(history) == 2 assert history[0]["cpu_percent"] == 10 assert history[1]["cpu_percent"] == 20 def test_cleanup_retains_fresh(store): """Cleanup with 0 hours should not delete just-inserted metrics.""" store.record_metric( cpu=10, mem_pct=20, mem_used=1000, mem_total=8000, disk_usage=[], load_avg=[], net_conns=0, ) store.cleanup_old_metrics(hours=0) assert store.get_latest_metrics() is not None def test_empty_store_returns_none(store): """Empty store returns None / empty lists gracefully.""" assert store.get_latest_metrics() is None assert store.get_recent_threats(10) == [] assert store.get_recent_scans(10) == [] assert store.get_recent_logs(10) == [] stats = store.get_threat_stats() assert stats["total"] == 0 def test_thread_safety(store): """Concurrent writes from multiple threads should not crash.""" errors = [] def writer(n): try: for i in range(10): store.record_metric( cpu=float(n * 10 + i), mem_pct=50, mem_used=4000, mem_total=8000, disk_usage=[], load_avg=[], net_conns=0, ) except Exception as e: errors.append(e) threads = [threading.Thread(target=writer, args=(i,)) for i in range(5)] for t in threads: t.start() for t in threads: t.join() assert len(errors) == 0