libmicrohttpd

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

test_https_get_parallel_threads.c (5838B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2007 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 /**
     23  * @file test_https_get_parallel_threads.c
     24  * @brief  Testcase for libmicrohttpd HTTPS GET operations with multi-threaded
     25  *         MHD daemon and several clients working in parallel
     26  * @author Sagie Amir
     27  * @author Christian Grothoff
     28  * @author Karlson2k (Evgeny Grin)
     29  *
     30  * TODO: add test for external select!
     31  */
     32 
     33 #include "platform.h"
     34 #include "microhttpd.h"
     35 #include <sys/stat.h>
     36 #include <limits.h>
     37 #include <curl/curl.h>
     38 #include <pthread.h>
     39 #ifdef MHD_HTTPS_REQUIRE_GCRYPT
     40 #include <gcrypt.h>
     41 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */
     42 #include "tls_test_common.h"
     43 #include "tls_test_keys.h"
     44 
     45 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this
     46    test into a marked, classifiable test error (TESTING.md, P5). */
     47 #include "mhd_panic_tripwire.h"
     48 
     49 #if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 4
     50 #undef MHD_CPU_COUNT
     51 #endif
     52 #if ! defined(MHD_CPU_COUNT)
     53 #define MHD_CPU_COUNT 4
     54 #endif
     55 
     56 /**
     57  * used when spawning multiple threads executing curl server requests
     58  *
     59  */
     60 static void *
     61 https_transfer_thread_adapter (void *args)
     62 {
     63   static int nonnull;
     64   struct https_test_data *cargs = args;
     65   unsigned int ret;
     66 
     67   ret = test_https_transfer (cargs->cls, cargs->port,
     68                              cargs->cipher_suite, cargs->proto_version);
     69   if (ret == 0)
     70     return NULL;
     71   return &nonnull;
     72 }
     73 
     74 
     75 /**
     76  * Test non-parallel requests.
     77  *
     78  * @return: 0 upon all client requests returning '0', 1 otherwise.
     79  *
     80  * TODO : make client_count a parameter - number of curl client threads to spawn
     81  */
     82 static unsigned int
     83 test_single_client (void *cls, uint16_t port, const char *cipher_suite,
     84                     int curl_proto_version)
     85 {
     86   void *client_thread_ret;
     87   struct https_test_data client_args =
     88   { NULL, port, cipher_suite, curl_proto_version };
     89   (void) cls;    /* Unused. Silent compiler warning. */
     90 
     91   client_thread_ret = https_transfer_thread_adapter (&client_args);
     92   if (client_thread_ret != NULL)
     93     return 1;
     94   return 0;
     95 }
     96 
     97 
     98 /**
     99  * Test parallel request handling.
    100  *
    101  * @return: 0 upon all client requests returning '0', 1 otherwise.
    102  *
    103  * TODO : make client_count a parameter - number of curl client threads to spawn
    104  */
    105 static unsigned int
    106 test_parallel_clients (void *cls, uint16_t port, const char *cipher_suite,
    107                        int curl_proto_version)
    108 {
    109   int i;
    110   int client_count = (MHD_CPU_COUNT - 1);
    111   void *client_thread_ret;
    112   pthread_t client_arr[client_count];
    113   struct https_test_data client_args =
    114   { NULL, port, cipher_suite, curl_proto_version };
    115   (void) cls;    /* Unused. Silent compiler warning. */
    116 
    117   for (i = 0; i < client_count; ++i)
    118   {
    119     if (pthread_create (&client_arr[i], NULL,
    120                         &https_transfer_thread_adapter, &client_args) != 0)
    121     {
    122       fprintf (stderr, "Error: failed to spawn test client threads.\n");
    123 
    124       return 1;
    125     }
    126   }
    127 
    128   /* check all client requests fulfilled correctly */
    129   for (i = 0; i < client_count; ++i)
    130   {
    131     if ((pthread_join (client_arr[i], &client_thread_ret) != 0) ||
    132         (client_thread_ret != NULL))
    133       return 1;
    134   }
    135 
    136   return 0;
    137 }
    138 
    139 
    140 int
    141 main (int argc, char *const *argv)
    142 {
    143   unsigned int errorCount = 0;
    144   const char *ssl_version;
    145   uint16_t port;
    146   unsigned int iseed;
    147   (void) argc;   /* Unused. Silent compiler warning. */
    148 
    149   if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
    150     port = 0;
    151   else
    152     port = 3010;
    153 
    154   /* initialize random seed used by curl clients */
    155   iseed = (unsigned int) time (NULL);
    156 
    157 #ifdef MHD_HTTPS_REQUIRE_GCRYPT
    158 #ifdef GCRYCTL_INITIALIZATION_FINISHED
    159   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    160 #endif
    161 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */
    162   srand (iseed);
    163   if (! testsuite_curl_global_init ())
    164     return 99;
    165   ssl_version = curl_version_info (CURLVERSION_NOW)->ssl_version;
    166   if (NULL == ssl_version)
    167   {
    168     fprintf (stderr, "Curl does not support SSL.  Cannot run the test.\n");
    169     curl_global_cleanup ();
    170     return 77;
    171   }
    172 
    173   errorCount +=
    174     test_wrap ("multi threaded daemon, single client", &test_single_client,
    175                NULL, port,
    176                MHD_USE_TLS | MHD_USE_ERROR_LOG | MHD_USE_THREAD_PER_CONNECTION
    177                | MHD_USE_INTERNAL_POLLING_THREAD,
    178                NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY,
    179                srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
    180                srv_self_signed_cert_pem, MHD_OPTION_END);
    181 
    182   errorCount +=
    183     test_wrap ("multi threaded daemon, parallel client",
    184                &test_parallel_clients, NULL, port,
    185                MHD_USE_TLS | MHD_USE_ERROR_LOG | MHD_USE_THREAD_PER_CONNECTION
    186                | MHD_USE_INTERNAL_POLLING_THREAD,
    187                NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY,
    188                srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT,
    189                srv_self_signed_cert_pem, MHD_OPTION_END);
    190 
    191   if (errorCount != 0)
    192     fprintf (stderr, "Failed test: %s, error: %u.\n", argv[0], errorCount);
    193 
    194   curl_global_cleanup ();
    195   return errorCount != 0 ? 1 : 0;
    196 }