gabriel / muse public

test_cache_status_fields.py file-level

at sha256:c · View file ↗ · Intel ↗

History
1 files
1 commits
0 hotspots
0 🧊 dead
0 💥 blast risk
sha256:a feat(shelf): --path scoped shelving, the native replacement for /tmp ba… · gabriel · Oct 22, 2026
1 """TDD tests for muse#49 Phase 2 — cache_hit/cache_misses on SelectionResult.
2
3 ``select_tests`` now threads a mutable ``cache_stats`` dict through
4 ``symbols_for_snapshot`` and ``build_forward_graph`` (both accept an
5 optional ``stats=`` kwarg that increments hit/miss counters in place).
6 The final ``SelectionResult`` exposes ``cache_hit`` (True only when zero
7 misses occurred across both caches) and ``cache_misses`` (the raw count).
8
9 These tests prove the *mechanism* — that the reported values trace back to
10 real cache misses in the underlying cache objects — rather than asserting
11 only on final selection output, which would pass trivially even if the
12 stats wiring were a no-op (test-selection correctness is independent of
13 cache warmth; only performance differs).
14 """
15
16 from __future__ import annotations
17
18 import logging
19 import pathlib
20
21 import pytest
22
23 from muse.core.callgraph_cache import CallGraphCache
24 from muse.core.object_store import write_object
25 from muse.core.paths import muse_dir
26 from muse.core.symbol_cache import SymbolCache
27 from muse.core.test_selection import ChangedSymbol, select_tests
28 from muse.core.types import Manifest, blob_id
29
30
31 def _make_repo(tmp_path: pathlib.Path) -> tuple[pathlib.Path, Manifest]:
32 dot_muse = muse_dir(tmp_path)
33 dot_muse.mkdir(exist_ok=True)
34
35 prod_src = b"""\
36 def compute(x: int) -> int:
37 return x * 2
38 """
39 test_src = b"""\
40 from prod import compute
41
42 def test_compute() -> None:
43 assert compute(2) == 4
44 """
45 prod_oid = blob_id(prod_src)
46 test_oid = blob_id(test_src)
47 write_object(tmp_path, prod_oid, prod_src)
48 write_object(tmp_path, test_oid, test_src)
49
50 (tmp_path / "prod.py").write_bytes(prod_src)
51 tests_dir = tmp_path / "tests"
52 tests_dir.mkdir(exist_ok=True)
53 (tests_dir / "test_prod.py").write_bytes(test_src)
54
55 manifest: Manifest = {
56 "prod.py": prod_oid,
57 "tests/test_prod.py": test_oid,
58 }
59 return tmp_path, manifest
60
61
62 class TestColdCacheReportsMiss:
63 def test_first_run_cache_hit_false_with_misses(self, tmp_path: pathlib.Path) -> None:
64 """A fully cold run (empty caches) must report cache_hit=False and
65 cache_misses > 0 — proving the counters actually observe the misses
66 that occur in symbols_for_snapshot/build_forward_graph, not a
67 hardcoded value."""
68 root, manifest = _make_repo(tmp_path)
69 changed = [ChangedSymbol(address="prod.py::compute", change_kind="modified")]
70
71 result = select_tests(
72 root, changed, manifest,
73 cache=SymbolCache.empty(),
74 callgraph_cache=CallGraphCache.empty(),
75 )
76
77 assert result["cache_hit"] is False
78 assert result["cache_misses"] > 0
79
80 def test_cold_run_emits_warning(
81 self, tmp_path: pathlib.Path, caplog: pytest.LogCaptureFixture
82 ) -> None:
83 """CT_03: the cold-rebuild path must emit a visible warning log line,
84 not fail silently with no feedback to the user."""
85 root, manifest = _make_repo(tmp_path)
86 changed = [ChangedSymbol(address="prod.py::compute", change_kind="modified")]
87
88 with caplog.at_level(logging.WARNING, logger="muse.core.test_selection"):
89 select_tests(
90 root, changed, manifest,
91 cache=SymbolCache.empty(),
92 callgraph_cache=CallGraphCache.empty(),
93 )
94
95 assert any("cache cold" in rec.message for rec in caplog.records), (
96 "expected a 'cache cold' warning log on a cold-cache run"
97 )
98
99
100 class TestWarmCacheReportsHit:
101 def test_second_run_cache_hit_true_zero_misses(self, tmp_path: pathlib.Path) -> None:
102 """Proves the mechanism directly: after warming both caches via a
103 first select_tests call, a second call against the SAME manifest
104 must report zero misses — i.e. the stats dict is actually wired to
105 the real cache .get() calls, not independently computed."""
106 root, manifest = _make_repo(tmp_path)
107 changed = [ChangedSymbol(address="prod.py::compute", change_kind="modified")]
108 sym_cache = SymbolCache.empty()
109 cg_cache = CallGraphCache.empty()
110
111 first = select_tests(root, changed, manifest, cache=sym_cache, callgraph_cache=cg_cache)
112 assert first["cache_hit"] is False # sanity: first run was indeed cold
113
114 second = select_tests(root, changed, manifest, cache=sym_cache, callgraph_cache=cg_cache)
115
116 assert second["cache_hit"] is True
117 assert second["cache_misses"] == 0
118
119 def test_warm_run_emits_no_cold_warning(
120 self, tmp_path: pathlib.Path, caplog: pytest.LogCaptureFixture
121 ) -> None:
122 root, manifest = _make_repo(tmp_path)
123 changed = [ChangedSymbol(address="prod.py::compute", change_kind="modified")]
124 sym_cache = SymbolCache.empty()
125 cg_cache = CallGraphCache.empty()
126
127 select_tests(root, changed, manifest, cache=sym_cache, callgraph_cache=cg_cache)
128
129 caplog.clear()
130 with caplog.at_level(logging.WARNING, logger="muse.core.test_selection"):
131 select_tests(root, changed, manifest, cache=sym_cache, callgraph_cache=cg_cache)
132
133 assert not any("cache cold" in rec.message for rec in caplog.records)
134
135
136 class TestEmptyChangedAddressesShortCircuit:
137 def test_no_changed_symbols_reports_hit_true(self, tmp_path: pathlib.Path) -> None:
138 """The early-return path (no changed symbols) never touches either
139 cache, so it must report a trivial cache_hit=True, cache_misses=0 —
140 it would be misleading to claim a miss when no lookup happened."""
141 root, manifest = _make_repo(tmp_path)
142
143 result = select_tests(root, [], manifest)
144
145 assert result["cache_hit"] is True
146 assert result["cache_misses"] == 0