1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 #include "test-utils.h"
5 static gboolean slow_https;
8 message_finished (SoupMessage *msg, gpointer user_data)
10 gboolean *finished = user_data;
16 request_started_cb (SoupSession *session, SoupMessage *msg,
17 SoupSocket *socket, gpointer user_data)
19 SoupSocket **ret = user_data;
25 do_message_to_session (SoupSession *session, const char *uri,
26 const char *comment, guint expected_status)
29 gboolean finished = FALSE;
32 debug_printf (1, " msg %s\n", comment);
33 msg = soup_message_new ("GET", uri);
35 g_signal_connect (msg, "finished",
36 G_CALLBACK (message_finished), &finished);
37 soup_session_send_message (session, msg);
39 soup_test_assert_message_status (msg, expected_status);
40 if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
41 g_assert_true (soup_message_is_keepalive (msg));
42 g_assert_true (finished);
44 g_signal_handlers_disconnect_by_func (msg,
45 G_CALLBACK (message_finished),
51 do_msg_tests_for_session (SoupSession *timeout_session,
52 SoupSession *idle_session,
53 SoupSession *plain_session,
57 SoupSocket *ret, *idle_first, *idle_second;
58 SoupSocket *plain_first, *plain_second;
61 g_signal_connect (idle_session, "request-started",
62 G_CALLBACK (request_started_cb), &ret);
63 do_message_to_session (idle_session, fast_uri, "fast to idle", SOUP_STATUS_OK);
64 idle_first = g_object_ref (ret);
68 g_signal_connect (plain_session, "request-started",
69 G_CALLBACK (request_started_cb), &ret);
70 do_message_to_session (plain_session, fast_uri, "fast to plain", SOUP_STATUS_OK);
71 plain_first = g_object_ref (ret);
74 do_message_to_session (timeout_session, fast_uri, "fast to timeout", SOUP_STATUS_OK);
75 do_message_to_session (timeout_session, slow_uri, "slow to timeout", SOUP_STATUS_IO_ERROR);
78 do_message_to_session (idle_session, fast_uri, "fast to idle", SOUP_STATUS_OK);
80 g_signal_handlers_disconnect_by_func (idle_session,
81 (gpointer)request_started_cb,
84 soup_test_assert (idle_first != idle_second,
85 "idle_session did not close first connection");
86 g_object_unref (idle_first);
90 do_message_to_session (plain_session, fast_uri, "fast to plain", SOUP_STATUS_OK);
92 g_signal_handlers_disconnect_by_func (plain_session,
93 (gpointer)request_started_cb,
96 soup_test_assert (plain_first == plain_second,
97 "plain_session closed connection");
98 g_object_unref (plain_first);
103 do_request_to_session (SoupSession *session, const char *uri,
104 const char *comment, gboolean expect_timeout)
108 GInputStream *stream;
109 GError *error = NULL;
110 gboolean finished = FALSE;
112 debug_printf (1, " req %s\n", comment);
113 req = soup_session_request (session, uri, NULL);
114 msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
116 g_signal_connect (msg, "finished",
117 G_CALLBACK (message_finished), &finished);
118 stream = soup_test_request_send (req, NULL, 0, &error);
121 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT);
123 g_assert_no_error (error);
124 g_clear_error (&error);
127 soup_test_request_read_all (req, stream, NULL, &error);
128 g_assert_no_error (error);
132 soup_test_request_close_stream (req, stream, NULL, &error);
133 g_assert_no_error (error);
134 g_object_unref (stream);
137 if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
138 g_assert_true (soup_message_is_keepalive (msg));
139 g_assert_true (finished);
141 g_signal_handlers_disconnect_by_func (msg,
142 G_CALLBACK (message_finished),
144 g_object_unref (msg);
145 g_object_unref (req);
149 do_req_tests_for_session (SoupSession *timeout_session,
150 SoupSession *idle_session,
151 SoupSession *plain_session,
152 const char *fast_uri,
153 const char *slow_uri)
155 SoupSocket *ret, *idle_first, *idle_second;
156 SoupSocket *plain_first, *plain_second;
159 g_signal_connect (idle_session, "request-started",
160 G_CALLBACK (request_started_cb), &ret);
161 do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE);
162 idle_first = g_object_ref (ret);
166 g_signal_connect (plain_session, "request-started",
167 G_CALLBACK (request_started_cb), &ret);
168 do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE);
169 plain_first = g_object_ref (ret);
172 do_request_to_session (timeout_session, fast_uri, "fast to timeout", FALSE);
173 do_request_to_session (timeout_session, slow_uri, "slow to timeout", TRUE);
176 do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE);
178 g_signal_handlers_disconnect_by_func (idle_session,
179 (gpointer)request_started_cb,
182 soup_test_assert (idle_first != idle_second,
183 "idle_session did not close first connection");
184 g_object_unref (idle_first);
188 do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE);
190 g_signal_handlers_disconnect_by_func (plain_session,
191 (gpointer)request_started_cb,
194 soup_test_assert (plain_first == plain_second,
195 "plain_session closed connection");
196 g_object_unref (plain_first);
201 do_async_timeout_tests (gconstpointer data)
203 SoupSession *timeout_session, *idle_session, *plain_session;
204 const char *fast_uri = data;
205 const char *slow_uri = g_build_path ("/", fast_uri, "slow", NULL);
208 if (g_str_has_prefix (fast_uri, "https")) {
209 SOUP_TEST_SKIP_IF_NO_TLS;
211 extra_slow = slow_https;
215 timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
216 SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1,
217 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
219 idle_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
220 SOUP_SESSION_IDLE_TIMEOUT, extra_slow ? 2 : 1,
221 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
223 /* The "plain" session also has an idle timeout, but it's longer
224 * than the test takes, so for our purposes it should behave like
227 plain_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
228 SOUP_SESSION_IDLE_TIMEOUT, 20,
229 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
232 do_msg_tests_for_session (timeout_session, idle_session, plain_session,
234 do_req_tests_for_session (timeout_session, idle_session, plain_session,
236 soup_test_session_abort_unref (timeout_session);
237 soup_test_session_abort_unref (idle_session);
238 soup_test_session_abort_unref (plain_session);
242 do_sync_timeout_tests (gconstpointer data)
244 SoupSession *timeout_session, *plain_session;
245 const char *fast_uri = data;
246 const char *slow_uri = g_build_path ("/", fast_uri, "slow", NULL);
249 if (g_str_has_prefix (fast_uri, "https")) {
250 SOUP_TEST_SKIP_IF_NO_TLS;
252 extra_slow = slow_https;
256 timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
257 SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1,
259 /* SOUP_SESSION_TIMEOUT doesn't work with sync sessions */
260 plain_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
262 do_msg_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri);
263 do_req_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri);
264 soup_test_session_abort_unref (timeout_session);
265 soup_test_session_abort_unref (plain_session);
269 timeout_finish_message (gpointer msg)
271 SoupServer *server = g_object_get_data (G_OBJECT (msg), "server");
273 soup_server_unpause_message (server, msg);
278 server_handler (SoupServer *server,
282 SoupClientContext *client,
285 soup_message_set_status (msg, SOUP_STATUS_OK);
286 soup_message_set_response (msg, "text/plain",
290 if (!strcmp (path, "/slow")) {
291 soup_server_pause_message (server, msg);
292 g_object_set_data (G_OBJECT (msg), "server", server);
293 soup_add_timeout (soup_server_get_async_context (server),
294 4000, timeout_finish_message, msg);
299 main (int argc, char **argv)
301 SoupServer *server, *https_server = NULL;
302 char *uri, *https_uri = NULL;
305 test_init (argc, argv, NULL);
307 server = soup_test_server_new (TRUE);
308 soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
309 uri = g_strdup_printf ("http://127.0.0.1:%u/",
310 soup_server_get_port (server));
313 SoupSession *test_session;
316 https_server = soup_test_server_new_ssl (TRUE);
317 soup_server_add_handler (https_server, NULL, server_handler, NULL, NULL);
318 https_uri = g_strdup_printf ("https://127.0.0.1:%u/",
319 soup_server_get_port (https_server));
321 /* The 1-second timeouts are too fast for some machines... */
322 test_session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
323 start = g_get_monotonic_time ();
324 do_message_to_session (test_session, uri, NULL, SOUP_STATUS_OK);
325 end = g_get_monotonic_time ();
326 soup_test_session_abort_unref (test_session);
327 debug_printf (2, " (https request took %0.3fs)\n", (end - start) / 1000000.0);
328 if (end - start > 750000) {
329 debug_printf (1, " (using extra-slow mode)\n\n");
332 debug_printf (2, "\n");
336 https_uri = g_strdup ("https://fail.");
338 g_test_add_data_func ("/timeout/http/async", uri, do_async_timeout_tests);
339 g_test_add_data_func ("/timeout/http/sync", uri, do_sync_timeout_tests);
340 g_test_add_data_func ("/timeout/https/async", https_uri, do_async_timeout_tests);
341 g_test_add_data_func ("/timeout/https/sync", https_uri, do_sync_timeout_tests);
347 soup_test_server_quit_unref (server);
349 soup_test_server_quit_unref (https_server);