Home | History | Annotate | Download | only in testcurl
      1 /* DO NOT CHANGE THIS LINE */
      2 /*
      3      This file is part of libmicrohttpd
      4      Copyright (C) 2007, 2009 Christian Grothoff
      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., 59 Temple Place - Suite 330,
     19      Boston, MA 02111-1307, USA.
     20 */
     21 
     22 /**
     23  * @file daemontest_get_response_cleanup.c
     24  * @brief  Testcase for libmicrohttpd response cleanup
     25  * @author Christian Grothoff
     26  */
     27 
     28 #include "MHD_config.h"
     29 #include "platform.h"
     30 #include <microhttpd.h>
     31 #include <stdlib.h>
     32 #include <unistd.h>
     33 #include <string.h>
     34 #include <time.h>
     35 #include <sys/types.h>
     36 #include <sys/wait.h>
     37 #include <fcntl.h>
     38 
     39 #ifndef WINDOWS
     40 #include <sys/socket.h>
     41 #include <unistd.h>
     42 #endif
     43 
     44 #ifdef _WIN32
     45 #ifndef WIN32_LEAN_AND_MEAN
     46 #define WIN32_LEAN_AND_MEAN 1
     47 #endif /* !WIN32_LEAN_AND_MEAN */
     48 #include <windows.h>
     49 #endif
     50 
     51 #if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
     52 #undef CPU_COUNT
     53 #endif
     54 #if !defined(CPU_COUNT)
     55 #define CPU_COUNT 2
     56 #endif
     57 
     58 #define TESTSTR "/* DO NOT CHANGE THIS LINE */"
     59 
     60 static int oneone;
     61 
     62 static int ok;
     63 
     64 
     65 static pid_t
     66 fork_curl (const char *url)
     67 {
     68   pid_t ret;
     69 
     70   ret = fork();
     71   if (ret != 0)
     72     return ret;
     73   execlp ("curl", "curl", "-s", "-N", "-o", "/dev/null", "-GET", url, NULL);
     74   fprintf (stderr,
     75 	   "Failed to exec curl: %s\n",
     76 	   strerror (errno));
     77   _exit (-1);
     78 }
     79 
     80 static void
     81 kill_curl (pid_t pid)
     82 {
     83   int status;
     84 
     85   //fprintf (stderr, "Killing curl\n");
     86   kill (pid, SIGTERM);
     87   waitpid (pid, &status, 0);
     88 }
     89 
     90 
     91 static ssize_t
     92 push_callback (void *cls, uint64_t pos, char *buf, size_t max)
     93 {
     94   if (max == 0)
     95     return 0;
     96   buf[0] = 'd';
     97   return 1;
     98 }
     99 
    100 static void
    101 push_free_callback (void *cls)
    102 {
    103   int *ok = cls;
    104 
    105   //fprintf (stderr, "Cleanup callback called!\n");
    106   *ok = 0;
    107 }
    108 
    109 
    110 static int
    111 ahc_echo (void *cls,
    112           struct MHD_Connection *connection,
    113           const char *url,
    114           const char *method,
    115           const char *version,
    116           const char *upload_data, size_t *upload_data_size,
    117           void **unused)
    118 {
    119   static int ptr;
    120   const char *me = cls;
    121   struct MHD_Response *response;
    122   int ret;
    123 
    124   //fprintf (stderr, "In CB: %s!\n", method);
    125   if (0 != strcmp (me, method))
    126     return MHD_NO;              /* unexpected method */
    127   if (&ptr != *unused)
    128     {
    129       *unused = &ptr;
    130       return MHD_YES;
    131     }
    132   *unused = NULL;
    133   response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
    134 						32 * 1024,
    135 						&push_callback,
    136 						&ok,
    137 						&push_free_callback);
    138   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
    139   MHD_destroy_response (response);
    140   if (ret == MHD_NO)
    141     abort ();
    142   return ret;
    143 }
    144 
    145 
    146 static int
    147 testInternalGet ()
    148 {
    149   struct MHD_Daemon *d;
    150   pid_t curl;
    151 
    152   ok = 1;
    153   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
    154                         11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
    155   if (d == NULL)
    156     return 1;
    157   curl = fork_curl ("http://127.0.0.1:11080/");
    158   sleep (1);
    159   kill_curl (curl);
    160   sleep (1);
    161   // fprintf (stderr, "Stopping daemon!\n");
    162   MHD_stop_daemon (d);
    163   if (ok != 0)
    164     return 2;
    165   return 0;
    166 }
    167 
    168 static int
    169 testMultithreadedGet ()
    170 {
    171   struct MHD_Daemon *d;
    172   pid_t curl;
    173 
    174   d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
    175                         1081, NULL, NULL, &ahc_echo, "GET",
    176 			MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 2,
    177 			MHD_OPTION_END);
    178   if (d == NULL)
    179     return 16;
    180   ok = 1;
    181   //fprintf (stderr, "Forking cURL!\n");
    182   curl = fork_curl ("http://127.0.0.1:1081/");
    183   sleep (1);
    184   kill_curl (curl);
    185   sleep (1);
    186   curl = fork_curl ("http://127.0.0.1:1081/");
    187   sleep (1);
    188   if (ok != 0)
    189     {
    190       kill_curl (curl);
    191       MHD_stop_daemon (d);
    192       return 64;
    193     }
    194   kill_curl (curl);
    195   sleep (1);
    196   //fprintf (stderr, "Stopping daemon!\n");
    197   MHD_stop_daemon (d);
    198   if (ok != 0)
    199     return 32;
    200 
    201   return 0;
    202 }
    203 
    204 static int
    205 testMultithreadedPoolGet ()
    206 {
    207   struct MHD_Daemon *d;
    208   pid_t curl;
    209 
    210   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
    211                         1081, NULL, NULL, &ahc_echo, "GET",
    212                         MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END);
    213   if (d == NULL)
    214     return 64;
    215   ok = 1;
    216   curl = fork_curl ("http://127.0.0.1:1081/");
    217   sleep (1);
    218   kill_curl (curl);
    219   sleep (1);
    220   //fprintf (stderr, "Stopping daemon!\n");
    221   MHD_stop_daemon (d);
    222   if (ok != 0)
    223     return 128;
    224   return 0;
    225 }
    226 
    227 static int
    228 testExternalGet ()
    229 {
    230   struct MHD_Daemon *d;
    231   fd_set rs;
    232   fd_set ws;
    233   fd_set es;
    234   MHD_socket max;
    235   time_t start;
    236   struct timeval tv;
    237   pid_t curl;
    238 
    239   d = MHD_start_daemon (MHD_USE_DEBUG,
    240                         1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
    241   if (d == NULL)
    242     return 256;
    243   curl = fork_curl ("http://127.0.0.1:1082/");
    244 
    245   start = time (NULL);
    246   while ((time (NULL) - start < 2))
    247     {
    248       max = 0;
    249       FD_ZERO (&rs);
    250       FD_ZERO (&ws);
    251       FD_ZERO (&es);
    252       if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
    253         {
    254           MHD_stop_daemon (d);
    255           return 4096;
    256         }
    257       tv.tv_sec = 0;
    258       tv.tv_usec = 1000;
    259       select (max + 1, &rs, &ws, &es, &tv);
    260       MHD_run (d);
    261     }
    262   kill_curl (curl);
    263   start = time (NULL);
    264   while ((time (NULL) - start < 2))
    265     {
    266       max = 0;
    267       FD_ZERO (&rs);
    268       FD_ZERO (&ws);
    269       FD_ZERO (&es);
    270       if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
    271         {
    272           MHD_stop_daemon (d);
    273           return 4096;
    274         }
    275       tv.tv_sec = 0;
    276       tv.tv_usec = 1000;
    277       select (max + 1, &rs, &ws, &es, &tv);
    278       MHD_run (d);
    279     }
    280   // fprintf (stderr, "Stopping daemon!\n");
    281   MHD_stop_daemon (d);
    282   if (ok != 0)
    283     return 1024;
    284   return 0;
    285 }
    286 
    287 
    288 int
    289 main (int argc, char *const *argv)
    290 {
    291   unsigned int errorCount = 0;
    292 
    293   oneone = (NULL != strrchr (argv[0], (int) '/')) ?
    294     (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
    295   errorCount += testInternalGet ();
    296   errorCount += testMultithreadedGet ();
    297   errorCount += testMultithreadedPoolGet ();
    298   errorCount += testExternalGet ();
    299   if (errorCount != 0)
    300     fprintf (stderr, "Error (code: %u)\n", errorCount);
    301   return errorCount != 0;       /* 0 == pass */
    302 }
    303