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 }