// Host SDK shim: only SDK calls are mocked; the driver lifecycle under test is // inserted verbatim from main/ble_wifi.c by ble-wifi-host.cjs. #include #include #include #include #include typedef int esp_err_t; #define ESP_OK 0 #define ESP_ERR_NO_MEM 1 #define ESP_ERR_INVALID_STATE 2 #define ESP_ERR_INVALID_ARG 3 #define ESP_ERR_TIMEOUT 4 #define ESP_FAIL 5 #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 IP_EVENT_STA_GOT_IP 1 #define WIFI_EVENT_STA_DISCONNECTED 2 #define WIFI_EVENT_STA_STOP 3 #define WIFI_STORAGE_RAM 1 #define WIFI_MODE_STA 1 #define WIFI_IF_STA 0 #define WIFI_AUTH_WPA2_PSK 3 #define WIFI_ALL_CHANNEL_SCAN 1 #define WIFI_CONNECT_AP_BY_SIGNAL 1 typedef int esp_event_base_t; typedef int *esp_event_handler_instance_t; typedef unsigned EventBits_t; typedef EventBits_t *EventGroupHandle_t; typedef struct { int placeholder; } esp_netif_t; typedef struct { int placeholder; } esp_netif_config_t; #define ESP_NETIF_DEFAULT_WIFI_STA() ((esp_netif_config_t){0}) typedef struct { unsigned reason; } wifi_event_sta_disconnected_t; typedef struct { int static_rx_buf_num, dynamic_rx_buf_num, static_tx_buf_num, cache_tx_buf_num; int ampdu_rx_enable, ampdu_tx_enable, amsdu_tx_enable; } wifi_init_config_t; #define WIFI_INIT_CONFIG_DEFAULT() ((wifi_init_config_t){16,32,16,32,1,1,0}) typedef struct { struct { char ssid[32], password[64]; struct { int authmode; } threshold; int scan_method, sort_method; } sta; } wifi_config_t; 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(esp_err_t err) {(void)err; return "mock";} static unsigned heap_caps_get_free_size(int cap) {(void)cap; return 50000;} static unsigned heap_caps_get_largest_free_block(int cap) {(void)cap; return 30000;} enum point { NONE, GROUP, NEW_NETIF, ATTACH, DEFAULT_HANDLERS, DRIVER, WIFI_HANDLER, IP_HANDLER, STORAGE, MODE, CONFIG, START, CONNECT, STOP, POINTS }; static int calls[POINTS], fail_point, failures, destroys, foreign; static bool should_connect, emit_disconnect, stop_ack; static EventBits_t bits; static esp_netif_t mock_station, other_station; static int handler_handles[2]; static wifi_config_t last_config; static void (*callback)(void *, esp_event_base_t, int32_t, void *); static bool fail(enum point point) { calls[point]++; if (fail_point == (int)point && failures) {failures--; return true;} return false; } static EventGroupHandle_t xEventGroupCreate(void) {return fail(GROUP) ? NULL : &bits;} static EventBits_t xEventGroupGetBits(EventGroupHandle_t e) {assert(e); return *e;} static EventBits_t xEventGroupSetBits(EventGroupHandle_t e, EventBits_t b) {return *e |= b;} static EventBits_t xEventGroupClearBits(EventGroupHandle_t e, EventBits_t b) {EventBits_t old=*e; *e &= ~b; return old;} static EventBits_t xEventGroupWaitBits(EventGroupHandle_t e, EventBits_t b, int clear, int all, int ticks) { (void)b; (void)clear; (void)all; (void)ticks; return *e; } static void vTaskDelay(int ticks) {(void)ticks;} static esp_netif_t *esp_netif_get_handle_from_ifkey(const char *key) { assert(!strcmp(key, "WIFI_STA")); return foreign ? &other_station : NULL; } static esp_netif_t *esp_netif_new(const esp_netif_config_t *c) { (void)c; return fail(NEW_NETIF) ? NULL : &mock_station; } static esp_err_t esp_netif_attach_wifi_station(esp_netif_t *n) {assert(n); return fail(ATTACH) ? ESP_FAIL : ESP_OK;} static esp_err_t esp_wifi_set_default_wifi_sta_handlers(void) {return fail(DEFAULT_HANDLERS) ? ESP_FAIL : ESP_OK;} static void esp_netif_destroy_default_wifi(esp_netif_t *n) {assert(n == &mock_station); destroys++;} static esp_err_t esp_wifi_init(const wifi_init_config_t *c) { assert(c->static_rx_buf_num == 4 && c->static_tx_buf_num == 4); assert(c->dynamic_rx_buf_num >= c->static_rx_buf_num && c->cache_tx_buf_num == 4); assert(!c->ampdu_rx_enable && !c->ampdu_tx_enable && !c->amsdu_tx_enable); return fail(DRIVER) ? ESP_ERR_NO_MEM : 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)id; (void)arg; if (fail(base == WIFI_EVENT ? WIFI_HANDLER : IP_HANDLER)) return ESP_ERR_NO_MEM; callback = cb; *instance = &handler_handles[base == WIFI_EVENT ? 0 : 1]; return ESP_OK; } static esp_err_t esp_wifi_set_storage(int storage) {assert(storage == WIFI_STORAGE_RAM); return fail(STORAGE) ? ESP_FAIL : ESP_OK;} static esp_err_t esp_wifi_set_mode(int mode) {assert(mode == WIFI_MODE_STA); return fail(MODE) ? ESP_FAIL : ESP_OK;} static esp_err_t esp_wifi_set_config(int iface, const wifi_config_t *c) { assert(iface == WIFI_IF_STA); last_config = *c; return fail(CONFIG) ? ESP_FAIL : ESP_OK; } static esp_err_t esp_wifi_start(void) {return fail(START) ? ESP_ERR_NO_MEM : ESP_OK;} static esp_err_t esp_wifi_connect(void) { if (fail(CONNECT)) return ESP_FAIL; if (should_connect) callback(NULL, IP_EVENT, IP_EVENT_STA_GOT_IP, NULL); else if (emit_disconnect) {wifi_event_sta_disconnected_t e = {201}; callback(NULL, WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &e);} return ESP_OK; } static esp_err_t esp_wifi_stop(void) { if (fail(STOP)) return ESP_FAIL; if (stop_ack) callback(NULL, WIFI_EVENT, WIFI_EVENT_STA_STOP, NULL); return ESP_OK; } /* PRODUCTION_SOURCE */ static void reset(void) { station=NULL; events=NULL; wifi_handler=NULL; ip_handler=NULL; driver_ready=false; prepared=false; started=false; stopping=false; memset(calls,0,sizeof(calls)); memset(&last_config,0,sizeof(last_config)); fail_point=NONE; failures=0; destroys=0; foreign=0; bits=0; should_connect=true; emit_disconnect=false; stop_ack=true; callback=NULL; } int main(void) { unsigned tests=0; reset(); assert(!ble_wifi_connected()); assert(ble_wifi_prepare()==ESP_OK && ble_wifi_prepare()==ESP_OK); assert(calls[DRIVER]==1 && calls[NEW_NETIF]==1 && calls[GROUP]==1); assert(calls[START]==0 && calls[CONNECT]==0); tests++; // Every initialization failure is recoverable, without duplicate owners. for (enum point p=GROUP; p<=MODE; ++p) { reset(); fail_point=p; failures=1; assert(ble_wifi_prepare()!=ESP_OK); assert(ble_wifi_prepare()==ESP_OK); assert(ble_wifi_prepare()==ESP_OK); assert(calls[NEW_NETIF] <= ((p==NEW_NETIF || p==ATTACH || p==DEFAULT_HANDLERS) ? 2 : 1)); assert(calls[GROUP] == (p==GROUP ? 2 : 1)); assert(calls[DRIVER] == (p==DRIVER ? 2 : 1)); assert(destroys == (p==ATTACH || p==DEFAULT_HANDLERS ? 1 : 0)); tests++; } reset(); fail_point=DRIVER; failures=10; for (int i=0; i<10; ++i) assert(ble_wifi_prepare()==ESP_ERR_NO_MEM); assert(ble_wifi_prepare()==ESP_OK); assert(calls[NEW_NETIF]==1 && calls[GROUP]==1 && calls[DEFAULT_HANDLERS]==1); tests++; reset(); foreign=1; assert(ble_wifi_prepare()==ESP_ERR_INVALID_STATE); assert(calls[NEW_NETIF]==0 && destroys==0); tests++; reset(); assert(ble_wifi_connect("test-network","test-password")==ESP_OK); assert(ble_wifi_connected()); assert(!strcmp(last_config.sta.ssid,"test-network")); assert(!strcmp(last_config.sta.password,"test-password")); assert(last_config.sta.threshold.authmode==WIFI_AUTH_WPA2_PSK); assert(ble_wifi_connect("new-network","new-password")==ESP_OK); assert(calls[DRIVER]==1 && calls[NEW_NETIF]==1 && calls[STOP]==1); assert(!strcmp(last_config.sta.ssid,"new-network")); tests++; for (enum point p=CONFIG; p<=CONNECT; ++p) { reset(); fail_point=p; failures=3; while(failures) assert(ble_wifi_connect("test-network","test-password")!=ESP_OK); assert(ble_wifi_connect("test-network","test-password")==ESP_OK); assert(calls[DRIVER]==1 && calls[NEW_NETIF]==1 && calls[GROUP]==1); tests++; } for (int disconnect=0; disconnect<2; ++disconnect) { reset(); should_connect=false; emit_disconnect=disconnect; assert(ble_wifi_connect("test-network","test-password")==ESP_ERR_TIMEOUT); assert(!ble_wifi_connected() && calls[START]==3 && calls[STOP]==3); should_connect=true; assert(ble_wifi_connect("test-network","test-password")==ESP_OK); assert(calls[NEW_NETIF]==1 && calls[DRIVER]==1); tests++; } reset(); assert(ble_wifi_connect("test-network","test-password")==ESP_OK); wifi_event_sta_disconnected_t e={201}; callback(NULL,WIFI_EVENT,WIFI_EVENT_STA_DISCONNECTED,&e); assert(!ble_wifi_connected()); tests++; reset(); assert(ble_wifi_connect("test-network","test-password")==ESP_OK); fail_point=STOP; failures=1; assert(ble_wifi_connect("test-network","test-password")==ESP_FAIL); assert(ble_wifi_connect("test-network","test-password")==ESP_OK); assert(calls[DRIVER]==1); tests++; reset(); assert(ble_wifi_connect("test-network","test-password")==ESP_OK); stop_ack=false; assert(ble_wifi_connect("test-network","test-password")==ESP_ERR_TIMEOUT); assert(ble_wifi_connect("test-network","test-password")==ESP_ERR_TIMEOUT); assert(calls[STOP]==1); assert(calls[CONNECT]==1); callback(NULL,WIFI_EVENT,WIFI_EVENT_STA_STOP,NULL); stop_ack=true; assert(ble_wifi_connect("test-network","test-password")==ESP_OK); tests++; reset(); assert(ble_wifi_connect(NULL,"password")==ESP_ERR_INVALID_ARG); assert(ble_wifi_connect("","password")==ESP_ERR_INVALID_ARG); assert(ble_wifi_connect("network",NULL)==ESP_ERR_INVALID_ARG); assert(calls[NEW_NETIF]==0); tests++; printf("PASS: %u Wi-Fi lifecycle/fault-injection cases (production C)\n",tests); return 0; }