-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_runtime_e2e.py
More file actions
307 lines (279 loc) · 9.85 KB
/
Copy pathtest_runtime_e2e.py
File metadata and controls
307 lines (279 loc) · 9.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
"""End-to-end tests — full event flow through Runtime.
Tests verify the complete pipeline: Runtime.publish() → bus → dispatch
→ service handle → emit → downstream service receives.
"""
from __future__ import annotations
from typing import Any, cast
from underwrite.__config__ import Configuration
from underwrite.__events__ import Event, EventType
from underwrite.__runtime__ import Runtime
def memory_runtime(enable_metrics: bool = True) -> Runtime:
"""Returns a Runtime backed by MemoryStore for test isolation."""
cfg = Configuration.default()
cfg.store.backend = "memory"
cfg.metrics.enabled = enable_metrics
cfg.tracing.enabled = False
cfg.metrics.export_interval = 0 # disable export thread
cfg.authz.enabled = False
return Runtime(config=cfg)
class TestPublishFlow:
def test_publish_through_runtime_delivers_to_service(self) -> None:
rt = memory_runtime()
bus = rt.bus
rt.register("audit")
rt.wire("audit")
bus.start()
rt.start(["audit"])
bus.publish(
Event(
event_type=EventType.LOAN_ORIGINATED,
source="test",
payload={"aadhaar": "1234-5678-9012", "principal": 50000},
)
)
audit = rt.get("audit")
assert audit is not None
records = [
e
for e in audit._ledger # type: ignore[attr-defined]
if e["event_type"] == EventType.LOAN_ORIGINATED
]
assert len(records) == 1
assert records[0]["payload"]["aadhaar"] == "***REDACTED***"
rt.stop()
def test_runtime_publish_method_creates_event(self) -> None:
cfg = Configuration.default()
cfg.authz.enabled = False
rt = Runtime(config=cfg)
bus = rt.bus
received: list[Event] = []
bus.subscribe("*", lambda e: received.append(e))
bus.start()
bus.publish(Event(event_type="custom.test", source="test", payload={"key": "value"}))
assert any(e.event_type == "custom.test" for e in received)
rt.stop()
def test_multiple_services_receive_same_event(self) -> None:
rt = memory_runtime()
bus = rt.bus
rt.register("mechanism")
rt.register("audit")
rt.wire("mechanism")
rt.wire("audit")
bus.start()
rt.start(["mechanism", "audit"])
mechanism = rt.get("mechanism")
assert mechanism is not None
mechanism.handle(
Event(
event_type="mechanism",
source="test",
payload={"command": "add_seed", "user": "bank", "base_budget": 200000},
)
)
audit = cast(Any, rt.get("audit"))
assert audit is not None
seed_events = [e for e in audit._ledger if e["event_type"] == EventType.SEED_ADDED]
assert len(seed_events) >= 1
state = rt.store.get("protocol:state")
assert state is not None
assert "bank" in state["seeds"]
rt.stop()
def test_service_emits_through_bus_downstream(self) -> None:
rt = memory_runtime()
bus = rt.bus
all_events: list[Event] = []
bus.subscribe("*", lambda e: all_events.append(e))
rt.register("mechanism")
rt.wire("mechanism")
bus.start()
rt.start(["mechanism"])
svc = rt.get("mechanism")
assert svc is not None
svc.handle(
Event(
event_type="mechanism",
source="test",
payload={"command": "add_seed", "user": "bank", "base_budget": 300000},
)
)
emitted_types = {e.event_type for e in all_events}
assert EventType.SEED_ADDED in emitted_types
rt.stop()
def test_audit_records_emitted_events_via_wiring(self) -> None:
rt = memory_runtime()
bus = rt.bus
rt.register("mechanism")
rt.register("audit")
rt.wire("mechanism")
rt.wire("audit")
bus.start()
rt.start(["mechanism", "audit"])
svc = rt.get("mechanism")
assert svc is not None
svc.handle(
Event(
event_type="mechanism",
source="test",
payload={"command": "add_seed", "user": "bank", "base_budget": 400000},
)
)
audit = cast(Any, rt.get("audit"))
assert audit is not None
seed_records = audit.events_by_type(EventType.SEED_ADDED)
assert len(seed_records) >= 1
rt.stop()
class TestRuntimeHealthE2E:
def test_health_reflects_running_services(self) -> None:
rt = Runtime()
checks = rt.health.status()["checks"]
assert "bus" in checks
assert "store" in checks
assert "services" in checks
rt.register("mechanism")
rt.wire("mechanism")
rt.start(["mechanism"])
checks = rt.health.status()["checks"]
svc_check = checks.get("service:mechanism", {})
assert svc_check.get("ok") is True
def test_stopped_service_shows_unhealthy(self) -> None:
rt = Runtime()
rt.register("mechanism")
rt.wire("mechanism")
rt.start(["mechanism"])
rt.stop()
checks = rt.health.status()["checks"]
svc_check = checks.get("service:mechanism", {})
assert svc_check.get("ok") is False
def test_bus_health_always_ok(self) -> None:
rt = Runtime()
checks = rt.health.status()["checks"]
assert checks["bus"]["ok"] is True
def test_store_health_always_ok(self) -> None:
rt = Runtime()
checks = rt.health.status()["checks"]
assert checks["store"]["ok"] is True
class TestMetricsE2E:
def test_metrics_recorded_when_enabled(self) -> None:
rt = Runtime()
assert rt.metrics is not None
rt.metrics.increment("test.counter", {"label": "e2e"})
snap = rt.metrics.snapshot()
counters = snap.get("counters", {})
assert any("test.counter" in k for k in counters)
rt.stop()
def test_events_emitted_increment_counter(self) -> None:
rt = memory_runtime()
bus = rt.bus
rt.register("mechanism")
rt.wire("mechanism")
bus.start()
rt.start(["mechanism"])
svc = rt.get("mechanism")
assert svc is not None
svc.handle(
Event(
event_type="mechanism",
source="test",
payload={"command": "add_seed", "user": "bank", "base_budget": 50000},
)
)
assert rt.metrics is not None
snap = rt.metrics.snapshot()
counters = snap.get("counters", {})
emitted_key = next((k for k in counters if "events.emitted" in k and "mechanism" in k), None)
assert emitted_key is not None
rt.stop()
def test_metrics_returns_collector_by_default(self) -> None:
rt = Runtime()
assert rt.metrics is not None
class TestGracefulShutdownE2E:
def test_stop_with_active_service(self) -> None:
rt = Runtime()
bus = rt.bus
rt.register("mechanism")
rt.wire("mechanism")
bus.start()
rt.start(["mechanism"])
svc = rt.get("mechanism")
assert svc is not None
assert svc.is_running
rt.stop()
svc = rt.get("mechanism")
assert svc is not None
assert svc.is_running is False
def test_stop_idempotent(self) -> None:
rt = Runtime()
rt.register("mechanism")
rt.wire("mechanism")
rt.start(["mechanism"])
rt.stop()
rt.stop()
rt.stop()
svc = rt.get("mechanism")
assert svc is not None
assert svc.is_running is False
def test_stop_with_no_services(self) -> None:
rt = Runtime()
rt.stop()
rt.stop()
class TestMultipleServiceCoordination:
def test_mechanism_and_audit_coexist(self) -> None:
rt = memory_runtime()
bus = rt.bus
rt.register("mechanism")
rt.register("audit")
rt.wire("mechanism")
rt.wire("audit")
bus.start()
rt.start(["mechanism", "audit"])
mech_svc = rt.get("mechanism")
assert mech_svc is not None
assert mech_svc.is_running
audit_svc = rt.get("audit")
assert audit_svc is not None
assert audit_svc.is_running
svc = rt.get("mechanism")
assert svc is not None
svc.handle(
Event(
event_type="mechanism",
source="test",
payload={"command": "add_seed", "user": "bank", "base_budget": 100000},
)
)
audit = rt.get("audit")
assert audit is not None
assert len(audit._ledger) >= 1 # type: ignore[attr-defined]
rt.stop()
mech_svc = rt.get("mechanism")
assert mech_svc is not None
assert mech_svc.is_running is False
audit_svc = rt.get("audit")
assert audit_svc is not None
assert audit_svc.is_running is False
def test_store_shared_between_services(self) -> None:
rt = memory_runtime()
bus = rt.bus
rt.register("mechanism")
rt.register("audit")
rt.wire("mechanism")
rt.wire("audit")
bus.start()
rt.start(["mechanism", "audit"])
mech_svc = rt.get("mechanism")
assert mech_svc is not None
mech_svc.handle(
Event(
event_type="mechanism",
source="test",
payload={"command": "add_seed", "user": "bank", "base_budget": 100000},
)
)
audit_svc = rt.get("audit")
assert audit_svc is not None
state_from_mech = mech_svc.store.get("protocol:state")
state_from_audit = audit_svc.store.get("protocol:state")
assert state_from_mech is not None
assert state_from_audit is not None
assert state_from_mech == state_from_audit
rt.stop()