Home | History | Annotate | Download | only in testcurl
      1 /*
      2      This file is part of libmicrohttpd
      3      Copyright (C) 2007, 2009, 2011 Christian Grothoff
      4 
      5      libmicrohttpd is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 2, or (at your
      8      option) any later version.
      9 
     10      libmicrohttpd is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libmicrohttpd; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     18      Boston, MA 02111-1307, USA.
     19 */
     20 
     21 /**
     22  * @file test_get.c
     23  * @brief  Testcase for libmicrohttpd GET operations
     24  *         TODO: test parsing of query
     25  * @author Christian Grothoff
     26  */
     27 
     28 #include "MHD_config.h"
     29 #include "platform.h"
     30 #include "platform_interface.h"
     31 #include <curl/curl.h>
     32 #include <microhttpd.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <time.h>
     36 
     37 #ifdef _WIN32
     38 #ifndef WIN32_LEAN_AND_MEAN
     39 #define WIN32_LEAN_AND_MEAN 1
     40 #endif /* !WIN32_LEAN_AND_MEAN */
     41 #include <windows.h>
     42 #endif
     43 
     44 #ifndef WINDOWS
     45 #include <unistd.h>
     46 #include <sys/socket.h>
     47 #endif
     48 
     49 #if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
     50 #undef CPU_COUNT
     51 #endif
     52 #if !defined(CPU_COUNT)
     53 #define CPU_COUNT 2
     54 #endif
     55 
     56 static int oneone;
     57 
     58 struct CBC
     59 {
     60   char *buf;
     61   size_t pos;
     62   size_t size;
     63 };
     64 
     65 static size_t
     66 copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
     67 {
     68   struct CBC *cbc = ctx;
     69 
     70   if (cbc->pos + size * nmemb > cbc->size)
     71     return 0;                   /* overflow */
     72   memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
     73   cbc->pos += size * nmemb;
     74   return size * nmemb;
     75 }
     76 
     77 static int
     78 ahc_echo (void *cls,
     79           struct MHD_Connection *connection,
     80           const char *url,
     81           const char *method,
     82           const char *version,
     83           const char *upload_data, size_t *upload_data_size,
     84           void **unused)
     85 {
     86   static int ptr;
     87   const char *me = cls;
     88   struct MHD_Response *response;
     89   int ret;
     90 
     91   if (0 != strcmp (me, method))
     92     return MHD_NO;              /* unexpected method */
     93   if (&ptr != *unused)
     94     {
     95       *unused = &ptr;
     96       return MHD_YES;
     97     }
     98   *unused = NULL;
     99   response = MHD_create_response_from_buffer (strlen (url),
    100 					      (void *) url,
    101 					      MHD_RESPMEM_MUST_COPY);
    102   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
    103   MHD_destroy_response (response);
    104   if (ret == MHD_NO)
    105     abort ();
    106   return ret;
    107 }
    108 
    109 
    110 static int
    111 testInternalGet (int poll_flag)
    112 {
    113   struct MHD_Daemon *d;
    114   CURL *c;
    115   char buf[2048];
    116   struct CBC cbc;
    117   CURLcode errornum;
    118 
    119   cbc.buf = buf;
    120   cbc.size = 2048;
    121   cbc.pos = 0;
    122   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG  | poll_flag,
    123                         11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
    124   if (d == NULL)
    125     return 1;
    126   c = curl_easy_init ();
    127   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11080/hello_world");
    128   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    129   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    130   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    131   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    132   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    133   if (oneone)
    134     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    135   else
    136     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    137   /* NOTE: use of CONNECTTIMEOUT without also
    138      setting NOSIGNAL results in really weird
    139      crashes on my system!*/
    140   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    141   if (CURLE_OK != (errornum = curl_easy_perform (c)))
    142     {
    143       fprintf (stderr,
    144                "curl_easy_perform failed: `%s'\n",
    145                curl_easy_strerror (errornum));
    146       curl_easy_cleanup (c);
    147       MHD_stop_daemon (d);
    148       return 2;
    149     }
    150   curl_easy_cleanup (c);
    151   MHD_stop_daemon (d);
    152   if (cbc.pos != strlen ("/hello_world"))
    153     return 4;
    154   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    155     return 8;
    156   return 0;
    157 }
    158 
    159 
    160 static int
    161 testMultithreadedGet (int poll_flag)
    162 {
    163   struct MHD_Daemon *d;
    164   CURL *c;
    165   char buf[2048];
    166   struct CBC cbc;
    167   CURLcode errornum;
    168 
    169   cbc.buf = buf;
    170   cbc.size = 2048;
    171   cbc.pos = 0;
    172   d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG  | poll_flag,
    173                         1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
    174   if (d == NULL)
    175     return 16;
    176   c = curl_easy_init ();
    177   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
    178   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    179   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    180   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    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, 1);
    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 32;
    199     }
    200   curl_easy_cleanup (c);
    201   MHD_stop_daemon (d);
    202   if (cbc.pos != strlen ("/hello_world"))
    203     return 64;
    204   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    205     return 128;
    206   return 0;
    207 }
    208 
    209 
    210 static int
    211 testMultithreadedPoolGet (int poll_flag)
    212 {
    213   struct MHD_Daemon *d;
    214   CURL *c;
    215   char buf[2048];
    216   struct CBC cbc;
    217   CURLcode errornum;
    218 
    219   cbc.buf = buf;
    220   cbc.size = 2048;
    221   cbc.pos = 0;
    222   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag,
    223                         1081, NULL, NULL, &ahc_echo, "GET",
    224                         MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END);
    225   if (d == NULL)
    226     return 16;
    227   c = curl_easy_init ();
    228   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
    229   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    230   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    231   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    232   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    233   if (oneone)
    234     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    235   else
    236     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    237   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    238   /* NOTE: use of CONNECTTIMEOUT without also
    239      setting NOSIGNAL results in really weird
    240      crashes on my system!*/
    241   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    242   if (CURLE_OK != (errornum = curl_easy_perform (c)))
    243     {
    244       fprintf (stderr,
    245                "curl_easy_perform failed: `%s'\n",
    246                curl_easy_strerror (errornum));
    247       curl_easy_cleanup (c);
    248       MHD_stop_daemon (d);
    249       return 32;
    250     }
    251   curl_easy_cleanup (c);
    252   MHD_stop_daemon (d);
    253   if (cbc.pos != strlen ("/hello_world"))
    254     return 64;
    255   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    256     return 128;
    257   return 0;
    258 }
    259 
    260 
    261 static int
    262 testExternalGet ()
    263 {
    264   struct MHD_Daemon *d;
    265   CURL *c;
    266   char buf[2048];
    267   struct CBC cbc;
    268   CURLM *multi;
    269   CURLMcode mret;
    270   fd_set rs;
    271   fd_set ws;
    272   fd_set es;
    273   MHD_socket max;
    274   int running;
    275   struct CURLMsg *msg;
    276   time_t start;
    277   struct timeval tv;
    278 
    279   multi = NULL;
    280   cbc.buf = buf;
    281   cbc.size = 2048;
    282   cbc.pos = 0;
    283   d = MHD_start_daemon (MHD_USE_DEBUG,
    284                         1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
    285   if (d == NULL)
    286     return 256;
    287   c = curl_easy_init ();
    288   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1082/hello_world");
    289   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    290   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    291   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    292   if (oneone)
    293     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    294   else
    295     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    296   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    297   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    298   /* NOTE: use of CONNECTTIMEOUT without also
    299      setting NOSIGNAL results in really weird
    300      crashes on my system! */
    301   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    302 
    303 
    304   multi = curl_multi_init ();
    305   if (multi == NULL)
    306     {
    307       curl_easy_cleanup (c);
    308       MHD_stop_daemon (d);
    309       return 512;
    310     }
    311   mret = curl_multi_add_handle (multi, c);
    312   if (mret != CURLM_OK)
    313     {
    314       curl_multi_cleanup (multi);
    315       curl_easy_cleanup (c);
    316       MHD_stop_daemon (d);
    317       return 1024;
    318     }
    319   start = time (NULL);
    320   while ((time (NULL) - start < 5) && (multi != NULL))
    321     {
    322       max = 0;
    323       FD_ZERO (&rs);
    324       FD_ZERO (&ws);
    325       FD_ZERO (&es);
    326       curl_multi_perform (multi, &running);
    327       mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
    328       if (mret != CURLM_OK)
    329         {
    330           curl_multi_remove_handle (multi, c);
    331           curl_multi_cleanup (multi);
    332           curl_easy_cleanup (c);
    333           MHD_stop_daemon (d);
    334           return 2048;
    335         }
    336       if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
    337         {
    338           curl_multi_remove_handle (multi, c);
    339           curl_multi_cleanup (multi);
    340           curl_easy_cleanup (c);
    341           MHD_stop_daemon (d);
    342           return 4096;
    343         }
    344       tv.tv_sec = 0;
    345       tv.tv_usec = 1000;
    346       select (max + 1, &rs, &ws, &es, &tv);
    347       curl_multi_perform (multi, &running);
    348       if (running == 0)
    349         {
    350           msg = curl_multi_info_read (multi, &running);
    351           if (msg == NULL)
    352             break;
    353           if (msg->msg == CURLMSG_DONE)
    354             {
    355               if (msg->data.result != CURLE_OK)
    356                 printf ("%s failed at %s:%d: `%s'\n",
    357                         "curl_multi_perform",
    358                         __FILE__,
    359                         __LINE__, curl_easy_strerror (msg->data.result));
    360               curl_multi_remove_handle (multi, c);
    361               curl_multi_cleanup (multi);
    362               curl_easy_cleanup (c);
    363               c = NULL;
    364               multi = NULL;
    365             }
    366         }
    367       MHD_run (d);
    368     }
    369   if (multi != NULL)
    370     {
    371       curl_multi_remove_handle (multi, c);
    372       curl_easy_cleanup (c);
    373       curl_multi_cleanup (multi);
    374     }
    375   MHD_stop_daemon (d);
    376   if (cbc.pos != strlen ("/hello_world"))
    377     return 8192;
    378   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    379     return 16384;
    380   return 0;
    381 }
    382 
    383 
    384 static int
    385 testUnknownPortGet (int poll_flag)
    386 {
    387   struct MHD_Daemon *d;
    388   const union MHD_DaemonInfo *di;
    389   CURL *c;
    390   char buf[2048];
    391   struct CBC cbc;
    392   CURLcode errornum;
    393 
    394   struct sockaddr_in addr;
    395   socklen_t addr_len = sizeof(addr);
    396   memset(&addr, 0, sizeof(addr));
    397   addr.sin_family = AF_INET;
    398   addr.sin_port = 0;
    399   addr.sin_addr.s_addr = INADDR_ANY;
    400 
    401   cbc.buf = buf;
    402   cbc.size = 2048;
    403   cbc.pos = 0;
    404   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG  | poll_flag,
    405                         1, NULL, NULL, &ahc_echo, "GET",
    406                         MHD_OPTION_SOCK_ADDR, &addr,
    407                         MHD_OPTION_END);
    408   if (d == NULL)
    409     return 32768;
    410 
    411   di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_LISTEN_FD);
    412   if (di == NULL)
    413     return 65536;
    414 
    415   if (0 != getsockname(di->listen_fd, (struct sockaddr *) &addr, &addr_len))
    416     return 131072;
    417 
    418   if (addr.sin_family != AF_INET)
    419     return 26214;
    420 
    421   snprintf(buf, sizeof(buf), "http://127.0.0.1:%hu/hello_world",
    422            ntohs(addr.sin_port));
    423 
    424   c = curl_easy_init ();
    425   curl_easy_setopt (c, CURLOPT_URL, buf);
    426   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    427   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    428   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    429   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    430   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    431   if (oneone)
    432     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    433   else
    434     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    435   /* NOTE: use of CONNECTTIMEOUT without also
    436      setting NOSIGNAL results in really weird
    437      crashes on my system! */
    438   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    439   if (CURLE_OK != (errornum = curl_easy_perform (c)))
    440     {
    441       fprintf (stderr,
    442                "curl_easy_perform failed: `%s'\n",
    443                curl_easy_strerror (errornum));
    444       curl_easy_cleanup (c);
    445       MHD_stop_daemon (d);
    446       return 524288;
    447     }
    448   curl_easy_cleanup (c);
    449   MHD_stop_daemon (d);
    450   if (cbc.pos != strlen ("/hello_world"))
    451     return 1048576;
    452   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    453     return 2097152;
    454   return 0;
    455 }
    456 
    457 
    458 static int
    459 testStopRace (int poll_flag)
    460 {
    461     struct sockaddr_in sin;
    462     MHD_socket fd;
    463     struct MHD_Daemon *d;
    464 
    465     d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG | poll_flag,
    466                          1081, NULL, NULL, &ahc_echo, "GET",
    467                          MHD_OPTION_CONNECTION_TIMEOUT, 5, MHD_OPTION_END);
    468     if (d == NULL)
    469        return 16;
    470 
    471     fd = socket (PF_INET, SOCK_STREAM, 0);
    472     if (fd == MHD_INVALID_SOCKET)
    473     {
    474        fprintf(stderr, "socket error\n");
    475        return 256;
    476     }
    477 
    478     memset(&sin, 0, sizeof(sin));
    479     sin.sin_family = AF_INET;
    480     sin.sin_port = htons(1081);
    481     sin.sin_addr.s_addr = htonl(0x7f000001);
    482 
    483     if (connect (fd, (struct sockaddr *)(&sin), sizeof(sin)) < 0)
    484     {
    485        fprintf(stderr, "connect error\n");
    486        MHD_socket_close_ (fd);
    487        return 512;
    488     }
    489 
    490     /*  printf("Waiting\n"); */
    491     /* Let the thread get going. */
    492     usleep(500000);
    493 
    494     /* printf("Stopping daemon\n"); */
    495     MHD_stop_daemon (d);
    496 
    497     MHD_socket_close_ (fd);
    498 
    499     /* printf("good\n"); */
    500     return 0;
    501 }
    502 
    503 
    504 static int
    505 ahc_empty (void *cls,
    506           struct MHD_Connection *connection,
    507           const char *url,
    508           const char *method,
    509           const char *version,
    510           const char *upload_data, size_t *upload_data_size,
    511           void **unused)
    512 {
    513   static int ptr;
    514   struct MHD_Response *response;
    515   int ret;
    516 
    517   if (0 != strcmp ("GET", method))
    518     return MHD_NO;              /* unexpected method */
    519   if (&ptr != *unused)
    520     {
    521       *unused = &ptr;
    522       return MHD_YES;
    523     }
    524   *unused = NULL;
    525   response = MHD_create_response_from_buffer (0,
    526 					      NULL,
    527 					      MHD_RESPMEM_PERSISTENT);
    528   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
    529   MHD_destroy_response (response);
    530   if (ret == MHD_NO)
    531     abort ();
    532   return ret;
    533 }
    534 
    535 
    536 static int
    537 curlExcessFound(CURL *c, curl_infotype type, char *data, size_t size, void *cls)
    538 {
    539   static const char *excess_found = "Excess found";
    540   const size_t str_size = strlen (excess_found);
    541 
    542   if (CURLINFO_TEXT == type
    543       && size >= str_size
    544       && 0 == strncmp(excess_found, data, str_size))
    545     *(int *)cls = 1;
    546   return 0;
    547 }
    548 
    549 
    550 static int
    551 testEmptyGet (int poll_flag)
    552 {
    553   struct MHD_Daemon *d;
    554   CURL *c;
    555   char buf[2048];
    556   struct CBC cbc;
    557   CURLcode errornum;
    558   int excess_found = 0;
    559 
    560   cbc.buf = buf;
    561   cbc.size = 2048;
    562   cbc.pos = 0;
    563   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG  | poll_flag,
    564                         11081, NULL, NULL, &ahc_empty, NULL, MHD_OPTION_END);
    565   if (d == NULL)
    566     return 4194304;
    567   c = curl_easy_init ();
    568   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11081/hello_world");
    569   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    570   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    571   curl_easy_setopt (c, CURLOPT_DEBUGFUNCTION, &curlExcessFound);
    572   curl_easy_setopt (c, CURLOPT_DEBUGDATA, &excess_found);
    573   curl_easy_setopt (c, CURLOPT_VERBOSE, 1);
    574   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    575   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    576   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    577   if (oneone)
    578     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    579   else
    580     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    581   /* NOTE: use of CONNECTTIMEOUT without also
    582      setting NOSIGNAL results in really weird
    583      crashes on my system!*/
    584   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    585   if (CURLE_OK != (errornum = curl_easy_perform (c)))
    586     {
    587       fprintf (stderr,
    588                "curl_easy_perform failed: `%s'\n",
    589                curl_easy_strerror (errornum));
    590       curl_easy_cleanup (c);
    591       MHD_stop_daemon (d);
    592       return 8388608;
    593     }
    594   curl_easy_cleanup (c);
    595   MHD_stop_daemon (d);
    596   if (cbc.pos != 0)
    597     return 16777216;
    598   if (excess_found)
    599     return 33554432;
    600   return 0;
    601 }
    602 
    603 
    604 int
    605 main (int argc, char *const *argv)
    606 {
    607   unsigned int errorCount = 0;
    608 
    609   oneone = (NULL != strrchr (argv[0], (int) '/')) ?
    610     (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
    611   if (0 != curl_global_init (CURL_GLOBAL_WIN32))
    612     return 2;
    613   errorCount += testInternalGet (0);
    614   errorCount += testMultithreadedGet (0);
    615   errorCount += testMultithreadedPoolGet (0);
    616   errorCount += testUnknownPortGet (0);
    617   errorCount += testStopRace (0);
    618   errorCount += testExternalGet ();
    619   errorCount += testEmptyGet (0);
    620   if (MHD_YES == MHD_is_feature_supported(MHD_FEATURE_POLL))
    621     {
    622       errorCount += testInternalGet(MHD_USE_POLL);
    623       errorCount += testMultithreadedGet(MHD_USE_POLL);
    624       errorCount += testMultithreadedPoolGet(MHD_USE_POLL);
    625       errorCount += testUnknownPortGet(MHD_USE_POLL);
    626       errorCount += testStopRace(MHD_USE_POLL);
    627       errorCount += testEmptyGet(MHD_USE_POLL);
    628     }
    629   if (MHD_YES == MHD_is_feature_supported(MHD_FEATURE_EPOLL))
    630     {
    631       errorCount += testInternalGet(MHD_USE_EPOLL_LINUX_ONLY);
    632       errorCount += testMultithreadedPoolGet(MHD_USE_EPOLL_LINUX_ONLY);
    633       errorCount += testUnknownPortGet(MHD_USE_EPOLL_LINUX_ONLY);
    634       errorCount += testEmptyGet(MHD_USE_EPOLL_LINUX_ONLY);
    635     }
    636   if (errorCount != 0)
    637     fprintf (stderr, "Error (code: %u)\n", errorCount);
    638   curl_global_cleanup ();
    639   return errorCount != 0;       /* 0 == pass */
    640 }
    641