Files

57 lines
4.5 KiB
JavaScript
Raw Permalink Normal View History

// Compile the real endpoint with the exact ESP-IDF cJSON implementation on a host.
const fs = require('node:fs'), path = require('node:path');
const src=fs.readFileSync(path.join(__dirname,'../main/ble_setup.c'),'utf8');
const jsonDir=path.join(process.env.IDF_PATH||'E:/Codex/toolchains/esp-idf-v5.5.1','components/json/cJSON');
const jsonHeader=fs.readFileSync(path.join(jsonDir,'cJSON.h'),'utf8');
const jsonSource=fs.readFileSync(path.join(jsonDir,'cJSON.c'),'utf8').replace('#include "cJSON.h"','');
const globals=src.slice(src.indexOf('typedef struct { uint32_t version;'),src.indexOf('static void show('));
const endpoint=src.slice(src.indexOf('static bool valid_password('),src.indexOf('static void terminate_link('));
process.stdout.write(jsonHeader+'\n'+jsonSource+`
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
typedef int esp_err_t;
#define ESP_OK 0
#define ESP_ERR_INVALID_ARG 1
#define ESP_ERR_NO_MEM 2
#define portMAX_DELAY 0
static int state_mutex;
static int64_t now=1,window_end=300000000;
static int64_t esp_timer_get_time(void){return now;}
static void xSemaphoreTake(int m,int t){(void)m;(void)t;}
static void xSemaphoreGive(int m){(void)m;}
static void mbedtls_platform_zeroize(void *p,size_t n){memset(p,0,n);}
static void show(const char *s){(void)s;}
static const char *ble_factory_id(void){return "KP01-B43A451634A8";}
static const char *ble_factory_model(void){return "ECHOEAR-S3";}
`+globals+endpoint+`
static cJSON *run(const char *text){uint8_t *out=NULL;ssize_t len=0;assert(endpoint(0,(uint8_t*)text,strlen(text),&out,&len,NULL)==ESP_OK);assert(out&&len==(ssize_t)strlen((char*)out));cJSON *j=cJSON_Parse((char*)out);free(out);return j;}
static void status_is(const char *request,const char *expected){cJSON *r=run(request);assert(!strcmp(json_string(r,"status"),expected));cJSON_Delete(r);}
int main(void){
const char *wifi="{\\"cmd\\":\\"configure\\",\\"wifi_ssid\\":\\"Home\\",\\"wifi_password\\":\\"TestOnly123\\",\\"bind_token\\":\\"\\"}";
cJSON *r=run("{\\"cmd\\":\\"get_info\\"}");assert(cJSON_GetObjectItem(r,"protocol_version")->valueint==2);assert(!strcmp(json_string(r,"device_id"),ble_factory_id()));cJSON_Delete(r);
status_is("{\\"cmd\\":\\"get_status\\"}","idle");
status_is(wifi,"received");assert(job.version==2&&job.token[0]==0);int64_t deadline=confirm_until;
status_is(wifi,"received");assert(confirm_until==deadline);
status_is("{\\"cmd\\":\\"configure\\",\\"wifi_ssid\\":\\"Other\\",\\"wifi_password\\":\\"TestOnly123\\",\\"bind_token\\":\\"\\"}","failed");assert(!strcmp(job.ssid,"Home"));
now=confirm_until;status_is("{\\"cmd\\":\\"get_status\\"}","failed");
status_is(wifi,"received");state=SUCCESS;status_is(wifi,"success");state=FAILED;
status_is("{\\"cmd\\":\\"configure\\",\\"wifi_ssid\\":\\"Home\\",\\"wifi_password\\":\\"TestOnly123\\",\\"bind_token\\":\\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\"}","received");assert(strlen(job.token)==43);
status_is(wifi,"failed");assert(strlen(job.token)==43);state=FAILED;
status_is("{\\"cmd\\":\\"configure\\",\\"wifi_ssid\\":\\"Home\\",\\"wifi_password\\":\\"short\\",\\"bind_token\\":\\"\\"}","failed");
status_is("{\\"cmd\\":\\"configure\\",\\"wifi_ssid\\":\\"Home\\",\\"wifi_password\\":\\"TestOnly123\\",\\"bind_token\\":\\"short\\"}","failed");
const char *bad[]={"{\\"cmd\\":\\"get_info\\",\\"cmd\\":\\"get_info\\"}","{\\"cmd\\":\\"get_info\\",\\"extra\\":\\"x\\"}","{\\"cmd\\":\\"get_info\\"}{}","{\\"cmd\\":\\"unknown\\"}"};
for(size_t i=0;i<sizeof(bad)/sizeof(bad[0]);i++){uint8_t *out=NULL;ssize_t len=0;assert(endpoint(0,(uint8_t*)bad[i],strlen(bad[i]),&out,&len,NULL)==ESP_ERR_INVALID_ARG);}
state=FAILED;
const char *reset="{\\\"cmd\\\":\\\"factory_reset\\\",\\\"wifi_ssid\\\":\\\"Home\\\",\\\"wifi_password\\\":\\\"TestOnly123\\\",\\\"bind_token\\\":\\\"\\\"}";
status_is(reset,"received");assert(job.version==3&&job.press[0]==0&&job.token[0]==0);
status_is(reset,"received");status_is(wifi,"failed");assert(job.version==3);
r=run("{\\\"cmd\\\":\\\"get_info\\\"}");assert(cJSON_IsTrue(cJSON_GetObjectItem(r,"factory_reset_supported")));cJSON_Delete(r);
state=FAILED;
status_is("{\\\"cmd\\\":\\\"factory_reset\\\",\\\"wifi_ssid\\\":\\\"Home\\\",\\\"wifi_password\\\":\\\"TestOnly123\\\",\\\"bind_token\\\":\\\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\"}","failed");
now=window_end;status_is(wifi,"failed");status_is(reset,"failed");
puts("PASS: plaintext C endpoint: info, bind/WiFi-only, idempotency, conflict, retries, timeout, malformed input");return 0;
}
`.replace(/\\\\"/g,'\\"'));