test_basic_checks.c (8777B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2016, 2024 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file test_basic_checks.c 41 * @brief test for create, start and destroy 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include "microhttpd2.h" 48 #include "mhdt_has_in_name.h" 49 50 /* Helper macros */ 51 52 #define ERR_PRINT_LINE() \ 53 ((void) fprintf (stderr, "At the line number %u: ", \ 54 (unsigned) __LINE__)) 55 56 /** 57 * Check whether SC code is OK, print error if not. 58 * @warning Do not use function call in the argument 59 * @param sc the status code to check 60 */ 61 #define tst_EXPECT_OK(sc) \ 62 ( (MHD_SC_OK == (sc)) ? (! 0) : \ 63 (ERR_PRINT_LINE (), \ 64 ((void) fprintf (stderr, "MHD function failed, returned: %u\n", \ 65 (unsigned int) (sc))), (0)) ) 66 #if 0 67 # define tst_EXPECT_OK(sc) \ 68 ( (MHD_SC_OK == (sc)) ? (! 0) : \ 69 (ERR_PRINT_LINE (), \ 70 ((void) fprintf (stderr, \ 71 "MHD function failed, returned: %s\n", \ 72 MHD_status_code_to_string_lazy (sc))), (0)) ) 73 #endif 74 75 /** 76 * Check whether SC code is OK, print error if not. 77 * @warning Do not use function call in the argument 78 * @param sc the status code to check 79 */ 80 #define tst_EXPECT_FAIL(sc) \ 81 ( (MHD_SC_OK != (sc)) ? (! 0) : \ 82 (ERR_PRINT_LINE (), \ 83 ((void) fprintf (stderr, "MHD function unexpectedly succeed.\n")), \ 84 (0)) ) 85 86 /** 87 * Check whether SC code is success/failure as expected, print error if not. 88 * @warning Do not use function call in the argument 89 * @param sc the status code to check 90 * @param expect_ok non-zero if SC should be OK, zero is SC should NOT be OK 91 */ 92 #define tst_EXPECT_CHECK(sc, expect_ok) \ 93 ((expect_ok) ? tst_EXPECT_OK ((sc)) : tst_EXPECT_FAIL ((sc))) 94 95 96 /* The test */ 97 98 static int use_start = 0; 99 100 static int use_ipv4 = 0; 101 102 static int use_ipv6 = 0; 103 104 static int use_ip_best = 0; 105 106 static int use_select = 0; 107 108 static int use_poll = 0; 109 110 static int use_epoll = 0; 111 112 static int use_int_thread = 0; 113 114 static int use_thread_per_conn = 0; 115 116 static int use_thread_pool = 0; 117 118 /* Dynamic run-time variables */ 119 120 static int err_flag = 0; 121 122 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_NONNULL_ (3) static const struct MHD_Action * 123 my_req_process (void *cls, 124 struct MHD_Request *request, 125 const struct MHD_String *path, 126 enum MHD_HTTP_Method method, 127 uint_fast64_t upload_size) 128 { 129 (void)cls; 130 (void)request; 131 (void)path; 132 (void)method; 133 (void)upload_size; 134 fprintf (stderr, "Unexpected call of the request callback.\n"); 135 err_flag = !0; 136 return NULL; 137 } 138 139 140 static struct MHD_Daemon * 141 test_daemon_create (void) 142 { 143 struct MHD_Daemon *d; 144 145 d = MHD_daemon_create (my_req_process, NULL); 146 if (NULL == d) 147 { 148 err_flag = !0; 149 ERR_PRINT_LINE (); 150 fprintf (stderr, "MHD_daemon_create() failed, NULL returned.\n"); 151 return NULL; 152 } 153 return d; 154 } 155 156 157 static int 158 test_daemon_setup (struct MHD_Daemon *d, 159 int should_succeed) 160 { 161 enum MHD_StatusCode sc; 162 int ret = !0; 163 164 if (use_ipv6) 165 { 166 sc = MHD_DAEMON_SET_OPTIONS ( \ 167 d, MHD_D_OPTION_BIND_PORT (MHD_AF_DUAL_v4_OPTIONAL, 0)); 168 if (!tst_EXPECT_CHECK (sc, should_succeed)) 169 ret = 0; 170 } 171 172 if (use_ipv4) 173 { 174 sc = MHD_DAEMON_SET_OPTIONS ( \ 175 d, MHD_D_OPTION_BIND_PORT (MHD_AF_DUAL_v6_OPTIONAL, 0)); 176 if (!tst_EXPECT_CHECK (sc, should_succeed)) 177 ret = 0; 178 } 179 180 if (use_ip_best) 181 { 182 sc = MHD_DAEMON_SET_OPTIONS ( \ 183 d, MHD_D_OPTION_BIND_PORT (MHD_AF_AUTO, 0)); 184 if (!tst_EXPECT_CHECK (sc, should_succeed)) 185 ret = 0; 186 } 187 188 if (use_select) 189 { 190 sc = MHD_DAEMON_SET_OPTIONS ( \ 191 d, MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_SELECT)); 192 if (!tst_EXPECT_CHECK (sc, should_succeed)) 193 ret = 0; 194 } 195 196 if (use_poll) 197 { 198 sc = MHD_DAEMON_SET_OPTIONS ( \ 199 d, MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_POLL)); 200 if (!tst_EXPECT_CHECK (sc, should_succeed)) 201 ret = 0; 202 } 203 204 if (use_epoll) 205 { 206 sc = MHD_DAEMON_SET_OPTIONS ( \ 207 d, MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_EPOLL)); 208 if (!tst_EXPECT_CHECK (sc, should_succeed)) 209 ret = 0; 210 } 211 212 if (use_int_thread) 213 { 214 sc = MHD_DAEMON_SET_OPTIONS ( \ 215 d, MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_WORKER_THREADS (1))); 216 if (!tst_EXPECT_CHECK (sc, should_succeed)) 217 ret = 0; 218 } 219 220 if (use_thread_per_conn) 221 { 222 sc = MHD_DAEMON_SET_OPTIONS ( \ 223 d, MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_THREAD_PER_CONNECTION ())); 224 if (!tst_EXPECT_CHECK (sc, should_succeed)) 225 ret = 0; 226 } 227 228 if (use_thread_pool) 229 { 230 sc = MHD_DAEMON_SET_OPTIONS ( \ 231 d, MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_WORKER_THREADS (4))); 232 if (!tst_EXPECT_CHECK (sc, should_succeed)) 233 ret = 0; 234 } 235 236 if (!ret) 237 err_flag = !0; 238 239 return ret; 240 } 241 242 243 static int 244 test_daemon_start (struct MHD_Daemon *d, 245 int should_succeed) 246 { 247 enum MHD_StatusCode sc; 248 249 sc = MHD_daemon_start (d); 250 if (!tst_EXPECT_CHECK (sc, should_succeed)) 251 { 252 err_flag = !0; 253 return 0; 254 } 255 256 return !0; 257 } 258 259 260 static int 261 test_simple (void) 262 { 263 struct MHD_Daemon *d; 264 int ret = !0; 265 266 err_flag = 0; 267 268 d = test_daemon_create (); 269 if (NULL == d) 270 return (ret && !err_flag); 271 272 test_daemon_setup (d, !0); 273 if (use_start) 274 test_daemon_start (d, !0); 275 276 test_daemon_setup (d, !use_start); 277 278 if (use_start) 279 test_daemon_start (d, 0); /* Second "start" should fail */ 280 281 MHD_daemon_destroy (d); 282 283 return (ret && !err_flag); 284 } 285 286 287 /** 288 * Initialise the test data 289 * @param prog_name the name of the this program 290 * @return non-zero if succeed, 291 * zero if failed 292 */ 293 static int 294 init_test (const char *prog_name) 295 { 296 if (mhdt_has_in_name (prog_name, "_start")) 297 use_start = !0; 298 299 if (mhdt_has_in_name (prog_name, "_ipv4")) 300 use_ipv4 = !0; 301 302 if (mhdt_has_in_name (prog_name, "_ipv6")) 303 use_ipv6 = !0; 304 305 if (mhdt_has_in_name (prog_name, "_ipbest")) 306 use_ip_best = !0; 307 308 use_select = mhdt_has_in_name (prog_name, "_select"); 309 310 use_poll = mhdt_has_in_name (prog_name, "_poll"); 311 312 use_epoll = mhdt_has_in_name (prog_name, "_epoll"); 313 314 use_int_thread = mhdt_has_in_name (prog_name, "_int_thread"); 315 316 use_thread_per_conn = mhdt_has_in_name (prog_name, "_thread_per_conn"); 317 318 use_thread_pool = mhdt_has_in_name (prog_name, "_thread_pool"); 319 320 return !0; 321 } 322 323 324 int 325 main (int argc, char *argv[]) 326 { 327 unsigned int num_err = 0; 328 (void)argc; /* Unused. Silence compiler warning. */ 329 330 if (!init_test (argv[0])) 331 { 332 fprintf (stderr, "Failed to initialise the test!\n"); 333 return 77; 334 } 335 336 if (!test_simple ()) 337 ++num_err; 338 339 if (0 != num_err) 340 { 341 fprintf (stderr, "Number of failed checks: %u\n", num_err); 342 return 2; 343 } 344 345 printf ("All checks succeed.\n"); 346 return 0; 347 }