gabriel / musehub public
test_phase4_load_commit_walk.py python
126 lines 4.5 KB
Raw
sha256:ef10830ce231e0a20efcb0e2586cb879471247e916616e6fdd0d51df459e2595 fix: typing audit — 0 violations, 0 untyped defs across all… Sonnet 4.6 minor ⚠ breaking 20 days ago
1 """TDD — Phase 4 of issue #40: dedup intel provider BFS into _load_commit_walk.
2
3 P4-1 Structural — each provider delegates to _load_commit_walk; no inline BFS
4 P4-2 Behavioural — _load_commit_walk returns correct BFS order for a 4-commit chain
5 P4-3 Behavioural — _load_commit_walk respects max_walk cap
6 """
7 from __future__ import annotations
8
9 import inspect
10 from types import SimpleNamespace
11 from unittest.mock import AsyncMock, MagicMock
12
13 import pytest
14
15
16 # ---------------------------------------------------------------------------
17 # P4-1 Structural — each provider delegates to _load_commit_walk
18 # ---------------------------------------------------------------------------
19
20 def test_p4_1_coupling_provider_delegates_to_load_commit_walk() -> None:
21 """CouplingProvider.compute must call _load_commit_walk; no inline walk_dag."""
22 from musehub.services import musehub_intel_providers as mod
23
24 src = inspect.getsource(mod.CouplingProvider.compute)
25 assert "_load_commit_walk" in src, (
26 "CouplingProvider.compute must delegate to _load_commit_walk."
27 )
28 assert "walk_dag" not in src, (
29 "CouplingProvider.compute still has an inline walk_dag call."
30 )
31
32
33 def test_p4_1_entangle_provider_delegates_to_load_commit_walk() -> None:
34 """EntangleProvider.compute must call _load_commit_walk; no inline walk_dag."""
35 from musehub.services import musehub_intel_providers as mod
36
37 src = inspect.getsource(mod.EntangleProvider.compute)
38 assert "_load_commit_walk" in src, (
39 "EntangleProvider.compute must delegate to _load_commit_walk."
40 )
41 assert "walk_dag" not in src, (
42 "EntangleProvider.compute still has an inline walk_dag call."
43 )
44
45
46 def test_p4_1_velocity_provider_delegates_to_load_commit_walk() -> None:
47 """VelocityProvider.compute must call _load_commit_walk; no inline walk_dag."""
48 from musehub.services import musehub_intel_providers as mod
49
50 src = inspect.getsource(mod.VelocityProvider.compute)
51 assert "_load_commit_walk" in src, (
52 "VelocityProvider.compute must delegate to _load_commit_walk."
53 )
54 assert "walk_dag" not in src, (
55 "VelocityProvider.compute still has an inline walk_dag call."
56 )
57
58
59 # ---------------------------------------------------------------------------
60 # Helpers for behavioural tests
61 # ---------------------------------------------------------------------------
62
63 def _row(commit_id: str, parent_ids: list[str]) -> None:
64 return SimpleNamespace(commit_id=commit_id, parent_ids=parent_ids)
65
66
67 def _make_session(rows: list[SimpleNamespace]) -> MagicMock:
68 """Fake session whose execute() returns an iterable of row SimpleNamespaces."""
69 session = MagicMock()
70 session.execute = AsyncMock(return_value=rows)
71 return session
72
73
74 # ---------------------------------------------------------------------------
75 # P4-2 Behavioural — correct BFS order for a 4-commit diamond
76 # ---------------------------------------------------------------------------
77
78 @pytest.mark.asyncio
79 async def test_p4_2_load_commit_walk_bfs_order() -> None:
80 """_load_commit_walk returns commits in BFS order for a diamond graph.
81
82 Diamond: A → B, A → C; B → D; C → D.
83 BFS from A: [A, B, C, D] (level-by-level).
84 """
85 from musehub.services.musehub_intel_providers import _load_commit_walk
86
87 rows = [
88 _row("A", ["B", "C"]),
89 _row("B", ["D"]),
90 _row("C", ["D"]),
91 _row("D", []),
92 ]
93 session = _make_session(rows)
94
95 result = await _load_commit_walk(session, "repo1", "A", max_walk=100)
96
97 assert result == ["A", "B", "C", "D"], (
98 f"Expected BFS order [A, B, C, D], got {result}"
99 )
100
101
102 # ---------------------------------------------------------------------------
103 # P4-3 Behavioural — max_walk cap
104 # ---------------------------------------------------------------------------
105
106 @pytest.mark.asyncio
107 async def test_p4_3_load_commit_walk_max_walk_cap() -> None:
108 """_load_commit_walk stops after max_walk commits have been collected.
109
110 Linear chain: A→B→C→D→E. max_walk=3 → [A, B, C].
111 """
112 from musehub.services.musehub_intel_providers import _load_commit_walk
113
114 rows = [
115 _row("A", ["B"]),
116 _row("B", ["C"]),
117 _row("C", ["D"]),
118 _row("D", ["E"]),
119 _row("E", []),
120 ]
121 session = _make_session(rows)
122
123 result = await _load_commit_walk(session, "repo1", "A", max_walk=3)
124
125 assert len(result) == 3, f"Expected exactly 3 commits, got {len(result)}"
126 assert result == ["A", "B", "C"], f"Expected [A, B, C], got {result}"
File History 1 commit
sha256:ef10830ce231e0a20efcb0e2586cb879471247e916616e6fdd0d51df459e2595 fix: typing audit — 0 violations, 0 untyped defs across all… Sonnet 4.6 minor 20 days ago