aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/test_put.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/test_put.c')
-rw-r--r--src/testcurl/test_put.c432
1 files changed, 432 insertions, 0 deletions
diff --git a/src/testcurl/test_put.c b/src/testcurl/test_put.c
new file mode 100644
index 00000000..ce3d8de7
--- /dev/null
+++ b/src/testcurl/test_put.c
@@ -0,0 +1,432 @@
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_put.c
23 * @brief Testcase for libmicrohttpd PUT operations
24 * @author Christian Grothoff
25 */
26
27#include "MHD_config.h"
28#include "platform.h"
29#include <curl/curl.h>
30#include <microhttpd.h>
31#include <stdlib.h>
32#include <string.h>
33#include <time.h>
34
35#ifndef WINDOWS
36#include <unistd.h>
37#endif
38
39static int oneone;
40
41struct CBC
42{
43 char *buf;
44 size_t pos;
45 size_t size;
46};
47
48static size_t
49putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
50{
51 unsigned int *pos = ptr;
52 unsigned int wrt;
53
54 wrt = size * nmemb;
55 if (wrt > 8 - (*pos))
56 wrt = 8 - (*pos);
57 memcpy (stream, &("Hello123"[*pos]), wrt);
58 (*pos) += wrt;
59 return wrt;
60}
61
62static size_t
63copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
64{
65 struct CBC *cbc = ctx;
66
67 if (cbc->pos + size * nmemb > cbc->size)
68 return 0; /* overflow */
69 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
70 cbc->pos += size * nmemb;
71 return size * nmemb;
72}
73
74static int
75ahc_echo (void *cls,
76 struct MHD_Connection *connection,
77 const char *url,
78 const char *method,
79 const char *version,
80 const char *upload_data, size_t *upload_data_size,
81 void **unused)
82{
83 int *done = cls;
84 struct MHD_Response *response;
85 int ret;
86
87 if (0 != strcmp ("PUT", method))
88 return MHD_NO; /* unexpected method */
89 if ((*done) == 0)
90 {
91 if (*upload_data_size != 8)
92 return MHD_YES; /* not yet ready */
93 if (0 == memcmp (upload_data, "Hello123", 8))
94 {
95 *upload_data_size = 0;
96 }
97 else
98 {
99 printf ("Invalid upload data `%8s'!\n", upload_data);
100 return MHD_NO;
101 }
102 *done = 1;
103 return MHD_YES;
104 }
105 response = MHD_create_response_from_buffer (strlen (url), (void*) url,
106 MHD_RESPMEM_MUST_COPY);
107 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
108 MHD_destroy_response (response);
109 return ret;
110}
111
112
113static int
114testInternalPut ()
115{
116 struct MHD_Daemon *d;
117 CURL *c;
118 char buf[2048];
119 struct CBC cbc;
120 unsigned int pos = 0;
121 int done_flag = 0;
122 CURLcode errornum;
123
124 cbc.buf = buf;
125 cbc.size = 2048;
126 cbc.pos = 0;
127 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
128 1080,
129 NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
130 if (d == NULL)
131 return 1;
132 c = curl_easy_init ();
133 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1080/hello_world");
134 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
135 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
136 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
137 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
138 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
139 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
140 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
141 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
142 if (oneone)
143 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
144 else
145 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
146 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
147 // NOTE: use of CONNECTTIMEOUT without also
148 // setting NOSIGNAL results in really weird
149 // crashes on my system!
150 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
151 if (CURLE_OK != (errornum = curl_easy_perform (c)))
152 {
153 fprintf (stderr,
154 "curl_easy_perform failed: `%s'\n",
155 curl_easy_strerror (errornum));
156 curl_easy_cleanup (c);
157 MHD_stop_daemon (d);
158 return 2;
159 }
160 curl_easy_cleanup (c);
161 MHD_stop_daemon (d);
162 if (cbc.pos != strlen ("/hello_world"))
163 return 4;
164 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
165 return 8;
166 return 0;
167}
168
169static int
170testMultithreadedPut ()
171{
172 struct MHD_Daemon *d;
173 CURL *c;
174 char buf[2048];
175 struct CBC cbc;
176 unsigned int pos = 0;
177 int done_flag = 0;
178 CURLcode errornum;
179
180 cbc.buf = buf;
181 cbc.size = 2048;
182 cbc.pos = 0;
183 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
184 1081,
185 NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
186 if (d == NULL)
187 return 16;
188 c = curl_easy_init ();
189 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
190 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
191 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
192 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
193 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
194 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
195 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
196 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
197 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
198 if (oneone)
199 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
200 else
201 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
202 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
203 // NOTE: use of CONNECTTIMEOUT without also
204 // setting NOSIGNAL results in really weird
205 // crashes on my system!
206 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
207 if (CURLE_OK != (errornum = curl_easy_perform (c)))
208 {
209 fprintf (stderr,
210 "curl_easy_perform failed: `%s'\n",
211 curl_easy_strerror (errornum));
212 curl_easy_cleanup (c);
213 MHD_stop_daemon (d);
214 return 32;
215 }
216 curl_easy_cleanup (c);
217 MHD_stop_daemon (d);
218 if (cbc.pos != strlen ("/hello_world"))
219 return 64;
220 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
221 return 128;
222
223 return 0;
224}
225
226static int
227testMultithreadedPoolPut ()
228{
229 struct MHD_Daemon *d;
230 CURL *c;
231 char buf[2048];
232 struct CBC cbc;
233 unsigned int pos = 0;
234 int done_flag = 0;
235 CURLcode errornum;
236
237 cbc.buf = buf;
238 cbc.size = 2048;
239 cbc.pos = 0;
240 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
241 1081,
242 NULL, NULL, &ahc_echo, &done_flag,
243 MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
244 if (d == NULL)
245 return 16;
246 c = curl_easy_init ();
247 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
248 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
249 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
250 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
251 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
252 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
253 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
254 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
255 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
256 if (oneone)
257 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
258 else
259 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
260 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
261 // NOTE: use of CONNECTTIMEOUT without also
262 // setting NOSIGNAL results in really weird
263 // crashes on my system!
264 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
265 if (CURLE_OK != (errornum = curl_easy_perform (c)))
266 {
267 fprintf (stderr,
268 "curl_easy_perform failed: `%s'\n",
269 curl_easy_strerror (errornum));
270 curl_easy_cleanup (c);
271 MHD_stop_daemon (d);
272 return 32;
273 }
274 curl_easy_cleanup (c);
275 MHD_stop_daemon (d);
276 if (cbc.pos != strlen ("/hello_world"))
277 return 64;
278 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
279 return 128;
280
281 return 0;
282}
283
284
285static int
286testExternalPut ()
287{
288 struct MHD_Daemon *d;
289 CURL *c;
290 char buf[2048];
291 struct CBC cbc;
292 CURLM *multi;
293 CURLMcode mret;
294 fd_set rs;
295 fd_set ws;
296 fd_set es;
297 int max;
298 int running;
299 struct CURLMsg *msg;
300 time_t start;
301 struct timeval tv;
302 unsigned int pos = 0;
303 int done_flag = 0;
304
305 multi = NULL;
306 cbc.buf = buf;
307 cbc.size = 2048;
308 cbc.pos = 0;
309 d = MHD_start_daemon (MHD_USE_DEBUG,
310 1082,
311 NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
312 if (d == NULL)
313 return 256;
314 c = curl_easy_init ();
315 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1082/hello_world");
316 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
317 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
318 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
319 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
320 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
321 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
322 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
323 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
324 if (oneone)
325 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
326 else
327 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
328 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
329 // NOTE: use of CONNECTTIMEOUT without also
330 // setting NOSIGNAL results in really weird
331 // crashes on my system!
332 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
333
334
335 multi = curl_multi_init ();
336 if (multi == NULL)
337 {
338 curl_easy_cleanup (c);
339 MHD_stop_daemon (d);
340 return 512;
341 }
342 mret = curl_multi_add_handle (multi, c);
343 if (mret != CURLM_OK)
344 {
345 curl_multi_cleanup (multi);
346 curl_easy_cleanup (c);
347 MHD_stop_daemon (d);
348 return 1024;
349 }
350 start = time (NULL);
351 while ((time (NULL) - start < 5) && (multi != NULL))
352 {
353 max = 0;
354 FD_ZERO (&rs);
355 FD_ZERO (&ws);
356 FD_ZERO (&es);
357 curl_multi_perform (multi, &running);
358 mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
359 if (mret != CURLM_OK)
360 {
361 curl_multi_remove_handle (multi, c);
362 curl_multi_cleanup (multi);
363 curl_easy_cleanup (c);
364 MHD_stop_daemon (d);
365 return 2048;
366 }
367 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
368 {
369 curl_multi_remove_handle (multi, c);
370 curl_multi_cleanup (multi);
371 curl_easy_cleanup (c);
372 MHD_stop_daemon (d);
373 return 4096;
374 }
375 tv.tv_sec = 0;
376 tv.tv_usec = 1000;
377 select (max + 1, &rs, &ws, &es, &tv);
378 curl_multi_perform (multi, &running);
379 if (running == 0)
380 {
381 msg = curl_multi_info_read (multi, &running);
382 if (msg == NULL)
383 break;
384 if (msg->msg == CURLMSG_DONE)
385 {
386 if (msg->data.result != CURLE_OK)
387 printf ("%s failed at %s:%d: `%s'\n",
388 "curl_multi_perform",
389 __FILE__,
390 __LINE__, curl_easy_strerror (msg->data.result));
391 curl_multi_remove_handle (multi, c);
392 curl_multi_cleanup (multi);
393 curl_easy_cleanup (c);
394 c = NULL;
395 multi = NULL;
396 }
397 }
398 MHD_run (d);
399 }
400 if (multi != NULL)
401 {
402 curl_multi_remove_handle (multi, c);
403 curl_easy_cleanup (c);
404 curl_multi_cleanup (multi);
405 }
406 MHD_stop_daemon (d);
407 if (cbc.pos != strlen ("/hello_world"))
408 return 8192;
409 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
410 return 16384;
411 return 0;
412}
413
414
415
416int
417main (int argc, char *const *argv)
418{
419 unsigned int errorCount = 0;
420
421 oneone = NULL != strstr (argv[0], "11");
422 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
423 return 2;
424 errorCount += testInternalPut ();
425 errorCount += testMultithreadedPut ();
426 errorCount += testMultithreadedPoolPut ();
427 errorCount += testExternalPut ();
428 if (errorCount != 0)
429 fprintf (stderr, "Error (code: %u)\n", errorCount);
430 curl_global_cleanup ();
431 return errorCount != 0; /* 0 == pass */
432}