-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_graph.py
More file actions
183 lines (160 loc) · 6.74 KB
/
Copy pathtest_graph.py
File metadata and controls
183 lines (160 loc) · 6.74 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
"""Tests for GraphService — read-only delegation graph queries.
Tests verify behavior through emitted events only:
- graph_path_result events
- graph_credit_limit_result events
- graph_users_result events
- Edge cases: empty state, unknown users, missing fields
"""
from __future__ import annotations
from typing import Any
from underwrite.__bus__ import LocalBus
from underwrite.__events__ import Event
from underwrite.__store__ import MemoryStore
from underwrite.services.graph.service import GraphService
def graph(store_data: dict[str, Any], bus=None) -> GraphService:
store = MemoryStore()
if store_data:
store.set("protocol:state", store_data)
return GraphService(service_id="graph", store=store, bus=bus)
class TestPathQuery:
def test_path_from_leaf_to_seed(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_path_result", lambda e: received.append(e))
svc = graph(
{
"parent": {"alice": "bank", "bob": "alice"},
"seeds": ["bank"],
},
bus=bus,
)
bus.start()
svc.handle(Event(event_type="graph_path", source="test", payload={"user": "bob"}))
assert received[0].payload["path"] == ["bank", "alice", "bob"]
def test_path_for_seed_itself(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_path_result", lambda e: received.append(e))
svc = graph({"parent": {}, "seeds": ["bank"]}, bus=bus)
bus.start()
svc.handle(Event(event_type="graph_path", source="test", payload={"user": "bank"}))
assert received[0].payload["path"] == ["bank"]
def test_path_for_unknown_user_returns_singleton(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_path_result", lambda e: received.append(e))
svc = graph({"parent": {}, "seeds": ["bank"]}, bus=bus)
bus.start()
svc.handle(Event(event_type="graph_path", source="test", payload={"user": "ghost"}))
assert received[0].payload["path"] == ["ghost"]
def test_path_with_broken_chain(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_path_result", lambda e: received.append(e))
svc = graph(
{
"parent": {"alice": "bank"},
"seeds": ["bank"],
},
bus=bus,
)
bus.start()
svc.handle(Event(event_type="graph_path", source="test", payload={"user": "orphan"}))
assert received[0].payload["path"] == ["orphan"]
def test_empty_state_path(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_path_result", lambda e: received.append(e))
svc = graph({}, bus=bus)
bus.start()
svc.handle(Event(event_type="graph_path", source="test", payload={"user": "x"}))
assert received[0].payload["path"] == ["x"]
class TestCreditLimitQuery:
def test_credit_limit_for_seed(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_credit_limit_result", lambda e: received.append(e))
svc = graph(
{
"seeds": ["bank"],
"base_budget": {"bank": 100000},
"earned": {"bank": 5000},
"parent": {},
"delegation": {},
"children": {},
},
bus=bus,
)
bus.start()
svc.handle(Event(event_type="graph_credit_limit", source="test", payload={"user": "bank"}))
assert received[0].payload["credit_limit"] == 105000.0
def test_credit_limit_for_user(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_credit_limit_result", lambda e: received.append(e))
svc = graph(
{
"seeds": ["bank"],
"base_budget": {"bank": 100000},
"earned": {"alice": 3000},
"parent": {"alice": "bank"},
"delegation": {"bank->alice": 50000},
"children": {"bank": ["alice"]},
},
bus=bus,
)
bus.start()
svc.handle(Event(event_type="graph_credit_limit", source="test", payload={"user": "alice"}))
assert received[0].payload["credit_limit"] == 53000.0
def test_credit_limit_with_outgoing_delegation(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_credit_limit_result", lambda e: received.append(e))
svc = graph(
{
"seeds": ["bank"],
"base_budget": {"bank": 100000},
"earned": {"bank": 0},
"parent": {},
"delegation": {"bank->alice": 30000},
"children": {"bank": ["alice"]},
},
bus=bus,
)
bus.start()
svc.handle(Event(event_type="graph_credit_limit", source="test", payload={"user": "bank"}))
assert received[0].payload["credit_limit"] == 70000.0
def test_empty_state_returns_zero(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_credit_limit_result", lambda e: received.append(e))
svc = graph({}, bus=bus)
bus.start()
svc.handle(Event(event_type="graph_credit_limit", source="test", payload={"user": "x"}))
assert received[0].payload["credit_limit"] == 0.0
class TestUsersQuery:
def test_returns_sorted_users(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_users_result", lambda e: received.append(e))
svc = graph({"earned": {"bank": 0, "alice": 0, "bob": 0}}, bus=bus)
bus.start()
svc.handle(Event(event_type="graph_users", source="test", payload={}))
assert received[0].payload["users"] == ["alice", "bank", "bob"]
def test_empty_state_returns_empty_list(self) -> None:
bus = LocalBus()
received: list[Event] = []
bus.subscribe("graph_users_result", lambda e: received.append(e))
svc = graph({}, bus=bus)
bus.start()
svc.handle(Event(event_type="graph_users", source="test", payload={}))
assert received[0].payload["users"] == []
class TestEdgeCases:
def test_ignores_unknown_event_type(self) -> None:
svc = graph({})
svc.handle(Event(event_type="unrelated", source="test", payload={}))
assert svc.is_running is False
def test_handles_none_store(self) -> None:
svc = GraphService(service_id="graph", store=MemoryStore())
svc.handle(Event(event_type="graph_users", source="test", payload={}))
assert svc.is_running is False