aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-11-04 21:57:17 +0100
committerChristian Grothoff <christian@grothoff.org>2016-11-04 21:57:17 +0100
commit94ff0707749af6998a051e10e86239d4f8506769 (patch)
tree3eb72889115d204d5f6fcb4b8745e352986b5f12
parentd7392e0882eb7b1cc559d25849204c966a5091ef (diff)
downloadlibmicrohttpd-94ff0707749af6998a051e10e86239d4f8506769.tar.gz
libmicrohttpd-94ff0707749af6998a051e10e86239d4f8506769.zip
adding test from Markus (adapted by me to C and MHD-style)
-rw-r--r--AUTHORS1
-rw-r--r--src/testcurl/Makefile.am9
-rw-r--r--src/testcurl/test_quiesce_stream.c207
3 files changed, 217 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index 0c781b7a..feb911e9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -23,6 +23,7 @@ Matthew Moore
23Colin Caughie <c.caughie@indigovision.com> 23Colin Caughie <c.caughie@indigovision.com>
24David Carvalho <andaris@gmail.com> 24David Carvalho <andaris@gmail.com>
25David Reiss <dreiss@facebook.com> 25David Reiss <dreiss@facebook.com>
26Markus Doppelbauer <doppelbauer@gmx.net>
26Matt Holiday 27Matt Holiday
27Michael Cronenworth <mike@cchtml.com> 28Michael Cronenworth <mike@cchtml.com>
28Milan Straka <straka@ufal.mff.cuni.cz> 29Milan Straka <straka@ufal.mff.cuni.cz>
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index 80f11d56..d0f403c6 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -52,6 +52,7 @@ check_PROGRAMS = \
52if HAVE_POSIX_THREADS 52if HAVE_POSIX_THREADS
53check_PROGRAMS += \ 53check_PROGRAMS += \
54 test_quiesce \ 54 test_quiesce \
55 test_quiesce_stream \
55 test_concurrent_stop \ 56 test_concurrent_stop \
56 perf_get_concurrent 57 perf_get_concurrent
57endif 58endif
@@ -114,6 +115,14 @@ test_quiesce_LDADD = \
114 $(top_builddir)/src/microhttpd/libmicrohttpd.la \ 115 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
115 $(PTHREAD_LIBS) @LIBCURL@ 116 $(PTHREAD_LIBS) @LIBCURL@
116 117
118test_quiesce_stream_SOURCES = \
119 test_quiesce_stream.c
120test_quiesce_stream_CFLAGS = \
121 $(PTHREAD_CFLAGS) $(AM_CFLAGS)
122test_quiesce_stream_LDADD = \
123 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
124 $(PTHREAD_LIBS) @LIBCURL@
125
117test_callback_SOURCES = \ 126test_callback_SOURCES = \
118 test_callback.c 127 test_callback.c
119test_callback_LDADD = \ 128test_callback_LDADD = \
diff --git a/src/testcurl/test_quiesce_stream.c b/src/testcurl/test_quiesce_stream.c
new file mode 100644
index 00000000..478b1109
--- /dev/null
+++ b/src/testcurl/test_quiesce_stream.c
@@ -0,0 +1,207 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file test_quiesce_stream.c
22 * @brief Testcase for libmicrohttpd quiescing
23 * @author Markus Doppelbauer
24 * @author Christian Grothoff
25 */
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29#include <errno.h>
30#include <arpa/inet.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <pthread.h>
34#include <microhttpd.h>
35
36
37static volatile unsigned int request_counter;
38
39
40static void
41http_PanicCallback (void *cls,
42 const char *file,
43 unsigned int line,
44 const char *reason)
45{
46 fprintf( stderr,
47 "PANIC: exit process: %s at %s:%u\n",
48 reason,
49 file,
50 line);
51 exit (EXIT_FAILURE);
52}
53
54
55static void *
56resume_connection (void *arg)
57{
58 struct MHD_Connection *connection = arg;
59
60 MHD_resume_connection (connection);
61 return NULL;
62}
63
64
65static void
66suspend_connection (struct MHD_Connection *connection)
67{
68 pthread_t thread_id;
69
70 MHD_suspend_connection (connection);
71 int status = pthread_create (&thread_id,
72 NULL,
73 &resume_connection,
74 connection);
75 if (0 != status)
76 {
77 fprintf (stderr,
78 "Could not create thead\n");
79 exit( EXIT_FAILURE );
80 }
81 pthread_detach (thread_id);
82}
83
84
85struct ContentReaderUserdata
86{
87 int bytes_written;
88 struct MHD_Connection *connection;
89};
90
91
92static ssize_t
93http_ContentReaderCallback (void *cls,
94 uint64_t pos,
95 char *buf,
96 size_t max)
97{
98 static const char alphabet[] = "\nABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
99 struct ContentReaderUserdata *userdata = cls;
100
101 if( userdata->bytes_written >= 1024)
102 {
103 fprintf( stderr,
104 "finish: %d\n",
105 request_counter);
106 return MHD_CONTENT_READER_END_OF_STREAM;
107 }
108 userdata->bytes_written++;
109 buf[0] = alphabet[userdata->bytes_written % (sizeof(alphabet) - 1)];
110 suspend_connection (userdata->connection);
111
112 return 1;
113}
114
115
116static int
117http_AccessHandlerCallback (void *cls,
118 struct MHD_Connection *connection,
119 const char *url,
120 const char *method,
121 const char *version,
122 const char *upload_data,
123 size_t *upload_data_size,
124 void **con_cls )
125{
126 int ret;
127
128 /* Never respond on first call */
129 if (NULL == *con_cls)
130 {
131 fprintf (stderr,
132 "start: %d\n",
133 ++request_counter);
134
135 struct ContentReaderUserdata *userdata = malloc (sizeof(struct ContentReaderUserdata));
136
137 if (NULL == userdata)
138 return MHD_NO;
139 userdata->bytes_written = 0;
140 userdata->connection = connection;
141 *con_cls = userdata;
142 return MHD_YES;
143 }
144
145 /* Second call: create response */
146 struct MHD_Response *response
147 = MHD_create_response_from_callback (-1,
148 32 * 1024,
149 &http_ContentReaderCallback,
150 *con_cls,
151 NULL);
152 ret = MHD_queue_response (connection,
153 MHD_HTTP_OK,
154 response);
155 MHD_destroy_response (response);
156
157 suspend_connection (connection);
158 return ret;
159}
160
161
162int
163main()
164{
165 // Panic callback
166 MHD_set_panic_func (&http_PanicCallback,
167 NULL);
168
169 // Flags
170 unsigned int daemon_flags
171 = MHD_USE_SELECT_INTERNALLY
172 | MHD_USE_EPOLL
173 | MHD_USE_SUSPEND_RESUME
174 | MHD_USE_PIPE_FOR_SHUTDOWN;
175
176 // Create daemon
177 struct MHD_Daemon *daemon = MHD_start_daemon (daemon_flags,
178 8000,
179 NULL,
180 NULL,
181 &http_AccessHandlerCallback,
182 NULL,
183 MHD_OPTION_END);
184 if (NULL == daemon)
185 return EXIT_FAILURE;
186 if (0 != system ("wget --server-response -q -O - 127.0.0.1:8000"))
187 {
188 MHD_stop_daemon (daemon);
189 return EXIT_SUCCESS;
190 }
191 // wait for a request
192 while (0 == request_counter)
193 sleep (1);
194
195 fprintf (stderr,
196 "quiesce\n");
197 MHD_quiesce_daemon (daemon);
198
199 /* wait a second */
200 sleep (1);
201
202 fprintf (stderr,
203 "stopping daemon\n");
204 MHD_stop_daemon (daemon);
205
206 return EXIT_SUCCESS;
207}