Files

170 lines
11 KiB
C
Raw Permalink Normal View History

#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;
}