|
| 1 | +/* |
| 2 | + Tests for the Wi-Fi |
| 3 | +*/ |
| 4 | +#include "string.h" |
| 5 | +#include "unity.h" |
| 6 | +#include "esp_system.h" |
| 7 | +#include "esp_event_loop.h" |
| 8 | +#include "esp_wifi.h" |
| 9 | +#include "esp_wifi_types.h" |
| 10 | +#include "esp_log.h" |
| 11 | +#include "test_utils.h" |
| 12 | +#include "freertos/task.h" |
| 13 | +#include "freertos/event_groups.h" |
| 14 | + |
| 15 | +static const char* TAG = "test_wifi"; |
| 16 | + |
| 17 | +#define GOT_IP_EVENT 0x00000001 |
| 18 | +#define DISCONNECT_EVENT 0x00000002 |
| 19 | + |
| 20 | +#define EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT 0x00000001 |
| 21 | +#define FULL_CAHNNEL_SCAN_DURATION_THRESHOLD 1500 |
| 22 | + |
| 23 | +static uint32_t wifi_event_handler_flag; |
| 24 | + |
| 25 | +xSemaphoreHandle cb_scan_num_mutex; |
| 26 | +xSemaphoreHandle task_scan_num_mutex; |
| 27 | +xSemaphoreHandle cb_scan_fail_mutex; |
| 28 | +xSemaphoreHandle task_scan_fail_mutex; |
| 29 | + |
| 30 | +static EventGroupHandle_t scan_task_exit; |
| 31 | +static EventGroupHandle_t wifi_events; |
| 32 | + |
| 33 | +struct timeval cb_scan_time_list[10]; |
| 34 | +struct timeval task_scan_time_list[10]; |
| 35 | + |
| 36 | +static uint32_t cb_scan_ap_num = 0; |
| 37 | +static uint32_t task_scan_ap_num = 0; |
| 38 | +static uint32_t cb_scan_fail_times = 0; |
| 39 | +static uint32_t task_scan_fail_times = 0; |
| 40 | + |
| 41 | +static esp_err_t event_handler(void *ctx, system_event_t *event) |
| 42 | +{ |
| 43 | + printf("ev_handle_called.\n"); |
| 44 | + uint16_t num = 0; |
| 45 | + struct timeval cb_tv = {0}; |
| 46 | + switch(event->event_id) { |
| 47 | + case SYSTEM_EVENT_STA_START: |
| 48 | + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); |
| 49 | + break; |
| 50 | + case SYSTEM_EVENT_STA_GOT_IP: |
| 51 | + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); |
| 52 | + ESP_LOGI(TAG, "got ip:%s\n", |
| 53 | + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); |
| 54 | + if (wifi_events) { |
| 55 | + xEventGroupSetBits(wifi_events, GOT_IP_EVENT); |
| 56 | + } |
| 57 | + break; |
| 58 | + case SYSTEM_EVENT_STA_DISCONNECTED: |
| 59 | + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); |
| 60 | + if (! (EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT & wifi_event_handler_flag) ) { |
| 61 | + TEST_ESP_OK(esp_wifi_connect()); |
| 62 | + } |
| 63 | + if (wifi_events) { |
| 64 | + xEventGroupSetBits(wifi_events, DISCONNECT_EVENT); |
| 65 | + } |
| 66 | + break; |
| 67 | + case SYSTEM_EVENT_SCAN_DONE: |
| 68 | + if (event->event_info.scan_done.status == 0) { |
| 69 | + esp_wifi_scan_get_ap_num(&num); |
| 70 | + xSemaphoreTake(cb_scan_num_mutex, portMAX_DELAY); |
| 71 | + cb_scan_ap_num += num; |
| 72 | + xSemaphoreGive(cb_scan_num_mutex); |
| 73 | + printf("+SCANDONE\n"); |
| 74 | + } |
| 75 | + else { |
| 76 | + gettimeofday(&cb_tv, NULL); |
| 77 | + xSemaphoreTake(cb_scan_fail_mutex, portMAX_DELAY); |
| 78 | + cb_scan_time_list[cb_scan_fail_times++] = cb_tv; |
| 79 | + xSemaphoreGive(cb_scan_fail_mutex); |
| 80 | + printf("+SCANFAIL\n"); |
| 81 | + } |
| 82 | + break; |
| 83 | + default: |
| 84 | + break; |
| 85 | + } |
| 86 | + return ESP_OK; |
| 87 | +} |
| 88 | + |
| 89 | +static void start_wifi_as_sta(void) |
| 90 | +{ |
| 91 | + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); |
| 92 | + cfg.nvs_enable = false; |
| 93 | + // do not auto connect |
| 94 | + wifi_event_handler_flag |= EVENT_HANDLER_FLAG_DO_NOT_AUTO_RECONNECT; |
| 95 | + TEST_ESP_OK(esp_event_loop_init(event_handler, NULL)); |
| 96 | + // can't deinit event loop, need to reset leak check |
| 97 | + unity_reset_leak_checks(); |
| 98 | + if (wifi_events == NULL) { |
| 99 | + wifi_events = xEventGroupCreate(); |
| 100 | + } else { |
| 101 | + xEventGroupClearBits(wifi_events, 0x00ffffff); |
| 102 | + } |
| 103 | + TEST_ESP_OK(esp_wifi_init(&cfg)); |
| 104 | + TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA)); |
| 105 | + TEST_ESP_OK(esp_wifi_start()); |
| 106 | +} |
| 107 | + |
| 108 | +static void stop_wifi(void) |
| 109 | +{ |
| 110 | + printf("stop wifi\n"); |
| 111 | + TEST_ESP_OK(esp_wifi_stop()); |
| 112 | + TEST_ESP_OK(esp_wifi_deinit()); |
| 113 | + if (wifi_events) { |
| 114 | + vEventGroupDelete(wifi_events); |
| 115 | + wifi_events = NULL; |
| 116 | + } |
| 117 | + vTaskDelay(1000/portTICK_PERIOD_MS); |
| 118 | +} |
| 119 | + |
| 120 | +static void scan_task(void *param) |
| 121 | +{ |
| 122 | + int32_t ret; |
| 123 | + uint16_t ap_num; |
| 124 | + float scan_duration = 0.0; |
| 125 | + struct timeval scan_tv_start = {0}, scan_tv_stop = {0}, task_tv = {0}; |
| 126 | + uint8_t task_id = *((uint8_t *) param); |
| 127 | + uint8_t *test_result = (uint8_t *) param; |
| 128 | + wifi_scan_config_t scan_config = {0}; |
| 129 | + for (int i = 0; i < 2; i++) { |
| 130 | + ap_num = 0; |
| 131 | + ESP_LOGI(TAG, "[%u] scan start", task_id); |
| 132 | + gettimeofday(&scan_tv_start, NULL); |
| 133 | + ret = esp_wifi_scan_start(&scan_config, true); |
| 134 | + if (ret == ESP_OK) { |
| 135 | + gettimeofday(&scan_tv_stop, NULL); |
| 136 | + scan_duration = (scan_tv_stop.tv_sec - scan_tv_start.tv_sec) + (scan_tv_stop.tv_usec - scan_tv_start.tv_usec) * 1e-6f; |
| 137 | + esp_wifi_scan_get_ap_num(&ap_num); |
| 138 | + ESP_LOGI(TAG, "[%u] scan succeed. duration: %.2f; ap_num: %d; ret: %d", task_id, scan_duration, ap_num, ret); |
| 139 | + if (scan_duration < FULL_CAHNNEL_SCAN_DURATION_THRESHOLD) { |
| 140 | + *test_result = 0; |
| 141 | + } |
| 142 | + } else { |
| 143 | + gettimeofday(&task_tv, NULL); |
| 144 | + xSemaphoreTake(task_scan_fail_mutex, portMAX_DELAY); |
| 145 | + task_scan_time_list[task_scan_fail_times++] = task_tv; |
| 146 | + xSemaphoreGive(task_scan_fail_mutex); |
| 147 | + ESP_LOGI(TAG, "[%u] scan fail, ret: %d", task_id, ret); |
| 148 | + vTaskDelay(300 / portTICK_PERIOD_MS); |
| 149 | + } |
| 150 | + xSemaphoreTake(task_scan_num_mutex, portMAX_DELAY); |
| 151 | + task_scan_ap_num += ap_num; |
| 152 | + xSemaphoreGive(task_scan_num_mutex); |
| 153 | + } |
| 154 | + ESP_LOGI(TAG, "[%u] scan task exit", task_id); |
| 155 | + xEventGroupSetBits(scan_task_exit, task_id); |
| 156 | + vTaskDelete(NULL); |
| 157 | +} |
| 158 | + |
| 159 | +TEST_CASE("wifi do block scan before scan finished","[wifi][ignore]") |
| 160 | +{ |
| 161 | + uint8_t i, ret[2]; |
| 162 | + float time_interval = 0.0; |
| 163 | + if (scan_task_exit == NULL) { |
| 164 | + scan_task_exit = xEventGroupCreate(); |
| 165 | + } |
| 166 | + if (cb_scan_num_mutex == NULL) { |
| 167 | + cb_scan_num_mutex = xSemaphoreCreateMutex(); |
| 168 | + } |
| 169 | + if (task_scan_num_mutex == NULL) { |
| 170 | + task_scan_num_mutex = xSemaphoreCreateMutex(); |
| 171 | + } |
| 172 | + if (cb_scan_fail_mutex == NULL) { |
| 173 | + cb_scan_fail_mutex = xSemaphoreCreateMutex(); |
| 174 | + } |
| 175 | + if (task_scan_fail_mutex == NULL) { |
| 176 | + task_scan_fail_mutex = xSemaphoreCreateMutex(); |
| 177 | + } |
| 178 | + test_case_uses_tcpip(); |
| 179 | + start_wifi_as_sta(); |
| 180 | + xEventGroupClearBits(scan_task_exit, BIT0 | BIT1); |
| 181 | + for (i = 1; i <= 2; i++) { |
| 182 | + ret[i-1] = i; |
| 183 | + if (xTaskCreate(scan_task, "scan task", 2048, &ret[i-1], 1, NULL) != pdTRUE) { |
| 184 | + printf("create scan task fail"); |
| 185 | + } |
| 186 | + vTaskDelay(500 / portTICK_PERIOD_MS); |
| 187 | + } |
| 188 | + xEventGroupWaitBits(scan_task_exit, BIT0 | BIT1, true, true, portMAX_DELAY); |
| 189 | + vTaskDelay(5000 / portTICK_PERIOD_MS); |
| 190 | + ESP_LOGI(TAG, "compare the ap nums got in cb and after esp_wifi_scan_start() finish"); |
| 191 | + if (cb_scan_ap_num != task_scan_ap_num) { |
| 192 | + TEST_IGNORE_MESSAGE("the ap nums are different"); |
| 193 | + } |
| 194 | + ESP_LOGI(TAG, "compare the times of printing SCANFAIL in cb and esp_wifi_scan_start() return error code"); |
| 195 | + if (cb_scan_fail_times != task_scan_fail_times) { |
| 196 | + TEST_IGNORE_MESSAGE("the times are different"); |
| 197 | + } |
| 198 | + ESP_LOGI(TAG, "check the time interval between printing SCANFAIL in cb and esp_wifi_scan_start() return error code"); |
| 199 | + for (i = 0; i < task_scan_fail_times; i++) { |
| 200 | + time_interval = (cb_scan_time_list[i].tv_sec - task_scan_time_list[i].tv_sec) + (cb_scan_time_list[i].tv_usec - task_scan_time_list[i].tv_usec) * 1e-6f; |
| 201 | + if (abs(time_interval) > 1) { |
| 202 | + TEST_IGNORE_MESSAGE("the time interval more than 1s"); |
| 203 | + } |
| 204 | + } |
| 205 | + ESP_LOGI(TAG, "check scan time"); |
| 206 | + for (i = 1; i <= 2; i++) { |
| 207 | + if (ret[i-1] != i) { |
| 208 | + TEST_IGNORE_MESSAGE("the scan time less than 1500ms"); |
| 209 | + } |
| 210 | + } |
| 211 | + stop_wifi(); |
| 212 | + vEventGroupDelete(scan_task_exit); |
| 213 | + vSemaphoreDelete(cb_scan_num_mutex); |
| 214 | + vSemaphoreDelete(task_scan_num_mutex); |
| 215 | + vSemaphoreDelete(cb_scan_fail_mutex); |
| 216 | + vSemaphoreDelete(task_scan_fail_mutex); |
| 217 | + scan_task_exit = NULL; |
| 218 | + cb_scan_num_mutex = NULL; |
| 219 | + task_scan_num_mutex = NULL; |
| 220 | + cb_scan_fail_mutex = NULL; |
| 221 | + task_scan_fail_mutex = NULL; |
| 222 | + TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of tcpip_adapter and event_loop."); |
| 223 | +} |
0 commit comments