test_post_loop.c (19240B)
1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007 Christian Grothoff 4 Copyright (C) 2014-2022 Evgeny Grin (Karlson2k) 5 6 libmicrohttpd is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published 8 by the Free Software Foundation; either version 2, or (at your 9 option) any later version. 10 11 libmicrohttpd is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with libmicrohttpd; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1301, USA. 20 */ 21 22 /** 23 * @file daemontest_post_loop.c 24 * @brief Testcase for libmicrohttpd POST operations using URL-encoding 25 * @author Christian Grothoff (inspired by bug report #1296) 26 * @author Karlson2k (Evgeny Grin) 27 */ 28 29 #include "MHD_config.h" 30 #include "platform.h" 31 #include <curl/curl.h> 32 #include <microhttpd.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <time.h> 36 #include <errno.h> 37 #include "mhd_has_in_name.h" 38 39 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this 40 test into a marked, classifiable test error (TESTING.md, P5). */ 41 #include "mhd_panic_tripwire.h" 42 43 #ifndef WINDOWS 44 #include <unistd.h> 45 #endif 46 47 #if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 2 48 #undef MHD_CPU_COUNT 49 #endif 50 #if ! defined(MHD_CPU_COUNT) 51 #define MHD_CPU_COUNT 2 52 #endif 53 54 #define POST_DATA \ 55 "<?xml version='1.0' ?>\n<xml>\n<data-id>1</data-id>\n</xml>\n" 56 57 #ifndef __APPLE__ 58 #define LOOPCOUNT 1000 59 #else /* __APPLE__ */ 60 /* FIXME: macOS may fail in this test with "unable to connect". Investigate deeper? */ 61 #define LOOPCOUNT 200 62 #endif /* __APPLE__ */ 63 64 static int oneone; 65 66 struct CBC 67 { 68 char *buf; 69 size_t pos; 70 size_t size; 71 }; 72 73 static size_t 74 copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) 75 { 76 struct CBC *cbc = ctx; 77 78 if (cbc->pos + size * nmemb > cbc->size) 79 return 0; /* overflow */ 80 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); 81 cbc->pos += size * nmemb; 82 return size * nmemb; 83 } 84 85 86 static enum MHD_Result 87 ahc_echo (void *cls, 88 struct MHD_Connection *connection, 89 const char *url, 90 const char *method, 91 const char *version, 92 const char *upload_data, size_t *upload_data_size, 93 void **req_cls) 94 { 95 static int marker; 96 struct MHD_Response *response; 97 enum MHD_Result ret; 98 (void) cls; (void) url; (void) version; /* Unused. Silent compiler warning. */ 99 (void) upload_data; (void) upload_data_size; /* Unused. Silent compiler warning. */ 100 101 if (0 != strcmp ("POST", method)) 102 { 103 printf ("METHOD: %s\n", method); 104 return MHD_NO; /* unexpected method */ 105 } 106 if ((*req_cls != NULL) && (0 == *upload_data_size)) 107 { 108 if (*req_cls != &marker) 109 abort (); 110 response = MHD_create_response_from_buffer_static (2, 111 "OK"); 112 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 113 MHD_destroy_response (response); 114 *req_cls = NULL; 115 return ret; 116 } 117 if (strlen (POST_DATA) != *upload_data_size) 118 return MHD_YES; 119 *upload_data_size = 0; 120 *req_cls = ▮ 121 return MHD_YES; 122 } 123 124 125 static unsigned int 126 testInternalPost (void) 127 { 128 struct MHD_Daemon *d; 129 CURL *c; 130 char buf[2048]; 131 struct CBC cbc; 132 CURLcode errornum; 133 int i; 134 char url[1024]; 135 uint16_t port; 136 137 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 138 port = 0; 139 else 140 { 141 port = 1350; 142 if (oneone) 143 port += 10; 144 } 145 146 cbc.buf = buf; 147 cbc.size = 2048; 148 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 149 port, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); 150 if (d == NULL) 151 return 1; 152 if (0 == port) 153 { 154 const union MHD_DaemonInfo *dinfo; 155 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 156 if ((NULL == dinfo) || (0 == dinfo->port) ) 157 { 158 MHD_stop_daemon (d); return 32; 159 } 160 port = dinfo->port; 161 } 162 for (i = 0; i < LOOPCOUNT; i++) 163 { 164 if (99 == i % 100) 165 fprintf (stderr, "."); 166 c = curl_easy_init (); 167 cbc.pos = 0; 168 buf[0] = '\0'; 169 snprintf (url, 170 sizeof (url), 171 "http://127.0.0.1:%u/hw%d", 172 (unsigned int) port, 173 i); 174 curl_easy_setopt (c, CURLOPT_URL, url); 175 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 176 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 177 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); 178 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); 179 curl_easy_setopt (c, CURLOPT_POST, 1L); 180 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 181 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 182 if (oneone) 183 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 184 else 185 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 186 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); 187 /* NOTE: use of CONNECTTIMEOUT without also 188 * setting NOSIGNAL results in really weird 189 * crashes on my system! */ 190 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 191 if (CURLE_OK != (errornum = curl_easy_perform (c))) 192 { 193 fprintf (stderr, 194 "curl_easy_perform failed: `%s'\n", 195 curl_easy_strerror (errornum)); 196 curl_easy_cleanup (c); 197 MHD_stop_daemon (d); 198 return 2; 199 } 200 curl_easy_cleanup (c); 201 if ((buf[0] != 'O') || (buf[1] != 'K')) 202 { 203 MHD_stop_daemon (d); 204 return 4; 205 } 206 } 207 MHD_stop_daemon (d); 208 if (LOOPCOUNT >= 99) 209 fprintf (stderr, "\n"); 210 return 0; 211 } 212 213 214 static unsigned int 215 testMultithreadedPost (void) 216 { 217 struct MHD_Daemon *d; 218 CURL *c; 219 char buf[2048]; 220 struct CBC cbc; 221 CURLcode errornum; 222 int i; 223 char url[1024]; 224 uint16_t port; 225 226 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 227 port = 0; 228 else 229 { 230 port = 1351; 231 if (oneone) 232 port += 10; 233 } 234 235 cbc.buf = buf; 236 cbc.size = 2048; 237 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION 238 | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 239 port, NULL, NULL, 240 &ahc_echo, NULL, 241 MHD_OPTION_END); 242 if (d == NULL) 243 return 16; 244 if (0 == port) 245 { 246 const union MHD_DaemonInfo *dinfo; 247 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 248 if ((NULL == dinfo) || (0 == dinfo->port) ) 249 { 250 MHD_stop_daemon (d); return 32; 251 } 252 port = dinfo->port; 253 } 254 for (i = 0; i < LOOPCOUNT; i++) 255 { 256 if (99 == i % 100) 257 fprintf (stderr, "."); 258 c = curl_easy_init (); 259 cbc.pos = 0; 260 buf[0] = '\0'; 261 snprintf (url, 262 sizeof (url), 263 "http://127.0.0.1:%u/hw%d", 264 (unsigned int) port, 265 i); 266 curl_easy_setopt (c, CURLOPT_URL, url); 267 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 268 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 269 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); 270 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); 271 curl_easy_setopt (c, CURLOPT_POST, 1L); 272 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 273 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 274 if (oneone) 275 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 276 else 277 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 278 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); 279 /* NOTE: use of CONNECTTIMEOUT without also 280 * setting NOSIGNAL results in really weird 281 * crashes on my system! */ 282 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 283 if (CURLE_OK != (errornum = curl_easy_perform (c))) 284 { 285 fprintf (stderr, 286 "curl_easy_perform failed: `%s'\n", 287 curl_easy_strerror (errornum)); 288 curl_easy_cleanup (c); 289 MHD_stop_daemon (d); 290 return 32; 291 } 292 curl_easy_cleanup (c); 293 if ((buf[0] != 'O') || (buf[1] != 'K')) 294 { 295 MHD_stop_daemon (d); 296 return 64; 297 } 298 } 299 MHD_stop_daemon (d); 300 if (LOOPCOUNT >= 99) 301 fprintf (stderr, "\n"); 302 return 0; 303 } 304 305 306 static unsigned int 307 testMultithreadedPoolPost (void) 308 { 309 struct MHD_Daemon *d; 310 CURL *c; 311 char buf[2048]; 312 struct CBC cbc; 313 CURLcode errornum; 314 int i; 315 char url[1024]; 316 uint16_t port; 317 318 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 319 port = 0; 320 else 321 { 322 port = 1352; 323 if (oneone) 324 port += 10; 325 } 326 327 cbc.buf = buf; 328 cbc.size = 2048; 329 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 330 port, NULL, NULL, &ahc_echo, NULL, 331 MHD_OPTION_THREAD_POOL_SIZE, MHD_CPU_COUNT, 332 MHD_OPTION_END); 333 if (d == NULL) 334 return 16; 335 if (0 == port) 336 { 337 const union MHD_DaemonInfo *dinfo; 338 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 339 if ((NULL == dinfo) || (0 == dinfo->port) ) 340 { 341 MHD_stop_daemon (d); return 32; 342 } 343 port = dinfo->port; 344 } 345 for (i = 0; i < LOOPCOUNT; i++) 346 { 347 if (99 == i % 100) 348 fprintf (stderr, "."); 349 c = curl_easy_init (); 350 cbc.pos = 0; 351 buf[0] = '\0'; 352 snprintf (url, 353 sizeof (url), 354 "http://127.0.0.1:%u/hw%d", 355 (unsigned int) port, 356 i); 357 curl_easy_setopt (c, CURLOPT_URL, url); 358 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 359 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 360 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); 361 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); 362 curl_easy_setopt (c, CURLOPT_POST, 1L); 363 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 364 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 365 if (oneone) 366 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 367 else 368 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 369 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); 370 /* NOTE: use of CONNECTTIMEOUT without also 371 * setting NOSIGNAL results in really weird 372 * crashes on my system! */ 373 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 374 if (CURLE_OK != (errornum = curl_easy_perform (c))) 375 { 376 fprintf (stderr, 377 "curl_easy_perform failed: `%s'\n", 378 curl_easy_strerror (errornum)); 379 curl_easy_cleanup (c); 380 MHD_stop_daemon (d); 381 return 32; 382 } 383 curl_easy_cleanup (c); 384 if ((buf[0] != 'O') || (buf[1] != 'K')) 385 { 386 MHD_stop_daemon (d); 387 return 64; 388 } 389 } 390 MHD_stop_daemon (d); 391 if (LOOPCOUNT >= 99) 392 fprintf (stderr, "\n"); 393 return 0; 394 } 395 396 397 static unsigned int 398 testExternalPost (void) 399 { 400 struct MHD_Daemon *d; 401 CURL *c; 402 char buf[2048]; 403 struct CBC cbc; 404 CURLM *multi; 405 CURLMcode mret; 406 fd_set rs; 407 fd_set ws; 408 fd_set es; 409 MHD_socket maxsock; 410 #ifdef MHD_WINSOCK_SOCKETS 411 int maxposixs; /* Max socket number unused on W32 */ 412 #else /* MHD_POSIX_SOCKETS */ 413 #define maxposixs maxsock 414 #endif /* MHD_POSIX_SOCKETS */ 415 int running; 416 struct CURLMsg *msg; 417 time_t start; 418 struct timeval tv; 419 int i; 420 uint64_t timeout64; 421 long ctimeout; 422 char url[1024]; 423 uint16_t port; 424 425 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 426 port = 0; 427 else 428 { 429 port = 1353; 430 if (oneone) 431 port += 10; 432 } 433 434 multi = NULL; 435 cbc.buf = buf; 436 cbc.size = 2048; 437 cbc.pos = 0; 438 d = MHD_start_daemon (MHD_USE_ERROR_LOG | MHD_USE_NO_THREAD_SAFETY, 439 port, NULL, NULL, &ahc_echo, NULL, 440 MHD_OPTION_APP_FD_SETSIZE, (int) FD_SETSIZE, 441 MHD_OPTION_END); 442 if (d == NULL) 443 return 256; 444 if (0 == port) 445 { 446 const union MHD_DaemonInfo *dinfo; 447 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 448 if ((NULL == dinfo) || (0 == dinfo->port) ) 449 { 450 MHD_stop_daemon (d); return 32; 451 } 452 port = dinfo->port; 453 } 454 multi = curl_multi_init (); 455 if (multi == NULL) 456 { 457 MHD_stop_daemon (d); 458 return 512; 459 } 460 for (i = 0; i < LOOPCOUNT; i++) 461 { 462 if (99 == i % 100) 463 fprintf (stderr, "."); 464 c = curl_easy_init (); 465 cbc.pos = 0; 466 buf[0] = '\0'; 467 snprintf (url, 468 sizeof (url), 469 "http://127.0.0.1:%u/hw%d", 470 (unsigned int) port, 471 i); 472 curl_easy_setopt (c, CURLOPT_URL, url); 473 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 474 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 475 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); 476 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); 477 curl_easy_setopt (c, CURLOPT_POST, 1L); 478 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 479 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 480 if (oneone) 481 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 482 else 483 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 484 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); 485 /* NOTE: use of CONNECTTIMEOUT without also 486 * setting NOSIGNAL results in really weird 487 * crashes on my system! */ 488 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 489 mret = curl_multi_add_handle (multi, c); 490 if (mret != CURLM_OK) 491 { 492 curl_multi_cleanup (multi); 493 curl_easy_cleanup (c); 494 MHD_stop_daemon (d); 495 return 1024; 496 } 497 start = time (NULL); 498 while ((time (NULL) - start < 5) && (multi != NULL)) 499 { 500 maxsock = MHD_INVALID_SOCKET; 501 maxposixs = -1; 502 FD_ZERO (&rs); 503 FD_ZERO (&ws); 504 FD_ZERO (&es); 505 while (CURLM_CALL_MULTI_PERFORM == 506 curl_multi_perform (multi, &running)) 507 ; 508 mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs); 509 if (mret != CURLM_OK) 510 { 511 curl_multi_remove_handle (multi, c); 512 curl_multi_cleanup (multi); 513 curl_easy_cleanup (c); 514 MHD_stop_daemon (d); 515 return 2048; 516 } 517 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock)) 518 { 519 curl_multi_remove_handle (multi, c); 520 curl_multi_cleanup (multi); 521 curl_easy_cleanup (c); 522 MHD_stop_daemon (d); 523 return 4096; 524 } 525 if (MHD_NO == MHD_get_timeout64 (d, &timeout64)) 526 timeout64 = 100; /* 100ms == INFTY -- CURL bug... */ 527 if ((CURLM_OK == curl_multi_timeout (multi, &ctimeout)) && 528 (ctimeout >= 0) && ((uint64_t) ctimeout < timeout64)) 529 timeout64 = (uint64_t) ctimeout; 530 if (0 == running) 531 timeout64 = 0; /* terminate quickly... */ 532 #if ! defined(_WIN32) || defined(__CYGWIN__) 533 tv.tv_sec = (time_t) (timeout64 / 1000); 534 #else /* Native W32 */ 535 tv.tv_sec = (long) (timeout64 / 1000); 536 #endif /* Native W32 */ 537 tv.tv_usec = (long) (1000 * (timeout64 % 1000)); 538 if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv)) 539 { 540 #ifdef MHD_POSIX_SOCKETS 541 if (EINTR != errno) 542 { 543 fprintf (stderr, "Unexpected select() error: %d. Line: %d\n", 544 (int) errno, __LINE__); 545 fflush (stderr); 546 exit (99); 547 } 548 #else 549 if ((WSAEINVAL != WSAGetLastError ()) || 550 (0 != rs.fd_count) || (0 != ws.fd_count) || (0 != es.fd_count) ) 551 { 552 fprintf (stderr, "Unexpected select() error: %d. Line: %d\n", 553 (int) WSAGetLastError (), __LINE__); 554 fflush (stderr); 555 exit (99); 556 } 557 Sleep (1); 558 #endif 559 } 560 while (CURLM_CALL_MULTI_PERFORM == 561 curl_multi_perform (multi, &running)) 562 ; 563 if (0 == running) 564 { 565 int pending; 566 int curl_fine = 0; 567 while (NULL != (msg = curl_multi_info_read (multi, &pending))) 568 { 569 if (msg->msg == CURLMSG_DONE) 570 { 571 if (msg->data.result == CURLE_OK) 572 curl_fine = 1; 573 else 574 { 575 fprintf (stderr, 576 "%s failed at %s:%d: `%s'\n", 577 "curl_multi_perform", 578 __FILE__, 579 __LINE__, curl_easy_strerror (msg->data.result)); 580 abort (); 581 } 582 } 583 } 584 if (! curl_fine) 585 { 586 fprintf (stderr, "libcurl haven't returned OK code\n"); 587 abort (); 588 } 589 break; 590 } 591 MHD_run (d); 592 } 593 if (NULL != c) 594 { 595 curl_multi_remove_handle (multi, c); 596 curl_easy_cleanup (c); 597 } 598 if ((buf[0] != 'O') || (buf[1] != 'K')) 599 { 600 curl_multi_cleanup (multi); 601 MHD_stop_daemon (d); 602 return 8192; 603 } 604 } 605 curl_multi_cleanup (multi); 606 MHD_stop_daemon (d); 607 if (LOOPCOUNT >= 99) 608 fprintf (stderr, "\n"); 609 return 0; 610 } 611 612 613 /** 614 * Time this round was started. 615 */ 616 static unsigned long long start_time; 617 618 619 /** 620 * Get the current timestamp 621 * 622 * @return current time in ms 623 */ 624 static unsigned long long 625 now (void) 626 { 627 struct timeval tv; 628 629 gettimeofday (&tv, NULL); 630 return (((unsigned long long) tv.tv_sec * 1000LL) 631 + ((unsigned long long) tv.tv_usec / 1000LL)); 632 } 633 634 635 int 636 main (int argc, char *const *argv) 637 { 638 unsigned int errorCount = 0; 639 (void) argc; /* Unused. Silent compiler warning. */ 640 641 if ((NULL == argv) || (0 == argv[0])) 642 return 99; 643 oneone = has_in_name (argv[0], "11"); 644 if (0 != curl_global_init (CURL_GLOBAL_WIN32)) 645 return 2; 646 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS)) 647 { 648 start_time = now (); 649 errorCount += testInternalPost (); 650 fprintf (stderr, 651 oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : 652 "%s: Sequential POSTs (http/1.0) %f/s\n", 653 "internal select", 654 (double) 1000 * LOOPCOUNT 655 / ((double) (now () - start_time) + 1.0)); 656 start_time = now (); 657 errorCount += testMultithreadedPost (); 658 fprintf (stderr, 659 oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : 660 "%s: Sequential POSTs (http/1.0) %f/s\n", 661 "multithreaded post", 662 (double) 1000 * LOOPCOUNT 663 / ((double) (now () - start_time) + 1.0)); 664 start_time = now (); 665 errorCount += testMultithreadedPoolPost (); 666 fprintf (stderr, 667 oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : 668 "%s: Sequential POSTs (http/1.0) %f/s\n", 669 "thread with pool", 670 (double) 1000 * LOOPCOUNT 671 / ((double) (now () - start_time) + 1.0)); 672 } 673 start_time = now (); 674 errorCount += testExternalPost (); 675 fprintf (stderr, 676 oneone ? "%s: Sequential POSTs (http/1.1) %f/s\n" : 677 "%s: Sequential POSTs (http/1.0) %f/s\n", 678 "external select", 679 (double) 1000 * LOOPCOUNT 680 / ((double) (now () - start_time) + 1.0)); 681 if (errorCount != 0) 682 fprintf (stderr, "Error (code: %u)\n", errorCount); 683 curl_global_cleanup (); 684 return (0 == errorCount) ? 0 : 1; /* 0 == pass */ 685 }