nx_mediapath_test.nx source
↩ module page · 91 lines · 4017 B
1// nx_mediapath_test.nx -- 1:1 KAT for self-healing best-media-path
2// selection (nx_mediapath.nx). Deterministic: build candidate LinkFlows
3// with known quality scores, assert mp_decide's KEEP/SWITCH/GIVEUP +
4// reason for each class (degrade-failover, anti-flap keep, meaningful-
5// better switch, all-poor least-bad, stuck-on-best-poor, no-incumbent).
6//
7// expect_exit: 0
8// license_tier: ORIGINAL
9
10import "nx_mediapath.nx"
11
12// build a flow with a target (srtt, jitter, loss_q16) -> deterministic lq_score.
13func mpt_flow(srtt_ms: i64, jit_ms: i64, loss_q16: i64) -> *LinkFlow {
14 let f: *LinkFlow = lq_flow_new()
15 f.srtt_x8 = srtt_ms << LQ_SRTT_SH
16 f.jitter_x16 = jit_ms << LQ_JIT_SH
17 f.loss_frac_q16 = loss_q16
18 return f
19}
20
21func main() -> i64 {
22 let flows: *i64 = sys_mmap(2 * 8) as *i64
23 let d: *MediaDecision = sys_mmap(MP_DECISION_BYTES) as *MediaDecision
24
25 let poor0: *LinkFlow = mpt_flow(300, 30, 6554) // score 0 (POOR, 10% loss)
26 let poor30: *LinkFlow = mpt_flow(300, 30, 0) // score 30 (POOR)
27 let fair50: *LinkFlow = mpt_flow(200, 5, 0) // score 50 (FAIR)
28 let good75: *LinkFlow = mpt_flow(75, 5, 0) // score 75 (GOOD)
29 let good80: *LinkFlow = mpt_flow(50, 5, 0) // score 80 (EXCELLENT boundary)
30 let exc96: *LinkFlow = mpt_flow(20, 0, 0) // score 96 (EXCELLENT)
31
32 // sanity: scores are what we expect
33 if lq_score(poor0) != 0 { return 90 }
34 if lq_score(poor30) != 30 { return 91 }
35 if lq_score(fair50) != 50 { return 92 }
36 if lq_score(good75) != 75 { return 93 }
37 if lq_score(exc96) != 96 { return 94 }
38
39 // ---- T1: incumbent degraded (POOR) + an EXCELLENT path -> SWITCH (failover) ----
40 flows[0] = poor0 as i64; flows[1] = exc96 as i64
41 mp_decide(flows, 2, 0, d)
42 if d.action != MP_SWITCH { return 1 }
43 if d.target_idx != 1 { return 2 }
44 if d.reason != MP_R_DEGRADED { return 3 }
45
46 // ---- T2: incumbent usable + only marginally-better alt -> KEEP (anti-flap) ----
47 flows[0] = good75 as i64; flows[1] = good80 as i64 // diff 5 < margin 15
48 mp_decide(flows, 2, 0, d)
49 if d.action != MP_KEEP { return 4 }
50 if d.target_idx != 0 { return 5 }
51 if d.reason != MP_R_HEALTHY { return 6 }
52
53 // ---- T3: incumbent usable + a MEANINGFULLY better path -> SWITCH (better) ----
54 flows[0] = fair50 as i64; flows[1] = exc96 as i64 // diff 46 >= margin
55 mp_decide(flows, 2, 0, d)
56 if d.action != MP_SWITCH { return 7 }
57 if d.target_idx != 1 { return 8 }
58 if d.reason != MP_R_BETTER { return 9 }
59
60 // ---- T4: all paths poor, incumbent the worst -> SWITCH to least-bad ----
61 flows[0] = poor0 as i64; flows[1] = poor30 as i64
62 mp_decide(flows, 2, 0, d)
63 if d.action != MP_SWITCH { return 10 }
64 if d.target_idx != 1 { return 11 }
65 if d.reason != MP_R_DEGRADED { return 12 }
66
67 // ---- T5: all poor, incumbent IS the least-bad -> KEEP, flag no-good-path ----
68 flows[0] = poor30 as i64; flows[1] = poor0 as i64
69 mp_decide(flows, 2, 0, d)
70 if d.action != MP_KEEP { return 13 }
71 if d.target_idx != 0 { return 14 }
72 if d.reason != MP_R_NONE { return 15 }
73
74 // ---- T6: no incumbent set -> adopt the best ----
75 flows[0] = fair50 as i64; flows[1] = exc96 as i64
76 mp_decide(flows, 2, 0 - 1, d)
77 if d.action != MP_SWITCH { return 16 }
78 if d.target_idx != 1 { return 17 }
79
80 sys_write(1, "T1-T6 best-media-path decisions OK (degrade-failover, anti-flap, better, least-bad, stuck, no-incumbent)\n", 104)
81
82 // ---- render the easy-for-anyone media-path actions ----
83 sys_write(1, "\n=== rendered ===\n", 18)
84 flows[0] = poor0 as i64; flows[1] = exc96 as i64
85 mp_decide(flows, 2, 0, d); mp_render(d) // degrade -> switch
86 flows[0] = good75 as i64; flows[1] = good80 as i64
87 mp_decide(flows, 2, 0, d); mp_render(d) // healthy -> keep
88
89 sys_write(1, "\nMEDIAPATH KAT PASS (quality-ranked self-healing path selection unifies link-quality + self-heal)\n", 98)
90 return 0
91}