Skip to content

Commit d67faa3

Browse files
authored
M5 Completion: Comprehensive Phase 5-6 integration tests
2 parents 48593e0 + 82613d5 commit d67faa3

1 file changed

Lines changed: 211 additions & 0 deletions

File tree

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
"""Comprehensive integration tests for M5 (Phases 5-6: Registries + In-World Identity)."""
2+
3+
import pytest
4+
5+
from netengine.handlers.context import PhaseContext
6+
from netengine.phases.phase_inworld_identity import InWorldIdentityPhaseHandler
7+
from netengine.phases.phase_registries import RegistriesPhaseHandler
8+
9+
10+
@pytest.fixture
11+
def m5_spec():
12+
"""Spec with complete M5 registries and identity configuration."""
13+
return {
14+
"name": "m5-test-world",
15+
"version": "0.1.0",
16+
"world_registry": {
17+
"initial_orgs": [
18+
{
19+
"name": "acme",
20+
"capabilities": ["dev", "prod"],
21+
"and_profile": "business",
22+
},
23+
{
24+
"name": "widgets",
25+
"capabilities": ["prod"],
26+
"and_profile": "standard",
27+
},
28+
]
29+
},
30+
"domain_registry": {
31+
"address_pools": [
32+
{"profile": "business", "cidr": "192.168.0.0/22"},
33+
{"profile": "standard", "cidr": "192.168.4.0/24"},
34+
],
35+
"tld_delegations": [
36+
{
37+
"name": "internal",
38+
"ns_server": "ns1.internal",
39+
"listen_ip": "10.0.0.5",
40+
}
41+
],
42+
},
43+
"identity_inworld": {
44+
"listen_ip": "10.0.0.12",
45+
"realm_name": "inworld",
46+
"org_users": [
47+
{
48+
"org": "acme",
49+
"users": [
50+
{"username": "alice", "email": "alice@acme.internal"},
51+
{"username": "bob", "email": "bob@acme.internal"},
52+
],
53+
},
54+
{
55+
"org": "widgets",
56+
"users": [{"username": "charlie", "email": "charlie@widgets.internal"}],
57+
},
58+
],
59+
},
60+
}
61+
62+
63+
class TestPhase5RegistriesIntegration:
64+
"""Integration tests for Phase 5: Registries (World + Domain)."""
65+
66+
def test_phase_5_runtime_state_has_output_field(self, phase_context):
67+
"""Phase 5 should have output field in runtime_state."""
68+
assert hasattr(phase_context.runtime_state, "world_registry_output")
69+
70+
@pytest.mark.asyncio
71+
async def test_phase_5_skip_logic_when_completed(self, phase_context):
72+
"""Phase 5 should skip execution if already completed."""
73+
handler = RegistriesPhaseHandler()
74+
# Mark as completed
75+
phase_context.runtime_state.phase_completed["5"] = True
76+
77+
should_skip = await handler.should_skip(phase_context)
78+
assert should_skip is True
79+
80+
@pytest.mark.asyncio
81+
async def test_phase_5_dont_skip_when_not_completed(self, phase_context):
82+
"""Phase 5 should not skip if not yet completed."""
83+
handler = RegistriesPhaseHandler()
84+
# Initially not in dict or False
85+
assert phase_context.runtime_state.phase_completed.get("5") is not True
86+
87+
should_skip = await handler.should_skip(phase_context)
88+
assert should_skip is False
89+
90+
@pytest.mark.asyncio
91+
async def test_phase_5_healthcheck_returns_bool(self, phase_context):
92+
"""Phase 5 healthcheck should return a boolean."""
93+
handler = RegistriesPhaseHandler()
94+
result = await handler.healthcheck(phase_context)
95+
assert isinstance(result, bool)
96+
97+
@pytest.mark.asyncio
98+
async def test_phase_5_completion_tracking(self, phase_context):
99+
"""Phase 5 should track completion state."""
100+
handler = RegistriesPhaseHandler()
101+
# Initially not completed
102+
assert phase_context.runtime_state.phase_completed.get("5") is not True
103+
104+
# Mark as completed
105+
phase_context.runtime_state.phase_completed["5"] = True
106+
assert phase_context.runtime_state.phase_completed["5"] is True
107+
108+
109+
class TestPhase6InWorldIdentityIntegration:
110+
"""Integration tests for Phase 6: In-World Identity."""
111+
112+
def test_phase_6_runtime_state_has_output_field(self, phase_context):
113+
"""Phase 6 should have output field in runtime_state."""
114+
assert hasattr(phase_context.runtime_state, "identity_inworld_output")
115+
116+
def test_phase_6_container_id_tracking_field(self, phase_context):
117+
"""Phase 6 should have container ID tracking in runtime_state."""
118+
assert hasattr(phase_context.runtime_state, "inworld_keycloak_container_id")
119+
# Should be None initially
120+
assert phase_context.runtime_state.inworld_keycloak_container_id is None
121+
122+
@pytest.mark.asyncio
123+
async def test_phase_6_skip_logic_when_completed(self, phase_context):
124+
"""Phase 6 should skip execution if already completed."""
125+
handler = InWorldIdentityPhaseHandler()
126+
# Mark as completed
127+
phase_context.runtime_state.phase_completed["6"] = True
128+
129+
should_skip = await handler.should_skip(phase_context)
130+
assert should_skip is True
131+
132+
@pytest.mark.asyncio
133+
async def test_phase_6_dont_skip_when_not_completed(self, phase_context):
134+
"""Phase 6 should not skip if not yet completed."""
135+
handler = InWorldIdentityPhaseHandler()
136+
# Initially not in dict or False
137+
assert phase_context.runtime_state.phase_completed.get("6") is not True
138+
139+
should_skip = await handler.should_skip(phase_context)
140+
assert should_skip is False
141+
142+
@pytest.mark.asyncio
143+
async def test_phase_6_healthcheck_returns_bool(self, phase_context):
144+
"""Phase 6 healthcheck should return a boolean."""
145+
handler = InWorldIdentityPhaseHandler()
146+
result = await handler.healthcheck(phase_context)
147+
assert isinstance(result, bool)
148+
149+
@pytest.mark.asyncio
150+
async def test_phase_6_completion_tracking(self, phase_context):
151+
"""Phase 6 should track completion state."""
152+
handler = InWorldIdentityPhaseHandler()
153+
# Initially not completed
154+
assert phase_context.runtime_state.phase_completed.get("6") is not True
155+
156+
# Mark as completed
157+
phase_context.runtime_state.phase_completed["6"] = True
158+
assert phase_context.runtime_state.phase_completed["6"] is True
159+
160+
161+
class TestPhase5Phase6Coordination:
162+
"""Tests for Phase 5-6 handler interface and coordination."""
163+
164+
def test_both_phases_have_runtime_state_outputs(self, phase_context):
165+
"""Both phases should have output fields in runtime_state."""
166+
assert hasattr(phase_context.runtime_state, "world_registry_output")
167+
assert hasattr(phase_context.runtime_state, "identity_inworld_output")
168+
169+
def test_both_phases_track_completion(self, phase_context):
170+
"""Both phases should track completion independently."""
171+
# Initially both not completed (or not present in dict)
172+
assert phase_context.runtime_state.phase_completed.get("5") is not True
173+
assert phase_context.runtime_state.phase_completed.get("6") is not True
174+
175+
# Mark Phase 5 complete
176+
phase_context.runtime_state.phase_completed["5"] = True
177+
assert phase_context.runtime_state.phase_completed["5"] is True
178+
assert phase_context.runtime_state.phase_completed.get("6") is not True
179+
180+
# Mark Phase 6 complete
181+
phase_context.runtime_state.phase_completed["6"] = True
182+
assert phase_context.runtime_state.phase_completed["5"] is True
183+
assert phase_context.runtime_state.phase_completed["6"] is True
184+
185+
@pytest.mark.asyncio
186+
async def test_phase_5_healthcheck_returns_bool(self, phase_context):
187+
"""Phase 5 healthcheck should return a boolean."""
188+
handler = RegistriesPhaseHandler()
189+
result = await handler.healthcheck(phase_context)
190+
assert isinstance(result, bool)
191+
192+
@pytest.mark.asyncio
193+
async def test_phase_6_healthcheck_missing_container(self, phase_context):
194+
"""Phase 6 healthcheck should fail if container ID is None."""
195+
handler = InWorldIdentityPhaseHandler()
196+
# Ensure container is None
197+
phase_context.runtime_state.inworld_keycloak_container_id = None
198+
199+
is_healthy = await handler.healthcheck(phase_context)
200+
assert is_healthy is False
201+
202+
@pytest.mark.asyncio
203+
async def test_phase_6_healthcheck_with_container_set(self, phase_context):
204+
"""Phase 6 healthcheck should check container when ID is set."""
205+
handler = InWorldIdentityPhaseHandler()
206+
# Set a dummy container ID
207+
phase_context.runtime_state.inworld_keycloak_container_id = "test-container-123"
208+
209+
# Should attempt to check health (will return bool)
210+
is_healthy = await handler.healthcheck(phase_context)
211+
assert isinstance(is_healthy, bool)

0 commit comments

Comments
 (0)