libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

test_daemon.c (6235B)


      1 /*
      2      This file is part of libmicrohttpd
      3      Copyright (C) 2007, 2017 Christian Grothoff
      4      Copyright (C) 2014--2023  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 test_daemon.c
     24  * @brief  Testcase for libmicrohttpd starts and stops
     25  * @author Christian Grothoff
     26  * @author Karlson2k (Evgeny Grin)
     27  */
     28 
     29 #include "platform.h"
     30 #include "microhttpd.h"
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <stdio.h>
     34 
     35 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this
     36    test into a marked, classifiable test error (TESTING.md, P5). */
     37 #include "mhd_panic_tripwire.h"
     38 
     39 #ifndef WINDOWS
     40 #include <unistd.h>
     41 #endif
     42 
     43 
     44 static unsigned int
     45 testStartError (void)
     46 {
     47   struct MHD_Daemon *d;
     48 
     49   d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0, NULL, NULL, NULL, NULL);
     50   if (NULL != d)
     51   {
     52     MHD_stop_daemon (d);
     53     fprintf (stderr,
     54              "Succeeded to start without MHD_AccessHandlerCallback?\n");
     55     return 1;
     56   }
     57   return 0;
     58 }
     59 
     60 
     61 static enum MHD_Result
     62 apc_nothing (void *cls,
     63              const struct sockaddr *addr,
     64              socklen_t addrlen)
     65 {
     66   (void) cls; (void) addr; (void) addrlen; /* Unused. Silent compiler warning. */
     67 
     68   return MHD_NO;
     69 }
     70 
     71 
     72 static enum MHD_Result
     73 apc_all (void *cls,
     74          const struct sockaddr *addr,
     75          socklen_t addrlen)
     76 {
     77   (void) cls; (void) addr; (void) addrlen; /* Unused. Silent compiler warning. */
     78 
     79   return MHD_YES;
     80 }
     81 
     82 
     83 static enum MHD_Result
     84 ahc_nothing (void *cls,
     85              struct MHD_Connection *connection,
     86              const char *url,
     87              const char *method,
     88              const char *version,
     89              const char *upload_data, size_t *upload_data_size,
     90              void **req_cls)
     91 {
     92   (void) cls; (void) connection; (void) url;         /* Unused. Silent compiler warning. */
     93   (void) method; (void) version; (void) upload_data; /* Unused. Silent compiler warning. */
     94   (void) upload_data_size; (void) req_cls;           /* Unused. Silent compiler warning. */
     95 
     96   return MHD_NO;
     97 }
     98 
     99 
    100 static unsigned int
    101 testStartStop (void)
    102 {
    103   struct MHD_Daemon *d;
    104 
    105   d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
    106                         0,
    107                         &apc_nothing, NULL,
    108                         &ahc_nothing, NULL,
    109                         MHD_OPTION_END);
    110   if (NULL == d)
    111   {
    112     fprintf (stderr,
    113              "Failed to start daemon on port %u\n",
    114              (unsigned int) 0);
    115     exit (3);
    116   }
    117   MHD_stop_daemon (d);
    118   return 0;
    119 }
    120 
    121 
    122 static unsigned int
    123 testExternalRun (int use_no_thread_safe)
    124 {
    125   struct MHD_Daemon *d;
    126   fd_set rs;
    127   MHD_socket maxfd;
    128   int i;
    129 
    130   d = MHD_start_daemon (MHD_USE_ERROR_LOG
    131                         | (use_no_thread_safe ? MHD_USE_NO_THREAD_SAFETY : 0),
    132                         0,
    133                         &apc_all, NULL,
    134                         &ahc_nothing, NULL,
    135                         MHD_OPTION_APP_FD_SETSIZE, (int) FD_SETSIZE,
    136                         MHD_OPTION_END);
    137 
    138   if (NULL == d)
    139   {
    140     fprintf (stderr,
    141              "Failed to start daemon on port %u\n",
    142              (unsigned int) 0);
    143     exit (3);
    144   }
    145   for (i = 0; i < 15; ++i)
    146   {
    147     maxfd = 0;
    148     FD_ZERO (&rs);
    149     if (MHD_YES != MHD_get_fdset (d, &rs, &rs, &rs, &maxfd))
    150     {
    151       MHD_stop_daemon (d);
    152       fprintf (stderr,
    153                "Failed in MHD_get_fdset().\n");
    154       return 256;
    155     }
    156     if (MHD_NO == MHD_run (d))
    157     {
    158       MHD_stop_daemon (d);
    159       fprintf (stderr,
    160                "Failed in MHD_run().\n");
    161       return 8;
    162     }
    163   }
    164   MHD_stop_daemon (d);
    165   return 0;
    166 }
    167 
    168 
    169 static unsigned int
    170 testThread (void)
    171 {
    172   struct MHD_Daemon *d;
    173 
    174   d = MHD_start_daemon (MHD_USE_ERROR_LOG | MHD_USE_INTERNAL_POLLING_THREAD,
    175                         0,
    176                         &apc_all, NULL,
    177                         &ahc_nothing, NULL,
    178                         MHD_OPTION_END);
    179 
    180   if (NULL == d)
    181   {
    182     fprintf (stderr,
    183              "Failed to start daemon on port %u.\n",
    184              (unsigned int) 0);
    185     exit (3);
    186   }
    187   if (MHD_run (d) != MHD_NO)
    188   {
    189     fprintf (stderr,
    190              "Failed in MHD_run().\n");
    191     return 32;
    192   }
    193   MHD_stop_daemon (d);
    194   return 0;
    195 }
    196 
    197 
    198 static unsigned int
    199 testMultithread (void)
    200 {
    201   struct MHD_Daemon *d;
    202 
    203   d = MHD_start_daemon (MHD_USE_ERROR_LOG | MHD_USE_INTERNAL_POLLING_THREAD
    204                         | MHD_USE_THREAD_PER_CONNECTION,
    205                         0,
    206                         &apc_all, NULL,
    207                         &ahc_nothing, NULL,
    208                         MHD_OPTION_END);
    209 
    210   if (NULL == d)
    211   {
    212     fprintf (stderr,
    213              "Failed to start daemon on port %u\n",
    214              (unsigned int) 0);
    215     exit (3);
    216   }
    217   if (MHD_run (d) != MHD_NO)
    218   {
    219     fprintf (stderr,
    220              "Failed in MHD_run().\n");
    221     return 128;
    222   }
    223   MHD_stop_daemon (d);
    224   return 0;
    225 }
    226 
    227 
    228 int
    229 main (int argc,
    230       char *const *argv)
    231 {
    232   unsigned int errorCount = 0;
    233   int has_threads_support;
    234   (void) argc; (void) argv; /* Unused. Silent compiler warning. */
    235 
    236   has_threads_support =
    237     (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_THREADS));
    238   errorCount += testStartError ();
    239   if (has_threads_support)
    240     errorCount += testStartStop ();
    241   if (has_threads_support)
    242     errorCount += testExternalRun (0);
    243   errorCount += testExternalRun (! 0);
    244   if (has_threads_support)
    245   {
    246     errorCount += testThread ();
    247     errorCount += testMultithread ();
    248   }
    249   if (0 != errorCount)
    250     fprintf (stderr,
    251              "Error (code: %u)\n",
    252              errorCount);
    253   return 0 != errorCount;       /* 0 == pass */
    254 }