1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2020, 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 ***************************************************************************/ 22 23 /* !checksrc! disable ASSIGNWITHINCONDITION 14 */ 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 #ifdef TPF 44 # include "select.h" 45 #endif 46 47 #include "curl_printf.h" 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 #ifdef UNITTESTS 77 extern int unitfail; 78 #endif 79 80 /* 81 ** TEST_ERR_* values must be greater than CURL_LAST CURLcode in order 82 ** to avoid confusion with any CURLcode or CURLMcode. These TEST_ERR_* 83 ** codes are returned to signal test specific situations and should 84 ** not get mixed with CURLcode or CURLMcode values. 85 ** 86 ** For portability reasons TEST_ERR_* values should be less than 127. 87 */ 88 89 #define TEST_ERR_MAJOR_BAD (CURLcode) 126 90 #define TEST_ERR_RUNS_FOREVER (CURLcode) 125 91 #define TEST_ERR_EASY_INIT (CURLcode) 124 92 #define TEST_ERR_MULTI (CURLcode) 123 93 #define TEST_ERR_NUM_HANDLES (CURLcode) 122 94 #define TEST_ERR_SELECT (CURLcode) 121 95 #define TEST_ERR_SUCCESS (CURLcode) 120 96 #define TEST_ERR_FAILURE (CURLcode) 119 97 #define TEST_ERR_USAGE (CURLcode) 118 98 #define TEST_ERR_FOPEN (CURLcode) 117 99 #define TEST_ERR_FSTAT (CURLcode) 116 100 #define TEST_ERR_BAD_TIMEOUT (CURLcode) 115 101 102 /* 103 ** Macros for test source code readability/maintainability. 104 ** 105 ** All of the following macros require that an int data type 'res' variable 106 ** exists in scope where macro is used, and that it has been initialized to 107 ** zero before the macro is used. 108 ** 109 ** exe_* and chk_* macros are helper macros not intended to be used from 110 ** outside of this header file. Arguments 'Y' and 'Z' of these represent 111 ** source code file and line number, while Arguments 'A', 'B', etc, are 112 ** the arguments used to actually call a libcurl function. 113 ** 114 ** All easy_* and multi_* macros call a libcurl function and evaluate if 115 ** the function has succeeded or failed. When the function succeeds 'res' 116 ** variable is not set nor cleared and program continues normal flow. On 117 ** the other hand if function fails 'res' variable is set and a jump to 118 ** label 'test_cleanup' is performed. 119 ** 120 ** Every easy_* and multi_* macros have a res_easy_* and res_multi_* macro 121 ** counterpart that operates in the same way with the exception that no 122 ** jump takes place in case of failure. res_easy_* and res_multi_* macros 123 ** should be immediately followed by checking if 'res' variable has been 124 ** set. 125 ** 126 ** 'res' variable when set will hold a CURLcode, CURLMcode, or any of the 127 ** TEST_ERR_* values defined above. It is advisable to return this value 128 ** as test result. 129 */ 130 131 /* ---------------------------------------------------------------- */ 132 133 #define exe_easy_init(A,Y,Z) do { \ 134 if(((A) = curl_easy_init()) == NULL) { \ 135 fprintf(stderr, "%s:%d curl_easy_init() failed\n", (Y), (Z)); \ 136 res = TEST_ERR_EASY_INIT; \ 137 } \ 138 } while(0) 139 140 #define res_easy_init(A) \ 141 exe_easy_init((A), (__FILE__), (__LINE__)) 142 143 #define chk_easy_init(A,Y,Z) do { \ 144 exe_easy_init((A), (Y), (Z)); \ 145 if(res) \ 146 goto test_cleanup; \ 147 } while(0) 148 149 #define easy_init(A) \ 150 chk_easy_init((A), (__FILE__), (__LINE__)) 151 152 /* ---------------------------------------------------------------- */ 153 154 #define exe_multi_init(A,Y,Z) do { \ 155 if(((A) = curl_multi_init()) == NULL) { \ 156 fprintf(stderr, "%s:%d curl_multi_init() failed\n", (Y), (Z)); \ 157 res = TEST_ERR_MULTI; \ 158 } \ 159 } while(0) 160 161 #define res_multi_init(A) \ 162 exe_multi_init((A), (__FILE__), (__LINE__)) 163 164 #define chk_multi_init(A,Y,Z) do { \ 165 exe_multi_init((A), (Y), (Z)); \ 166 if(res) \ 167 goto test_cleanup; \ 168 } while(0) 169 170 #define multi_init(A) \ 171 chk_multi_init((A), (__FILE__), (__LINE__)) 172 173 /* ---------------------------------------------------------------- */ 174 175 #define exe_easy_setopt(A,B,C,Y,Z) do { \ 176 CURLcode ec; \ 177 if((ec = curl_easy_setopt((A), (B), (C))) != CURLE_OK) { \ 178 fprintf(stderr, "%s:%d curl_easy_setopt() failed, " \ 179 "with code %d (%s)\n", \ 180 (Y), (Z), (int)ec, curl_easy_strerror(ec)); \ 181 res = ec; \ 182 } \ 183 } while(0) 184 185 #define res_easy_setopt(A, B, C) \ 186 exe_easy_setopt((A), (B), (C), (__FILE__), (__LINE__)) 187 188 #define chk_easy_setopt(A, B, C, Y, Z) do { \ 189 exe_easy_setopt((A), (B), (C), (Y), (Z)); \ 190 if(res) \ 191 goto test_cleanup; \ 192 } while(0) 193 194 #define easy_setopt(A, B, C) \ 195 chk_easy_setopt((A), (B), (C), (__FILE__), (__LINE__)) 196 197 /* ---------------------------------------------------------------- */ 198 199 #define exe_multi_setopt(A, B, C, Y, Z) do { \ 200 CURLMcode ec; \ 201 if((ec = curl_multi_setopt((A), (B), (C))) != CURLM_OK) { \ 202 fprintf(stderr, "%s:%d curl_multi_setopt() failed, " \ 203 "with code %d (%s)\n", \ 204 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 205 res = TEST_ERR_MULTI; \ 206 } \ 207 } while(0) 208 209 #define res_multi_setopt(A,B,C) \ 210 exe_multi_setopt((A), (B), (C), (__FILE__), (__LINE__)) 211 212 #define chk_multi_setopt(A,B,C,Y,Z) do { \ 213 exe_multi_setopt((A), (B), (C), (Y), (Z)); \ 214 if(res) \ 215 goto test_cleanup; \ 216 } while(0) 217 218 #define multi_setopt(A,B,C) \ 219 chk_multi_setopt((A), (B), (C), (__FILE__), (__LINE__)) 220 221 /* ---------------------------------------------------------------- */ 222 223 #define exe_multi_add_handle(A,B,Y,Z) do { \ 224 CURLMcode ec; \ 225 if((ec = curl_multi_add_handle((A), (B))) != CURLM_OK) { \ 226 fprintf(stderr, "%s:%d curl_multi_add_handle() failed, " \ 227 "with code %d (%s)\n", \ 228 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 229 res = TEST_ERR_MULTI; \ 230 } \ 231 } while(0) 232 233 #define res_multi_add_handle(A, B) \ 234 exe_multi_add_handle((A), (B), (__FILE__), (__LINE__)) 235 236 #define chk_multi_add_handle(A, B, Y, Z) do { \ 237 exe_multi_add_handle((A), (B), (Y), (Z)); \ 238 if(res) \ 239 goto test_cleanup; \ 240 } while(0) 241 242 #define multi_add_handle(A, B) \ 243 chk_multi_add_handle((A), (B), (__FILE__), (__LINE__)) 244 245 /* ---------------------------------------------------------------- */ 246 247 #define exe_multi_remove_handle(A,B,Y,Z) do { \ 248 CURLMcode ec; \ 249 if((ec = curl_multi_remove_handle((A), (B))) != CURLM_OK) { \ 250 fprintf(stderr, "%s:%d curl_multi_remove_handle() failed, " \ 251 "with code %d (%s)\n", \ 252 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 253 res = TEST_ERR_MULTI; \ 254 } \ 255 } while(0) 256 257 #define res_multi_remove_handle(A, B) \ 258 exe_multi_remove_handle((A), (B), (__FILE__), (__LINE__)) 259 260 #define chk_multi_remove_handle(A, B, Y, Z) do { \ 261 exe_multi_remove_handle((A), (B), (Y), (Z)); \ 262 if(res) \ 263 goto test_cleanup; \ 264 } while(0) 265 266 267 #define multi_remove_handle(A, B) \ 268 chk_multi_remove_handle((A), (B), (__FILE__), (__LINE__)) 269 270 /* ---------------------------------------------------------------- */ 271 272 #define exe_multi_perform(A,B,Y,Z) do { \ 273 CURLMcode ec; \ 274 if((ec = curl_multi_perform((A), (B))) != CURLM_OK) { \ 275 fprintf(stderr, "%s:%d curl_multi_perform() failed, " \ 276 "with code %d (%s)\n", \ 277 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 278 res = TEST_ERR_MULTI; \ 279 } \ 280 else if(*((B)) < 0) { \ 281 fprintf(stderr, "%s:%d curl_multi_perform() succeeded, " \ 282 "but returned invalid running_handles value (%d)\n", \ 283 (Y), (Z), (int)*((B))); \ 284 res = TEST_ERR_NUM_HANDLES; \ 285 } \ 286 } while(0) 287 288 #define res_multi_perform(A, B) \ 289 exe_multi_perform((A), (B), (__FILE__), (__LINE__)) 290 291 #define chk_multi_perform(A, B, Y, Z) do { \ 292 exe_multi_perform((A), (B), (Y), (Z)); \ 293 if(res) \ 294 goto test_cleanup; \ 295 } while(0) 296 297 #define multi_perform(A,B) \ 298 chk_multi_perform((A), (B), (__FILE__), (__LINE__)) 299 300 /* ---------------------------------------------------------------- */ 301 302 #define exe_multi_fdset(A, B, C, D, E, Y, Z) do { \ 303 CURLMcode ec; \ 304 if((ec = curl_multi_fdset((A), (B), (C), (D), (E))) != CURLM_OK) { \ 305 fprintf(stderr, "%s:%d curl_multi_fdset() failed, " \ 306 "with code %d (%s)\n", \ 307 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 308 res = TEST_ERR_MULTI; \ 309 } \ 310 else if(*((E)) < -1) { \ 311 fprintf(stderr, "%s:%d curl_multi_fdset() succeeded, " \ 312 "but returned invalid max_fd value (%d)\n", \ 313 (Y), (Z), (int)*((E))); \ 314 res = TEST_ERR_NUM_HANDLES; \ 315 } \ 316 } while(0) 317 318 #define res_multi_fdset(A, B, C, D, E) \ 319 exe_multi_fdset((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 320 321 #define chk_multi_fdset(A, B, C, D, E, Y, Z) do { \ 322 exe_multi_fdset((A), (B), (C), (D), (E), (Y), (Z)); \ 323 if(res) \ 324 goto test_cleanup; \ 325 } while(0) 326 327 #define multi_fdset(A, B, C, D, E) \ 328 chk_multi_fdset((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 329 330 /* ---------------------------------------------------------------- */ 331 332 #define exe_multi_timeout(A,B,Y,Z) do { \ 333 CURLMcode ec; \ 334 if((ec = curl_multi_timeout((A), (B))) != CURLM_OK) { \ 335 fprintf(stderr, "%s:%d curl_multi_timeout() failed, " \ 336 "with code %d (%s)\n", \ 337 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 338 res = TEST_ERR_BAD_TIMEOUT; \ 339 } \ 340 else if(*((B)) < -1L) { \ 341 fprintf(stderr, "%s:%d curl_multi_timeout() succeeded, " \ 342 "but returned invalid timeout value (%ld)\n", \ 343 (Y), (Z), (long)*((B))); \ 344 res = TEST_ERR_BAD_TIMEOUT; \ 345 } \ 346 } while(0) 347 348 #define res_multi_timeout(A, B) \ 349 exe_multi_timeout((A), (B), (__FILE__), (__LINE__)) 350 351 #define chk_multi_timeout(A, B, Y, Z) do { \ 352 exe_multi_timeout((A), (B), (Y), (Z)); \ 353 if(res) \ 354 goto test_cleanup; \ 355 } while(0) 356 357 #define multi_timeout(A, B) \ 358 chk_multi_timeout((A), (B), (__FILE__), (__LINE__)) 359 360 /* ---------------------------------------------------------------- */ 361 362 #define exe_multi_poll(A,B,C,D,E,Y,Z) do { \ 363 CURLMcode ec; \ 364 if((ec = curl_multi_poll((A), (B), (C), (D), (E))) != CURLM_OK) { \ 365 fprintf(stderr, "%s:%d curl_multi_poll() failed, " \ 366 "with code %d (%s)\n", \ 367 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 368 res = TEST_ERR_MULTI; \ 369 } \ 370 else if(*((E)) < 0) { \ 371 fprintf(stderr, "%s:%d curl_multi_poll() succeeded, " \ 372 "but returned invalid numfds value (%d)\n", \ 373 (Y), (Z), (int)*((E))); \ 374 res = TEST_ERR_NUM_HANDLES; \ 375 } \ 376 } while(0) 377 378 #define res_multi_poll(A, B, C, D, E) \ 379 exe_multi_poll((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 380 381 #define chk_multi_poll(A, B, C, D, E, Y, Z) do { \ 382 exe_multi_poll((A), (B), (C), (D), (E), (Y), (Z)); \ 383 if(res) \ 384 goto test_cleanup; \ 385 } while(0) 386 387 #define multi_poll(A, B, C, D, E) \ 388 chk_multi_poll((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 389 390 /* ---------------------------------------------------------------- */ 391 392 #define exe_multi_wakeup(A,Y,Z) do { \ 393 CURLMcode ec; \ 394 if((ec = curl_multi_wakeup((A))) != CURLM_OK) { \ 395 fprintf(stderr, "%s:%d curl_multi_wakeup() failed, " \ 396 "with code %d (%s)\n", \ 397 (Y), (Z), (int)ec, curl_multi_strerror(ec)); \ 398 res = TEST_ERR_MULTI; \ 399 } \ 400 } while(0) 401 402 #define res_multi_wakeup(A) \ 403 exe_multi_wakeup((A), (__FILE__), (__LINE__)) 404 405 #define chk_multi_wakeup(A, Y, Z) do { \ 406 exe_multi_wakeup((A), (Y), (Z)); \ 407 if(res) \ 408 goto test_cleanup; \ 409 } while(0) 410 411 #define multi_wakeup(A) \ 412 chk_multi_wakeup((A), (__FILE__), (__LINE__)) 413 414 /* ---------------------------------------------------------------- */ 415 416 #define exe_select_test(A, B, C, D, E, Y, Z) do { \ 417 int ec; \ 418 if(select_wrapper((A), (B), (C), (D), (E)) == -1) { \ 419 ec = SOCKERRNO; \ 420 fprintf(stderr, "%s:%d select() failed, with " \ 421 "errno %d (%s)\n", \ 422 (Y), (Z), ec, strerror(ec)); \ 423 res = TEST_ERR_SELECT; \ 424 } \ 425 } while(0) 426 427 #define res_select_test(A, B, C, D, E) \ 428 exe_select_test((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 429 430 #define chk_select_test(A, B, C, D, E, Y, Z) do { \ 431 exe_select_test((A), (B), (C), (D), (E), (Y), (Z)); \ 432 if(res) \ 433 goto test_cleanup; \ 434 } while(0) 435 436 #define select_test(A, B, C, D, E) \ 437 chk_select_test((A), (B), (C), (D), (E), (__FILE__), (__LINE__)) 438 439 /* ---------------------------------------------------------------- */ 440 441 #define start_test_timing() do { \ 442 tv_test_start = tutil_tvnow(); \ 443 } while(0) 444 445 #define exe_test_timedout(Y,Z) do { \ 446 if(tutil_tvdiff(tutil_tvnow(), tv_test_start) > TEST_HANG_TIMEOUT) { \ 447 fprintf(stderr, "%s:%d ABORTING TEST, since it seems " \ 448 "that it would have run forever.\n", (Y), (Z)); \ 449 res = TEST_ERR_RUNS_FOREVER; \ 450 } \ 451 } while(0) 452 453 #define res_test_timedout() \ 454 exe_test_timedout((__FILE__), (__LINE__)) 455 456 #define chk_test_timedout(Y, Z) do { \ 457 exe_test_timedout(Y, Z); \ 458 if(res) \ 459 goto test_cleanup; \ 460 } while(0) 461 462 #define abort_on_test_timeout() \ 463 chk_test_timedout((__FILE__), (__LINE__)) 464 465 /* ---------------------------------------------------------------- */ 466 467 #define exe_global_init(A,Y,Z) do { \ 468 CURLcode ec; \ 469 if((ec = curl_global_init((A))) != CURLE_OK) { \ 470 fprintf(stderr, "%s:%d curl_global_init() failed, " \ 471 "with code %d (%s)\n", \ 472 (Y), (Z), (int)ec, curl_easy_strerror(ec)); \ 473 res = ec; \ 474 } \ 475 } while(0) 476 477 #define res_global_init(A) \ 478 exe_global_init((A), (__FILE__), (__LINE__)) 479 480 #define chk_global_init(A, Y, Z) do { \ 481 exe_global_init((A), (Y), (Z)); \ 482 if(res) \ 483 return res; \ 484 } while(0) 485 486 /* global_init() is different than other macros. In case of 487 failure it 'return's instead of going to 'test_cleanup'. */ 488 489 #define global_init(A) \ 490 chk_global_init((A), (__FILE__), (__LINE__)) 491 492 /* ---------------------------------------------------------------- */ 493