#!/usr/bin/env python3 """Tests for health check module.""" import json import os import sys import tempfile import unittest from pathlib import Path from unittest.mock import patch sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) from tools.health_check import HealthCheck class TestHealthCheckIndividual(unittest.TestCase): """Test individual health checks.""" def test_check_disk_space(self): ok, detail = HealthCheck.check_disk_space() self.assertIsInstance(ok, bool) self.assertIn("GB", detail) self.assertIn("free", detail) def test_check_memory_file_exists(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".md", delete=False) as f: f.write("# Memory\nTest content\n") f.flush() with patch.object(HealthCheck, "check_memory_file", staticmethod( lambda: (True, f"MEMORY.md: 2 lines, {os.path.getsize(f.name)} bytes") )): ok, detail = HealthCheck.check_memory_file() self.assertTrue(ok) os.unlink(f.name) def test_check_skills_count(self): with tempfile.TemporaryDirectory() as tmp: # Create a fake skill skill_dir = Path(tmp) / "test-skill" skill_dir.mkdir() (skill_dir / "SKILL.md").write_text("---\nname: test\n---\n# Test") with patch.object(HealthCheck, "check_skills_count", staticmethod( lambda: (True, "1 skills installed") )): ok, detail = HealthCheck.check_skills_count() self.assertTrue(ok) self.assertIn("1", detail) def test_check_cron_jobs_valid(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: json.dump([ {"id": "1", "status": "active"}, {"id": "2", "status": "paused"}, ], f) f.flush() # Test the logic directly jobs = json.loads(Path(f.name).read_text()) active = sum(1 for j in jobs if j.get("status") == "active") self.assertEqual(active, 1) os.unlink(f.name) class TestHealthCheckRunner(unittest.TestCase): """Test the health check runner.""" def test_check_method(self): hc = HealthCheck() result = hc.check("test_pass", lambda: (True, "all good")) self.assertEqual(result["status"], "PASS") self.assertEqual(result["detail"], "all good") def test_check_failure(self): hc = HealthCheck() result = hc.check("test_fail", lambda: (False, "broken")) self.assertEqual(result["status"], "FAIL") def test_check_exception(self): hc = HealthCheck() def boom(): raise RuntimeError("kaboom") result = hc.check("test_error", boom) self.assertEqual(result["status"], "ERROR") self.assertIn("kaboom", result["detail"]) def test_check_critical_flag(self): hc = HealthCheck() result = hc.check("test_crit", lambda: (False, "bad"), critical=True) self.assertTrue(result["critical"]) def test_run_all_returns_structure(self): hc = HealthCheck() result = hc.run_all() self.assertIn("timestamp", result) self.assertIn("total", result) self.assertIn("passed", result) self.assertIn("failed", result) self.assertIn("healthy", result) self.assertIn("checks", result) self.assertIsInstance(result["checks"], list) self.assertGreater(result["total"], 0) def test_format_report(self): hc = HealthCheck() result = hc.run_all() report = hc.format_report(result) self.assertIn("Ezra Health Check", report) self.assertIn("HEALTHY", report.upper()) self.assertIn("|", report) # Table format class TestHealthCheckLive(unittest.TestCase): """Live checks against actual infrastructure (may fail in CI).""" def test_disk_space_live(self): ok, detail = HealthCheck.check_disk_space() # Should always work on a real system self.assertIsInstance(ok, bool) self.assertRegex(detail, r'\d+\.\d+GB free') def test_hermes_gateway_live(self): ok, detail = HealthCheck.check_hermes_gateway() # Just verify it runs without error self.assertIsInstance(ok, bool) self.assertIsInstance(detail, str) if __name__ == "__main__": unittest.main()