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