code wiki / (root) / nx_circadian_test.nx

nx_circadian_test.nx source

↩ module page · 96 lines · 4064 B

1// nx_circadian_test.nx -- smoke for nx_circadian. 2 3import "nx_syscalls.nx" 4import "nx_circadian.nx" 5 6func main() -> i64 { 7 let now: nx_size = 1000000000 // 1000 sec base 8 9 // 1: enum validity 10 if nx_cd_rhythm_is_valid(NX_CD_RHYTHM_SUBSTRATE_HEARTBEAT) != 1 { return 1 } 11 if nx_cd_rhythm_is_valid(NX_CD_RHYTHM_SEASONAL) != 1 { return 2 } 12 if nx_cd_rhythm_is_valid(-1) != 0 { return 3 } 13 if nx_cd_rhythm_is_valid(6) != 0 { return 4 } 14 if NX_CD_RHYTHM_N != 6 { return 5 } 15 16 if nx_cd_drift_is_valid(NX_CD_DRIFT_OK) != 1 { return 6 } 17 if nx_cd_drift_is_valid(NX_CD_DRIFT_MAJOR) != 1 { return 7 } 18 if nx_cd_drift_is_valid(NX_CD_DRIFT_INVALID) != 0 { return 8 } 19 20 if nx_cd_v_is_valid(NX_CD_V_OK) != 1 { return 9 } 21 if nx_cd_v_is_valid(-1) != 0 { return 10 } 22 23 // 2: canonical period 24 if nx_cd_rhythm_canonical_period_ms(NX_CD_RHYTHM_SUBSTRATE_HEARTBEAT) != 30000 { return 11 } 25 if nx_cd_rhythm_canonical_period_ms(NX_CD_RHYTHM_DAILY) != 86400000 { return 12 } 26 if nx_cd_rhythm_canonical_period_ms(NX_CD_RHYTHM_WEEKLY) != 604800000 { return 13 } 27 28 // 3: rhythm construction 29 let c: *NxCircadianRhythm = nx_cd_rhythm_new(NX_CD_RHYTHM_SUBSTRATE_HEARTBEAT, now) 30 if c.rhythm != NX_CD_RHYTHM_SUBSTRATE_HEARTBEAT { return 14 } 31 if c.period_ms != 30000 { return 15 } 32 if c.last_tick_at_us != now { return 16 } 33 if c.tick_count != 0 { return 17 } 34 if c.accumulated_drift_us != 0 { return 18 } 35 36 // 4: invalid rhythm returns null 37 let c_bad: *NxCircadianRhythm = nx_cd_rhythm_new(99, now) 38 if c_bad != (0 as *NxCircadianRhythm) { return 19 } 39 40 // 5: due_for_tick -- false right after creation 41 if nx_cd_due_for_tick(c, now) != 0 { return 20 } 42 43 // 6: due_for_tick -- true after period (30 sec = 30M us) 44 if nx_cd_due_for_tick(c, now + 30000000) != 1 { return 21 } 45 46 // 7: due_for_tick -- false just before period 47 if nx_cd_due_for_tick(c, now + 29000000) != 0 { return 22 } 48 49 // 8: tick within tolerance accumulates small drift 50 let v: nx_int = nx_cd_tick(c, now + 30000000) // exact period 51 if v != NX_CD_V_OK { return 23 } 52 if c.tick_count != 1 { return 24 } 53 if c.accumulated_drift_us != 0 { return 25 } // exact 54 55 // 9: tick with drift 56 let v2: nx_int = nx_cd_tick(c, now + 60000000 + 100000) // +100ms late 57 if v2 != NX_CD_V_OK { return 26 } 58 if c.tick_count != 2 { return 27 } 59 if c.accumulated_drift_us != 100000 { return 28 } // 100ms in us 60 61 // 10: drift classification 62 let d_ok: nx_int = nx_cd_drift_classify(c) 63 // 100ms drift on 30sec period -> 100000us / 30000000us = ~0.33% -> OK 64 if d_ok != NX_CD_DRIFT_OK { return 29 } 65 66 // 11: accumulate more drift -> MINOR 67 nx_cd_tick(c, now + 90000000 + 500000) // +500ms drift accumulated 68 // Total now 600ms = 0.6M us; on 30sec period 30M us 69 // minor threshold = period/100 = 300K us; major = period/10 = 3M us 70 // 600K us > 300K -> MINOR 71 let d_minor: nx_int = nx_cd_drift_classify(c) 72 if d_minor != NX_CD_DRIFT_MINOR { return 30 } 73 74 // 12: re-sync clears drift 75 let r: nx_int = nx_cd_resync(c, now + 200000000) 76 if r != NX_CD_V_OK { return 31 } 77 if c.accumulated_drift_us != 0 { return 32 } 78 let d_post: nx_int = nx_cd_drift_classify(c) 79 if d_post != NX_CD_DRIFT_OK { return 33 } 80 81 // 13: major drift threshold (>10% of period = >3M us) 82 let c2: *NxCircadianRhythm = nx_cd_rhythm_new(NX_CD_RHYTHM_SUBSTRATE_HEARTBEAT, now) 83 // Single tick 35 sec late -> 5 sec drift = 5M us on 30sec period = 16.7% 84 nx_cd_tick(c2, now + 35000000) 85 let d_major: nx_int = nx_cd_drift_classify(c2) 86 if d_major != NX_CD_DRIFT_MAJOR { return 34 } 87 88 // 14: null handling 89 let null_c: *NxCircadianRhythm = (0 as i64) as *NxCircadianRhythm 90 if nx_cd_tick(null_c, now) != NX_CD_V_ERR_NULL_INPUT { return 35 } 91 if nx_cd_drift_classify(null_c) != NX_CD_DRIFT_INVALID { return 36 } 92 if nx_cd_resync(null_c, now) != NX_CD_V_ERR_NULL_INPUT { return 37 } 93 if nx_cd_due_for_tick(null_c, now) != 0 { return 38 } 94 95 return 0 96}