1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 /* Now include the curl_setup.h file from libcurl's private libdir (the source 26 version, but that might include "curl_config.h" from the build dir so we 27 need both of them in the include path), so that we get good in-depth 28 knowledge about the system we're building this on */ 29 30 #define CURL_NO_OLDIES 31 32 #include "curl_setup.h" 33 34 #include <curl/curl.h> 35 36 #ifdef HAVE_SYS_SELECT_H 37 /* since so many tests use select(), we can just as well include it here */ 38 #include <sys/select.h> 39 #elif defined(HAVE_UNISTD_H) 40 #include <unistd.h> 41 #endif 42 43 #include "curl_printf.h" 44 45 #ifdef WIN32 46 #define sleep(sec) Sleep ((sec)*1000) 47 #endif 48 49 #define test_setopt(A,B,C) \ 50 if((res = curl_easy_setopt((A), (B), (C))) != CURLE_OK) \ 51 goto test_cleanup 52 53 #define test_multi_setopt(A,B,C) \ 54 if((res = curl_multi_setopt((A), (B), (C))) != CURLE_OK) \ 55 goto test_cleanup 56 57 extern char *libtest_arg2; /* set by first.c to the argv[2] or NULL */ 58 extern char *libtest_arg3; /* set by first.c to the argv[3] or NULL */ 59 60 /* argc and argv as passed in to the main() function */ 61 extern int test_argc; 62 extern char **test_argv; 63 64 extern struct timeval tv_test_start; /* for test timing */ 65 66 extern int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc, 67 struct timeval *tv); 68 69 extern void wait_ms(int ms); /* wait this many milliseconds */ 70 71 extern int test(char *URL); /* the actual test function provided by each 72 individual libXXX.c file */ 73 74 extern char *hexdump(const unsigned char *buffer, size_t len); 75 76 extern int unitfail; 77 78 /* 79 ** TEST_ERR_* values must be greater than CURL_LAST CURLcode in order 80 ** to avoid confusion with any CURLcode or CURLMcode. These TEST_ERR_* 81 ** codes are returned to signal test specific situations and should 82 ** not get mixed with CURLcode or CURLMcode values. 83 ** 84 ** For portability reasons TEST_ERR_* values should be less than 127. 85 */ 86 87 #define TEST_ERR_MAJOR_BAD (CURLcode) 126 88 #define TEST_ERR_RUNS_FOREVER (CURLcode) 125 89 #define TEST_ERR_EASY_INIT (CURLcode) 124 90 #define TEST_ERR_MULTI (CURLcode) 123 91 #define TEST_ERR_NUM_HANDLES (CURLcode) 122 92 #define TEST_ERR_SELECT (CURLcode) 121 93 #define TEST_ERR_SUCCESS (CURLcode) 120 94 #define TEST_ERR_FAILURE (CURLcode) 119 95 #define TEST_ERR_USAGE (CURLcode) 118 96 #define TEST_ERR_FOPEN (CURLcode) 117 97 #define TEST_ERR_FSTAT (CURLcode) 116 98 #define TEST_ERR_BAD_TIMEOUT (CURLcode) 115 99 100 /* 101 ** Macros for test source code readability/maintainability. 102 ** 103 ** All of the following macros require that an int data type 'res' variable 104 ** exists in scope where macro is used, and that it has been initialized to 105 ** zero before the macro is used. 106 ** 107 ** exe_* and chk_* macros are helper macros not intended to be used from 108 ** outside of this header file. Arguments 'Y' and 'Z' of these represent 109 ** source code file and line number, while Arguments 'A', 'B', etc, are 110 ** the arguments used to actually call a libcurl function. 111 ** 112 ** All easy_* and multi_* macros call a libcurl function and evaluate if 113 ** the function has succeeded or failed. When the function succeeds 'res' 114 ** variable is not set nor cleared and program continues normal flow. On 115 ** the other hand if function fails 'res' variable is set and a jump to 116 ** label 'test_cleanup' is performed. 117 ** 118 ** Every easy_* and multi_* macros have a res_easy_* and res_multi_* macro 119 ** counterpart that operates in the same way with the exception that no 120 ** jump takes place in case of failure. res_easy_* and res_multi_* macros 121 ** should be immediately followed by checking if 'res' variable has been 122 ** set. 123 ** 124 ** 'res' variable when set will hold a CURLcode, CURLMcode, or any of the 125 ** TEST_ERR_* values defined above. It is advisable to return this value 126 ** as test result. 127 */ 128 129 /* ---------------------------------------------------------------- */ 130 131 #define exe_easy_init(A,Y,Z) do { \ 132 if(((A) = curl_easy_init()) == NULL) { \ 133 fprintf(stderr, "%s:%d curl_easy_init() failed\n", (Y), (Z)); \ 134 res = TEST_ERR_EASY_INIT; \ 135 } \ 136 } while(0) 137 138 #define res_easy_init(A) \ 139 exe_easy_init((A), (__FILE__), (__LINE__)) 140 141 #define chk_easy_init(A,Y,Z) do { \ 142 exe_easy_init((A), (Y), (Z)); \ 143 if(res) \ 144 goto test_cleanup; \ 145 } while(0) 146 147 #define easy_init(A) \ 148 chk_easy_init((A), (__FILE__), (__LINE__)) 149 150 /* ---------------------------------------------------------------- */ 151 152 #define exe_multi_init(A,Y,Z) do { \ 153 if(((A) = curl_multi_init()) == NULL) { \ 154 fprintf(stderr, "%s:%d curl_multi_init() failed\n", (Y), (Z)); \ 155 res = TEST_ERR_MULTI; \ 156 } \ 157 } while(0) 158 159 #define res_multi_init(A) \ 160 exe_multi_init((A), (__FILE__), (__LINE__)) 161 162 #define chk_multi_init(A,Y,Z) do { \ 163 exe_multi_init((A), (Y), (Z)); \ 164 if(res) \ 165 goto test_cleanup; \ 166 } while(0) 167 168 #define multi_init(A) \ 169 chk_multi_init((A), (__FILE__), (__LINE__)) 170 171 /* ---------------------------------------------------------------- */ 172 173 #define exe_easy_setopt(A,B,C,Y,Z) do { \ 174 CURLcode ec; \ 175 if((ec = curl_easy_setopt((A), (B), (C))) != CURLE_OK) { \ 176 fprintf(stderr, "%s:%d curl_easy_setopt() failed, " \ 177 "with code %d (%s)\n", \ 178 (Y), (Z), (int)ec, curl_easy_strerror(ec)); \ 179 res = ec; \ 180 } \ 181 } while(0) 182 183 #define res_easy_setopt(A, B, C) \ 184 exe_easy_setopt((A), (B), (C), (__FILE__), (__LINE__)) 185 186 #define chk_easy_setopt(A, B, C, Y, Z) do { \ 187 exe_easy_setopt((A), (B), (C), (Y), (Z)); \ 188 if(res) \ 189 goto test_cleanup; \ 190 } while(0) 191 192 #define easy_setopt(A, B, C) \ 193 chk_easy_setopt((A), (B), (C), (__FILE__), (__LINE__)) 194 195 /* ---------------------------------------------------------------- */ 196 197 #define exe_multi_setopt(A, B, C, Y, Z) do { \ 198 CURLMcode ec; \ 199 if((ec = curl_multi_setopt((A), (B), (C))) != CURLM_OK) { \ 200 fprintf(stderr, "%s:%d curl_multi_setopt() failed, " \ 201 "with code %d (%s)\n", \ 202 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 203 res = TEST_ERR_MULTI; \ 204 } \ 205 } while(0) 206 207 #define res_multi_setopt(A,B,C) \ 208 exe_multi_setopt((A), (B), (C), (__FILE__), (__LINE__)) 209 210 #define chk_multi_setopt(A,B,C,Y,Z) do { \ 211 exe_multi_setopt((A), (B), (C), (Y), (Z)); \ 212 if(res) \ 213 goto test_cleanup; \ 214 } while(0) 215 216 #define multi_setopt(A,B,C) \ 217 chk_multi_setopt((A), (B), (C), (__FILE__), (__LINE__)) 218 219 /* ---------------------------------------------------------------- */ 220 221 #define exe_multi_add_handle(A,B,Y,Z) do { \ 222 CURLMcode ec; \ 223 if((ec = curl_multi_add_handle((A), (B))) != CURLM_OK) { \ 224 fprintf(stderr, "%s:%d curl_multi_add_handle() failed, " \ 225 "with code %d (%s)\n", \ 226 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 227 res = TEST_ERR_MULTI; \ 228 } \ 229 } while(0) 230 231 #define res_multi_add_handle(A, B) \ 232 exe_multi_add_handle((A), (B), (__FILE__), (__LINE__)) 233 234 #define chk_multi_add_handle(A, B, Y, Z) do { \ 235 exe_multi_add_handle((A), (B), (Y), (Z)); \ 236 if(res) \ 237 goto test_cleanup; \ 238 } while(0) 239 240 #define multi_add_handle(A, B) \ 241 chk_multi_add_handle((A), (B), (__FILE__), (__LINE__)) 242 243 /* ---------------------------------------------------------------- */ 244 245 #define exe_multi_remove_handle(A,B,Y,Z) do { \ 246 CURLMcode ec; \ 247 if((ec = curl_multi_remove_handle((A), (B))) != CURLM_OK) { \ 248 fprintf(stderr, "%s:%d curl_multi_remove_handle() failed, " \ 249 "with code %d (%s)\n", \ 250 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 251 res = TEST_ERR_MULTI; \ 252 } \ 253 } while(0) 254 255 #define res_multi_remove_handle(A, B) \ 256 exe_multi_remove_handle((A), (B), (__FILE__), (__LINE__)) 257 258 #define chk_multi_remove_handle(A, B, Y, Z) do { \ 259 exe_multi_remove_handle((A), (B), (Y), (Z)); \ 260 if(res) \ 261 goto test_cleanup; \ 262 } while(0) 263 264 265 #define multi_remove_handle(A, B) \ 266 chk_multi_remove_handle((A), (B), (__FILE__), (__LINE__)) 267 268 /* ---------------------------------------------------------------- */ 269 270 #define exe_multi_perform(A,B,Y,Z) do { \ 271 CURLMcode ec; \ 272 if((ec = curl_multi_perform((A), (B))) != CURLM_OK) { \ 273 fprintf(stderr, "%s:%d curl_multi_perform() failed, " \ 274 "with code %d (%s)\n", \ 275 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 276 res = TEST_ERR_MULTI; \ 277 } \ 278 else if(*((B)) < 0) { \ 279 fprintf(stderr, "%s:%d curl_multi_perform() succeeded, " \ 280 "but returned invalid running_handles value (%d)\n", \ 281 (Y), (Z), (int)*((B))); \ 282 res = TEST_ERR_NUM_HANDLES; \ 283 } \ 284 } while(0) 285 286 #define res_multi_perform(A, B) \ 287 exe_multi_perform((A), (B), (__FILE__), (__LINE__)) 288 289 #define chk_multi_perform(A, B, Y, Z) do { \ 290 exe_multi_perform((A), (B), (Y), (Z)); \ 291 if(res) \ 292 goto test_cleanup; \ 293 } while(0) 294 295 #define multi_perform(A,B) \ 296 chk_multi_perform((A), (B), (__FILE__), (__LINE__)) 297 298 /* ---------------------------------------------------------------- */ 299 300 #define exe_multi_fdset(A, B, C, D, E, Y, Z) do { \ 301 CURLMcode ec; \ 302 if((ec = curl_multi_fdset((A), (B), (C), (D), (E))) != CURLM_OK) { \ 303 fprintf(stderr, "%s:%d curl_multi_fdset() failed, " \ 304 "with code %d (%s)\n", \ 305 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 306 res = TEST_ERR_MULTI; \ 307 } \ 308 else if(*((E)) < -1) { \ 309 fprintf(stderr, "%s:%d curl_multi_fdset() succeeded, " \ 310 "but returned invalid max_fd value (%d)\n", \ 311 (Y), (Z), (int)*((E))); \ 312 res = TEST_ERR_NUM_HANDLES; \ 313 } \ 314 } while(0) 315 316 #define res_multi_fdset(A, B, C, D, E) \ 317 exe_multi_fdset((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 318 319 #define chk_multi_fdset(A, B, C, D, E, Y, Z) do { \ 320 exe_multi_fdset((A), (B), (C), (D), (E), (Y), (Z)); \ 321 if(res) \ 322 goto test_cleanup; \ 323 } while(0) 324 325 #define multi_fdset(A, B, C, D, E) \ 326 chk_multi_fdset((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 327 328 /* ---------------------------------------------------------------- */ 329 330 #define exe_multi_timeout(A,B,Y,Z) do { \ 331 CURLMcode ec; \ 332 if((ec = curl_multi_timeout((A), (B))) != CURLM_OK) { \ 333 fprintf(stderr, "%s:%d curl_multi_timeout() failed, " \ 334 "with code %d (%s)\n", \ 335 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 336 res = TEST_ERR_BAD_TIMEOUT; \ 337 } \ 338 else if(*((B)) < -1L) { \ 339 fprintf(stderr, "%s:%d curl_multi_timeout() succeeded, " \ 340 "but returned invalid timeout value (%ld)\n", \ 341 (Y), (Z), (long)*((B))); \ 342 res = TEST_ERR_BAD_TIMEOUT; \ 343 } \ 344 } while(0) 345 346 #define res_multi_timeout(A, B) \ 347 exe_multi_timeout((A), (B), (__FILE__), (__LINE__)) 348 349 #define chk_multi_timeout(A, B, Y, Z) do { \ 350 exe_multi_timeout((A), (B), (Y), (Z)); \ 351 if(res) \ 352 goto test_cleanup; \ 353 } while(0) 354 355 #define multi_timeout(A, B) \ 356 chk_multi_timeout((A), (B), (__FILE__), (__LINE__)) 357 358 /* ---------------------------------------------------------------- */ 359 360 #define exe_multi_poll(A,B,C,D,E,Y,Z) do { \ 361 CURLMcode ec; \ 362 if((ec = curl_multi_poll((A), (B), (C), (D), (E))) != CURLM_OK) { \ 363 fprintf(stderr, "%s:%d curl_multi_poll() failed, " \ 364 "with code %d (%s)\n", \ 365 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 366 res = TEST_ERR_MULTI; \ 367 } \ 368 else if(*((E)) < 0) { \ 369 fprintf(stderr, "%s:%d curl_multi_poll() succeeded, " \ 370 "but returned invalid numfds value (%d)\n", \ 371 (Y), (Z), (int)*((E))); \ 372 res = TEST_ERR_NUM_HANDLES; \ 373 } \ 374 } while(0) 375 376 #define res_multi_poll(A, B, C, D, E) \ 377 exe_multi_poll((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 378 379 #define chk_multi_poll(A, B, C, D, E, Y, Z) do { \ 380 exe_multi_poll((A), (B), (C), (D), (E), (Y), (Z)); \ 381 if(res) \ 382 goto test_cleanup; \ 383 } while(0) 384 385 #define multi_poll(A, B, C, D, E) \ 386 chk_multi_poll((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 387 388 /* ---------------------------------------------------------------- */ 389 390 #define exe_multi_wakeup(A,Y,Z) do { \ 391 CURLMcode ec; \ 392 if((ec = curl_multi_wakeup((A))) != CURLM_OK) { \ 393 fprintf(stderr, "%s:%d curl_multi_wakeup() failed, " \ 394 "with code %d (%s)\n", \ 395 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 396 res = TEST_ERR_MULTI; \ 397 } \ 398 } while(0) 399 400 #define res_multi_wakeup(A) \ 401 exe_multi_wakeup((A), (__FILE__), (__LINE__)) 402 403 #define chk_multi_wakeup(A, Y, Z) do { \ 404 exe_multi_wakeup((A), (Y), (Z)); \ 405 if(res) \ 406 goto test_cleanup; \ 407 } while(0) 408 409 #define multi_wakeup(A) \ 410 chk_multi_wakeup((A), (__FILE__), (__LINE__)) 411 412 /* ---------------------------------------------------------------- */ 413 414 #define exe_select_test(A, B, C, D, E, Y, Z) do { \ 415 int ec; \ 416 if(select_wrapper((A), (B), (C), (D), (E)) == -1) { \ 417 ec = SOCKERRNO; \ 418 fprintf(stderr, "%s:%d select() failed, with " \ 419 "errno %d (%s)\n", \ 420 (Y), (Z), ec, strerror(ec)); \ 421 res = TEST_ERR_SELECT; \ 422 } \ 423 } while(0) 424 425 #define res_select_test(A, B, C, D, E) \ 426 exe_select_test((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 427 428 #define chk_select_test(A, B, C, D, E, Y, Z) do { \ 429 exe_select_test((A), (B), (C), (D), (E), (Y), (Z)); \ 430 if(res) \ 431 goto test_cleanup; \ 432 } while(0) 433 434 #define select_test(A, B, C, D, E) \ 435 chk_select_test((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 436 437 /* ---------------------------------------------------------------- */ 438 439 #define start_test_timing() do { \ 440 tv_test_start = tutil_tvnow(); \ 441 } while(0) 442 443 #define exe_test_timedout(Y,Z) do { \ 444 if(tutil_tvdiff(tutil_tvnow(), tv_test_start) > TEST_HANG_TIMEOUT) { \ 445 fprintf(stderr, "%s:%d ABORTING TEST, since it seems " \ 446 "that it would have run forever.\n", (Y), (Z)); \ 447 res = TEST_ERR_RUNS_FOREVER; \ 448 } \ 449 } while(0) 450 451 #define res_test_timedout() \ 452 exe_test_timedout((__FILE__), (__LINE__)) 453 454 #define chk_test_timedout(Y, Z) do { \ 455 exe_test_timedout(Y, Z); \ 456 if(res) \ 457 goto test_cleanup; \ 458 } while(0) 459 460 #define abort_on_test_timeout() \ 461 chk_test_timedout((__FILE__), (__LINE__)) 462 463 /* ---------------------------------------------------------------- */ 464 465 #define exe_global_init(A,Y,Z) do { \ 466 CURLcode ec; \ 467 if((ec = curl_global_init((A))) != CURLE_OK) { \ 468 fprintf(stderr, "%s:%d curl_global_init() failed, " \ 469 "with code %d (%s)\n", \ 470 (Y), (Z), (int)ec, curl_easy_strerror(ec)); \ 471 res = ec; \ 472 } \ 473 } while(0) 474 475 #define res_global_init(A) \ 476 exe_global_init((A), (__FILE__), (__LINE__)) 477 478 #define chk_global_init(A, Y, Z) do { \ 479 exe_global_init((A), (Y), (Z)); \ 480 if(res) \ 481 return res; \ 482 } while(0) 483 484 /* global_init() is different than other macros. In case of 485 failure it 'return's instead of going to 'test_cleanup'. */ 486 487 #define global_init(A) \ 488 chk_global_init((A), (__FILE__), (__LINE__)) 489 490 #define NO_SUPPORT_BUILT_IN \ 491 int test(char *URL) \ 492 { \ 493 (void)URL; \ 494 fprintf(stderr, "Missing support\n"); \ 495 return 1; \ 496 } 497 498 /* ---------------------------------------------------------------- */ 499