Files
bot-bottle/tests/unit/__init__.py
T
didericis 8d3799445a
lint / lint (push) Failing after 2m13s
test: isolate HOME for the unit suite (hermetic audit/queue/state)
The unit suite could write to and flock the real ~/.bot-bottle: state,
queue, and audit dirs all derive from supervise.bot_bottle_root() ->
Path.home(). A test taking a flock on the real audit log blocks
indefinitely when a live bottle's supervise sidecar holds that lock
(observed: a `coverage run` hung at 0% CPU), and unisolated tests
otherwise pollute the developer's home dir.

Point HOME at a throwaway temp dir for the whole tests/unit package
(restored + cleaned at exit). Tests that set their own HOME now restore
to the isolated dir, not the real one; tests that patch bot_bottle_root
directly are unaffected.

Closes #302

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NkwFXLFff9PYPy4wgVBJp9
2026-06-26 20:35:19 -04:00

36 lines
1.2 KiB
Python

"""Unit-test package init.
Isolates ``HOME`` to a throwaway directory for the entire unit suite so
no test ever reads or writes the real ``~/.bot-bottle`` (state, queue,
and audit dirs all derive from ``supervise.bot_bottle_root()`` →
``Path.home()``). Without this, a test that takes a ``flock`` on the
real audit log can **block indefinitely** when a live bottle's supervise
sidecar holds that lock — observed as a hung ``coverage run`` at 0% CPU —
and unisolated tests otherwise pollute the developer's home dir.
Individual tests that need their own ``HOME`` still override
``os.environ['HOME']`` and restore it; they now restore to this isolated
dir rather than the real one, so isolation holds either way. Tests that
patch ``supervise.bot_bottle_root`` directly are unaffected.
"""
from __future__ import annotations
import atexit
import os
import shutil
import tempfile
_real_home = os.environ.get("HOME")
_tmp_home = tempfile.mkdtemp(prefix="bot-bottle-unit-home.")
os.environ["HOME"] = _tmp_home
@atexit.register
def _restore_home() -> None:
if _real_home is None:
os.environ.pop("HOME", None)
else:
os.environ["HOME"] = _real_home
shutil.rmtree(_tmp_home, ignore_errors=True)