# SPDX-License-Identifier: AGPL-3.0-only # Copyright (c) 2026 sol pbc from __future__ import annotations import sys from unittest.mock import patch import pytest from solstone.think import health_cli from solstone.think.health_cli import ( fetch_supervisor_status, health_check, main, print_status, ) def test_health_check_no_socket(tmp_path, monkeypatch, capsys): monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) result = health_check() captured = capsys.readouterr() assert result == 1 assert "callosum socket not found" in captured.err def test_fetch_supervisor_status_returns_dict(tmp_path, monkeypatch, capsys): monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) sock = tmp_path / "health" / "callosum.sock" sock.parent.mkdir(parents=True) sock.touch() status = { "tract": "supervisor", "event": "status", "services": [{"name": "supervisor", "pid": 111, "uptime_seconds": 120}], "crashed": [], "tasks": [], "queues": {}, "stale_heartbeats": [], "schedules": [], "callosum_clients": 1, } with patch("solstone.think.health_cli.CallosumConnection") as mock_conn_cls: mock_conn = mock_conn_cls.return_value def _start(*, callback): callback(status) mock_conn.start.side_effect = _start mock_conn.stop.return_value = None result = fetch_supervisor_status(timeout=health_cli.STATUS_TIMEOUT) assert result is status mock_conn.stop.assert_called_once() captured = capsys.readouterr() assert captured.out == "" assert captured.err == "" def test_fetch_supervisor_status_no_socket(tmp_path, monkeypatch, capsys): monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) result = fetch_supervisor_status() assert result is None captured = capsys.readouterr() assert captured.out == "" assert captured.err == "" def test_fetch_supervisor_status_timeout(tmp_path, monkeypatch, capsys): monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) sock = tmp_path / "health" / "callosum.sock" sock.parent.mkdir(parents=True) sock.touch() monkeypatch.setattr("solstone.think.health_cli.STATUS_TIMEOUT", 0.1) with patch("solstone.think.health_cli.CallosumConnection") as mock_conn_cls: mock_conn = mock_conn_cls.return_value mock_conn.start.return_value = None mock_conn.stop.return_value = None result = fetch_supervisor_status(timeout=health_cli.STATUS_TIMEOUT) assert result is None mock_conn.stop.assert_called_once() captured = capsys.readouterr() assert captured.out == "" assert captured.err == "" def test_health_check_prints_status(capsys): status = { "services": [ {"name": "supervisor", "pid": 1001, "uptime_seconds": 65}, {"name": "observer", "pid": 2002, "uptime_seconds": 5}, ], "crashed": [{"name": "sync", "restart_attempts": 2}], "tasks": [{"name": "daily", "duration_seconds": 12}], "queues": {"indexer": 3, "planner": 0}, "stale_heartbeats": [], "callosum_clients": 5, } print_status(status) output = capsys.readouterr().out assert "Services:" in output assert "supervisor" in output assert "pid 1001" in output assert "observer" in output assert "Crashed:" in output assert "sync" in output assert "Tasks:" in output assert "daily" in output assert "queued indexer" in output assert "Heartbeat: ok" in output assert "Callosum: 5 clients" in output def test_health_check_renders_stuck_marker(capsys): status = { "services": [], "tasks": [ { "name": "providers", "duration_seconds": 313656, "max_runtime_seconds": 300, "stuck": True, } ], "queues": {}, } print_status(status) output = capsys.readouterr().out assert " providers 313656s STUCK (cap 300s)" in output def test_health_check_renders_slow_marker(capsys): status = { "services": [], "tasks": [ { "name": "providers", "duration_seconds": 240, "max_runtime_seconds": 300, "slow": True, "stuck": False, } ], "queues": {}, } print_status(status) output = capsys.readouterr().out assert " providers 240s SLOW (cap 300s)" in output assert "STUCK" not in output def test_health_check_renders_stuck_only_when_slow_and_stuck(capsys): status = { "services": [], "tasks": [ { "name": "providers", "duration_seconds": 313656, "max_runtime_seconds": 300, "slow": True, "stuck": True, } ], "queues": {}, } print_status(status) output = capsys.readouterr().out assert " providers 313656s STUCK (cap 300s)" in output assert "SLOW" not in output def test_healthy_task_rendering_unchanged(capsys): status = { "services": [], "tasks": [ { "name": "providers", "duration_seconds": 12, "max_runtime_seconds": 300, "stuck": False, } ], "queues": {}, } print_status(status) output = capsys.readouterr().out assert "STUCK" not in output assert " providers 12s" in output.splitlines() def test_health_check_timeout(tmp_path, monkeypatch, capsys): monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) sock = tmp_path / "health" / "callosum.sock" sock.parent.mkdir(parents=True) sock.touch() monkeypatch.setattr("solstone.think.health_cli.STATUS_TIMEOUT", 0.1) with patch("solstone.think.health_cli.CallosumConnection") as mock_conn_cls: mock_conn = mock_conn_cls.return_value mock_conn.start.return_value = None mock_conn.stop.return_value = None result = health_check() captured = capsys.readouterr() assert result == 1 assert "Timed out waiting for supervisor status" in captured.err mock_conn.stop.assert_called_once() def test_health_check_receives_status(tmp_path, monkeypatch, capsys): monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) sock = tmp_path / "health" / "callosum.sock" sock.parent.mkdir(parents=True) sock.touch() with patch("solstone.think.health_cli.CallosumConnection") as mock_conn_cls: mock_conn = mock_conn_cls.return_value def _start(*, callback): callback( { "tract": "supervisor", "event": "status", "services": [ {"name": "supervisor", "pid": 111, "uptime_seconds": 120} ], "tasks": [], "queues": {}, "stale_heartbeats": [], } ) mock_conn.start.side_effect = _start mock_conn.stop.return_value = None result = health_check() captured = capsys.readouterr() assert result == 0 assert "Services:" in captured.out assert "supervisor" in captured.out def test_main_routes_to_logs(monkeypatch): monkeypatch.setattr(sys, "argv", ["journal health", "logs", "--help"]) with patch( "solstone.think.logs_cli.main", side_effect=SystemExit(0) ) as mock_logs_main: with pytest.raises(SystemExit): main() mock_logs_main.assert_called_once()