aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2007-12-06 02:06:49 +0000
committerChristian Grothoff <christian@grothoff.org>2007-12-06 02:06:49 +0000
commit0826971bfb9887de4d29394470b3da5407a1b741 (patch)
tree9292a023dcaaaafe5326bdb1e395ffb8c1a01835
parent82f18e91985a790f7b4abac77e6de801da7bdec9 (diff)
downloadlibmicrohttpd-0826971bfb9887de4d29394470b3da5407a1b741.tar.gz
libmicrohttpd-0826971bfb9887de4d29394470b3da5407a1b741.zip
testcase for 1296
-rw-r--r--src/daemon/daemontest_post_loop.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/src/daemon/daemontest_post_loop.c b/src/daemon/daemontest_post_loop.c
new file mode 100644
index 00000000..c24dcf52
--- /dev/null
+++ b/src/daemon/daemontest_post_loop.c
@@ -0,0 +1,350 @@
1/*
2 This file is part of libmicrohttpd
3 (C) 2007 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_post_loop.c
23 * @brief Testcase for libmicrohttpd POST operations using URL-encoding
24 * @author Christian Grothoff (inspired by bug report #1296)
25 */
26
27#include "config.h"
28#include <curl/curl.h>
29#include <microhttpd.h>
30#include <stdlib.h>
31#include <string.h>
32#include <time.h>
33
34#ifndef WINDOWS
35#include <unistd.h>
36#endif
37
38#define POST_DATA "<?xml version='1.0' ?>\n<xml>\n<data-id>1</data-id>\n</xml>\n"
39
40#define LOOPCOUNT 100
41
42static int oneone;
43
44struct CBC
45{
46 char *buf;
47 size_t pos;
48 size_t size;
49};
50
51static size_t
52copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
53{
54 struct CBC *cbc = ctx;
55
56 if (cbc->pos + size * nmemb > cbc->size)
57 return 0; /* overflow */
58 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
59 cbc->pos += size * nmemb;
60 return size * nmemb;
61}
62
63static int
64ahc_echo (void *cls,
65 struct MHD_Connection *connection,
66 const char *url,
67 const char *method,
68 const char *version,
69 const char *upload_data, unsigned int *upload_data_size,
70 void **unused)
71{
72 struct MHD_Response *response;
73 int ret;
74
75 if (0 != strcmp ("POST", method))
76 {
77 printf ("METHOD: %s\n", method);
78 return MHD_NO; /* unexpected method */
79 }
80 if (strlen(POST_DATA) != *upload_data_size)
81 return MHD_NO;
82 *upload_data_size = 0;
83 response = MHD_create_response_from_data (2,
84 "OK",
85 MHD_NO, MHD_NO);
86 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
87 MHD_destroy_response (response);
88 return ret;
89}
90
91
92static int
93testInternalPost ()
94{
95 struct MHD_Daemon *d;
96 CURL *c;
97 char buf[2048];
98 struct CBC cbc;
99 CURLcode errornum;
100 int i;
101
102 cbc.buf = buf;
103 cbc.size = 2048;
104 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
105 8008, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
106 if (d == NULL)
107 return 1;
108 for (i=0;i<LOOPCOUNT;i++) {
109 c = curl_easy_init ();
110 cbc.pos = 0;
111 buf[0] = '\0';
112 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world");
113 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
114 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
115 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
116 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
117 curl_easy_setopt (c, CURLOPT_POST, 1L);
118 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
119 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
120 if (oneone)
121 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
122 else
123 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
124 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
125 // NOTE: use of CONNECTTIMEOUT without also
126 // setting NOSIGNAL results in really weird
127 // crashes on my system!
128 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
129 if (CURLE_OK != (errornum = curl_easy_perform (c)))
130 {
131 fprintf (stderr,
132 "curl_easy_perform failed: `%s'\n",
133 curl_easy_strerror (errornum));
134 curl_easy_cleanup (c);
135 MHD_stop_daemon (d);
136 return 2;
137 }
138 curl_easy_cleanup (c);
139 if ( (buf[0] != 'O') ||
140 (buf[1] != 'K') ) {
141 MHD_stop_daemon (d);
142 return 4;
143 }
144 }
145 MHD_stop_daemon (d);
146 return 0;
147}
148
149static int
150testMultithreadedPost ()
151{
152 struct MHD_Daemon *d;
153 CURL *c;
154 char buf[2048];
155 struct CBC cbc;
156 CURLcode errornum;
157 int i;
158
159 cbc.buf = buf;
160 cbc.size = 2048;
161 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
162 8009, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
163 if (d == NULL)
164 return 16;
165 for (i=0;i<LOOPCOUNT;i++) {
166 c = curl_easy_init ();
167 cbc.pos = 0;
168 buf[0] = '\0';
169 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
170 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
171 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
172 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
173 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
174 curl_easy_setopt (c, CURLOPT_POST, 1L);
175 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
176 curl_easy_setopt (c, CURLOPT_TIMEOUT, 2L);
177 if (oneone)
178 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
179 else
180 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
181 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 2L);
182 // NOTE: use of CONNECTTIMEOUT without also
183 // setting NOSIGNAL results in really weird
184 // crashes on my system!
185 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
186 if (CURLE_OK != (errornum = curl_easy_perform (c)))
187 {
188 fprintf (stderr,
189 "curl_easy_perform failed: `%s'\n",
190 curl_easy_strerror (errornum));
191 curl_easy_cleanup (c);
192 MHD_stop_daemon (d);
193 return 32;
194 }
195 curl_easy_cleanup (c);
196 if ( (buf[0] != 'O') ||
197 (buf[1] != 'K') ) {
198 MHD_stop_daemon (d);
199 return 64;
200 }
201 }
202 MHD_stop_daemon (d);
203 return 0;
204}
205
206
207static int
208testExternalPost ()
209{
210 struct MHD_Daemon *d;
211 CURL *c;
212 char buf[2048];
213 struct CBC cbc;
214 CURLM *multi;
215 CURLMcode mret;
216 fd_set rs;
217 fd_set ws;
218 fd_set es;
219 int max;
220 int running;
221 struct CURLMsg *msg;
222 time_t start;
223 struct timeval tv;
224 int i;
225
226 multi = NULL;
227 cbc.buf = buf;
228 cbc.size = 2048;
229 cbc.pos = 0;
230 d = MHD_start_daemon (MHD_USE_DEBUG,
231 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END);
232 if (d == NULL)
233 return 256;
234 multi = curl_multi_init ();
235 if (multi == NULL)
236 {
237 MHD_stop_daemon (d);
238 return 512;
239 }
240 for (i=0;i<LOOPCOUNT;i++) {
241 c = curl_easy_init ();
242 cbc.pos = 0;
243 buf[0] = '\0';
244 curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
245 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
246 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
247 curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
248 curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
249 curl_easy_setopt (c, CURLOPT_POST, 1L);
250 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
251 curl_easy_setopt (c, CURLOPT_TIMEOUT, 5L);
252 if (oneone)
253 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
254 else
255 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
256 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
257 // NOTE: use of CONNECTTIMEOUT without also
258 // setting NOSIGNAL results in really weird
259 // crashes on my system!
260 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
261 mret = curl_multi_add_handle (multi, c);
262 if (mret != CURLM_OK)
263 {
264 curl_multi_cleanup (multi);
265 curl_easy_cleanup (c);
266 MHD_stop_daemon (d);
267 return 1024;
268 }
269 start = time (NULL);
270 while ((time (NULL) - start < 5) && (multi != NULL))
271 {
272 max = 0;
273 FD_ZERO (&rs);
274 FD_ZERO (&ws);
275 FD_ZERO (&es);
276 curl_multi_perform (multi, &running);
277 mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
278 if (mret != CURLM_OK)
279 {
280 curl_multi_remove_handle (multi, c);
281 curl_multi_cleanup (multi);
282 curl_easy_cleanup (c);
283 MHD_stop_daemon (d);
284 return 2048;
285 }
286 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
287 {
288 curl_multi_remove_handle (multi, c);
289 curl_multi_cleanup (multi);
290 curl_easy_cleanup (c);
291 MHD_stop_daemon (d);
292 return 4096;
293 }
294 tv.tv_sec = 0;
295 tv.tv_usec = 1000;
296 select (max + 1, &rs, &ws, &es, &tv);
297 curl_multi_perform (multi, &running);
298 if (running == 0)
299 {
300 msg = curl_multi_info_read (multi, &running);
301 if (msg == NULL)
302 break;
303 if (msg->msg == CURLMSG_DONE)
304 {
305 if (msg->data.result != CURLE_OK)
306 printf ("%s failed at %s:%d: `%s'\n",
307 "curl_multi_perform",
308 __FILE__,
309 __LINE__, curl_easy_strerror (msg->data.result));
310 curl_multi_remove_handle (multi, c);
311 curl_multi_cleanup (multi);
312 curl_easy_cleanup (c);
313 c = NULL;
314 multi = NULL;
315 }
316 }
317 MHD_run (d);
318 }
319 curl_multi_remove_handle (multi, c);
320 curl_easy_cleanup (c);
321 if ( (buf[0] != 'O') ||
322 (buf[1] != 'K') ) {
323 curl_multi_cleanup (multi);
324 MHD_stop_daemon (d);
325 return 8192;
326 }
327 }
328 curl_multi_cleanup (multi);
329 MHD_stop_daemon (d);
330 return 0;
331}
332
333
334
335int
336main (int argc, char *const *argv)
337{
338 unsigned int errorCount = 0;
339
340 oneone = NULL != strstr (argv[0], "11");
341 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
342 return 2;
343 errorCount += testInternalPost ();
344 errorCount += testMultithreadedPost ();
345 errorCount += testExternalPost ();
346 if (errorCount != 0)
347 fprintf (stderr, "Error (code: %u)\n", errorCount);
348 curl_global_cleanup ();
349 return errorCount != 0; /* 0 == pass */
350}