test_basic_checks.c (8785B)
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; (void) request; (void) path; (void) method; (void) upload_size; 130 fprintf (stderr, "Unexpected call of the request callback.\n"); 131 err_flag = ! 0; 132 return NULL; 133 } 134 135 136 static struct MHD_Daemon * 137 test_daemon_create (void) 138 { 139 struct MHD_Daemon *d; 140 141 d = MHD_daemon_create (my_req_process, NULL); 142 if (NULL == d) 143 { 144 err_flag = ! 0; 145 ERR_PRINT_LINE (); 146 fprintf (stderr, "MHD_daemon_create() failed, NULL returned.\n"); 147 return NULL; 148 } 149 return d; 150 } 151 152 153 static int 154 test_daemon_setup (struct MHD_Daemon *d, 155 int should_succeed) 156 { 157 enum MHD_StatusCode sc; 158 int ret = ! 0; 159 160 if (use_ipv6) 161 { 162 sc = MHD_DAEMON_SET_OPTIONS ( \ 163 d, MHD_D_OPTION_BIND_PORT (MHD_AF_DUAL_v4_OPTIONAL, 0)); 164 if (! tst_EXPECT_CHECK (sc,should_succeed)) 165 ret = 0; 166 } 167 168 if (use_ipv4) 169 { 170 sc = MHD_DAEMON_SET_OPTIONS ( \ 171 d, MHD_D_OPTION_BIND_PORT (MHD_AF_DUAL_v6_OPTIONAL, 0)); 172 if (! tst_EXPECT_CHECK (sc,should_succeed)) 173 ret = 0; 174 } 175 176 if (use_ip_best) 177 { 178 sc = MHD_DAEMON_SET_OPTIONS ( \ 179 d, MHD_D_OPTION_BIND_PORT (MHD_AF_AUTO, 0)); 180 if (! tst_EXPECT_CHECK (sc,should_succeed)) 181 ret = 0; 182 } 183 184 if (use_select) 185 { 186 sc = MHD_DAEMON_SET_OPTIONS ( \ 187 d, MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_SELECT)); 188 if (! tst_EXPECT_CHECK (sc,should_succeed)) 189 ret = 0; 190 } 191 192 if (use_poll) 193 { 194 sc = MHD_DAEMON_SET_OPTIONS ( \ 195 d, MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_POLL)); 196 if (! tst_EXPECT_CHECK (sc, should_succeed)) 197 ret = 0; 198 } 199 200 if (use_epoll) 201 { 202 sc = MHD_DAEMON_SET_OPTIONS ( \ 203 d, MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_EPOLL)); 204 if (! tst_EXPECT_CHECK (sc,should_succeed)) 205 ret = 0; 206 } 207 208 if (use_int_thread) 209 { 210 sc = MHD_DAEMON_SET_OPTIONS ( \ 211 d, MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_WORKER_THREADS (1))); 212 if (! tst_EXPECT_CHECK (sc, should_succeed)) 213 ret = 0; 214 } 215 216 if (use_thread_per_conn) 217 { 218 sc = MHD_DAEMON_SET_OPTIONS ( \ 219 d, MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_THREAD_PER_CONNECTION ())); 220 if (! tst_EXPECT_CHECK (sc, should_succeed)) 221 ret = 0; 222 } 223 224 if (use_thread_pool) 225 { 226 sc = MHD_DAEMON_SET_OPTIONS ( \ 227 d, MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_WORKER_THREADS (4))); 228 if (! tst_EXPECT_CHECK (sc, should_succeed)) 229 ret = 0; 230 } 231 232 if (! ret) 233 err_flag = ! 0; 234 235 return ret; 236 } 237 238 239 static int 240 test_daemon_start (struct MHD_Daemon *d, 241 int should_succeed) 242 { 243 enum MHD_StatusCode sc; 244 245 sc = MHD_daemon_start (d); 246 if (! tst_EXPECT_CHECK (sc,should_succeed)) 247 { 248 err_flag = ! 0; 249 return 0; 250 } 251 252 return ! 0; 253 } 254 255 256 static int 257 test_simple (void) 258 { 259 struct MHD_Daemon *d; 260 int ret = ! 0; 261 262 err_flag = 0; 263 264 d = test_daemon_create (); 265 if (NULL == d) 266 return (ret && ! err_flag); 267 268 test_daemon_setup (d, ! 0); 269 if (use_start) 270 test_daemon_start (d, ! 0); 271 272 test_daemon_setup (d, ! use_start); 273 274 if (use_start) 275 test_daemon_start (d, 0); /* Second "start" should fail */ 276 277 MHD_daemon_destroy (d); 278 279 return (ret && ! err_flag); 280 } 281 282 283 /** 284 * Initialise the test data 285 * @param prog_name the name of the this program 286 * @return non-zero if succeed, 287 * zero if failed 288 */ 289 static int 290 init_test (const char *prog_name) 291 { 292 if (mhdt_has_in_name (prog_name, "_start")) 293 use_start = ! 0; 294 295 if (mhdt_has_in_name (prog_name, "_ipv4")) 296 use_ipv4 = ! 0; 297 298 if (mhdt_has_in_name (prog_name, "_ipv6")) 299 use_ipv6 = ! 0; 300 301 if (mhdt_has_in_name (prog_name, "_ipbest")) 302 use_ip_best = ! 0; 303 304 use_select = mhdt_has_in_name (prog_name, "_select"); 305 306 use_poll = mhdt_has_in_name (prog_name, "_poll"); 307 308 use_epoll = mhdt_has_in_name (prog_name, "_epoll"); 309 310 use_int_thread = mhdt_has_in_name (prog_name, "_int_thread"); 311 312 use_thread_per_conn = mhdt_has_in_name (prog_name, "_thread_per_conn"); 313 314 use_thread_pool = mhdt_has_in_name (prog_name, "_thread_pool"); 315 316 return ! 0; 317 } 318 319 320 int 321 main (int argc, char *argv[]) 322 { 323 unsigned int num_err = 0; 324 (void) argc; /* Unused. Silence compiler warning. */ 325 326 if (! init_test (argv[0])) 327 { 328 fprintf (stderr, "Failed to initialise the test!\n"); 329 return 77; 330 } 331 332 if (! test_simple ()) 333 ++num_err; 334 335 if (0 != num_err) 336 { 337 fprintf (stderr, "Number of failed checks: %u\n", num_err); 338 return 2; 339 } 340 341 printf ("All checks succeed.\n"); 342 return 0; 343 }