nx_bench_companion_test.nx source
↩ module page · 150 lines · 6357 B
1// nx_bench_companion_test.nx -- smoke for the bench-capture primitive.
2//
3// Drives a small parallel-companion session through known operations,
4// captures the report, and asserts every substrate counter has the
5// exact value the operations should have produced. Substrate-honest:
6// every assertion compares against a counter the operations actually
7// drove, not an aspirational target.
8
9import "nx_syscalls.nx"
10import "nx_tier.nx"
11import "nx_actor.nx"
12import "nx_message.nx"
13import "nx_resource_arbiter.nx"
14import "nx_interrupt_broker.nx"
15import "nx_session.nx"
16import "nx_bench_companion.nx"
17
18func main() -> i64 {
19 let now: nx_size = 1000000
20
21 // 1: verdict enum
22 if nx_bc_v_is_valid(NX_BC_V_OK) != 1 { return 1 }
23 if nx_bc_v_is_valid(NX_BC_V_INVALID) != 1 { return 2 }
24 if nx_bc_v_is_valid(NX_BC_V_N) != 0 { return 3 }
25 if nx_bc_v_is_valid(-1) != 0 { return 4 }
26
27 // 2: empty report after construction
28 let r: *NxBenchReport = nx_bc_report_new()
29 if (r as i64) == 0 { return 5 }
30 if r.n_actors != 0 { return 6 }
31 if r.verdict != NX_BC_V_OK { return 7 }
32 if nx_bc_report_verdict(r) != NX_BC_V_OK { return 8 }
33
34 // 3: build a session + drive known operations
35 let s: *NxSession = nx_session_new_default(now)
36 if nx_session_is_ready(s) != 1 { return 9 }
37
38 // Spawn 3 actors
39 nx_session_spawn_actor(s, 101, 1, 80, 0, now)
40 nx_session_spawn_actor(s, 102, 4, 60, 0, now)
41 nx_session_spawn_actor(s, 103, 5, 50, 0, now)
42
43 // Subscribe 102 + 103 to LLM_TOKEN (= 2 subscriptions)
44 nx_session_subscribe(s, 102, NX_MS_KIND_LLM_TOKEN)
45 nx_session_subscribe(s, 103, NX_MS_KIND_LLM_TOKEN)
46
47 // Step actor 101 twice (= 2 steps in scheduler counter)
48 nx_ac_step(s.scheduler, 101, 5000, now + 100)
49 nx_ac_step(s.scheduler, 101, 5000, now + 200)
50
51 // Complete 101 + fail 102 (forces specific final counts)
52 nx_ac_complete(s.scheduler, 101)
53 nx_ac_fail(s.scheduler, 102)
54 // 103 stays in READY (counted as neither completed nor failed)
55
56 // Set up arbiter + grant 1 request fully + deny 1
57 nx_ra_set_budget(s.arbiter, NX_RA_KIND_VRAM_BYTES, 1000)
58 nx_ra_set_max_share(s.arbiter, NX_RA_KIND_VRAM_BYTES, 1024)
59 let out_buf: *u8 = sys_mmap(8)
60 let out_g: *i64 = out_buf as *i64
61 nx_ra_request(s.arbiter, 101, NX_RA_KIND_VRAM_BYTES, 500, 80, 0, out_g, now)
62 // Try a request that would exceed budget -- denial
63 nx_ra_request(s.arbiter, 102, NX_RA_KIND_VRAM_BYTES, 600, 60, 0, out_g, now)
64
65 // File an operator interrupt + arbitrate against a yieldable op
66 nx_ib_file(s.broker, 9001, NX_IB_KIND_OPERATOR_INPUT, NX_IB_DL_REALTIME, 95, 0, now)
67 let op: *NxRunningOp = nx_ib_op_new(101, 50, now, 100000, now + 1000, 1)
68 nx_ib_arbitrate(s.broker, 9001, op, now + 2000)
69
70 // 4: capture session counters into the report
71 if nx_bc_capture(s, r, 11, now + 3000) != NX_BC_V_OK { return 10 }
72
73 // 5: scheduler counters match operations
74 if r.n_actors != 3 { return 11 }
75 if r.actors_completed != 1 { return 12 }
76 if r.actors_failed != 1 { return 13 }
77 // Actor 103 still READY, 101 completed, 102 failed
78 if r.actors_running != 0 { return 14 }
79 if r.actors_waiting != 0 { return 15 }
80 if r.total_actor_steps != 2 { return 16 }
81 if r.cumulative_runtime_us != 10000 { return 17 } // 2 steps * 5000us
82 if r.epoch_count != 0 { return 18 }
83 if nx_bc_report_actors_completed(r) != 1 { return 19 }
84 if nx_bc_report_total_steps(r) != 2 { return 20 }
85
86 // 6: bus counters -- 2 subscriptions to LLM_TOKEN
87 if r.n_subscriptions != 2 { return 21 }
88
89 // 7: multiplexer empty (we never pushed)
90 if r.mux_pending != 0 { return 22 }
91
92 // 8: arbiter counters -- 1 grant_full (101 got 500/500) + 1 grant_partial
93 // (102 requested 600 but free_pool was 500 -> partial grant of 500).
94 // nx_ra_request grants what it can when free_pool < requested, rather
95 // than denying outright; that's the cooperative arbitration discipline.
96 if r.arb_grants_full != 1 { return 23 }
97 if r.arb_grants_partial != 1 { return 24 }
98 if r.arb_denials != 0 { return 25 }
99 if r.arb_preemptions != 0 { return 26 }
100
101 // 9: broker counters -- 1 grant (operator input on yieldable op)
102 if r.broker_grants != 1 { return 27 }
103 if r.broker_refusals != 0 { return 28 }
104 if r.broker_deadline_misses != 0 { return 29 }
105
106 // 10: captured_at_us recorded
107 if r.captured_at_us != (now + 3000) { return 30 }
108 if r.verdict != NX_BC_V_OK { return 31 }
109
110 // 11: capture into null report rejected cleanly
111 let null_r: *NxBenchReport = (0 as i64) as *NxBenchReport
112 if nx_bc_capture(s, null_r, 11, now) != NX_BC_V_NULL_REPORT { return 32 }
113
114 // 12: capture from null session rejected
115 let null_s: *NxSession = (0 as i64) as *NxSession
116 if nx_bc_capture(null_s, r, 11, now) != NX_BC_V_NULL_SESSION { return 33 }
117
118 // 13: capture from a not-ready session rejected
119 let bad_s: *NxSession = nx_session_new(0, 1, 1, 1, 1, 1, 1, 1000000, 1, 50000, now)
120 if nx_bc_capture(bad_s, r, 11, now) != NX_BC_V_SESSION_NOT_READY { return 34 }
121
122 // 14: capture with negative subscription-kinds-to-count rejected
123 if nx_bc_capture(s, r, -1, now) != NX_BC_V_INVALID { return 35 }
124
125 // 15: paired-diff -- capture again after spawning 1 more actor
126 let r2: *NxBenchReport = nx_bc_report_new()
127 nx_session_spawn_actor(s, 104, 5, 40, 0, now)
128 nx_ac_step(s.scheduler, 103, 3000, now + 4000)
129 nx_bc_capture(s, r2, 11, now + 5000)
130
131 let diff: *NxBenchReport = nx_bc_report_new()
132 if nx_bc_diff(r, r2, diff) != NX_BC_V_OK { return 36 }
133 // 1 new actor, 1 new step, +3000 runtime
134 if diff.n_actors != 1 { return 37 }
135 if diff.total_actor_steps != 1 { return 38 }
136 if diff.cumulative_runtime_us != 3000 { return 39 }
137 if diff.captured_at_us != 2000 { return 40 } // 5000 - 3000
138
139 // 16: diff null guards
140 if nx_bc_diff(null_r, r2, diff) != NX_BC_V_NULL_REPORT { return 41 }
141 if nx_bc_diff(r, null_r, diff) != NX_BC_V_NULL_REPORT { return 42 }
142 if nx_bc_diff(r, r2, null_r) != NX_BC_V_NULL_REPORT { return 43 }
143
144 // 17: accessor null guards
145 if nx_bc_report_verdict(null_r) != NX_BC_V_NULL_REPORT { return 44 }
146 if nx_bc_report_actors_completed(null_r) != 0 { return 45 }
147 if nx_bc_report_total_steps(null_r) != 0 { return 46 }
148
149 return 0
150}