/ components / esp_http_server / test / test_http_server.c
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  }