code wiki / (root) / nx_iot_scene_sync_test.nx

nx_iot_scene_sync_test.nx source

↩ module page · 119 lines · 6665 B

1// nx_iot_scene_sync_test.nx -- gate for the lights-stay-in-sync organ. 2// 3// Proves the operator's "repeatable self-fixing" sync as PURE LOGIC: 4// - sealed-enum validity 5// - init + set_scene establishes a single source of truth (epoch bumps) 6// - new devices start OUT of sync; resync_all converges the whole fleet 7// - all_in_sync flips correctly; count_desynced is exact 8// - DROP+HEAL: a device marked desynced is out of sync, then resync pulls 9// it back -- and REPEATING the drop+heal re-fixes it every time 10// - MEASURED syncs_restored / desyncs_seen grow with each cycle 11// - a SCENE CHANGE knocks the whole fleet out of sync (new epoch) until 12// re-applied -- the room re-syncs as one 13// - idempotent add (#10); not-found / bad-arg guards 14// 15// expect_exit: 0 16// 17// license_tier: ORIGINAL 18 19import "nx_syscalls_x86_64.nx" 20import "nx_iot_scene_sync.nx" 21 22func main() -> i64 { 23 // ---- sealed-enum validity -------------------------------------- 24 if nx_iot_sync_verdict_is_valid(NX_IOT_SYNC_OK) != 1 { return 1 } 25 if nx_iot_sync_verdict_is_valid(NX_IOT_SYNC_NEEDS_RESYNC) != 1 { return 2 } 26 if nx_iot_sync_verdict_is_valid(NX_IOT_SYNC_N) != 0 { return 3 } 27 if nx_iot_sync_verdict_is_valid(-1) != 0 { return 4 } 28 29 let reg: *IotSceneReg = sys_mmap(128) as *IotSceneReg 30 let devs: *i64 = sys_mmap(256) as *i64 // 16 device slots * 2 i64 31 32 // ---- init ------------------------------------------------------ 33 if nx_iot_scene_init(reg, 8) != NX_IOT_SYNC_OK { return 10 } 34 if nx_iot_scene_epoch(reg) != 0 { return 11 } 35 if nx_iot_scene_count(reg) != 0 { return 12 } 36 if nx_iot_scene_all_in_sync(reg, devs) != 1 { return 13 } // empty = vacuously synced 37 if nx_iot_scene_init(0 as *IotSceneReg, 8) != NX_IOT_SYNC_BAD_ARG { return 14 } 38 39 // ---- set the desired scene (warm white, 70%) -> epoch 1 -------- 40 if nx_iot_scene_set(reg, 1, 70, 30, 80, 2700) != NX_IOT_SYNC_OK { return 20 } 41 if nx_iot_scene_epoch(reg) != 1 { return 21 } 42 if nx_iot_scene_get_brightness(reg) != 70 { return 22 } 43 if nx_iot_scene_get_on(reg) != 1 { return 23 } 44 45 // ---- add 3 lights -> all OUT of sync --------------------------- 46 if nx_iot_scene_add_device(reg, devs, 101) != NX_IOT_SYNC_OK { return 30 } 47 if nx_iot_scene_add_device(reg, devs, 102) != NX_IOT_SYNC_OK { return 31 } 48 if nx_iot_scene_add_device(reg, devs, 103) != NX_IOT_SYNC_OK { return 32 } 49 if nx_iot_scene_count(reg) != 3 { return 33 } 50 if nx_iot_scene_add_device(reg, devs, 101) != NX_IOT_SYNC_OK { return 34 } // idempotent 51 if nx_iot_scene_count(reg) != 3 { return 35 } 52 if nx_iot_scene_all_in_sync(reg, devs) != 0 { return 36 } 53 if nx_iot_scene_count_desynced(reg, devs) != 3 { return 37 } 54 if nx_iot_scene_needs_resync(reg, devs, 101) != 1 { return 38 } 55 if nx_iot_scene_in_sync(reg, devs, 101) != 0 { return 39 } 56 57 // ---- converge the whole room -> all in sync -------------------- 58 if nx_iot_scene_resync_all(reg, devs) != 3 { return 40 } // 3 restored 59 if nx_iot_scene_all_in_sync(reg, devs) != 1 { return 41 } 60 if nx_iot_scene_count_desynced(reg, devs) != 0 { return 42 } 61 if nx_iot_scene_syncs_restored(reg) != 3 { return 43 } 62 if nx_iot_scene_in_sync(reg, devs, 102) != 1 { return 44 } 63 64 // ---- THE SELF-FIX: a light drops/blinks + heals -> re-synced --- 65 // device 102 dropped WiFi, re-paired (watchdog+anchor), came back at its 66 // DEFAULT state -> out of sync. The loop pulls it back to the scene. 67 if nx_iot_scene_mark_desynced(reg, devs, 102) != NX_IOT_SYNC_OK { return 50 } 68 if nx_iot_scene_all_in_sync(reg, devs) != 0 { return 51 } 69 if nx_iot_scene_count_desynced(reg, devs) != 1 { return 52 } 70 if nx_iot_scene_needs_resync(reg, devs, 102) != 1 { return 53 } 71 if nx_iot_scene_desyncs_seen(reg) != 1 { return 54 } 72 let r1: i64 = nx_iot_scene_resync(reg, devs, 102) 73 if r1 != 1 { return 55 } // a re-sync happened 74 if nx_iot_scene_all_in_sync(reg, devs) != 1 { return 56 } // back in sync 75 if nx_iot_scene_syncs_restored(reg) != 4 { return 57 } 76 if nx_iot_scene_resync(reg, devs, 102) != 0 { return 58 } // already in sync -> no-op 77 78 // ---- REPEATABLE: 102 blinks again + again, fixed each time ----- 79 nx_iot_scene_mark_desynced(reg, devs, 102) 80 nx_iot_scene_resync(reg, devs, 102) 81 nx_iot_scene_mark_desynced(reg, devs, 102) 82 nx_iot_scene_resync(reg, devs, 102) 83 if nx_iot_scene_all_in_sync(reg, devs) != 1 { return 60 } 84 if nx_iot_scene_desyncs_seen(reg) != 3 { return 61 } // 3 blinks total 85 if nx_iot_scene_syncs_restored(reg) != 6 { return 62 } // 3 + 3 auto re-syncs 86 // a different light drifts too -> still converges 87 nx_iot_scene_mark_desynced(reg, devs, 101) 88 nx_iot_scene_mark_desynced(reg, devs, 103) 89 if nx_iot_scene_count_desynced(reg, devs) != 2 { return 63 } 90 if nx_iot_scene_resync_all(reg, devs) != 2 { return 64 } 91 if nx_iot_scene_all_in_sync(reg, devs) != 1 { return 65 } 92 if nx_iot_scene_syncs_restored(reg) != 8 { return 66 } 93 94 // ---- SCENE CHANGE: new epoch knocks the whole room out of sync - 95 // operator picks a new colour -> every light must re-apply as one. 96 if nx_iot_scene_set(reg, 1, 40, 200, 100, 4000) != NX_IOT_SYNC_OK { return 70 } 97 if nx_iot_scene_epoch(reg) != 2 { return 71 } 98 if nx_iot_scene_get_brightness(reg) != 40 { return 72 } 99 if nx_iot_scene_all_in_sync(reg, devs) != 0 { return 73 } // all behind the new epoch 100 if nx_iot_scene_count_desynced(reg, devs) != 3 { return 74 } 101 if nx_iot_scene_resync_all(reg, devs) != 3 { return 75 } // re-apply to all (atomic via clock master) 102 if nx_iot_scene_all_in_sync(reg, devs) != 1 { return 76 } 103 if nx_iot_scene_syncs_restored(reg) != 11 { return 77 } 104 105 // ---- guards ---------------------------------------------------- 106 if nx_iot_scene_mark_applied(reg, devs, 999) != NX_IOT_SYNC_NOT_FOUND { return 80 } 107 if nx_iot_scene_mark_desynced(reg, devs, 999) != NX_IOT_SYNC_NOT_FOUND { return 81 } 108 if nx_iot_scene_resync(reg, devs, 999) != -1 { return 82 } 109 if nx_iot_scene_in_sync(reg, devs, 999) != 0 { return 83 } 110 // capacity guard (small registry) 111 let reg2: *IotSceneReg = sys_mmap(128) as *IotSceneReg 112 let devs2: *i64 = sys_mmap(64) as *i64 113 if nx_iot_scene_init(reg2, 2) != NX_IOT_SYNC_OK { return 84 } 114 if nx_iot_scene_add_device(reg2, devs2, 1) != NX_IOT_SYNC_OK { return 85 } 115 if nx_iot_scene_add_device(reg2, devs2, 2) != NX_IOT_SYNC_OK { return 86 } 116 if nx_iot_scene_add_device(reg2, devs2, 3) != NX_IOT_SYNC_FULL { return 87 } 117 118 return 0 119}