From 765635e720f9100adf716fe0c5bc6f2621a41f08 Mon Sep 17 00:00:00 2001 From: zvx Date: Thu, 21 May 2026 14:23:31 +0000 Subject: [PATCH] chore(M): make enrichment-cache path test-hermetic via conftest autouse fixture Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/conftest.py | 19 ++++++++++++++++ tests/test_supervisor_integration.py | 34 ++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 97a4f5d..fca89f0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,25 @@ from unittest.mock import AsyncMock, MagicMock, patch from central.bootstrap_config import Settings +@pytest.fixture(autouse=True) +def isolate_enrichment_cache(tmp_path, monkeypatch): + """Redirect the supervisor's enrichment cache off the production path. + + `central.supervisor.ENRICHMENT_CACHE_DB_PATH` defaults to + /var/lib/central/enrichment_cache.db. Constructing a Supervisor opens it, + so without this fixture the suite writes to (or, for any user without write + access to /var/lib/central, fails on) the live cache. Point it at a + per-test temp dir so no test ever touches the production path. + """ + import central.supervisor as supervisor_mod + + monkeypatch.setattr( + supervisor_mod, + "ENRICHMENT_CACHE_DB_PATH", + tmp_path / "enrichment_cache.db", + ) + + @pytest.fixture(scope="session") def event_loop(): """Create an event loop for the test session.""" diff --git a/tests/test_supervisor_integration.py b/tests/test_supervisor_integration.py index 20360fe..fa3a420 100644 --- a/tests/test_supervisor_integration.py +++ b/tests/test_supervisor_integration.py @@ -139,12 +139,18 @@ class MockNWSAdapter: @pytest.fixture def mock_nats(): - """Mock NATS connection.""" + """Mock NATS connection. + + nats-py's `nc.jetstream()` is synchronous, so model it with a sync + MagicMock. (As an AsyncMock attribute, `supervisor._js = nc.jetstream()` + would assign an unawaited coroutine — the "coroutine ... was never awaited" + warning — rather than the JetStream mock.) + """ mock_nc = AsyncMock() mock_nc.publish = AsyncMock() mock_js = AsyncMock() mock_js.publish = AsyncMock() - mock_nc.jetstream.return_value = mock_js + mock_nc.jetstream = MagicMock(return_value=mock_js) return mock_nc @@ -574,3 +580,27 @@ class TestEnableDisableEnableIntegration: # State should be gone assert "nws" not in supervisor._adapter_states + + +def test_enrichment_cache_path_is_hermetic(mock_config_store, tmp_path: Path) -> None: + """No test may touch the production enrichment cache. + + The autouse `isolate_enrichment_cache` fixture (conftest) must redirect + ENRICHMENT_CACHE_DB_PATH off /var/lib/central onto a per-test temp dir, and + constructing a Supervisor must open the cache there — not in production. + """ + import central.supervisor as supervisor_mod + + patched = supervisor_mod.ENRICHMENT_CACHE_DB_PATH + assert tmp_path in patched.parents + assert "/var/lib/central" not in str(patched) + + supervisor = supervisor_mod.Supervisor( + config_source=MockConfigSource(), + config_store=mock_config_store, + nats_url="nats://localhost:4222", + cloudevents_config=None, + ) + # __init__ opened the cache at the temp path, leaving the db file behind. + assert patched.exists() + assert supervisor._enrichment_cache is not None