Files
story/firmware/echoear-platform-agent/tests/network-reconnect-host.c
T
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

170 lines
11 KiB
C

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
typedef int esp_err_t;
#define ESP_OK 0
#define ESP_FAIL 1
#define ESP_ERR_NO_MEM 2
#define BIT0 1
#define BIT1 2
#define BIT2 4
#define pdFALSE 0
#define pdMS_TO_TICKS(x) (x)
#define MALLOC_CAP_INTERNAL 1
#define ESP_EVENT_ANY_ID (-1)
#define WIFI_EVENT 1
#define IP_EVENT 2
#define WIFI_EVENT_STA_START 1
#define WIFI_EVENT_STA_DISCONNECTED 2
#define WIFI_EVENT_STA_STOP 3
#define IP_EVENT_STA_GOT_IP 1
#define WIFI_MODE_STA 1
#define WIFI_STORAGE_RAM 1
#define WIFI_IF_STA 0
#define WIFI_ALL_CHANNEL_SCAN 1
#define WIFI_CONNECT_AP_BY_SIGNAL 1
#define WIFI_AUTH_OPEN 0
#define WIFI_PS_NONE 0
#define NVS_READONLY 0
#define NVS_READWRITE 1
#define ESP_ERROR_CHECK(x) assert((x)==ESP_OK)
#define bzero(p,n) memset(p,0,n)
typedef unsigned EventBits_t;
typedef EventBits_t *EventGroupHandle_t;
typedef int esp_event_base_t;
typedef int esp_event_handler_instance_t;
typedef int esp_netif_t;
typedef int nvs_handle_t;
typedef struct { EventGroupHandle_t event_group; char ssid[33],password[64]; int reconnect_count; char ip_address[16]; } network_t;
typedef struct { struct { int ip; } ip_info; } ip_event_got_ip_t;
typedef struct { int8_t rssi; uint8_t primary,bssid[6]; } wifi_ap_record_t;
typedef struct { int static_rx_buf_num,static_tx_buf_num,dynamic_rx_buf_num,cache_tx_buf_num,rx_ba_win; } wifi_init_config_t;
#define WIFI_INIT_CONFIG_DEFAULT() ((wifi_init_config_t){0})
typedef struct { struct { char ssid[32],password[64]; int scan_method,sort_method; struct {int authmode;} threshold; bool bssid_set; uint8_t bssid[6],channel; } sta; } wifi_config_t;
typedef struct { uint8_t *ssid; } wifi_scan_config_t;
typedef struct { bool active; void (*callback)(void *); void *arg; } mock_timer_t;
typedef mock_timer_t *esp_timer_handle_t;
typedef struct { void (*callback)(void *); void *arg; const char *name; } esp_timer_create_args_t;
static EventBits_t event_bits;
static mock_timer_t timer;
static wifi_config_t current_config;
static bool initial_connected,ble_configured,identity_configured,timer_create_failure,commit_failure;
static char saved_ssid[33],saved_password[64];
static uint8_t saved_setup_requested;
static int connect_error,connect_calls,ap_calls,stop_calls,deinit_calls,netif_destroyed,timer_starts;
void handler_event_wifi_st(void *,esp_event_base_t,int32_t,void *);
void handler_event_ip_st(void *,esp_event_base_t,int32_t,void *);
static void mock_log(const char *tag,const char *format,...) {(void)tag;(void)format;}
#define ESP_LOGI(...) mock_log(__VA_ARGS__)
#define ESP_LOGW(...) mock_log(__VA_ARGS__)
#define ESP_LOGE(...) mock_log(__VA_ARGS__)
static const char *esp_err_to_name(int err) {(void)err;return "mock error";}
static unsigned heap_caps_get_free_size(int cap) {(void)cap;return 64000;}
static unsigned heap_caps_get_largest_free_block(int cap) {(void)cap;return 32000;}
static EventGroupHandle_t xEventGroupCreate(void) {event_bits=0;return &event_bits;}
static EventBits_t xEventGroupGetBits(EventGroupHandle_t group) {return *group;}
static EventBits_t xEventGroupSetBits(EventGroupHandle_t group,EventBits_t bits) {return *group|=bits;}
static EventBits_t xEventGroupClearBits(EventGroupHandle_t group,EventBits_t bits) {EventBits_t old=*group;*group&=~bits;return old;}
static EventBits_t xEventGroupWaitBits(EventGroupHandle_t group,EventBits_t bits,int clear,int all,int ticks) {
(void)clear;(void)all;(void)ticks;
if(bits==(BIT0|BIT1)) {
if(initial_connected) {ip_event_got_ip_t e={{1}};handler_event_ip_st(NULL,IP_EVENT,IP_EVENT_STA_GOT_IP,&e);}
else for(int i=0;i<6;i++) handler_event_wifi_st(NULL,WIFI_EVENT,WIFI_EVENT_STA_DISCONNECTED,NULL);
}
return *group;
}
static esp_err_t esp_timer_create(const esp_timer_create_args_t *args,esp_timer_handle_t *out) {
if(timer_create_failure)return ESP_ERR_NO_MEM;
timer.callback=args->callback;timer.arg=args->arg;*out=&timer;return ESP_OK;
}
static esp_err_t esp_timer_start_once(esp_timer_handle_t handle,uint64_t micros) {assert(handle&&!handle->active&&micros==10000000);handle->active=true;timer_starts++;return ESP_OK;}
static esp_err_t esp_timer_stop(esp_timer_handle_t handle) {handle->active=false;return ESP_OK;}
static bool esp_timer_is_active(esp_timer_handle_t handle) {return handle->active;}
static esp_err_t nvs_open(const char *name,int mode,nvs_handle_t *handle) {assert(!strcmp(name,"wifi"));(void)mode;*handle=1;return ESP_OK;}
static esp_err_t nvs_get_u8(nvs_handle_t handle,const char *key,uint8_t *value) {(void)handle;assert(!strcmp(key,"setup_requested"));*value=saved_setup_requested;return ESP_OK;}
static esp_err_t nvs_get_str(nvs_handle_t handle,const char *key,char *value,size_t *len) {(void)handle;const char *s=!strcmp(key,"ssid")?saved_ssid:saved_password;assert(strlen(s)<*len);strcpy(value,s);return ESP_OK;}
static esp_err_t nvs_set_u8(nvs_handle_t handle,const char *key,uint8_t value) {(void)handle;assert(!strcmp(key,"setup_requested"));saved_setup_requested=value;return ESP_OK;}
static esp_err_t nvs_commit(nvs_handle_t handle) {(void)handle;return commit_failure?ESP_FAIL:ESP_OK;}
static void nvs_close(nvs_handle_t handle) {(void)handle;}
static bool platform_identity_is_configured(void) {return identity_configured;}
static bool ble_cloud_configured(void) {return ble_configured;}
static void configure_ap(void) {ap_calls++;}
static esp_err_t esp_netif_init(void) {return ESP_OK;}
static esp_err_t esp_event_handler_instance_register(esp_event_base_t base,int id,void (*cb)(void *,esp_event_base_t,int32_t,void *),void *arg,esp_event_handler_instance_t *instance) {(void)base;(void)id;(void)cb;(void)arg;*instance=1;return ESP_OK;}
static esp_err_t esp_event_handler_instance_unregister(esp_event_base_t base,int id,esp_event_handler_instance_t instance) {(void)base;(void)id;(void)instance;return ESP_OK;}
static esp_netif_t *esp_netif_create_default_wifi_sta(void) {static int station;return &station;}
static void esp_netif_destroy_default_wifi(esp_netif_t *station) {assert(station);netif_destroyed++;}
static esp_err_t esp_wifi_init(wifi_init_config_t *cfg) {assert(cfg->static_rx_buf_num==6&&cfg->static_tx_buf_num==6);return ESP_OK;}
static esp_err_t esp_wifi_set_mode(int mode) {(void)mode;return ESP_OK;}
static esp_err_t esp_wifi_set_storage(int mode) {(void)mode;return ESP_OK;}
static esp_err_t esp_wifi_set_ps(int mode) {(void)mode;return ESP_OK;}
static esp_err_t esp_wifi_set_config(int iface,const wifi_config_t *cfg) {(void)iface;current_config=*cfg;return ESP_OK;}
static esp_err_t esp_wifi_get_config(int iface,wifi_config_t *cfg) {(void)iface;*cfg=current_config;return ESP_OK;}
static esp_err_t esp_wifi_start(void) {handler_event_wifi_st(NULL,WIFI_EVENT,WIFI_EVENT_STA_START,NULL);return ESP_OK;}
static esp_err_t esp_wifi_stop(void) {stop_calls++;return ESP_OK;}
static esp_err_t esp_wifi_deinit(void) {deinit_calls++;return ESP_OK;}
static esp_err_t esp_wifi_connect(void) {connect_calls++;return connect_error;}
static esp_err_t esp_wifi_sta_get_ap_info(wifi_ap_record_t *record) {memset(record,0,sizeof(*record));record->rssi=-42;record->primary=6;return ESP_OK;}
static esp_err_t esp_wifi_scan_start(wifi_scan_config_t *scan,bool block) {(void)scan;(void)block;return ESP_FAIL;}
static esp_err_t esp_wifi_scan_get_ap_records(uint16_t *count,wifi_ap_record_t *records) {(void)records;*count=0;return ESP_OK;}
static void esp_ip4addr_ntoa(const int *address,char *out,size_t len) {(void)address;snprintf(out,len,"192.168.1.2");}
/* PRODUCTION_SOURCE */
static void reset(void) {
memset(&network,0,sizeof(network));memset(&timer,0,sizeof(timer));memset(&current_config,0,sizeof(current_config));
network_error=ESP_OK;reconnect_timer=NULL;reconnect_enabled=false;
event_bits=0;initial_connected=true;ble_configured=true;identity_configured=true;
timer_create_failure=commit_failure=false;saved_setup_requested=0;
strcpy(saved_ssid,"saved-network");strcpy(saved_password,"saved-password");
connect_error=connect_calls=ap_calls=stop_calls=deinit_calls=netif_destroyed=timer_starts=0;
}
static void disconnected(void) {handler_event_wifi_st(NULL,WIFI_EVENT,WIFI_EVENT_STA_DISCONNECTED,NULL);}
static void fire_timer(void) {assert(timer.active);timer.active=false;timer.callback(timer.arg);}
int main(void) {
reset();assert(configure_network());assert(is_connected()&&!ap_calls&&!timer.active);
current_config.sta.bssid_set=true;current_config.sta.channel=6;
int base=connect_calls;
for(int i=0;i<5;i++)disconnected();
assert(connect_calls==base+5&&!is_connected()&&!timer.active);
assert(!current_config.sta.bssid_set&&current_config.sta.channel==0);
disconnected();assert(timer.active&&(event_bits&BIT1)&&!network.ip_address[0]);
for(int i=0;i<20;i++) {fire_timer();disconnected();assert(timer.active);}
assert(connect_calls==base+25); // Recover even after more than 5 attempts.
ip_event_got_ip_t ip={{1}};handler_event_ip_st(NULL,IP_EVENT,IP_EVENT_STA_GOT_IP,&ip);
assert(is_connected()&&!(event_bits&BIT1)&&!timer.active&&network.reconnect_count==0);
base=connect_calls;timer.callback(NULL);assert(connect_calls==base); // Late timer after IP cannot reconnect.
for(int i=0;i<6;i++)disconnected();assert(timer.active);
handler_event_wifi_st(NULL,WIFI_EVENT,WIFI_EVENT_STA_STOP,NULL);
base=connect_calls;disconnected();timer.callback(NULL);
assert(!timer.active&&!reconnect_enabled&&!is_connected()&&connect_calls==base);
reset();assert(configure_network());connect_error=ESP_FAIL;disconnected();assert(timer.active);
fire_timer();assert(timer.active);connect_error=ESP_OK;fire_timer();assert(!timer.active);
reset();initial_connected=false;
assert(!configure_network()&&network_last_error()==ESP_OK);
assert(saved_setup_requested==1&&!ap_calls&&stop_calls==1&&deinit_calls==1&&netif_destroyed==1);
assert(!timer.active&&!reconnect_enabled&&!strcmp(saved_ssid,"saved-network")&&!strcmp(saved_password,"saved-password"));
base=connect_calls;timer.callback(NULL);assert(connect_calls==base); // No driver call after teardown.
reset();initial_connected=false;ble_configured=false;
assert(!configure_network()&&ap_calls==1&&saved_setup_requested==0);
reset();initial_connected=false;commit_failure=true;
assert(!configure_network()&&network_last_error()==ESP_FAIL&&!ap_calls);
reset();saved_ssid[0]=0;
assert(!configure_network()&&saved_setup_requested==1&&!ap_calls&&!stop_calls);
reset();timer_create_failure=true;
assert(!configure_network()&&network_last_error()==ESP_ERR_NO_MEM&&!connect_calls&&!ap_calls);
puts("PASS production network: prolonged disconnect, BSSID fallback, delayed retry, IP recovery, stop guards, BLE boot fallback, credentials preserved, commit failure, legacy AP");
return 0;
}