Files
story/firmware/echoear-platform-agent/tests/screen-wake-host.cjs
T

60 lines
4.3 KiB
JavaScript
Raw Normal View History

// Exercise the real durable wake state machine with failed hardware/NVS/replies.
const fs=require('node:fs'), path=require('node:path');
const root=path.resolve(__dirname,'..');
const json=path.join(process.env.IDF_PATH||'E:/Codex/toolchains/esp-idf-v5.5.1','components/json/cJSON');
const source=fs.readFileSync(path.join(root,'main/device_screen_wake.c'),'utf8').replace(/^#include[^\n]*\n/gm,'');
process.stdout.write(fs.readFileSync(path.join(json,'cJSON.h'),'utf8')+'\n'+fs.readFileSync(path.join(json,'cJSON.c'),'utf8').replace('#include "cJSON.h"','')+String.raw`
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdatomic.h>
typedef int esp_err_t,nvs_handle_t;
#define ESP_OK 0
#define ESP_FAIL -1
#define ESP_ERR_NVS_NOT_FOUND 1
#define ESP_ERR_INVALID_STATE 2
#define ESP_ERR_INVALID_RESPONSE 3
#define NVS_READONLY 0
#define NVS_READWRITE 1
static bool standby,storage_fail,power_fail,present,staged_present;
static unsigned calls,commits,nonce;
static unsigned char stored[256],staged[256];
static size_t stored_size,staged_size;
static bool call_client_standby(void){return standby;}
static int device_power_apply(const char *mode,bool held){assert(!strcmp(mode,"active")&&!held);calls++;if(power_fail)return -1;standby=false;return 0;}
static void esp_fill_random(void *out,size_t size){uint32_t *p=out;for(size_t i=0;i<size/4;i++)p[i]=++nonce;}
static int nvs_open(const char *name,int mode,int *n){assert(!strcmp(name,"control"));*n=1;return 0;}
static int nvs_get_blob(int n,const char *key,void *out,size_t *size){if(!present)return ESP_ERR_NVS_NOT_FOUND;assert(*size>=stored_size);memcpy(out,stored,stored_size);*size=stored_size;return 0;}
static int nvs_set_blob(int n,const char *key,const void *data,size_t size){assert(size<sizeof(staged));memcpy(staged,data,size);staged_size=size;staged_present=true;return 0;}
static int nvs_erase_key(int n,const char *key){staged_present=false;return present?0:ESP_ERR_NVS_NOT_FOUND;}
static int nvs_commit(int n){if(storage_fail)return -1;memcpy(stored,staged,staged_size);stored_size=staged_size;present=staged_present;commits++;return 0;}
static void nvs_close(int n){}
`+source+String.raw`
static cJSON *report(void){cJSON *r=cJSON_CreateObject();device_screen_wake_add_report(r);return r;}
static cJSON *receipt(const char *result){cJSON *r=report(),*w=cJSON_GetObjectItem(r,"screen_wake");assert(w);cJSON_AddStringToObject(w,"result",result);return r;}
int main(void){
assert(device_screen_wake_init()==0);
device_screen_wake_request();assert(device_screen_wake_poll(4)==0&&calls==0&&!present);
standby=true;device_screen_wake_request();assert(device_screen_wake_poll(0)==0&&calls==0&&!present);
assert(device_screen_wake_poll(4)==0&&!standby&&present&&calls==1&&commits==1);
char id[37];strcpy(id,pending.id);assert(id[14]=='4'&&id[19]=='8');
device_screen_wake_request();assert(device_screen_wake_poll(4)==0&&!strcmp(id,pending.id)&&commits==1);
cJSON *r=cJSON_CreateObject();assert(device_screen_wake_ack(r)==ESP_ERR_INVALID_RESPONSE);cJSON_Delete(r);
r=receipt("applied");storage_fail=true;assert(device_screen_wake_ack(r)!=0&&present);
storage_fail=false;assert(device_screen_wake_ack(r)==0&&!present);cJSON_Delete(r);
// Failed persistence does not activate the microphone or display.
standby=true;storage_fail=true;device_screen_wake_request();unsigned before=calls;
assert(device_screen_wake_poll(5)!=0&&calls==before&&standby);
storage_fail=false;power_fail=true;assert(device_screen_wake_poll(5)!=0&&present&&standby);
r=report();assert(!cJSON_GetObjectItem(r,"screen_wake"));cJSON_Delete(r);
power_fail=false;assert(device_screen_wake_poll(5)==0&&!standby);strcpy(id,pending.id);
// An offline wake survives reboot, and its original revision/ID is retained.
standby=true;assert(device_screen_wake_init()==0);assert(device_screen_wake_poll(0)==0&&!standby&&!strcmp(id,pending.id)&&pending.revision==5);
r=receipt("superseded");assert(device_screen_wake_ack(r)==0&&!present);cJSON_Delete(r);
assert(device_screen_wake_poll(8)==0&&!present);
((wake_event_t*)stored)->version=2;present=true;stored_size=sizeof(wake_event_t);
assert(device_screen_wake_init()==ESP_ERR_INVALID_STATE);
puts("PASS screen wake: wake-only tap, startup intent, durable offline/reboot intent, duplicate tap, failed persistence/hardware/ACK, revision-fenced receipts");
}
`);