Files
story/firmware/echoear-platform-agent/tests/device-restart-host.cjs
T

49 lines
3.0 KiB
JavaScript
Raw Normal View History

// 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 <assert.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <setjmp.h>
#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;
}
`);