add missing slash in %configure
[platform/upstream/libsoup.git] / tests / requester-test.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2011 Red Hat, Inc.
4  */
5
6 /* Kill SoupRequester-related deprecation warnings */
7 #define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40
8
9 #include "test-utils.h"
10
11 SoupServer *server;
12 GMainLoop *loop;
13 char buf[1024];
14
15 SoupBuffer *response, *auth_response;
16
17 #define REDIRECT_HTML_BODY "<html><body>Try again</body></html>\r\n"
18 #define AUTH_HTML_BODY "<html><body>Unauthorized</body></html>\r\n"
19
20 static gboolean
21 slow_finish_message (gpointer msg)
22 {
23         SoupServer *server = g_object_get_data (G_OBJECT (msg), "server");
24
25         soup_server_unpause_message (server, msg);
26         return FALSE;
27 }
28
29 static void
30 slow_pause_message (SoupMessage *msg, gpointer server)
31 {
32         soup_server_pause_message (server, msg);
33         soup_add_timeout (soup_server_get_async_context (server),
34                           1000, slow_finish_message, msg);
35 }
36
37 static void
38 server_callback (SoupServer *server, SoupMessage *msg,
39                  const char *path, GHashTable *query,
40                  SoupClientContext *context, gpointer data)
41 {
42         gboolean chunked = FALSE;
43         int i;
44
45         if (strcmp (path, "/auth") == 0) {
46                 soup_message_set_status (msg, SOUP_STATUS_UNAUTHORIZED);
47                 soup_message_set_response (msg, "text/html",
48                                            SOUP_MEMORY_STATIC,
49                                            AUTH_HTML_BODY,
50                                            strlen (AUTH_HTML_BODY));
51                 soup_message_headers_append (msg->response_headers,
52                                              "WWW-Authenticate",
53                                              "Basic: realm=\"requester-test\"");
54                 return;
55         } else if (strcmp (path, "/foo") == 0) {
56                 soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/");
57                 /* Make the response HTML so if we sniff that instead of the
58                  * real body, we'll notice.
59                  */
60                 soup_message_set_response (msg, "text/html",
61                                            SOUP_MEMORY_STATIC,
62                                            REDIRECT_HTML_BODY,
63                                            strlen (REDIRECT_HTML_BODY));
64                 return;
65         } else if (strcmp (path, "/chunked") == 0) {
66                 chunked = TRUE;
67         } else if (strcmp (path, "/non-persistent") == 0) {
68                 soup_message_headers_append (msg->response_headers,
69                                              "Connection", "close");
70         } else if (!strcmp (path, "/slow")) {
71                 g_object_set_data (G_OBJECT (msg), "server", server);
72                 g_signal_connect (msg, "wrote-headers",
73                                   G_CALLBACK (slow_pause_message), server);
74         }
75
76         soup_message_set_status (msg, SOUP_STATUS_OK);
77
78         if (chunked) {
79                 soup_message_headers_set_encoding (msg->response_headers,
80                                                    SOUP_ENCODING_CHUNKED);
81
82                 for (i = 0; i < response->length; i += 8192) {
83                         SoupBuffer *tmp;
84
85                         tmp = soup_buffer_new_subbuffer (response, i,
86                                                          MIN (8192, response->length - i));
87                         soup_message_body_append_buffer (msg->response_body, tmp);
88                         soup_buffer_free (tmp);
89                 }
90                 soup_message_body_complete (msg->response_body);
91         } else
92                 soup_message_body_append_buffer (msg->response_body, response);
93 }
94
95 typedef struct {
96         GString *body;
97         gboolean cancel;
98 } RequestData;
99
100 static void
101 stream_closed (GObject *source, GAsyncResult *res, gpointer user_data)
102 {
103         GInputStream *stream = G_INPUT_STREAM (source);
104         GError *error = NULL;
105
106         g_input_stream_close_finish (stream, res, &error);
107         g_assert_no_error (error);
108         g_main_loop_quit (loop);
109         g_object_unref (stream);
110 }
111
112 static void
113 test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data)
114 {
115         GInputStream *stream = G_INPUT_STREAM (source);
116         RequestData *data = user_data;
117         GString *body = data->body;
118         GError *error = NULL;
119         gsize nread;
120
121         nread = g_input_stream_read_finish (stream, res, &error);
122         if (nread == -1) {
123                 g_assert_no_error (error);
124                 g_error_free (error);
125                 g_input_stream_close (stream, NULL, NULL);
126                 g_object_unref (stream);
127                 g_main_loop_quit (loop);
128                 return;
129         } else if (nread == 0) {
130                 g_input_stream_close_async (stream,
131                                             G_PRIORITY_DEFAULT, NULL,
132                                             stream_closed, NULL);
133                 return;
134         }
135
136         g_string_append_len (body, buf, nread);
137         g_input_stream_read_async (stream, buf, sizeof (buf),
138                                    G_PRIORITY_DEFAULT, NULL,
139                                    test_read_ready, data);
140 }
141
142 static void
143 auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
144 {
145         RequestData *data = user_data;
146         GInputStream *stream;
147         GError *error = NULL;
148         SoupMessage *msg;
149         const char *content_type;
150
151         stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error);
152         if (!stream) {
153                 g_assert_no_error (error);
154                 g_clear_error (&error);
155                 g_main_loop_quit (loop);
156                 return;
157         }
158
159         msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source));
160         soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED);
161         g_object_unref (msg);
162
163         content_type = soup_request_get_content_type (SOUP_REQUEST (source));
164         g_assert_cmpstr (content_type, ==, "text/html");
165
166         g_input_stream_read_async (stream, buf, sizeof (buf),
167                                    G_PRIORITY_DEFAULT, NULL,
168                                    test_read_ready, data);
169 }
170
171 static void
172 test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
173 {
174         RequestData *data = user_data;
175         GInputStream *stream;
176         GError *error = NULL;
177         const char *content_type;
178
179         stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error);
180         if (data->cancel) {
181                 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
182                 g_clear_error (&error);
183                 g_main_loop_quit (loop);
184                 return;
185         } else {
186                 g_assert_no_error (error);
187                 if (!stream) {
188                         g_main_loop_quit (loop);
189                         g_clear_error (&error);
190                         return;
191                 }
192         }
193
194         content_type = soup_request_get_content_type (SOUP_REQUEST (source));
195         g_assert_cmpstr (content_type, ==, "text/plain");
196
197         g_input_stream_read_async (stream, buf, sizeof (buf),
198                                    G_PRIORITY_DEFAULT, NULL,
199                                    test_read_ready, data);
200 }
201
202 static void
203 cancel_message (SoupMessage *msg, gpointer session)
204 {
205         soup_session_cancel_message (session, msg, SOUP_STATUS_FORBIDDEN);
206 }
207
208 static void
209 request_started (SoupSession *session, SoupMessage *msg,
210                  SoupSocket *socket, gpointer user_data)
211 {
212         SoupSocket **save_socket = user_data;
213
214         g_clear_object (save_socket);
215         *save_socket = g_object_ref (socket);
216 }
217
218 static void
219 do_async_test (SoupSession *session, SoupURI *uri,
220                GAsyncReadyCallback callback, guint expected_status,
221                SoupBuffer *expected_response,
222                gboolean persistent, gboolean cancel)
223 {
224         SoupRequester *requester;
225         SoupRequest *request;
226         guint started_id;
227         SoupSocket *socket = NULL;
228         SoupMessage *msg;
229         RequestData data;
230
231         if (SOUP_IS_SESSION_ASYNC (session))
232                 requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER));
233         else
234                 requester = NULL;
235
236         data.body = g_string_new (NULL);
237         data.cancel = cancel;
238         if (requester)
239                 request = soup_requester_request_uri (requester, uri, NULL);
240         else
241                 request = soup_session_request_uri (session, uri, NULL);
242         msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
243
244         if (cancel) {
245                 g_signal_connect (msg, "got-headers",
246                                   G_CALLBACK (cancel_message), session);
247         }
248
249         started_id = g_signal_connect (session, "request-started",
250                                        G_CALLBACK (request_started),
251                                        &socket);
252
253         soup_request_send_async (request, NULL, callback, &data);
254         g_object_unref (request);
255
256         loop = g_main_loop_new (soup_session_get_async_context (session), TRUE);
257         g_main_loop_run (loop);
258         g_main_loop_unref (loop);
259
260         g_signal_handler_disconnect (session, started_id);
261
262         soup_test_assert_message_status (msg, expected_status);
263         g_object_unref (msg);
264
265         if (expected_response) {
266                 soup_assert_cmpmem (data.body->str, data.body->len,
267                                     expected_response->data, expected_response->length);
268         } else
269                 g_assert_cmpint (data.body->len, ==, 0);
270
271         if (persistent)
272                 g_assert_true (soup_socket_is_connected (socket));
273         else
274                 g_assert_false (soup_socket_is_connected (socket));
275
276         g_object_unref (socket);
277
278         g_string_free (data.body, TRUE);
279 }
280
281 static void
282 do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
283 {
284         SoupRequester *requester;
285         SoupURI *uri;
286
287         if (SOUP_IS_SESSION_ASYNC (session)) {
288                 requester = soup_requester_new ();
289                 soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
290                 g_object_unref (requester);
291         }
292         soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER);
293
294         debug_printf (1, "    basic test\n");
295         uri = soup_uri_new (base_uri);
296         do_async_test (session, uri, test_sent,
297                        SOUP_STATUS_OK, response,
298                        TRUE, FALSE);
299         soup_uri_free (uri);
300
301         debug_printf (1, "    chunked test\n");
302         uri = soup_uri_new (base_uri);
303         soup_uri_set_path (uri, "/chunked");
304         do_async_test (session, uri, test_sent,
305                        SOUP_STATUS_OK, response,
306                        TRUE, FALSE);
307         soup_uri_free (uri);
308
309         debug_printf (1, "    auth test\n");
310         uri = soup_uri_new (base_uri);
311         soup_uri_set_path (uri, "/auth");
312         do_async_test (session, uri, auth_test_sent,
313                        SOUP_STATUS_UNAUTHORIZED, auth_response,
314                        TRUE, FALSE);
315         soup_uri_free (uri);
316
317         debug_printf (1, "    non-persistent test\n");
318         uri = soup_uri_new (base_uri);
319         soup_uri_set_path (uri, "/non-persistent");
320         do_async_test (session, uri, test_sent,
321                        SOUP_STATUS_OK, response,
322                        FALSE, FALSE);
323         soup_uri_free (uri);
324
325         debug_printf (1, "    cancellation test\n");
326         uri = soup_uri_new (base_uri);
327         soup_uri_set_path (uri, "/");
328         do_async_test (session, uri, test_sent,
329                        SOUP_STATUS_FORBIDDEN, NULL,
330                        FALSE, TRUE);
331         soup_uri_free (uri);
332 }
333
334 static void
335 do_simple_plain_test (gconstpointer uri)
336 {
337         SoupSession *session;
338
339         g_test_bug ("653707");
340
341         session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
342         do_test_for_thread_and_context (session, uri);
343         soup_test_session_abort_unref (session);
344 }
345
346 static void
347 do_simple_async_test (gconstpointer uri)
348 {
349         SoupSession *session;
350
351         g_test_bug ("653707");
352
353         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
354                                          SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
355                                          NULL);
356         do_test_for_thread_and_context (session, uri);
357         soup_test_session_abort_unref (session);
358 }
359
360 static void
361 do_test_with_context_and_type (const char *uri, gboolean plain_session)
362 {
363         GMainContext *async_context;
364         SoupSession *session;
365
366         g_test_bug ("653707");
367
368         async_context = g_main_context_new ();
369         g_main_context_push_thread_default (async_context);
370
371         session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC,
372                                          SOUP_SESSION_ASYNC_CONTEXT, async_context,
373                                          SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
374                                          NULL);
375
376         do_test_for_thread_and_context (session, uri);
377         soup_test_session_abort_unref (session);
378
379         g_main_context_pop_thread_default (async_context);
380         g_main_context_unref (async_context);
381 }
382
383 static void
384 do_async_test_with_context (gconstpointer uri)
385 {
386         do_test_with_context_and_type (uri, FALSE);
387 }
388
389 static void
390 do_plain_test_with_context (gconstpointer uri)
391 {
392         do_test_with_context_and_type (uri, TRUE);
393 }
394
395 static gpointer
396 async_test_thread (gpointer uri)
397 {
398         do_test_with_context_and_type (uri, TRUE);
399         return NULL;
400 }
401
402 static gpointer
403 plain_test_thread (gpointer uri)
404 {
405         do_test_with_context_and_type (uri, FALSE);
406         return NULL;
407 }
408
409 static void
410 do_async_test_in_thread (gconstpointer uri)
411 {
412         GThread *thread;
413
414         thread = g_thread_new ("do_async_test_in_thread",
415                                async_test_thread,
416                                (gpointer)uri);
417         g_thread_join (thread);
418 }
419
420 static void
421 do_plain_test_in_thread (gconstpointer uri)
422 {
423         GThread *thread;
424
425         thread = g_thread_new ("do_plain_test_in_thread",
426                                plain_test_thread,
427                                (gpointer)uri);
428         g_thread_join (thread);
429 }
430
431 static void
432 do_sync_request (SoupSession *session, SoupRequest *request,
433                  guint expected_status, SoupBuffer *expected_response,
434                  gboolean persistent, gboolean cancel)
435 {
436         GInputStream *in;
437         SoupMessage *msg;
438         GError *error = NULL;
439         GString *body;
440         char buf[1024];
441         gssize nread;
442         guint started_id;
443         SoupSocket *socket = NULL;
444
445         msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
446         if (cancel) {
447                 g_signal_connect (msg, "got-headers",
448                                   G_CALLBACK (cancel_message), session);
449         }
450
451         started_id = g_signal_connect (session, "request-started",
452                                        G_CALLBACK (request_started),
453                                        &socket);
454
455         in = soup_request_send (request, NULL, &error);
456         g_signal_handler_disconnect (session, started_id);
457         if (cancel) {
458                 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
459                 g_clear_error (&error);
460                 g_object_unref (msg);
461                 g_object_unref (socket);
462                 return;
463         } else if (!in) {
464                 g_assert_no_error (error);
465                 g_clear_error (&error);
466                 g_object_unref (msg);
467                 g_object_unref (socket);
468                 return;
469         }
470
471         soup_test_assert_message_status (msg, expected_status);
472         g_object_unref (msg);
473
474         body = g_string_new (NULL);
475         do {
476                 nread = g_input_stream_read (in, buf, sizeof (buf),
477                                              NULL, &error);
478                 g_assert_no_error (error);
479                 if (nread == -1) {
480                         g_clear_error (&error);
481                         break;
482                 }
483                 g_string_append_len (body, buf, nread);
484         } while (nread > 0);
485
486         g_input_stream_close (in, NULL, &error);
487         g_assert_no_error (error);
488         g_clear_error (&error);
489         g_object_unref (in);
490
491         if (expected_response) {
492                 soup_assert_cmpmem (body->str, body->len,
493                                     expected_response->data, expected_response->length);
494         } else
495                 g_assert_cmpint (body->len, ==, 0);
496
497         if (persistent)
498                 g_assert_true (soup_socket_is_connected (socket));
499         else
500                 g_assert_false (soup_socket_is_connected (socket));
501         g_object_unref (socket);
502
503         g_string_free (body, TRUE);
504 }
505
506 static void
507 do_sync_tests_for_session (SoupSession *session, const char *uri_string)
508 {
509         SoupRequester *requester;
510         SoupRequest *request;
511         SoupURI *uri;
512
513         requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER));
514
515         uri = soup_uri_new (uri_string);
516
517         debug_printf (1, "    basic test\n");
518         if (requester)
519                 request = soup_requester_request_uri (requester, uri, NULL);
520         else
521                 request = soup_session_request_uri (session, uri, NULL);
522         do_sync_request (session, request,
523                          SOUP_STATUS_OK, response,
524                          TRUE, FALSE);
525         g_object_unref (request);
526
527         debug_printf (1, "    chunked test\n");
528         soup_uri_set_path (uri, "/chunked");
529         if (requester)
530                 request = soup_requester_request_uri (requester, uri, NULL);
531         else
532                 request = soup_session_request_uri (session, uri, NULL);
533         do_sync_request (session, request,
534                          SOUP_STATUS_OK, response,
535                          TRUE, FALSE);
536         g_object_unref (request);
537
538         debug_printf (1, "    auth test\n");
539         soup_uri_set_path (uri, "/auth");
540         if (requester)
541                 request = soup_requester_request_uri (requester, uri, NULL);
542         else
543                 request = soup_session_request_uri (session, uri, NULL);
544         do_sync_request (session, request,
545                          SOUP_STATUS_UNAUTHORIZED, auth_response,
546                          TRUE, FALSE);
547         g_object_unref (request);
548
549         debug_printf (1, "    non-persistent test\n");
550         soup_uri_set_path (uri, "/non-persistent");
551         if (requester)
552                 request = soup_requester_request_uri (requester, uri, NULL);
553         else
554                 request = soup_session_request_uri (session, uri, NULL);
555         do_sync_request (session, request,
556                          SOUP_STATUS_OK, response,
557                          FALSE, FALSE);
558         g_object_unref (request);
559
560         debug_printf (1, "    cancel test\n");
561         soup_uri_set_path (uri, "/");
562         if (requester)
563                 request = soup_requester_request_uri (requester, uri, NULL);
564         else
565                 request = soup_session_request_uri (session, uri, NULL);
566         do_sync_request (session, request,
567                          SOUP_STATUS_FORBIDDEN, NULL,
568                          TRUE, TRUE);
569         g_object_unref (request);
570
571         soup_uri_free (uri);
572 }
573
574 static void
575 do_plain_sync_test (gconstpointer uri)
576 {
577         SoupSession *session;
578
579         session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
580         do_sync_tests_for_session (session, uri);
581         soup_test_session_abort_unref (session);
582 }
583
584 static void
585 do_sync_sync_test (gconstpointer uri)
586 {
587         SoupSession *session;
588         SoupRequester *requester;
589
590         session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
591         requester = soup_requester_new ();
592         soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
593         g_object_unref (requester);
594         do_sync_tests_for_session (session, uri);
595         soup_test_session_abort_unref (session);
596 }
597
598 static void
599 do_null_char_request (SoupSession *session, const char *encoded_data,
600                       const char *expected_data, int expected_len)
601 {
602         GError *error = NULL;
603         GInputStream *stream;
604         SoupRequest *request;
605         SoupURI *uri;
606         char *uri_string, buf[256];
607         gsize nread;
608
609         uri_string = g_strdup_printf ("data:text/html,%s", encoded_data);
610         uri = soup_uri_new (uri_string);
611         g_free (uri_string);
612
613         request = soup_session_request_uri (session, uri, NULL);
614         stream = soup_test_request_send (request, NULL, 0, &error);
615         g_assert_no_error (error);
616         if (error) {
617                 g_error_free (error);
618                 g_object_unref (request);
619                 soup_uri_free (uri);
620                 return;
621         }
622
623         g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error);
624         g_assert_no_error (error);
625         g_clear_error (&error);
626
627         soup_test_request_close_stream (request, stream, NULL, &error);
628         g_assert_no_error (error);
629         g_clear_error (&error);
630
631         soup_assert_cmpmem (buf, nread, expected_data, expected_len);
632
633         g_object_unref (stream);
634         g_object_unref (request);
635         soup_uri_free (uri);
636 }
637
638 static void
639 do_null_char_test_for_session (SoupSession *session)
640 {
641         static struct {
642                 const char *encoded_data;
643                 const char *expected_data;
644                 int expected_len;
645         } test_cases[] = {
646                 { "%3Cscript%3Ea%3D'%00'%3C%2Fscript%3E", "<script>a='\0'</script>", 22 },
647                 { "%00%3Cscript%3Ea%3D42%3C%2Fscript%3E", "\0<script>a=42</script>", 22 },
648                 { "%3Cscript%3E%00%3Cbr%2F%3E%3C%2Fscript%3E%00", "<script>\0<br/></script>\0", 24 },
649         };
650         static int num_test_cases = G_N_ELEMENTS(test_cases);
651         int i;
652
653         for (i = 0; i < num_test_cases; i++) {
654                 do_null_char_request (session, test_cases[i].encoded_data,
655                                       test_cases[i].expected_data, test_cases[i].expected_len);
656         }
657 }
658
659 static void
660 do_plain_null_char_test (void)
661 {
662         SoupSession *session;
663
664         session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
665         do_null_char_test_for_session (session);
666         soup_test_session_abort_unref (session);
667 }
668
669 static void
670 do_async_null_char_test (void)
671 {
672         SoupSession *session;
673
674         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
675                                          SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
676                                          NULL);
677         do_null_char_test_for_session (session);
678         soup_test_session_abort_unref (session);
679 }
680
681 static void
682 close_test_msg_finished (SoupMessage *msg,
683                          gpointer     user_data)
684 {
685         gboolean *finished = user_data;
686
687         *finished = TRUE;
688 }
689
690 static void
691 do_close_test_for_session (SoupSession *session,
692                            SoupURI     *uri)
693 {
694         GError *error = NULL;
695         GInputStream *stream;
696         SoupRequest *request;
697         guint64 start, end;
698         GCancellable *cancellable;
699         SoupMessage *msg;
700         gboolean finished = FALSE;
701
702         debug_printf (1, "    normal close\n");
703
704         request = soup_session_request_uri (session, uri, NULL);
705         stream = soup_test_request_send (request, NULL, 0, &error);
706         g_assert_no_error (error);
707         if (error) {
708                 g_error_free (error);
709                 g_object_unref (request);
710                 return;
711         }
712
713         start = g_get_monotonic_time ();
714         soup_test_request_close_stream (request, stream, NULL, &error);
715         g_assert_no_error (error);
716         g_clear_error (&error);
717         end = g_get_monotonic_time ();
718
719         g_assert_cmpint (end - start, <=, 500000);
720
721         g_object_unref (stream);
722         g_object_unref (request);
723
724
725         debug_printf (1, "    error close\n");
726
727         request = soup_session_request_uri (session, uri, NULL);
728         msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
729         g_signal_connect (msg, "finished", G_CALLBACK (close_test_msg_finished), &finished);
730         g_object_unref (msg);
731
732         stream = soup_test_request_send (request, NULL, 0, &error);
733         g_assert_no_error (error);
734         if (error) {
735                 g_error_free (error);
736                 g_object_unref (request);
737                 return;
738         }
739
740         cancellable = g_cancellable_new ();
741         g_cancellable_cancel (cancellable);
742         soup_test_request_close_stream (request, stream, cancellable, &error);
743         if (error)
744                 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
745         g_clear_error (&error);
746
747         g_assert_true (finished);
748
749         g_object_unref (stream);
750         g_object_unref (request);
751 }
752
753 static void
754 do_async_close_test (gconstpointer uri)
755 {
756         SoupSession *session;
757         SoupURI *slow_uri;
758
759         g_test_bug ("695652");
760         g_test_bug ("711260");
761
762         slow_uri = soup_uri_new (uri);
763         soup_uri_set_path (slow_uri, "/slow");
764
765         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
766                                          SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
767                                          NULL);
768         do_close_test_for_session (session, slow_uri);
769         soup_test_session_abort_unref (session);
770
771         soup_uri_free (slow_uri);
772 }
773
774 static void
775 do_sync_close_test (gconstpointer uri)
776 {
777         SoupSession *session;
778         SoupURI *slow_uri;
779
780         g_test_bug ("695652");
781         g_test_bug ("711260");
782
783         slow_uri = soup_uri_new (uri);
784         soup_uri_set_path (slow_uri, "/slow");
785
786         debug_printf (1, "  SoupSessionSync\n");
787         session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
788                                          SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
789                                          NULL);
790         do_close_test_for_session (session, slow_uri);
791         soup_test_session_abort_unref (session);
792
793         soup_uri_free (slow_uri);
794 }
795
796 int
797 main (int argc, char **argv)
798 {
799         char *uri;
800         int ret;
801
802         test_init (argc, argv, NULL);
803
804         response = soup_test_get_index ();
805         auth_response = soup_buffer_new (SOUP_MEMORY_STATIC,
806                                          AUTH_HTML_BODY,
807                                          strlen (AUTH_HTML_BODY));
808
809         server = soup_test_server_new (TRUE);
810         soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
811
812         uri = g_strdup_printf ("http://127.0.0.1:%u/foo", soup_server_get_port (server));
813
814         g_test_add_data_func ("/requester/simple/SoupSession", uri, do_simple_plain_test);
815         g_test_add_data_func ("/requester/simple/SoupSessionAsync", uri, do_simple_async_test);
816         g_test_add_data_func ("/requester/threaded/SoupSession", uri, do_plain_test_in_thread);
817         g_test_add_data_func ("/requester/threaded/SoupSessionAsync", uri, do_async_test_in_thread);
818         g_test_add_data_func ("/requester/context/SoupSession", uri, do_plain_test_with_context);
819         g_test_add_data_func ("/requester/context/SoupSessionAsync", uri, do_async_test_with_context);
820         g_test_add_data_func ("/requester/sync/SoupSession", uri, do_plain_sync_test);
821         g_test_add_data_func ("/requester/sync/SoupSessionSync", uri, do_sync_sync_test);
822         g_test_add_func ("/requester/null-char/SoupSession", do_plain_null_char_test);
823         g_test_add_func ("/requester/null-char/SoupSessionAsync", do_async_null_char_test);
824         g_test_add_data_func ("/requester/close/SoupSessionAsync", uri, do_async_close_test);
825         g_test_add_data_func ("/requester/close/SoupSessionSync", uri, do_sync_close_test);
826
827         ret = g_test_run ();
828
829         g_free (uri);
830         soup_buffer_free (auth_response);
831         soup_test_server_quit_unref (server);
832
833         test_cleanup ();
834         return ret;
835 }