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 daemontest_urlparse.c
     23  * @brief  Testcase for libmicrohttpd url parsing
     24  * @author Christian Grothoff
     25  */
     26 
     27 #include "MHD_config.h"
     28 #include "platform.h"
     29 #include <curl/curl.h>
     30 #include <microhttpd.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <time.h>
     34 
     35 #ifdef _WIN32
     36 #ifndef WIN32_LEAN_AND_MEAN
     37 #define WIN32_LEAN_AND_MEAN 1
     38 #endif /* !WIN32_LEAN_AND_MEAN */
     39 #include <windows.h>
     40 #endif
     41 
     42 #ifndef WINDOWS
     43 #include <unistd.h>
     44 #include <sys/socket.h>
     45 #endif
     46 
     47 static int oneone;
     48 
     49 static int matches;
     50 
     51 struct CBC
     52 {
     53   char *buf;
     54   size_t pos;
     55   size_t size;
     56 };
     57 
     58 static size_t
     59 copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
     60 {
     61   struct CBC *cbc = ctx;
     62 
     63   if (cbc->pos + size * nmemb > cbc->size)
     64     return 0;                   /* overflow */
     65   memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
     66   cbc->pos += size * nmemb;
     67   return size * nmemb;
     68 }
     69 
     70 static int
     71 test_values (void *cls,
     72 	     enum MHD_ValueKind kind,
     73 	     const char *key,
     74 	     const char *value)
     75 {
     76   if ( (0 == strcmp (key, "a")) &&
     77        (0 == strcmp (value, "b")) )
     78     matches += 1;
     79   if ( (0 == strcmp (key, "c")) &&
     80        (0 == strcmp (value, "")) )
     81     matches += 2;
     82   if ( (0 == strcmp (key, "d")) &&
     83        (NULL == value) )
     84     matches += 4;
     85   return MHD_YES;
     86 }
     87 
     88 static int
     89 ahc_echo (void *cls,
     90           struct MHD_Connection *connection,
     91           const char *url,
     92           const char *method,
     93           const char *version,
     94           const char *upload_data, size_t *upload_data_size,
     95           void **unused)
     96 {
     97   static int ptr;
     98   const char *me = cls;
     99   struct MHD_Response *response;
    100   int ret;
    101 
    102   if (0 != strcmp (me, method))
    103     return MHD_NO;              /* unexpected method */
    104   if (&ptr != *unused)
    105     {
    106       *unused = &ptr;
    107       return MHD_YES;
    108     }
    109   MHD_get_connection_values (connection,
    110 			     MHD_GET_ARGUMENT_KIND,
    111 			     &test_values,
    112 			     NULL);
    113   *unused = NULL;
    114   response = MHD_create_response_from_buffer (strlen (url),
    115 					      (void *) url,
    116 					      MHD_RESPMEM_MUST_COPY);
    117   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
    118   MHD_destroy_response (response);
    119   if (ret == MHD_NO)
    120     abort ();
    121   return ret;
    122 }
    123 
    124 
    125 static int
    126 testInternalGet (int poll_flag)
    127 {
    128   struct MHD_Daemon *d;
    129   CURL *c;
    130   char buf[2048];
    131   struct CBC cbc;
    132   CURLcode errornum;
    133 
    134   cbc.buf = buf;
    135   cbc.size = 2048;
    136   cbc.pos = 0;
    137   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG  | poll_flag,
    138                         11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
    139   if (d == NULL)
    140     return 1;
    141   c = curl_easy_init ();
    142   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11080/hello_world?a=b&c=&d");
    143   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    144   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    145   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    146   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    147   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    148   if (oneone)
    149     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    150   else
    151     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    152   /* NOTE: use of CONNECTTIMEOUT without also
    153      setting NOSIGNAL results in really weird
    154      crashes on my system!*/
    155   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    156   if (CURLE_OK != (errornum = curl_easy_perform (c)))
    157     {
    158       fprintf (stderr,
    159                "curl_easy_perform failed: `%s'\n",
    160                curl_easy_strerror (errornum));
    161       curl_easy_cleanup (c);
    162       MHD_stop_daemon (d);
    163       return 2;
    164     }
    165   curl_easy_cleanup (c);
    166   MHD_stop_daemon (d);
    167   if (cbc.pos != strlen ("/hello_world"))
    168     return 4;
    169   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    170     return 8;
    171   if (matches != 7)
    172     return 16;
    173   return 0;
    174 }
    175 
    176 
    177 int
    178 main (int argc, char *const *argv)
    179 {
    180   unsigned int errorCount = 0;
    181 
    182   oneone = (NULL != strrchr (argv[0], (int) '/')) ?
    183     (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
    184   if (0 != curl_global_init (CURL_GLOBAL_WIN32))
    185     return 2;
    186   errorCount += testInternalGet (0);
    187   if (errorCount != 0)
    188     fprintf (stderr, "Error (code: %u)\n", errorCount);
    189   curl_global_cleanup ();
    190   return errorCount != 0;       /* 0 == pass */
    191 }
    192