1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 Red Hat, Inc.
17 #include <libsoup/soup-address.h>
18 #include <libsoup/soup-message.h>
19 #include <libsoup/soup-misc.h>
20 #include <libsoup/soup-server.h>
21 #include <libsoup/soup-session-async.h>
22 #include <libsoup/soup-session-sync.h>
24 #include "test-utils.h"
26 static char *base_uri;
35 request_failed (SoupMessage *msg, gpointer data)
39 if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
40 g_source_destroy (sd->timeout);
45 add_body_chunk (gpointer data)
49 soup_message_body_append (sd->msg->response_body,
50 SOUP_MEMORY_STATIC, "OK\r\n", 4);
51 soup_message_body_complete (sd->msg->response_body);
52 soup_server_unpause_message (sd->server, sd->msg);
53 g_object_unref (sd->msg);
59 server_callback (SoupServer *server, SoupMessage *msg,
60 const char *path, GHashTable *query,
61 SoupClientContext *context, gpointer data)
65 if (msg->method != SOUP_METHOD_GET) {
66 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
70 soup_message_set_status (msg, SOUP_STATUS_OK);
71 if (!strcmp (path, "/fast")) {
72 soup_message_set_response (msg, "text/plain",
73 SOUP_MEMORY_STATIC, "OK\r\n", 4);
77 soup_message_headers_set_encoding (msg->response_headers,
78 SOUP_ENCODING_CHUNKED);
80 soup_server_pause_message (server, msg);
82 sd = g_new (SlowData, 1);
85 sd->timeout = soup_add_timeout (
86 soup_server_get_async_context (server),
87 200, add_body_chunk, sd);
88 g_signal_connect (msg, "finished",
89 G_CALLBACK (request_failed), sd);
92 /* Test 1: An async session in another thread with its own
93 * async_context can complete a request while the main thread's main
97 static gboolean idle_start_test1_thread (gpointer loop);
98 static gpointer test1_thread (gpointer user_data);
100 static GCond *test1_cond;
101 static GMutex *test1_mutex;
108 debug_printf (1, "Test 1: blocking the main thread does not block other thread\n");
110 test1_cond = g_cond_new ();
111 test1_mutex = g_mutex_new ();
113 loop = g_main_loop_new (NULL, FALSE);
114 g_idle_add (idle_start_test1_thread, loop);
115 g_main_loop_run (loop);
116 g_main_loop_unref (loop);
118 g_mutex_free (test1_mutex);
119 g_cond_free (test1_cond);
123 idle_start_test1_thread (gpointer loop)
128 g_mutex_lock (test1_mutex);
129 thread = g_thread_create (test1_thread, base_uri, TRUE, NULL);
131 g_get_current_time (&time);
133 if (g_cond_timed_wait (test1_cond, test1_mutex, &time))
134 g_thread_join (thread);
136 debug_printf (1, " timeout!\n");
140 g_mutex_unlock (test1_mutex);
141 g_main_loop_quit (loop);
146 test1_finished (SoupSession *session, SoupMessage *msg, gpointer loop)
148 g_main_loop_quit (loop);
152 test1_thread (gpointer user_data)
154 SoupSession *session;
155 GMainContext *async_context;
160 /* Wait for main thread to be waiting on test1_cond */
161 g_mutex_lock (test1_mutex);
162 g_mutex_unlock (test1_mutex);
164 async_context = g_main_context_new ();
165 session = soup_test_session_new (
166 SOUP_TYPE_SESSION_ASYNC,
167 SOUP_SESSION_ASYNC_CONTEXT, async_context,
169 g_main_context_unref (async_context);
171 uri = g_build_filename (base_uri, "slow", NULL);
173 debug_printf (1, " send_message\n");
174 msg = soup_message_new ("GET", uri);
175 soup_session_send_message (session, msg);
176 if (msg->status_code != SOUP_STATUS_OK) {
177 debug_printf (1, " unexpected status: %d %s\n",
178 msg->status_code, msg->reason_phrase);
181 g_object_unref (msg);
183 debug_printf (1, " queue_message\n");
184 msg = soup_message_new ("GET", uri);
185 loop = g_main_loop_new (async_context, FALSE);
187 soup_session_queue_message (session, msg, test1_finished, loop);
188 g_main_loop_run (loop);
189 g_main_loop_unref (loop);
190 if (msg->status_code != SOUP_STATUS_OK) {
191 debug_printf (1, " unexpected status: %d %s\n",
192 msg->status_code, msg->reason_phrase);
195 g_object_unref (msg);
197 soup_test_session_abort_unref (session);
200 g_cond_signal (test1_cond);
204 /* Test 2: An async session in the main thread with its own
205 * async_context runs independently of the default main loop.
208 static gboolean idle_test2_fail (gpointer user_data);
214 GMainContext *async_context;
215 SoupSession *session;
219 debug_printf (1, "Test 2: a session with its own context is independent of the main loop.\n");
221 idle = g_idle_add_full (G_PRIORITY_HIGH, idle_test2_fail, NULL, NULL);
223 async_context = g_main_context_new ();
224 session = soup_test_session_new (
225 SOUP_TYPE_SESSION_ASYNC,
226 SOUP_SESSION_ASYNC_CONTEXT, async_context,
228 g_main_context_unref (async_context);
230 uri = g_build_filename (base_uri, "slow", NULL);
232 debug_printf (1, " send_message\n");
233 msg = soup_message_new ("GET", uri);
234 soup_session_send_message (session, msg);
235 if (msg->status_code != SOUP_STATUS_OK) {
236 debug_printf (1, " unexpected status: %d %s\n",
237 msg->status_code, msg->reason_phrase);
240 g_object_unref (msg);
242 soup_test_session_abort_unref (session);
245 g_source_remove (idle);
249 idle_test2_fail (gpointer user_data)
251 debug_printf (1, " idle ran!\n");
258 main (int argc, char **argv)
262 test_init (argc, argv, NULL);
264 server = soup_test_server_new (TRUE);
265 soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
266 base_uri = g_strdup_printf ("http://127.0.0.1:%u/",
267 soup_server_get_port (server));
273 soup_test_server_quit_unref (server);