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

76 lines
5.4 KiB
JavaScript
Raw Normal View History

// Execute the actual reset implementation with cloud/NVS fault injection.
const fs=require('fs'),path=require('path');
const root=path.resolve(__dirname,'..'),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_reset.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"','')+`
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef int esp_err_t;
typedef int 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_ARG 3
#define ESP_ERR_INVALID_RESPONSE 4
#define ESP_ERR_NO_MEM 5
#define ESP_ERR_INVALID_SIZE 6
#define NVS_READONLY 0
#define NVS_READWRITE 1
static const char *spaces[]={"factory_reset","voice","platform","control","ble_setup","wifi"};
static unsigned char durable[1024],staged[1024];static size_t durable_len,staged_len;
static int erased,posts,deny_state,deny_reset,bad_response,fail_phase,fail_clear,fail_save_once;
static char first_body[512];
static void mbedtls_platform_zeroize(void *p,size_t n){memset(p,0,n);}
static bool ble_cloud_configured(void){return true;}
static int ble_cloud_sync_time(void){return 0;}
static const char *device_ota_version(void){return "1.7.0-controls.test";}
static int nvs_open(const char *space,int mode,int *n){for(int i=0;i<6;i++)if(!strcmp(space,spaces[i])){*n=i;return 0;}assert(!"forbidden namespace");return -1;}
static void nvs_close(int n){}
static int nvs_set_blob(int n,const char *key,const void *v,size_t size){assert(n==0&&!strcmp(key,"record")&&size<=sizeof(staged));memcpy(staged,v,size);staged_len=size;return 0;}
static int nvs_get_blob(int n,const char *key,void *v,size_t *size){assert(n==0&&!strcmp(key,"record"));if(!durable_len)return ESP_ERR_NVS_NOT_FOUND;assert(*size>=durable_len);memcpy(v,durable,durable_len);*size=durable_len;return 0;}
static int nvs_commit(int n){
if(n==0){uint32_t phase=0;memcpy(&phase,staged+4,4);if(fail_save_once&&phase==(unsigned)fail_phase){fail_save_once=0;return -1;}memcpy(durable,staged,staged_len);durable_len=staged_len;}
return 0;
}
static int nvs_erase_all(int n){assert(n==1||n==4||n==5);if(fail_clear==n)return -1;erased|=1<<n;return 0;}
static int nvs_erase_key(int n,const char *key){assert(n==2||n==3);assert(strcmp(key,"device_id")&&strcmp(key,"device_secret")&&strcmp(key,"ota")&&strcmp(key,"installed"));if(fail_clear==n)return -1;erased|=1<<n;return 0;}
static int platform_request(const char *method,const char *path,const char *body,const char *id,char **raw){
assert(!strcmp(method,"POST"));*raw=NULL;
if(!strcmp(path,"/api/v1/device/factory-reset/state")){if(deny_state)return ESP_ERR_INVALID_RESPONSE;*raw=strdup("{\\"ok\\":true,\\"data\\":{\\"reset_counter\\":0}}");return 0;}
assert(!strcmp(path,"/api/v1/device/factory-reset"));posts++;
if(first_body[0])assert(!strcmp(first_body,body));else strcpy(first_body,body);
if(deny_reset)return ESP_FAIL;
cJSON *request=cJSON_Parse(body);assert(request);
const char *rid=cJSON_GetObjectItem(request,"reset_id")->valuestring;
char response[1024];snprintf(response,sizeof(response),"{\\"ok\\":true,\\"data\\":{\\"reset_id\\":\\"%s\\",\\"reset_counter\\":%d,\\"activation_state\\":\\"CLAIMABLE\\",\\"license_action\\":\\"RETAINED\\",\\"local_actions\\":[\\"clear_volc_credential\\",\\"clear_user_context\\",\\"clear_session_state\\",\\"clear_network_credentials\\",\\"reboot_to_claimable\\"]}}",rid,bad_response?2:1);
*raw=strdup(response);cJSON_Delete(request);return 0;
}
`+source+`
static const char *rid="40000000-0000-4000-8000-000000000001";
static void fresh(void){memset(durable,0,sizeof(durable));memset(staged,0,sizeof(staged));durable_len=staged_len=0;erased=posts=deny_state=deny_reset=bad_response=fail_phase=fail_clear=fail_save_once=0;first_body[0]=0;}
static int phase(void){reset_record_t r;assert(load(&r)==0);return r.phase;}
int main(void){
fresh();assert(device_reset_boot_cleanup()==0&&erased==0);
deny_state=1;assert(device_reset_from_setup(rid)!=0&&erased==0&&posts==0&&phase()==0);
fresh();deny_reset=1;assert(device_reset_from_setup(rid)!=0&&erased==0&&phase()==1);assert(device_reset_boot_cleanup()==0&&erased==0);
deny_reset=0;assert(device_reset_from_setup(rid)==0&&phase()==3&&erased==62&&posts==2);
assert(device_reset_from_setup(rid)==0&&posts==2); // Lost BLE acknowledgement.
fresh();bad_response=1;assert(device_reset_from_setup(rid)!=0&&erased==0&&phase()==1);
fresh();fail_phase=1;fail_save_once=1;assert(device_reset_from_setup(rid)!=0&&erased==0&&posts==0);
fresh();fail_phase=2;fail_save_once=1;assert(device_reset_from_setup(rid)!=0&&erased==0&&phase()==1);
assert(device_reset_from_setup(rid)==0&&phase()==3&&posts==2);
fresh();fail_clear=5;assert(device_reset_from_setup(rid)!=0&&phase()==2&&erased==30); // Cut before Wi-Fi cleanup.
fail_clear=0;assert(device_reset_boot_cleanup()==0&&phase()==3&&erased==62&&posts==1);
fresh();fail_phase=3;fail_save_once=1;assert(device_reset_from_setup(rid)!=0&&phase()==2&&erased==62);
assert(device_reset_boot_cleanup()==0&&phase()==3&&posts==1);
fresh();durable_len=5;assert(device_reset_boot_cleanup()!=0&&erased==0);
puts("PASS production reset: authorization, exact replay, durable approval, interrupted cleanup, preserved identity/OTA");
}
`);