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