diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-08-18 08:56:18 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-08-18 08:56:18 +0000 |
commit | ecd561acd954650eca77c3bd93ff70b90e92dc6a (patch) | |
tree | 93409a32aae8feb3f4aa498a287b16d3bb4bedfb | |
parent | 1d7773c8a4e10ba26ac3c0351a170e257c381dbf (diff) | |
download | libmicrohttpd-ecd561acd954650eca77c3bd93ff70b90e92dc6a.tar.gz libmicrohttpd-ecd561acd954650eca77c3bd93ff70b90e92dc6a.zip |
new testcase
-rw-r--r-- | src/testcurl/Makefile.am | 7 | ||||
-rw-r--r-- | src/testcurl/test_callback.c | 183 |
2 files changed, 190 insertions, 0 deletions
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am index fda0e437..36e78739 100644 --- a/src/testcurl/Makefile.am +++ b/src/testcurl/Makefile.am | |||
@@ -48,6 +48,7 @@ check_PROGRAMS = \ | |||
48 | daemontest_iplimit11 \ | 48 | daemontest_iplimit11 \ |
49 | daemontest_termination \ | 49 | daemontest_termination \ |
50 | daemontest_timeout \ | 50 | daemontest_timeout \ |
51 | test_callback \ | ||
51 | perf_get $(PERF_GET_CONCURRENT) | 52 | perf_get $(PERF_GET_CONCURRENT) |
52 | 53 | ||
53 | 54 | ||
@@ -77,6 +78,12 @@ daemontest_get_LDADD = \ | |||
77 | $(top_builddir)/src/daemon/libmicrohttpd.la \ | 78 | $(top_builddir)/src/daemon/libmicrohttpd.la \ |
78 | @LIBCURL@ | 79 | @LIBCURL@ |
79 | 80 | ||
81 | test_callback_SOURCES = \ | ||
82 | test_callback.c | ||
83 | test_callback_LDADD = \ | ||
84 | $(top_builddir)/src/daemon/libmicrohttpd.la \ | ||
85 | @LIBCURL@ | ||
86 | |||
80 | perf_get_SOURCES = \ | 87 | perf_get_SOURCES = \ |
81 | perf_get.c \ | 88 | perf_get.c \ |
82 | gauger.h | 89 | gauger.h |
diff --git a/src/testcurl/test_callback.c b/src/testcurl/test_callback.c new file mode 100644 index 00000000..c5c34e03 --- /dev/null +++ b/src/testcurl/test_callback.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | (C) 2007, 2009, 2011 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 test_callback.c | ||
23 | * @brief Testcase for MHD not calling the callback too often | ||
24 | * @author Jan Seeger | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include "MHD_config.h" | ||
30 | #include "platform.h" | ||
31 | #include <curl/curl.h> | ||
32 | #include <microhttpd.h> | ||
33 | |||
34 | struct callback_closure { | ||
35 | unsigned int called; | ||
36 | }; | ||
37 | |||
38 | |||
39 | static ssize_t | ||
40 | called_twice(void *cls, uint64_t pos, char *buf, size_t max) | ||
41 | { | ||
42 | struct callback_closure *cls2 = cls; | ||
43 | |||
44 | if (cls2->called == 0) | ||
45 | { | ||
46 | memset(buf, 0, max); | ||
47 | strcat(buf, "test"); | ||
48 | cls2->called = 1; | ||
49 | return strlen(buf); | ||
50 | } | ||
51 | if (cls2->called == 1) | ||
52 | { | ||
53 | cls2->called = 2; | ||
54 | return MHD_CONTENT_READER_END_OF_STREAM; | ||
55 | } | ||
56 | fprintf(stderr, | ||
57 | "Handler called after returning END_OF_STREAM!\n"); | ||
58 | return MHD_CONTENT_READER_END_WITH_ERROR; | ||
59 | } | ||
60 | |||
61 | |||
62 | static int | ||
63 | callback(void *cls, struct MHD_Connection *connection, const char *url, | ||
64 | const char *method, const char *version, const char *upload_data, | ||
65 | size_t *upload_data_size, void **con_cls) { | ||
66 | struct callback_closure *cbc = calloc(1, sizeof(struct callback_closure)); | ||
67 | struct MHD_Response *r; | ||
68 | |||
69 | r = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 1024, | ||
70 | &called_twice, cbc, | ||
71 | &free); | ||
72 | MHD_queue_response(connection, 200, r); | ||
73 | MHD_destroy_response(r); | ||
74 | return MHD_YES; | ||
75 | } | ||
76 | |||
77 | |||
78 | static size_t | ||
79 | discard_buffer (void *ptr, size_t size, size_t nmemb, void *ctx) | ||
80 | { | ||
81 | return size * nmemb; | ||
82 | } | ||
83 | |||
84 | |||
85 | int main(int argc, char **argv) | ||
86 | { | ||
87 | struct MHD_Daemon *d; | ||
88 | fd_set rs; | ||
89 | fd_set ws; | ||
90 | fd_set es; | ||
91 | int max; | ||
92 | CURL *c; | ||
93 | CURLM *multi; | ||
94 | CURLMcode mret; | ||
95 | struct CURLMsg *msg; | ||
96 | int running; | ||
97 | struct timeval tv; | ||
98 | int extra; | ||
99 | |||
100 | d = MHD_start_daemon(MHD_USE_DEBUG, | ||
101 | 8000, | ||
102 | NULL, | ||
103 | NULL, | ||
104 | callback, | ||
105 | NULL, | ||
106 | MHD_OPTION_END); | ||
107 | c = curl_easy_init (); | ||
108 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:8000/"); | ||
109 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &discard_buffer); | ||
110 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
111 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
112 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
113 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
114 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
115 | multi = curl_multi_init (); | ||
116 | if (multi == NULL) | ||
117 | { | ||
118 | curl_easy_cleanup (c); | ||
119 | MHD_stop_daemon (d); | ||
120 | return 1; | ||
121 | } | ||
122 | mret = curl_multi_add_handle (multi, c); | ||
123 | if (mret != CURLM_OK) | ||
124 | { | ||
125 | curl_multi_cleanup (multi); | ||
126 | curl_easy_cleanup (c); | ||
127 | MHD_stop_daemon (d); | ||
128 | return 2; | ||
129 | } | ||
130 | extra = 10; | ||
131 | while ( (c != NULL) || (--extra > 0) ) | ||
132 | { | ||
133 | max = -1; | ||
134 | FD_ZERO(&ws); | ||
135 | FD_ZERO(&rs); | ||
136 | FD_ZERO(&es); | ||
137 | curl_multi_perform (multi, &running); | ||
138 | mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); | ||
139 | if (mret != CURLM_OK) | ||
140 | { | ||
141 | curl_multi_remove_handle (multi, c); | ||
142 | curl_multi_cleanup (multi); | ||
143 | curl_easy_cleanup (c); | ||
144 | MHD_stop_daemon (d); | ||
145 | return 3; | ||
146 | } | ||
147 | if (MHD_YES != | ||
148 | MHD_get_fdset(d, &rs, &ws, &es, &max)) | ||
149 | { | ||
150 | curl_multi_remove_handle (multi, c); | ||
151 | curl_multi_cleanup (multi); | ||
152 | curl_easy_cleanup (c); | ||
153 | MHD_stop_daemon (d); | ||
154 | return 4; | ||
155 | } | ||
156 | tv.tv_sec = 0; | ||
157 | tv.tv_usec = 1000; | ||
158 | select(max + 1, &rs, &ws, &es, &tv); | ||
159 | curl_multi_perform (multi, &running); | ||
160 | if (running == 0) | ||
161 | { | ||
162 | msg = curl_multi_info_read (multi, &running); | ||
163 | if (msg == NULL) | ||
164 | break; | ||
165 | if (msg->msg == CURLMSG_DONE) | ||
166 | { | ||
167 | if (msg->data.result != CURLE_OK) | ||
168 | printf ("%s failed at %s:%d: `%s'\n", | ||
169 | "curl_multi_perform", | ||
170 | __FILE__, | ||
171 | __LINE__, curl_easy_strerror (msg->data.result)); | ||
172 | curl_multi_remove_handle (multi, c); | ||
173 | curl_multi_cleanup (multi); | ||
174 | curl_easy_cleanup (c); | ||
175 | c = NULL; | ||
176 | multi = NULL; | ||
177 | } | ||
178 | } | ||
179 | MHD_run(d); | ||
180 | } | ||
181 | MHD_stop_daemon(d); | ||
182 | return 0; | ||
183 | } | ||