test_http_server.c
1 // Copyright 2018 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <stdlib.h> 16 #include <stdbool.h> 17 #include <esp_system.h> 18 #include <esp_http_server.h> 19 20 #include "unity.h" 21 #include "test_utils.h" 22 23 int pre_start_mem, post_stop_mem, post_stop_min_mem; 24 bool basic_sanity = true; 25 26 esp_err_t null_func(httpd_req_t *req) 27 { 28 return ESP_OK; 29 } 30 31 httpd_uri_t handler_limit_uri (char* path) 32 { 33 httpd_uri_t uri = { 34 .uri = path, 35 .method = HTTP_GET, 36 .handler = null_func, 37 .user_ctx = NULL, 38 }; 39 return uri; 40 }; 41 42 static inline unsigned num_digits(unsigned x) 43 { 44 unsigned digits = 1; 45 while ((x = x/10) != 0) { 46 digits++; 47 } 48 return digits; 49 } 50 51 #define HTTPD_TEST_MAX_URI_HANDLERS 8 52 53 void test_handler_limit(httpd_handle_t hd) 54 { 55 int i; 56 char x[HTTPD_TEST_MAX_URI_HANDLERS+1][num_digits(HTTPD_TEST_MAX_URI_HANDLERS)+1]; 57 httpd_uri_t uris[HTTPD_TEST_MAX_URI_HANDLERS+1]; 58 59 for (i = 0; i < HTTPD_TEST_MAX_URI_HANDLERS + 1; i++) { 60 sprintf(x[i],"%d",i); 61 uris[i] = handler_limit_uri(x[i]); 62 } 63 64 /* Register multiple instances of the same handler for MAX URI Handlers */ 65 for (i = 0; i < HTTPD_TEST_MAX_URI_HANDLERS; i++) { 66 TEST_ASSERT(httpd_register_uri_handler(hd, &uris[i]) == ESP_OK); 67 } 68 69 /* Register the MAX URI + 1 Handlers should fail */ 70 TEST_ASSERT(httpd_register_uri_handler(hd, &uris[HTTPD_TEST_MAX_URI_HANDLERS]) != ESP_OK); 71 72 /* Unregister the one of the Handler should pass */ 73 TEST_ASSERT(httpd_unregister_uri_handler(hd, uris[0].uri, uris[0].method) == ESP_OK); 74 75 /* Unregister non added Handler should fail */ 76 TEST_ASSERT(httpd_unregister_uri_handler(hd, uris[0].uri, uris[0].method) != ESP_OK); 77 78 /* Register the MAX URI Handler should pass */ 79 TEST_ASSERT(httpd_register_uri_handler(hd, &uris[0]) == ESP_OK); 80 81 /* Reregister same instance of handler should fail */ 82 TEST_ASSERT(httpd_register_uri_handler(hd, &uris[0]) != ESP_OK); 83 84 /* Register the MAX URI + 1 Handlers should fail */ 85 TEST_ASSERT(httpd_register_uri_handler(hd, &uris[HTTPD_TEST_MAX_URI_HANDLERS]) != ESP_OK); 86 87 /* Unregister the same handler for MAX URI Handlers */ 88 for (i = 0; i < HTTPD_TEST_MAX_URI_HANDLERS; i++) { 89 TEST_ASSERT(httpd_unregister_uri_handler(hd, uris[i].uri, uris[i].method) == ESP_OK); 90 } 91 basic_sanity = false; 92 } 93 94 /********************* Test Handler Limit End *******************/ 95 96 httpd_handle_t test_httpd_start(uint16_t id) 97 { 98 httpd_handle_t hd; 99 httpd_config_t config = HTTPD_DEFAULT_CONFIG(); 100 config.max_uri_handlers = HTTPD_TEST_MAX_URI_HANDLERS; 101 config.server_port += id; 102 config.ctrl_port += id; 103 TEST_ASSERT(httpd_start(&hd, &config) == ESP_OK) 104 return hd; 105 } 106 107 #define SERVER_INSTANCES 2 108 109 /* Currently this only tests for the number of tasks. 110 * Heap leakage is not tested as LWIP allocates memory 111 * which may not be freed immedietly causing erroneous 112 * evaluation. Another test to implement would be the 113 * monitoring of open sockets, but LWIP presently provides 114 * no such API for getting the number of open sockets. 115 */ 116 TEST_CASE("Leak Test", "[HTTP SERVER]") 117 { 118 httpd_handle_t hd[SERVER_INSTANCES]; 119 unsigned task_count; 120 bool res = true; 121 122 test_case_uses_tcpip(); 123 124 task_count = uxTaskGetNumberOfTasks(); 125 printf("Initial task count: %d\n", task_count); 126 127 pre_start_mem = esp_get_free_heap_size(); 128 129 for (int i = 0; i < SERVER_INSTANCES; i++) { 130 hd[i] = test_httpd_start(i); 131 vTaskDelay(10); 132 unsigned num_tasks = uxTaskGetNumberOfTasks(); 133 task_count++; 134 if (num_tasks != task_count) { 135 printf("Incorrect task count (starting): %d expected %d\n", 136 num_tasks, task_count); 137 res = false; 138 } 139 } 140 141 for (int i = 0; i < SERVER_INSTANCES; i++) { 142 if (httpd_stop(hd[i]) != ESP_OK) { 143 printf("Failed to stop httpd task %d\n", i); 144 res = false; 145 } 146 vTaskDelay(10); 147 unsigned num_tasks = uxTaskGetNumberOfTasks(); 148 task_count--; 149 if (num_tasks != task_count) { 150 printf("Incorrect task count (stopping): %d expected %d\n", 151 num_tasks, task_count); 152 res = false; 153 } 154 } 155 post_stop_mem = esp_get_free_heap_size(); 156 TEST_ASSERT(res == true); 157 } 158 159 TEST_CASE("Basic Functionality Tests", "[HTTP SERVER]") 160 { 161 httpd_handle_t hd; 162 httpd_config_t config = HTTPD_DEFAULT_CONFIG(); 163 164 test_case_uses_tcpip(); 165 166 TEST_ASSERT(httpd_start(&hd, &config) == ESP_OK); 167 test_handler_limit(hd); 168 TEST_ASSERT(httpd_stop(hd) == ESP_OK); 169 } 170 171 TEST_CASE("URI Wildcard Matcher Tests", "[HTTP SERVER]") 172 { 173 struct uritest { 174 const char *template; 175 const char *uri; 176 bool matches; 177 }; 178 179 struct uritest uris[] = { 180 {"/", "/", true}, 181 {"", "", true}, 182 {"/", "", false}, 183 {"/wrong", "/", false}, 184 {"/", "/wrong", false}, 185 {"/asdfghjkl/qwertrtyyuiuioo", "/asdfghjkl/qwertrtyyuiuioo", true}, 186 {"/path", "/path", true}, 187 {"/path", "/path/", false}, 188 {"/path/", "/path", false}, 189 190 {"?", "", false}, // this is not valid, but should not crash 191 {"?", "sfsdf", false}, 192 193 {"/path/?", "/pa", false}, 194 {"/path/?", "/path", true}, 195 {"/path/?", "/path/", true}, 196 {"/path/?", "/path/alalal", false}, 197 198 {"/path/*", "/path", false}, 199 {"/path/*", "/", false}, 200 {"/path/*", "/path/", true}, 201 {"/path/*", "/path/blabla", true}, 202 203 {"*", "", true}, 204 {"*", "/", true}, 205 {"*", "/aaa", true}, 206 207 {"/path/?*", "/pat", false}, 208 {"/path/?*", "/pathb", false}, 209 {"/path/?*", "/pathxx", false}, 210 {"/path/?*", "/pathblabla", false}, 211 {"/path/?*", "/path", true}, 212 {"/path/?*", "/path/", true}, 213 {"/path/?*", "/path/blabla", true}, 214 215 {"/path/*?", "/pat", false}, 216 {"/path/*?", "/pathb", false}, 217 {"/path/*?", "/pathxx", false}, 218 {"/path/*?", "/path", true}, 219 {"/path/*?", "/path/", true}, 220 {"/path/*?", "/path/blabla", true}, 221 222 {"/path/*/xxx", "/path/", false}, 223 {"/path/*/xxx", "/path/*/xxx", true}, 224 {} 225 }; 226 227 struct uritest *ut = &uris[0]; 228 229 while(ut->template != 0) { 230 bool match = httpd_uri_match_wildcard(ut->template, ut->uri, strlen(ut->uri)); 231 TEST_ASSERT(match == ut->matches); 232 ut++; 233 } 234 } 235 236 TEST_CASE("Max Allowed Sockets Test", "[HTTP SERVER]") 237 { 238 test_case_uses_tcpip(); 239 240 httpd_handle_t hd; 241 httpd_config_t config = HTTPD_DEFAULT_CONFIG(); 242 243 /* Starting server with default config options should pass */ 244 TEST_ASSERT(httpd_start(&hd, &config) == ESP_OK); 245 TEST_ASSERT(httpd_stop(hd) == ESP_OK); 246 247 /* Default value of max_open_sockets is already set as per 248 * maximum limit imposed by LWIP. Increasing this beyond the 249 * maximum allowed value, without increasing LWIP limit, 250 * should fail */ 251 config.max_open_sockets += 1; 252 TEST_ASSERT(httpd_start(&hd, &config) != ESP_OK); 253 }