Skip to content

Commit 1ded4d2

Browse files
thomas-manginclaude
andcommitted
test: promote subsystem-list functional test from WIP
Activate the subsystem-list.ci test that exercises the ze-system:subsystem-list RPC, verifying it returns structured per-plugin data (name, stage, running, command-count) rather than a hardcoded stub. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a9ab55b commit 1ded4d2

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

test/plugin/subsystem-list.ci

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Test: subsystem-list returns real plugin data (not hardcoded ["bgp"])
2+
# Exercises: dispatch-command -> ze-system:subsystem-list -> handleSystemSubsystemList
3+
# Verifies AC-9: returns JSON array with name, stage, running, command-count per plugin
4+
5+
# ze-peer: accepts connection
6+
stdin=peer:terminator=EOF_PEER
7+
option=tcp_connections:value=1
8+
option=timeout:value=15s
9+
option=asn:value=65001
10+
expect=bgp:conn=1:seq=1:hex=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00170200000000
11+
EOF_PEER
12+
13+
tmpfs=subsystem-list-test.run:mode=755:terminator=EOF_RUN
14+
#!/usr/bin/env python3
15+
import json
16+
import sys
17+
import time
18+
from ze_api import API
19+
20+
def dispatch(api, command):
21+
resp = api._call_engine(
22+
'ze-plugin-engine:dispatch-command', {'command': command})
23+
if resp is None:
24+
return {'status': 'error', 'data': 'engine call returned None'}
25+
return resp.get('result', {})
26+
27+
def main():
28+
api = API()
29+
api.declare_done()
30+
api.wait_for_config()
31+
api.capability_done()
32+
api.wait_for_registry()
33+
api.ready()
34+
time.sleep(1.0)
35+
36+
try:
37+
# Call the wire method directly (system RPCs are not in the CLI tree)
38+
resp = api._call_engine('ze-system:subsystem-list', {})
39+
if resp is None:
40+
print('FAIL: subsystem-list returned None', file=sys.stderr)
41+
sys.exit(1)
42+
result = resp.get('result', {})
43+
status = result.get('status')
44+
if status != 'done':
45+
print(f'FAIL: status={status} data={result.get("data")}', file=sys.stderr)
46+
sys.exit(1)
47+
48+
data = result.get('data', {})
49+
if isinstance(data, str):
50+
data = json.loads(data)
51+
52+
subsystems = data.get('subsystems', [])
53+
count = data.get('count', 0)
54+
55+
if count < 1:
56+
print(f'FAIL: expected at least 1 subsystem, got {count}', file=sys.stderr)
57+
sys.exit(1)
58+
59+
# Verify each entry has the expected fields
60+
for sub in subsystems:
61+
if not isinstance(sub, dict):
62+
print(f'FAIL: subsystem entry is not a dict: {sub}', file=sys.stderr)
63+
sys.exit(1)
64+
for field in ('name', 'stage', 'running', 'command-count'):
65+
if field not in sub:
66+
print(f'FAIL: missing field {field!r} in {sub}', file=sys.stderr)
67+
sys.exit(1)
68+
69+
names = [s['name'] for s in subsystems]
70+
print(f'OK: subsystem-list returned {count} subsystem(s): {names}', file=sys.stderr)
71+
api._call_engine('ze-system:daemon-shutdown', {})
72+
api.wait_for_shutdown()
73+
except SystemExit:
74+
raise
75+
except Exception as e:
76+
print(f'FAIL: unexpected error: {e}', file=sys.stderr)
77+
sys.exit(1)
78+
79+
if __name__ == '__main__':
80+
main()
81+
EOF_RUN
82+
83+
stdin=ze-bgp:terminator=EOF_CONF
84+
plugin {
85+
external subsystem-list-test {
86+
run ./subsystem-list-test.run
87+
encoder json
88+
}
89+
}
90+
91+
bgp {
92+
peer peer1 {
93+
connection {
94+
remote {
95+
ip 127.0.0.1
96+
}
97+
local {
98+
ip 127.0.0.1
99+
accept false
100+
}
101+
}
102+
session {
103+
asn {
104+
local 65000
105+
remote 65001
106+
}
107+
router-id 1.2.3.4
108+
family {
109+
ipv4/unicast {
110+
prefix {
111+
maximum 10000
112+
}
113+
}
114+
}
115+
capability {
116+
graceful-restart disable
117+
}
118+
}
119+
behavior {
120+
group-updates disable
121+
}
122+
123+
process subsystem-list-test {
124+
}
125+
}
126+
}
127+
EOF_CONF
128+
129+
cmd=background:seq=1:exec=ze-peer --port $PORT:stdin=peer
130+
cmd=foreground:seq=2:exec=ze -:stdin=ze-bgp:timeout=15s
131+
expect=exit:code=0

0 commit comments

Comments
 (0)