add missing slash in %configure
[platform/upstream/libsoup.git] / tests / session-test.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 #include "test-utils.h"
4
5 static gboolean server_processed_message;
6 static gboolean timeout;
7 static GMainLoop *loop;
8 static SoupMessagePriority expected_priorities[3];
9
10 static gboolean
11 timeout_cb (gpointer user_data)
12 {
13         gboolean *timeout = user_data;
14
15         *timeout = TRUE;
16         return FALSE;
17 }
18
19 static void
20 server_handler (SoupServer        *server,
21                 SoupMessage       *msg, 
22                 const char        *path,
23                 GHashTable        *query,
24                 SoupClientContext *client,
25                 gpointer           user_data)
26 {
27         if (!strcmp (path, "/request-timeout")) {
28                 GMainContext *context = soup_server_get_async_context (server);
29                 GSource *timer;
30
31                 timer = g_timeout_source_new (100);
32                 g_source_set_callback (timer, timeout_cb, &timeout, NULL);
33                 g_source_attach (timer, context);
34                 g_source_unref (timer);
35         } else
36                 server_processed_message = TRUE;
37
38         soup_message_set_status (msg, SOUP_STATUS_OK);
39         soup_message_set_response (msg, "text/plain",
40                                    SOUP_MEMORY_STATIC,
41                                    "ok\r\n", 4);
42 }
43
44 static void
45 finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
46 {
47         gboolean *finished = user_data;
48
49         *finished = TRUE;
50 }
51
52 static void
53 cancel_message_cb (SoupMessage *msg, gpointer session)
54 {
55         soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
56         g_main_loop_quit (loop);
57 }
58
59 static void
60 do_test_for_session (SoupSession *session,
61                      const char *uri,
62                      gboolean queue_is_async,
63                      gboolean send_is_blocking,
64                      gboolean cancel_is_immediate)
65 {
66         SoupMessage *msg;
67         gboolean finished, local_timeout;
68         guint timeout_id;
69         char *timeout_uri;
70
71         debug_printf (1, "  queue_message\n");
72         debug_printf (2, "    requesting timeout\n");
73         timeout_uri = g_strdup_printf ("%s/request-timeout", uri);
74         msg = soup_message_new ("GET", timeout_uri);
75         g_free (timeout_uri);
76         soup_session_send_message (session, msg);
77         g_object_unref (msg);
78
79         msg = soup_message_new ("GET", uri);
80         server_processed_message = timeout = finished = FALSE;
81         soup_session_queue_message (session, msg, finished_cb, &finished);
82         while (!timeout)
83                 g_usleep (100);
84         debug_printf (2, "    got timeout\n");
85
86         if (queue_is_async) {
87                 g_assert_false (server_processed_message);
88                 debug_printf (2, "    waiting for finished\n");
89                 while (!finished)
90                         g_main_context_iteration (NULL, TRUE);
91                 g_assert_true (server_processed_message);
92         } else {
93                 g_assert_true (server_processed_message);
94                 g_assert_false (finished);
95                 debug_printf (2, "    waiting for finished\n");
96                 while (!finished)
97                         g_main_context_iteration (NULL, TRUE);
98         }
99
100         debug_printf (1, "  send_message\n");
101         msg = soup_message_new ("GET", uri);
102         server_processed_message = local_timeout = FALSE;
103         timeout_id = g_idle_add_full (G_PRIORITY_HIGH, timeout_cb, &local_timeout, NULL);
104         soup_session_send_message (session, msg);
105
106         g_assert_true (server_processed_message);
107
108         if (send_is_blocking) {
109                 soup_test_assert (!local_timeout,
110                                   "send_message ran main loop");
111         } else {
112                 soup_test_assert (local_timeout,
113                                   "send_message didn't run main loop");
114         }
115
116         if (!local_timeout)
117                 g_source_remove (timeout_id);
118
119         if (!queue_is_async)
120                 return;
121
122         debug_printf (1, "  cancel_message\n");
123         msg = soup_message_new ("GET", uri);
124         g_object_ref (msg);
125         finished = FALSE;
126         soup_session_queue_message (session, msg, finished_cb, &finished);
127         g_signal_connect (msg, "wrote-headers",
128                           G_CALLBACK (cancel_message_cb), session);
129
130         loop = g_main_loop_new (NULL, FALSE);
131         g_main_loop_run (loop);
132
133         if (cancel_is_immediate)
134                 g_assert_true (finished);
135         else
136                 g_assert_false (finished);
137
138         if (!finished) {
139                 debug_printf (2, "    waiting for finished\n");
140                 while (!finished)
141                         g_main_context_iteration (NULL, TRUE);
142         }
143
144         soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
145         g_object_unref (msg);
146 }
147
148 static void
149 do_plain_tests (gconstpointer uri)
150 {
151         SoupSession *session;
152
153         session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
154         do_test_for_session (session, uri, TRUE, TRUE, FALSE);
155         soup_test_session_abort_unref (session);
156 }
157
158 static void
159 do_async_tests (gconstpointer uri)
160 {
161         SoupSession *session;
162
163         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
164         do_test_for_session (session, uri, TRUE, FALSE, TRUE);
165         soup_test_session_abort_unref (session);
166 }
167
168 static void
169 do_sync_tests (gconstpointer uri)
170 {
171         SoupSession *session;
172
173         session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
174         do_test_for_session (session, uri, FALSE, TRUE, FALSE);
175         soup_test_session_abort_unref (session);
176 }
177
178 static void
179 priority_test_finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
180 {
181         guint *finished_count = user_data;
182         SoupMessagePriority priority = soup_message_get_priority (msg);
183
184         debug_printf (1, "  received message %d with priority %d\n",
185                       *finished_count, priority);
186
187         soup_test_assert (priority == expected_priorities[*finished_count],
188                           "message %d should have priority %d (%d found)",
189                           *finished_count, expected_priorities[*finished_count], priority);
190
191         (*finished_count)++;
192 }
193
194 static void
195 do_priority_tests (gconstpointer data)
196 {
197         const char *uri = data;
198         SoupSession *session;
199         int i, finished_count = 0;
200         SoupMessagePriority priorities[] =
201                 { SOUP_MESSAGE_PRIORITY_LOW,
202                   SOUP_MESSAGE_PRIORITY_HIGH,
203                   SOUP_MESSAGE_PRIORITY_NORMAL };
204
205         g_test_bug ("696277");
206
207         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
208         g_object_set (session, "max-conns", 1, NULL);
209
210         expected_priorities[0] = SOUP_MESSAGE_PRIORITY_HIGH;
211         expected_priorities[1] = SOUP_MESSAGE_PRIORITY_NORMAL;
212         expected_priorities[2] = SOUP_MESSAGE_PRIORITY_LOW;
213
214         for (i = 0; i < 3; i++) {
215                 char *msg_uri;
216                 SoupMessage *msg;
217
218                 msg_uri = g_strdup_printf ("%s/%d", uri, i);
219                 msg = soup_message_new ("GET", uri);
220                 g_free (msg_uri);
221
222                 soup_message_set_priority (msg, priorities[i]);
223                 soup_session_queue_message (session, msg, priority_test_finished_cb, &finished_count);
224         }
225
226         debug_printf (2, "    waiting for finished\n");
227         while (finished_count != 3)
228                 g_main_context_iteration (NULL, TRUE);
229
230         soup_test_session_abort_unref (session);
231 }
232
233 static void
234 test_session_properties (const char *name,
235                          SoupSession *session,
236                          GProxyResolver *expected_proxy_resolver,
237                          GTlsDatabase *expected_tls_database)
238 {
239         GProxyResolver *proxy_resolver = NULL;
240         GTlsDatabase *tlsdb = NULL;
241
242         g_object_get (G_OBJECT (session),
243                       SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver,
244                       SOUP_SESSION_TLS_DATABASE, &tlsdb,
245                       NULL);
246
247         soup_test_assert (proxy_resolver == expected_proxy_resolver,
248                           "%s has %s proxy resolver",
249                           name, proxy_resolver ? (expected_proxy_resolver ? "wrong" : "a") : "no");
250         soup_test_assert (tlsdb == expected_tls_database,
251                           "%s has %s TLS database",
252                           name, tlsdb ? (expected_tls_database ? "wrong" : "a") : "no");
253
254         g_clear_object (&proxy_resolver);
255         g_clear_object (&tlsdb);
256 }
257
258 static void
259 do_property_tests (void)
260 {
261         SoupSession *session;
262         GProxyResolver *proxy_resolver, *default_proxy_resolver;
263         GTlsDatabase *tlsdb, *default_tlsdb;
264         SoupURI *uri;
265
266         g_test_bug ("708696");
267
268         default_proxy_resolver = g_proxy_resolver_get_default ();
269         default_tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
270
271         /* NOTE: We intentionally do not use soup_test_session_new() here */
272
273         session = g_object_new (SOUP_TYPE_SESSION,
274                                 NULL);
275         test_session_properties ("Base plain session", session,
276                                  default_proxy_resolver, default_tlsdb);
277         g_object_unref (session);
278
279         session = g_object_new (SOUP_TYPE_SESSION,
280                                 SOUP_SESSION_PROXY_RESOLVER, NULL,
281                                 NULL);
282         test_session_properties ("Session with NULL :proxy-resolver", session,
283                                  NULL, default_tlsdb);
284         g_object_unref (session);
285
286         proxy_resolver = g_simple_proxy_resolver_new (NULL, NULL);
287         session = g_object_new (SOUP_TYPE_SESSION,
288                                 SOUP_SESSION_PROXY_RESOLVER, proxy_resolver,
289                                 NULL);
290         test_session_properties ("Session with non-NULL :proxy-resolver", session,
291                                  proxy_resolver, default_tlsdb);
292         g_object_unref (proxy_resolver);
293         g_object_unref (session);
294
295         session = g_object_new (SOUP_TYPE_SESSION,
296                                 SOUP_SESSION_PROXY_URI, NULL,
297                                 NULL);
298         test_session_properties ("Session with NULL :proxy-uri", session,
299                                  NULL, default_tlsdb);
300         g_object_unref (session);
301
302         uri = soup_uri_new ("http://example.com/");
303         session = g_object_new (SOUP_TYPE_SESSION,
304                                 SOUP_SESSION_PROXY_URI, uri,
305                                 NULL);
306         g_object_get (G_OBJECT (session),
307                       SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver,
308                       NULL);
309         test_session_properties ("Session with non-NULL :proxy-uri", session,
310                                  proxy_resolver, default_tlsdb);
311         g_assert_cmpstr (G_OBJECT_TYPE_NAME (proxy_resolver), ==, "GSimpleProxyResolver");
312         g_object_unref (proxy_resolver);
313         g_object_unref (session);
314         soup_uri_free (uri);
315
316         G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
317         session = g_object_new (SOUP_TYPE_SESSION,
318                                 SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_URI_RESOLVER,
319                                 NULL);
320         test_session_properties ("Session with removed proxy resolver feature", session,
321                                  NULL, default_tlsdb);
322         g_object_unref (session);
323         G_GNUC_END_IGNORE_DEPRECATIONS;
324
325         session = g_object_new (SOUP_TYPE_SESSION,
326                                 SOUP_SESSION_TLS_DATABASE, NULL,
327                                 NULL);
328         test_session_properties ("Session with NULL :tls-database", session,
329                                  default_proxy_resolver, NULL);
330         g_object_unref (session);
331
332         /* g_tls_file_database_new() will fail with the dummy backend,
333          * so we can only do this test if we have a real TLS backend.
334          */
335         if (tls_available) {
336                 GError *error = NULL;
337
338                 tlsdb = g_tls_file_database_new (g_test_get_filename (G_TEST_DIST,
339                                                                       "test-cert.pem",
340                                                                       NULL), &error);
341                 g_assert_no_error (error);
342
343                 session = g_object_new (SOUP_TYPE_SESSION,
344                                         SOUP_SESSION_TLS_DATABASE, tlsdb,
345                                         NULL);
346                 test_session_properties ("Session with non-NULL :tls-database", session,
347                                          default_proxy_resolver, tlsdb);
348                 g_object_unref (tlsdb);
349                 g_object_unref (session);
350         }
351
352         session = g_object_new (SOUP_TYPE_SESSION,
353                                 SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE,
354                                 NULL);
355         test_session_properties ("Session with :ssl-use-system-ca-file FALSE", session,
356                                  default_proxy_resolver, NULL);
357         g_object_unref (session);
358
359         session = g_object_new (SOUP_TYPE_SESSION,
360                                 SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
361                                 NULL);
362         test_session_properties ("Session with :ssl-use-system-ca-file TRUE", session,
363                                  default_proxy_resolver, default_tlsdb);
364         g_object_unref (session);
365 }
366
367 int
368 main (int argc, char **argv)
369 {
370         SoupServer *server;
371         char *uri, *timeout_uri;
372         int ret;
373
374         test_init (argc, argv, NULL);
375
376         server = soup_test_server_new (TRUE);
377         soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
378         uri = g_strdup_printf ("http://127.0.0.1:%u",
379                                soup_server_get_port (server));
380         timeout_uri = g_strdup_printf ("%s/request-timeout", uri);
381
382         g_test_add_data_func ("/session/SoupSession", uri, do_plain_tests);
383         g_test_add_data_func ("/session/SoupSessionAsync", uri, do_async_tests);
384         g_test_add_data_func ("/session/SoupSessionSync", uri, do_sync_tests);
385         g_test_add_data_func ("/session/priority", uri, do_priority_tests);
386         g_test_add_func ("/session/property", do_property_tests);
387
388         ret = g_test_run ();
389
390         g_free (uri);
391         g_free (timeout_uri);
392         soup_test_server_quit_unref (server);
393
394         test_cleanup ();
395         return ret;
396 }