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