// Exercise the production reboot command with persisted-receipt and MQTT spies. const fs=require('fs'),path=require('path'); const source=fs.readFileSync(path.join(__dirname,'../main/device_control.c'),'utf8'); const json=path.join(process.env.IDF_PATH||'E:/Codex/toolchains/esp-idf-v5.5.1','components/json/cJSON'); const command=source.slice(source.indexOf('static void command('),source.indexOf('void device_control_prepare_restart(')); const shutdown=source.slice(source.indexOf('void device_control_prepare_restart('),source.indexOf('void device_control_heartbeat(')); process.stdout.write(fs.readFileSync(path.join(json,'cJSON.h'),'utf8')+'\n'+fs.readFileSync(path.join(json,'cJSON.c'),'utf8').replace('#include "cJSON.h"','')+` #include #include #include #include #define ESP_OK 0 #define ESP_LOGW(...) ((void)0) #define pdMS_TO_TICKS(x) (x) typedef int esp_err_t; static void *mqtt; static atomic_bool connected,stopping; static int busy,ack_failure,persist_failure,stop_failure,acknowledged,persisted,stopped,restarted,left; static jmp_buf restart_jump; static bool call_client_enter_maintenance(void){return !busy;} static void call_client_leave_maintenance(void){left++;} static const char *text(const cJSON *j,const char *k){const cJSON *v=cJSON_GetObjectItemCaseSensitive(j,k);return cJSON_IsString(v)?v->valuestring:"";} static int ack(const char *id,const char *status,cJSON *result,bool reboot){ if(!strcmp(status,"ACKNOWLEDGED")){acknowledged++;return ack_failure;} if(reboot){assert(!strcmp(status,"SUCCEEDED"));if(persist_failure)return -1;persisted++;return 0;} assert(strcmp(status,"SUCCEEDED"));return 0; } static int esp_mqtt_client_stop(void *client){assert(persisted);assert(!atomic_load(&connected)&&atomic_load(&stopping));stopped++;return stop_failure;} static void vTaskDelay(int ticks){assert(ticks==100);} static void esp_restart(void){assert(persisted&&atomic_load(&stopping));if(mqtt)assert(stopped==1);restarted++;longjmp(restart_jump,1);} static cJSON *diagnostics(void){return NULL;} static int apply_config(const cJSON *j,bool held){return -1;} `+shutdown+command+` static void run(void){ cJSON *j=cJSON_Parse("{\\"id\\":\\"40000000-0000-4000-8000-000000000001\\",\\"type\\":\\"reboot\\"}"); if(!setjmp(restart_jump))command(j,NULL);cJSON_Delete(j); } static void reset(void){mqtt=(void*)1;connected=true;stopping=false;busy=ack_failure=persist_failure=stop_failure=acknowledged=persisted=stopped=restarted=left=0;} int main(void){ reset();run();assert(acknowledged==1&&persisted==1&&stopped==1&&restarted==1&&!left); reset();busy=1;run();assert(!acknowledged&&!stopped&&!restarted); reset();ack_failure=-1;run();assert(!persisted&&!stopped&&!restarted&&left==1); reset();persist_failure=-1;run();assert(!persisted&&!stopped&&!restarted&&left==1); reset();mqtt=NULL;run();assert(restarted==1&&!stopped); reset();stop_failure=-1;run();assert(restarted==1&&stopped==1); puts("PASS production reboot: persist before disconnect, busy/ACK/storage guards, MQTT stop failure");return 0; } `);