# Copyright 2026 Umbra Tools (umbratools.com) # SPDX-License-Identifier: Apache-2.0 """Tests for the web-UI voice-maintenance banner marker. The marker is a small JSON file whose ``pid`` field gates the banner: a run that died without clearing the file must not leave the banner up forever, so ``active_voice_maintenance`` checks the owner is still alive. """ from __future__ import annotations import json import os from typing import TYPE_CHECKING import pytest if TYPE_CHECKING: from pathlib import Path from umbraaudio import voice_maintenance as vm @pytest.fixture def marker(tmp_path, monkeypatch: pytest.MonkeyPatch) -> Path: path = tmp_path / "voice_maintenance.json" monkeypatch.setattr(vm, "MAINTENANCE_FILE", path) return path def test_set_writes_marker_with_live_pid(marker: Path) -> None: vm.set_voice_maintenance("analysis in progress") assert marker.exists() data = json.loads(marker.read_text()) assert data["pid"] == os.getpid() assert "analysis" in data["reason"] def test_active_returns_marker_while_owner_alive(marker: Path) -> None: vm.set_voice_maintenance("analysis in progress") active = vm.active_voice_maintenance() assert active is not None assert active["pid"] == os.getpid() def test_active_none_when_no_marker(marker: Path) -> None: assert vm.active_voice_maintenance() is None def test_clear_removes_marker(marker: Path) -> None: vm.set_voice_maintenance("analysis in progress") vm.clear_voice_maintenance() assert not marker.exists() assert vm.active_voice_maintenance() is None def test_clear_missing_marker_is_idempotent(marker: Path) -> None: vm.clear_voice_maintenance() vm.clear_voice_maintenance() def test_active_none_when_owner_dead(marker: Path) -> None: marker.write_text( json.dumps({"pid": 2**24, "started_at": 1, "reason": "dead owner"}) ) assert vm.active_voice_maintenance() is None def test_active_none_on_corrupt_marker(marker: Path) -> None: marker.write_text("{not json") assert vm.active_voice_maintenance() is None def test_active_none_on_bad_pid_type(marker: Path) -> None: marker.write_text( json.dumps({"pid": "not-an-int", "started_at": 1, "reason": "bad"}) ) assert vm.active_voice_maintenance() is None