• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright 2007-2012 Red Hat, Inc.
4  */
5 
6 #include "test-utils.h"
7 
8 SoupServer *server, *ssl_server;
9 SoupURI *base_uri, *ssl_base_uri;
10 
11 static gboolean
auth_callback(SoupAuthDomain * auth_domain,SoupMessage * msg,const char * username,const char * password,gpointer data)12 auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg,
13 	       const char *username, const char *password, gpointer data)
14 {
15 	return !strcmp (username, "user") && !strcmp (password, "password");
16 }
17 
18 static gboolean
timeout_finish_message(gpointer msg)19 timeout_finish_message (gpointer msg)
20 {
21 	SoupServer *server = g_object_get_data (G_OBJECT (msg), "server");
22 
23 	soup_server_unpause_message (server, msg);
24 	return FALSE;
25 }
26 
27 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)28 server_callback (SoupServer *server, SoupMessage *msg,
29 		 const char *path, GHashTable *query,
30 		 SoupClientContext *context, gpointer data)
31 {
32 	SoupURI *uri = soup_message_get_uri (msg);
33 	const char *server_protocol = data;
34 
35 	if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) {
36 		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
37 		return;
38 	}
39 
40 	if (!strcmp (path, "/redirect")) {
41 		soup_message_set_redirect (msg, SOUP_STATUS_FOUND, "/");
42 		return;
43 	}
44 
45 	if (!strcmp (path, "/alias-redirect")) {
46 		SoupURI *redirect_uri;
47 		char *redirect_string;
48 		const char *redirect_protocol;
49 
50 		redirect_protocol = soup_message_headers_get_one (msg->request_headers, "X-Redirect-Protocol");
51 
52 		redirect_uri = soup_uri_copy (uri);
53 		soup_uri_set_scheme (redirect_uri, "foo");
54 		if (!g_strcmp0 (redirect_protocol, "https"))
55 			soup_uri_set_port (redirect_uri, ssl_base_uri->port);
56 		else
57 			soup_uri_set_port (redirect_uri, base_uri->port);
58 		soup_uri_set_path (redirect_uri, "/alias-redirected");
59 		redirect_string = soup_uri_to_string (redirect_uri, FALSE);
60 
61 		soup_message_set_redirect (msg, SOUP_STATUS_FOUND, redirect_string);
62 		g_free (redirect_string);
63 		soup_uri_free (redirect_uri);
64 		return;
65 	} else if (!strcmp (path, "/alias-redirected")) {
66 		soup_message_set_status (msg, SOUP_STATUS_OK);
67 		soup_message_headers_append (msg->response_headers,
68 					     "X-Redirected-Protocol",
69 					     server_protocol);
70 		return;
71 	}
72 
73 	if (!strcmp (path, "/slow")) {
74 		soup_server_pause_message (server, msg);
75 		g_object_set_data (G_OBJECT (msg), "server", server);
76 		soup_add_timeout (g_main_context_get_thread_default (),
77 				  1000, timeout_finish_message, msg);
78 	}
79 
80 	soup_message_set_status (msg, SOUP_STATUS_OK);
81 	if (!strcmp (uri->host, "foo")) {
82 		soup_message_set_response (msg, "text/plain",
83 					   SOUP_MEMORY_STATIC, "foo-index", 9);
84 		return;
85 	} else {
86 		soup_message_set_response (msg, "text/plain",
87 					   SOUP_MEMORY_STATIC, "index", 5);
88 		return;
89 	}
90 }
91 
92 /* Host header handling: client must be able to override the default
93  * value, server must be able to recognize different Host values.
94  */
95 static void
do_host_test(void)96 do_host_test (void)
97 {
98 	SoupSession *session;
99 	SoupMessage *one, *two;
100 
101 	g_test_bug ("539803");
102 
103 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
104 
105 	one = soup_message_new_from_uri ("GET", base_uri);
106 	two = soup_message_new_from_uri ("GET", base_uri);
107 	soup_message_headers_replace (two->request_headers, "Host", "foo");
108 
109 	soup_session_send_message (session, one);
110 	soup_session_send_message (session, two);
111 
112 	soup_test_session_abort_unref (session);
113 
114 	soup_test_assert_message_status (one, SOUP_STATUS_OK);
115 	g_assert_cmpstr (one->response_body->data, ==, "index");
116 	g_object_unref (one);
117 
118 	soup_test_assert_message_status (two, SOUP_STATUS_OK);
119 	g_assert_cmpstr (two->response_body->data, ==, "foo-index");
120 	g_object_unref (two);
121 }
122 
123 /* request with too big header should be discarded with a IO error to
124  * prevent DOS attacks.
125  */
126 static void
do_host_big_header(void)127 do_host_big_header (void)
128 {
129 	SoupMessage *msg;
130 	SoupSession *session;
131 	int i;
132 
133 	g_test_bug ("792173");
134 
135 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
136 
137 	msg = soup_message_new_from_uri ("GET", base_uri);
138 	for (i = 0; i < 2048; i++) {
139 		char *key = g_strdup_printf ("test-long-header-key%d", i);
140 		char *value = g_strdup_printf ("test-long-header-key%d", i);
141 		soup_message_headers_append (msg->request_headers, key, value);
142 		g_free (value);
143 		g_free (key);
144 	}
145 
146 	soup_session_send_message (session, msg);
147 
148 	soup_test_session_abort_unref (session);
149 
150 	soup_test_assert_message_status (msg, SOUP_STATUS_IO_ERROR);
151 
152 	g_object_unref (msg);
153 }
154 
155 /* Dropping the application's ref on the session from a callback
156  * should not cause the session to be freed at an incorrect time.
157  * (This test will crash if it fails.)
158  */
159 static void
cu_one_completed(SoupSession * session,SoupMessage * msg,gpointer loop)160 cu_one_completed (SoupSession *session, SoupMessage *msg, gpointer loop)
161 {
162 	debug_printf (2, "  Message 1 completed\n");
163 	soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT);
164 	g_object_unref (session);
165 }
166 
167 static gboolean
cu_idle_quit(gpointer loop)168 cu_idle_quit (gpointer loop)
169 {
170 	g_main_loop_quit (loop);
171 	return FALSE;
172 }
173 
174 static void
cu_two_completed(SoupSession * session,SoupMessage * msg,gpointer loop)175 cu_two_completed (SoupSession *session, SoupMessage *msg, gpointer loop)
176 {
177 	debug_printf (2, "  Message 2 completed\n");
178 	soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT);
179 	g_idle_add (cu_idle_quit, loop);
180 }
181 
182 static void
do_callback_unref_test(void)183 do_callback_unref_test (void)
184 {
185 	SoupServer *bad_server;
186 	SoupSession *session;
187 	SoupMessage *one, *two;
188 	GMainLoop *loop;
189 	SoupURI *bad_uri;
190 
191 	g_test_bug ("533473");
192 
193 	/* Get a guaranteed-bad URI */
194 	bad_server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
195 	bad_uri = soup_test_server_get_uri (bad_server, "http", NULL);
196 	soup_test_server_quit_unref (bad_server);
197 
198 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
199 	g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
200 
201 	loop = g_main_loop_new (NULL, TRUE);
202 
203 	one = soup_message_new_from_uri ("GET", bad_uri);
204 	g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one);
205 	two = soup_message_new_from_uri ("GET", bad_uri);
206 	g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two);
207 	soup_uri_free (bad_uri);
208 
209 	soup_session_queue_message (session, one, cu_one_completed, loop);
210 	soup_session_queue_message (session, two, cu_two_completed, loop);
211 
212 	g_main_loop_run (loop);
213 	g_main_loop_unref (loop);
214 
215 	g_assert_null (session);
216 	if (session) {
217 		g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session);
218 		g_object_unref (session);
219 	}
220 	g_assert_null (one);
221 	if (one) {
222 		g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one);
223 		g_object_unref (one);
224 	}
225 	g_assert_null (two);
226 	if (two) {
227 		g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two);
228 		g_object_unref (two);
229 	}
230 
231 	/* Otherwise, if we haven't crashed, we're ok. */
232 }
233 
234 static void
cur_one_completed(GObject * source,GAsyncResult * result,gpointer session)235 cur_one_completed (GObject *source, GAsyncResult *result, gpointer session)
236 {
237 	SoupRequest *one = SOUP_REQUEST (source);
238 	GError *error = NULL;
239 
240 	debug_printf (2, "  Request 1 completed\n");
241 	soup_request_send_finish (one, result, &error);
242 	g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED);
243 	g_clear_error (&error);
244 
245 	g_object_unref (session);
246 }
247 
248 static gboolean
cur_idle_quit(gpointer loop)249 cur_idle_quit (gpointer loop)
250 {
251 	g_main_loop_quit (loop);
252 	return FALSE;
253 }
254 
255 static void
cur_two_completed(GObject * source,GAsyncResult * result,gpointer loop)256 cur_two_completed (GObject *source, GAsyncResult *result, gpointer loop)
257 {
258 	SoupRequest *two = SOUP_REQUEST (source);
259 	GError *error = NULL;
260 
261 	debug_printf (2, "  Request 2 completed\n");
262 	soup_request_send_finish (two, result, &error);
263 	g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED);
264 	g_clear_error (&error);
265 
266 	g_idle_add (cur_idle_quit, loop);
267 }
268 
269 static void
do_callback_unref_req_test(void)270 do_callback_unref_req_test (void)
271 {
272 	SoupServer *bad_server;
273 	SoupSession *session;
274 	SoupRequest *one, *two;
275 	GMainLoop *loop;
276 	SoupURI *bad_uri;
277 
278 	/* Get a guaranteed-bad URI */
279 	bad_server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
280 	bad_uri = soup_test_server_get_uri (bad_server, "http", NULL);
281 	soup_test_server_quit_unref (bad_server);
282 
283 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
284 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
285 					 NULL);
286 	g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
287 
288 	loop = g_main_loop_new (NULL, TRUE);
289 
290 	one = soup_session_request_uri (session, bad_uri, NULL);
291 	g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one);
292 	two = soup_session_request_uri (session, bad_uri, NULL);
293 	g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two);
294 	soup_uri_free (bad_uri);
295 
296 	soup_request_send_async (one, NULL, cur_one_completed, session);
297 	g_object_unref (one);
298 	soup_request_send_async (two, NULL, cur_two_completed, loop);
299 	g_object_unref (two);
300 
301 	g_main_loop_run (loop);
302 	g_main_loop_unref (loop);
303 
304 	g_assert_null (session);
305 	if (session) {
306 		g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session);
307 		g_object_unref (session);
308 	}
309 	g_assert_null (one);
310 	if (one) {
311 		g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one);
312 		g_object_unref (one);
313 	}
314 	g_assert_null (two);
315 	if (two) {
316 		g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two);
317 		g_object_unref (two);
318 	}
319 
320 	/* Otherwise, if we haven't crashed, we're ok. */
321 }
322 
323 /* SoupSession should clean up all signal handlers on a message after
324  * it is finished, allowing the message to be reused if desired.
325  */
326 static void
ensure_no_signal_handlers(SoupMessage * msg,guint * signal_ids,guint n_signal_ids)327 ensure_no_signal_handlers (SoupMessage *msg, guint *signal_ids, guint n_signal_ids)
328 {
329 	int i;
330 	guint id;
331 
332 	for (i = 0; i < n_signal_ids; i++) {
333 		id = g_signal_handler_find (msg, G_SIGNAL_MATCH_ID, signal_ids[i],
334 					    0, NULL, NULL, NULL);
335 		soup_test_assert (id == 0,
336 				  "message has handler for '%s'",
337 				  g_signal_name (signal_ids[i]));
338 	}
339 }
340 
341 static void
reuse_test_authenticate(SoupSession * session,SoupMessage * msg,SoupAuth * auth,gboolean retrying)342 reuse_test_authenticate (SoupSession *session, SoupMessage *msg,
343 			 SoupAuth *auth, gboolean retrying)
344 {
345 	/* Get it wrong the first time, then succeed */
346 	if (!retrying)
347 		soup_auth_authenticate (auth, "user", "wrong password");
348 	else
349 		soup_auth_authenticate (auth, "user", "password");
350 }
351 
352 static void
do_msg_reuse_test(void)353 do_msg_reuse_test (void)
354 {
355 	SoupSession *session;
356 	SoupMessage *msg;
357 	SoupURI *uri;
358 	guint *signal_ids, n_signal_ids;
359 
360 	g_test_bug ("559054");
361 
362 	signal_ids = g_signal_list_ids (SOUP_TYPE_MESSAGE, &n_signal_ids);
363 
364 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
365 	g_signal_connect (session, "authenticate",
366 			  G_CALLBACK (reuse_test_authenticate), NULL);
367 
368 	debug_printf (1, "  First message\n");
369 	msg = soup_message_new_from_uri ("GET", base_uri);
370 	soup_session_send_message (session, msg);
371 	ensure_no_signal_handlers (msg, signal_ids, n_signal_ids);
372 
373 	debug_printf (1, "  Redirect message\n");
374 	uri = soup_uri_new_with_base (base_uri, "/redirect");
375 	soup_message_set_uri (msg, uri);
376 	soup_uri_free (uri);
377 	soup_session_send_message (session, msg);
378 	g_assert_true (soup_uri_equal (soup_message_get_uri (msg), base_uri));
379 	ensure_no_signal_handlers (msg, signal_ids, n_signal_ids);
380 
381 	debug_printf (1, "  Auth message\n");
382 	uri = soup_uri_new_with_base (base_uri, "/auth");
383 	soup_message_set_uri (msg, uri);
384 	soup_uri_free (uri);
385 	soup_session_send_message (session, msg);
386 	soup_test_assert_message_status (msg, SOUP_STATUS_OK);
387 	ensure_no_signal_handlers (msg, signal_ids, n_signal_ids);
388 
389 	/* One last try to make sure the auth stuff got cleaned up */
390 	debug_printf (1, "  Last message\n");
391 	soup_message_set_uri (msg, base_uri);
392 	soup_session_send_message (session, msg);
393 	ensure_no_signal_handlers (msg, signal_ids, n_signal_ids);
394 
395 	soup_test_session_abort_unref (session);
396 	g_object_unref (msg);
397 	g_free (signal_ids);
398 }
399 
400 /* Handle unexpectedly-early aborts. */
401 static void
ea_msg_completed_one(SoupSession * session,SoupMessage * msg,gpointer loop)402 ea_msg_completed_one (SoupSession *session, SoupMessage *msg, gpointer loop)
403 {
404 	debug_printf (2, "  Message 1 completed\n");
405 	soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
406 	g_main_loop_quit (loop);
407 }
408 
409 static gboolean
ea_abort_session(gpointer session)410 ea_abort_session (gpointer session)
411 {
412 	soup_session_abort (session);
413 	return FALSE;
414 }
415 
416 static void
ea_connection_state_changed(GObject * conn,GParamSpec * pspec,gpointer session)417 ea_connection_state_changed (GObject *conn, GParamSpec *pspec, gpointer session)
418 {
419 	SoupConnectionState state;
420 
421 	g_object_get (conn, "state", &state, NULL);
422 	if (state == SOUP_CONNECTION_CONNECTING) {
423 		g_idle_add_full (G_PRIORITY_HIGH,
424 				 ea_abort_session,
425 				 session, NULL);
426 		g_signal_handlers_disconnect_by_func (conn, ea_connection_state_changed, session);
427 	}
428 }
429 
430 static void
ea_connection_created(SoupSession * session,GObject * conn,gpointer user_data)431 ea_connection_created (SoupSession *session, GObject *conn, gpointer user_data)
432 {
433 	g_signal_connect (conn, "notify::state",
434 			  G_CALLBACK (ea_connection_state_changed), session);
435 	g_signal_handlers_disconnect_by_func (session, ea_connection_created, user_data);
436 }
437 
438 static void
ea_message_starting(SoupMessage * msg,SoupSession * session)439 ea_message_starting (SoupMessage *msg, SoupSession *session)
440 {
441 	soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
442 }
443 
444 static void
do_early_abort_test(void)445 do_early_abort_test (void)
446 {
447 	SoupSession *session;
448 	SoupMessage *msg;
449 	GMainContext *context;
450 	GMainLoop *loop;
451 
452 	g_test_bug ("596074");
453 	g_test_bug ("618641");
454 
455 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
456 	msg = soup_message_new_from_uri ("GET", base_uri);
457 
458 	context = g_main_context_default ();
459 	loop = g_main_loop_new (context, TRUE);
460 	soup_session_queue_message (session, msg, ea_msg_completed_one, loop);
461 	g_main_context_iteration (context, FALSE);
462 
463 	soup_session_abort (session);
464 	while (g_main_context_pending (context))
465 		g_main_context_iteration (context, FALSE);
466 	g_main_loop_unref (loop);
467 	soup_test_session_abort_unref (session);
468 
469 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
470 	msg = soup_message_new_from_uri ("GET", base_uri);
471 
472 	g_signal_connect (session, "connection-created",
473 			  G_CALLBACK (ea_connection_created), NULL);
474 	soup_session_send_message (session, msg);
475 	debug_printf (2, "  Message 2 completed\n");
476 
477 	soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
478 	g_object_unref (msg);
479 
480 	while (g_main_context_pending (context))
481 		g_main_context_iteration (context, FALSE);
482 
483 	soup_test_session_abort_unref (session);
484 
485 	g_test_bug ("668098");
486 
487 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
488 	msg = soup_message_new_from_uri ("GET", base_uri);
489 
490 	g_signal_connect (msg, "starting",
491 			  G_CALLBACK (ea_message_starting), session);
492 	soup_session_send_message (session, msg);
493 	debug_printf (2, "  Message 3 completed\n");
494 
495 	soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
496 	g_object_unref (msg);
497 
498 	while (g_main_context_pending (context))
499 		g_main_context_iteration (context, FALSE);
500 
501 	soup_test_session_abort_unref (session);
502 }
503 
504 static void
ear_one_completed(GObject * source,GAsyncResult * result,gpointer user_data)505 ear_one_completed (GObject *source, GAsyncResult *result, gpointer user_data)
506 {
507 	GError *error = NULL;
508 
509 	debug_printf (2, "  Request 1 completed\n");
510 	soup_request_send_finish (SOUP_REQUEST (source), result, &error);
511 	g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED);
512 	g_clear_error (&error);
513 }
514 
515 static void
ear_two_completed(GObject * source,GAsyncResult * result,gpointer loop)516 ear_two_completed (GObject *source, GAsyncResult *result, gpointer loop)
517 {
518 	GError *error = NULL;
519 
520 	debug_printf (2, "  Request 2 completed\n");
521 	soup_request_send_finish (SOUP_REQUEST (source), result, &error);
522 	g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED);
523 	g_clear_error (&error);
524 
525 	g_main_loop_quit (loop);
526 }
527 
528 static void
ear_three_completed(GObject * source,GAsyncResult * result,gpointer loop)529 ear_three_completed (GObject *source, GAsyncResult *result, gpointer loop)
530 {
531 	GError *error = NULL;
532 
533 	debug_printf (2, "  Request 3 completed\n");
534 	soup_request_send_finish (SOUP_REQUEST (source), result, &error);
535 	g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
536 	g_clear_error (&error);
537 
538 	g_main_loop_quit (loop);
539 }
540 
541 static void
ear_message_starting(SoupMessage * msg,gpointer cancellable)542 ear_message_starting (SoupMessage *msg, gpointer cancellable)
543 {
544 	g_cancellable_cancel (cancellable);
545 }
546 
547 static void
ear_request_queued(SoupSession * session,SoupMessage * msg,gpointer cancellable)548 ear_request_queued (SoupSession *session, SoupMessage *msg,
549 		    gpointer cancellable)
550 {
551 	g_signal_connect (msg, "starting",
552 			  G_CALLBACK (ear_message_starting),
553 			  cancellable);
554 }
555 
556 static void
do_early_abort_req_test(void)557 do_early_abort_req_test (void)
558 {
559 	SoupSession *session;
560 	SoupRequest *req;
561 	GMainContext *context;
562 	GMainLoop *loop;
563 	GCancellable *cancellable;
564 
565 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
566 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
567 					 NULL);
568 	req = soup_session_request_uri (session, base_uri, NULL);
569 
570 	context = g_main_context_default ();
571 	loop = g_main_loop_new (context, TRUE);
572 	soup_request_send_async (req, NULL, ear_one_completed, NULL);
573 	g_object_unref (req);
574 	g_main_context_iteration (context, FALSE);
575 
576 	soup_session_abort (session);
577 	while (g_main_context_pending (context))
578 		g_main_context_iteration (context, FALSE);
579 	soup_test_session_abort_unref (session);
580 
581 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
582 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
583 					 NULL);
584 	req = soup_session_request_uri (session, base_uri, NULL);
585 
586 	g_signal_connect (session, "connection-created",
587 			  G_CALLBACK (ea_connection_created), NULL);
588 	soup_request_send_async (req, NULL, ear_two_completed, loop);
589 	g_main_loop_run (loop);
590 	g_object_unref (req);
591 
592 	while (g_main_context_pending (context))
593 		g_main_context_iteration (context, FALSE);
594 
595 	soup_test_session_abort_unref (session);
596 
597 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
598 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
599 					 NULL);
600 	req = soup_session_request_uri (session, base_uri, NULL);
601 
602 	cancellable = g_cancellable_new ();
603 	g_signal_connect (session, "request-queued",
604 			  G_CALLBACK (ear_request_queued), cancellable);
605 	soup_request_send_async (req, cancellable, ear_three_completed, loop);
606 	g_main_loop_run (loop);
607 	g_object_unref (req);
608 	g_object_unref (cancellable);
609 
610 	while (g_main_context_pending (context))
611 		g_main_context_iteration (context, FALSE);
612 
613 	soup_test_session_abort_unref (session);
614 	g_main_loop_unref (loop);
615 }
616 
617 static void
do_one_accept_language_test(const char * language,const char * expected_header)618 do_one_accept_language_test (const char *language, const char *expected_header)
619 {
620 	SoupSession *session;
621 	SoupMessage *msg;
622 	const char *val;
623 
624 	debug_printf (1, "  LANGUAGE=%s\n", language);
625 	g_setenv ("LANGUAGE", language, TRUE);
626 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
627 					 SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
628 					 NULL);
629 	msg = soup_message_new_from_uri ("GET", base_uri);
630 	soup_session_send_message (session, msg);
631 	soup_test_session_abort_unref (session);
632 
633 	soup_test_assert_message_status (msg, SOUP_STATUS_OK);
634 	val = soup_message_headers_get_list (msg->request_headers,
635 					     "Accept-Language");
636 	g_assert_cmpstr (val, ==, expected_header);
637 
638 	g_object_unref (msg);
639 }
640 
641 static void
do_accept_language_test(void)642 do_accept_language_test (void)
643 {
644 	const char *orig_language;
645 
646 	g_test_bug ("602547");
647 
648 	orig_language = g_getenv ("LANGUAGE");
649 	do_one_accept_language_test ("C", "en");
650 	do_one_accept_language_test ("fr_FR", "fr-fr, fr;q=0.9");
651 	do_one_accept_language_test ("fr_FR:de:en_US", "fr-fr, fr;q=0.9, de;q=0.8, en-us;q=0.7, en;q=0.6");
652 
653 	if (orig_language)
654 		g_setenv ("LANGUAGE", orig_language, TRUE);
655 	else
656 		g_unsetenv ("LANGUAGE");
657 }
658 
659 static gboolean
cancel_message_timeout(gpointer msg)660 cancel_message_timeout (gpointer msg)
661 {
662 	SoupSession *session = g_object_get_data (G_OBJECT (msg), "session");
663 
664 	soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
665 	g_object_unref (msg);
666 	g_object_unref (session);
667 	return FALSE;
668 }
669 
670 static gpointer
cancel_message_thread(gpointer msg)671 cancel_message_thread (gpointer msg)
672 {
673 	SoupSession *session = g_object_get_data (G_OBJECT (msg), "session");
674 
675 	g_usleep (100000); /* .1s */
676 	soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
677 	g_object_unref (msg);
678 	g_object_unref (session);
679 	return NULL;
680 }
681 
682 static void
set_done(SoupSession * session,SoupMessage * msg,gpointer user_data)683 set_done (SoupSession *session, SoupMessage *msg, gpointer user_data)
684 {
685 	gboolean *done = user_data;
686 
687 	*done = TRUE;
688 }
689 
690 static void
do_cancel_while_reading_test_for_session(SoupSession * session)691 do_cancel_while_reading_test_for_session (SoupSession *session)
692 {
693 	SoupMessage *msg;
694 	GThread *thread = NULL;
695 	SoupURI *uri;
696 	gboolean done = FALSE;
697 
698 	uri = soup_uri_new_with_base (base_uri, "/slow");
699 	msg = soup_message_new_from_uri ("GET", uri);
700 	soup_uri_free (uri);
701 
702 	g_object_set_data (G_OBJECT (msg), "session", session);
703 	g_object_ref (msg);
704 	g_object_ref (session);
705 	if (SOUP_IS_SESSION_ASYNC (session))
706 		g_timeout_add (100, cancel_message_timeout, msg);
707 	else
708 		thread = g_thread_new ("cancel_message_thread", cancel_message_thread, msg);
709 
710 	/* We intentionally don't use soup_session_send_message() here,
711 	 * because it holds an extra ref on the SoupMessageQueueItem
712 	 * relative to soup_session_queue_message().
713 	 */
714 	g_object_ref (msg);
715 	soup_session_queue_message (session, msg, set_done, &done);
716 	while (!done)
717 		g_main_context_iteration (NULL, TRUE);
718 
719 	soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
720 	g_object_unref (msg);
721 
722 	if (thread)
723 		g_thread_join (thread);
724 }
725 
726 static void
do_cancel_while_reading_test(void)727 do_cancel_while_reading_test (void)
728 {
729 	SoupSession *session;
730 
731 	g_test_bug ("637741");
732 	g_test_bug ("676038");
733 
734 	debug_printf (1, "  Async session\n");
735 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
736 	do_cancel_while_reading_test_for_session (session);
737 	soup_test_session_abort_unref (session);
738 
739 	debug_printf (1, "  Sync session\n");
740 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
741 	do_cancel_while_reading_test_for_session (session);
742 	soup_test_session_abort_unref (session);
743 }
744 
745 static void
do_cancel_while_reading_req_test_for_session(SoupSession * session,guint flags)746 do_cancel_while_reading_req_test_for_session (SoupSession *session,
747 					      guint flags)
748 {
749 	SoupRequest *req;
750 	SoupURI *uri;
751 	GCancellable *cancellable;
752 	GError *error = NULL;
753 
754 	uri = soup_uri_new_with_base (base_uri, "/slow");
755 	req = soup_session_request_uri (session, uri, NULL);
756 	soup_uri_free (uri);
757 
758 	cancellable = g_cancellable_new ();
759 	soup_test_request_send (req, cancellable, flags, &error);
760 	g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
761 	g_clear_error (&error);
762 
763 	g_object_unref (req);
764 	g_object_unref (cancellable);
765 }
766 
767 static void
do_cancel_while_reading_immediate_req_test(void)768 do_cancel_while_reading_immediate_req_test (void)
769 {
770 	SoupSession *session;
771 	guint flags;
772 
773 	g_test_bug ("692310");
774 
775 	flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE;
776 
777 	debug_printf (1, "  Async session\n");
778 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
779 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
780 					 NULL);
781 	do_cancel_while_reading_req_test_for_session (session, flags);
782 	soup_test_session_abort_unref (session);
783 
784 	debug_printf (1, "  Sync session\n");
785 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
786 					 NULL);
787 	do_cancel_while_reading_req_test_for_session (session, flags);
788 	soup_test_session_abort_unref (session);
789 }
790 
791 static void
do_cancel_while_reading_delayed_req_test(void)792 do_cancel_while_reading_delayed_req_test (void)
793 {
794 	SoupSession *session;
795 	guint flags;
796 
797 	flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_SOON;
798 
799 	debug_printf (1, "  Async session\n");
800 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
801 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
802 					 NULL);
803 	do_cancel_while_reading_req_test_for_session (session, flags);
804 	soup_test_session_abort_unref (session);
805 
806 	debug_printf (1, "  Sync session\n");
807 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
808 					 NULL);
809 	do_cancel_while_reading_req_test_for_session (session, flags);
810 	soup_test_session_abort_unref (session);
811 }
812 
813 static void
do_cancel_while_reading_preemptive_req_test(void)814 do_cancel_while_reading_preemptive_req_test (void)
815 {
816 	SoupSession *session;
817 	guint flags;
818 
819 	g_test_bug ("637039");
820 
821 	flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE;
822 
823 	debug_printf (1, "  Async session\n");
824 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
825 					 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
826 					 NULL);
827 	do_cancel_while_reading_req_test_for_session (session, flags);
828 	soup_test_session_abort_unref (session);
829 
830 	debug_printf (1, "  Sync session\n");
831 	session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC,
832 					 NULL);
833 	do_cancel_while_reading_req_test_for_session (session, flags);
834 	soup_test_session_abort_unref (session);
835 }
836 
837 static void
do_aliases_test_for_session(SoupSession * session,const char * redirect_protocol)838 do_aliases_test_for_session (SoupSession *session,
839 			     const char *redirect_protocol)
840 {
841 	SoupMessage *msg;
842 	SoupURI *uri;
843 	const char *redirected_protocol;
844 
845 	uri = soup_uri_new_with_base (base_uri, "/alias-redirect");
846 	msg = soup_message_new_from_uri ("GET", uri);
847 	if (redirect_protocol)
848 		soup_message_headers_append (msg->request_headers, "X-Redirect-Protocol", redirect_protocol);
849 	soup_uri_free (uri);
850 	soup_session_send_message (session, msg);
851 
852 	redirected_protocol = soup_message_headers_get_one (msg->response_headers, "X-Redirected-Protocol");
853 
854 	g_assert_cmpstr (redirect_protocol, ==, redirected_protocol);
855 	if (redirect_protocol)
856 		soup_test_assert_message_status (msg, SOUP_STATUS_OK);
857 	else
858 		soup_test_assert_message_status (msg, SOUP_STATUS_FOUND);
859 
860 	g_object_unref (msg);
861 }
862 
863 static void
do_aliases_test(void)864 do_aliases_test (void)
865 {
866 	SoupSession *session;
867 	char *aliases[] = { "foo", NULL };
868 
869 	debug_printf (1, "  Default behavior\n");
870 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
871 	do_aliases_test_for_session (session, "http");
872 	soup_test_session_abort_unref (session);
873 
874 	if (tls_available) {
875 		debug_printf (1, "  foo-means-https\n");
876 		session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
877 						 SOUP_SESSION_HTTPS_ALIASES, aliases,
878 						 NULL);
879 		do_aliases_test_for_session (session, "https");
880 		soup_test_session_abort_unref (session);
881 	} else
882 		debug_printf (1, "  foo-means-https -- SKIPPING\n");
883 
884 	debug_printf (1, "  foo-means-nothing\n");
885 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
886 					 SOUP_SESSION_HTTP_ALIASES, NULL,
887 					 NULL);
888 	do_aliases_test_for_session (session, NULL);
889 	soup_test_session_abort_unref (session);
890 }
891 
892 static void
do_idle_on_dispose_test(void)893 do_idle_on_dispose_test (void)
894 {
895 	SoupSession *session;
896 	SoupMessage *msg;
897 	GMainContext *async_context;
898 
899 	g_test_bug ("667364");
900 
901 	async_context = g_main_context_new ();
902 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
903 					 SOUP_SESSION_ASYNC_CONTEXT, async_context,
904 					 NULL);
905 
906 	msg = soup_message_new_from_uri ("GET", base_uri);
907 	soup_session_send_message (session, msg);
908 	g_object_unref (msg);
909 
910 	while (g_main_context_iteration (async_context, FALSE))
911 		;
912 
913 	g_object_run_dispose (G_OBJECT (session));
914 
915 	if (g_main_context_iteration (async_context, FALSE))
916 		soup_test_assert (FALSE, "idle was queued");
917 
918 	g_object_unref (session);
919 	g_main_context_unref (async_context);
920 }
921 
922 static void
do_pause_abort_test(void)923 do_pause_abort_test (void)
924 {
925 	SoupSession *session;
926 	SoupMessage *msg;
927 	gpointer ptr;
928 
929 	g_test_bug ("673905");
930 
931 	session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
932 
933 	msg = soup_message_new_from_uri ("GET", base_uri);
934 	soup_session_queue_message (session, msg, NULL, NULL);
935 	soup_session_pause_message (session, msg);
936 
937 	g_object_add_weak_pointer (G_OBJECT (msg), &ptr);
938 	soup_test_session_abort_unref (session);
939 
940 	g_assert_null (ptr);
941 }
942 
943 static GMainLoop *pause_cancel_loop;
944 
945 static void
pause_cancel_got_headers(SoupMessage * msg,gpointer user_data)946 pause_cancel_got_headers (SoupMessage *msg, gpointer user_data)
947 {
948 	SoupSession *session = user_data;
949 
950 	soup_session_pause_message (session, msg);
951 	g_main_loop_quit (pause_cancel_loop);
952 }
953 
954 static void
pause_cancel_finished(SoupSession * session,SoupMessage * msg,gpointer user_data)955 pause_cancel_finished (SoupSession *session, SoupMessage *msg, gpointer user_data)
956 {
957 	gboolean *finished = user_data;
958 
959 	*finished = TRUE;
960 	g_main_loop_quit (pause_cancel_loop);
961 }
962 
963 static gboolean
pause_cancel_timeout(gpointer user_data)964 pause_cancel_timeout (gpointer user_data)
965 {
966 	gboolean *timed_out = user_data;
967 
968 	*timed_out = TRUE;
969 	g_main_loop_quit (pause_cancel_loop);
970 	return FALSE;
971 }
972 
973 static void
do_pause_cancel_test(void)974 do_pause_cancel_test (void)
975 {
976 	SoupSession *session;
977 	SoupMessage *msg;
978 	gboolean finished = FALSE, timed_out = FALSE;
979 	guint timeout_id;
980 
981 	g_test_bug ("745094");
982 
983 	session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
984 	pause_cancel_loop = g_main_loop_new (NULL, FALSE);
985 
986 	timeout_id = g_timeout_add_seconds (5, pause_cancel_timeout, &timed_out);
987 
988 	msg = soup_message_new_from_uri ("GET", base_uri);
989 	g_object_ref (msg);
990 	g_signal_connect (msg, "got-headers",
991 			  G_CALLBACK (pause_cancel_got_headers), session);
992 
993 	soup_session_queue_message (session, msg, pause_cancel_finished, &finished);
994 	g_main_loop_run (pause_cancel_loop);
995 	g_assert_false (finished);
996 
997 	soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
998 	g_main_loop_run (pause_cancel_loop);
999 	g_assert_true (finished);
1000 	g_assert_false (timed_out);
1001 
1002 	soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED);
1003 	g_object_unref (msg);
1004 
1005 	soup_test_session_abort_unref (session);
1006 	g_main_loop_unref (pause_cancel_loop);
1007 	if (!timed_out)
1008 		g_source_remove (timeout_id);
1009 }
1010 
1011 static gboolean
run_echo_server(gpointer user_data)1012 run_echo_server (gpointer user_data)
1013 {
1014 	GIOStream *stream = user_data;
1015 	GInputStream *istream;
1016 	GDataInputStream *distream;
1017 	GOutputStream *ostream;
1018 	char *str, *caps;
1019 	gssize n;
1020 	GError *error = NULL;
1021 
1022 	istream = g_io_stream_get_input_stream (stream);
1023 	distream = G_DATA_INPUT_STREAM (g_data_input_stream_new (istream));
1024 	ostream = g_io_stream_get_output_stream (stream);
1025 
1026 	/* Echo until the client disconnects */
1027 	while (TRUE) {
1028 		str = g_data_input_stream_read_line (distream, NULL, NULL, &error);
1029 		g_assert_no_error (error);
1030 		if (!str)
1031 			break;
1032 
1033 		caps = g_ascii_strup (str, -1);
1034 		n = g_output_stream_write (ostream, caps, strlen (caps), NULL, &error);
1035 		g_assert_no_error (error);
1036 		g_assert_cmpint (n, ==, strlen (caps));
1037 		n = g_output_stream_write (ostream, "\n", 1, NULL, &error);
1038 		g_assert_no_error (error);
1039 		g_assert_cmpint (n, ==, 1);
1040 		g_free (caps);
1041 		g_free (str);
1042 	}
1043 
1044 	g_object_unref (distream);
1045 
1046 	g_io_stream_close (stream, NULL, &error);
1047 	g_assert_no_error (error);
1048 	g_object_unref (stream);
1049 
1050 	return FALSE;
1051 }
1052 
1053 static void
steal_after_upgrade(SoupMessage * msg,gpointer user_data)1054 steal_after_upgrade (SoupMessage *msg, gpointer user_data)
1055 {
1056 	SoupClientContext *context = user_data;
1057 	GIOStream *stream;
1058 	GSource *source;
1059 
1060 	/* This should not ever be seen. */
1061 	soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
1062 
1063 	stream = soup_client_context_steal_connection (context);
1064 
1065 	source = g_idle_source_new ();
1066 	g_source_set_callback (source, run_echo_server, stream, NULL);
1067 	g_source_attach (source, g_main_context_get_thread_default ());
1068 	g_source_unref (source);
1069 }
1070 
1071 static void
upgrade_server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)1072 upgrade_server_callback (SoupServer *server, SoupMessage *msg,
1073 			 const char *path, GHashTable *query,
1074 			 SoupClientContext *context, gpointer data)
1075 {
1076 	if (msg->method != SOUP_METHOD_GET) {
1077 		soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
1078 		return;
1079 	}
1080 
1081 	soup_message_set_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS);
1082 	soup_message_headers_append (msg->request_headers, "Upgrade", "ECHO");
1083 	soup_message_headers_append (msg->request_headers, "Connection", "upgrade");
1084 
1085 	g_signal_connect (msg, "wrote-informational",
1086 			  G_CALLBACK (steal_after_upgrade), context);
1087 }
1088 
1089 static void
callback_not_reached(SoupSession * session,SoupMessage * msg,gpointer user_data)1090 callback_not_reached (SoupSession *session, SoupMessage *msg, gpointer user_data)
1091 {
1092 	g_assert_not_reached ();
1093 }
1094 
1095 static void
switching_protocols(SoupMessage * msg,gpointer user_data)1096 switching_protocols (SoupMessage *msg, gpointer user_data)
1097 {
1098 	GIOStream **out_iostream = user_data;
1099 	SoupSession *session = g_object_get_data (G_OBJECT (msg), "SoupSession");
1100 
1101 	*out_iostream = soup_session_steal_connection (session, msg);
1102 }
1103 
1104 static void
do_stealing_test(gconstpointer data)1105 do_stealing_test (gconstpointer data)
1106 {
1107 	gboolean sync = GPOINTER_TO_INT (data);
1108 	SoupServer *server;
1109 	SoupURI *uri;
1110 	SoupSession *session;
1111 	SoupMessage *msg;
1112 	GIOStream *iostream;
1113 	GInputStream *istream;
1114 	GDataInputStream *distream;
1115 	GOutputStream *ostream;
1116 	int i;
1117 	gssize n;
1118 	char *str, *caps;
1119 	GError *error = NULL;
1120 	static const char *strings[] = { "one", "two", "three", "four", "five" };
1121 
1122 	server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
1123 	uri = soup_test_server_get_uri (server, SOUP_URI_SCHEME_HTTP, "127.0.0.1");
1124 	soup_server_add_handler (server, NULL, upgrade_server_callback, NULL, NULL);
1125 
1126 	session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
1127 	msg = soup_message_new_from_uri ("GET", uri);
1128 	soup_message_headers_append (msg->request_headers, "Upgrade", "echo");
1129 	soup_message_headers_append (msg->request_headers, "Connection", "upgrade");
1130 	g_object_set_data (G_OBJECT (msg), "SoupSession", session);
1131 
1132 	soup_message_add_status_code_handler (msg, "got-informational",
1133 					      SOUP_STATUS_SWITCHING_PROTOCOLS,
1134 					      G_CALLBACK (switching_protocols), &iostream);
1135 
1136 	iostream = NULL;
1137 
1138 	if (sync) {
1139 		soup_session_send_message (session, msg);
1140 		soup_test_assert_message_status (msg, SOUP_STATUS_SWITCHING_PROTOCOLS);
1141 	} else {
1142 		g_object_ref (msg);
1143 		soup_session_queue_message (session, msg, callback_not_reached, NULL);
1144 		while (iostream == NULL)
1145 			g_main_context_iteration (NULL, TRUE);
1146 	}
1147 
1148 	g_assert (iostream != NULL);
1149 
1150 	g_object_unref (msg);
1151 	soup_test_session_abort_unref (session);
1152 	soup_uri_free (uri);
1153 
1154 	/* Now iostream connects to a (capitalizing) echo server */
1155 
1156 	istream = g_io_stream_get_input_stream (iostream);
1157 	distream = G_DATA_INPUT_STREAM (g_data_input_stream_new (istream));
1158 	ostream = g_io_stream_get_output_stream (iostream);
1159 
1160 	for (i = 0; i < G_N_ELEMENTS (strings); i++) {
1161 		n = g_output_stream_write (ostream, strings[i], strlen (strings[i]),
1162 					   NULL, &error);
1163 		g_assert_no_error (error);
1164 		g_assert_cmpint (n, ==, strlen (strings[i]));
1165 		n = g_output_stream_write (ostream, "\n", 1, NULL, &error);
1166 		g_assert_no_error (error);
1167 		g_assert_cmpint (n, ==, 1);
1168 	}
1169 
1170 	for (i = 0; i < G_N_ELEMENTS (strings); i++) {
1171 		str = g_data_input_stream_read_line (distream, NULL, NULL, &error);
1172 		g_assert_no_error (error);
1173 		caps = g_ascii_strup (strings[i], -1);
1174 		g_assert_cmpstr (caps, ==, str);
1175 		g_free (caps);
1176 		g_free (str);
1177 	}
1178 
1179 	g_object_unref (distream);
1180 
1181 	g_io_stream_close (iostream, NULL, &error);
1182 	g_assert_no_error (error);
1183 	g_object_unref (iostream);
1184 
1185 	/* We can't do this until the end because it's in another thread, and
1186 	 * soup_test_server_quit_unref() will wait for that thread to exit.
1187 	 */
1188 	soup_test_server_quit_unref (server);
1189 }
1190 
1191 int
main(int argc,char ** argv)1192 main (int argc, char **argv)
1193 {
1194 	SoupAuthDomain *auth_domain;
1195 	int ret;
1196 
1197 	test_init (argc, argv, NULL);
1198 
1199 	server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
1200 	soup_server_add_handler (server, NULL, server_callback, "http", NULL);
1201 	base_uri = soup_test_server_get_uri (server, "http", NULL);
1202 
1203 	auth_domain = soup_auth_domain_basic_new (
1204 		SOUP_AUTH_DOMAIN_REALM, "misc-test",
1205 		SOUP_AUTH_DOMAIN_ADD_PATH, "/auth",
1206 		SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback,
1207 		NULL);
1208 	soup_server_add_auth_domain (server, auth_domain);
1209 	g_object_unref (auth_domain);
1210 
1211 	if (tls_available) {
1212 		ssl_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
1213 		soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL);
1214 		ssl_base_uri = soup_test_server_get_uri (ssl_server, "https", "127.0.0.1");
1215 	}
1216 
1217 	g_test_add_func ("/misc/bigheader", do_host_big_header);
1218 	g_test_add_func ("/misc/host", do_host_test);
1219 	g_test_add_func ("/misc/callback-unref/msg", do_callback_unref_test);
1220 	g_test_add_func ("/misc/callback-unref/req", do_callback_unref_req_test);
1221 	g_test_add_func ("/misc/msg-reuse", do_msg_reuse_test);
1222 	g_test_add_func ("/misc/early-abort/msg", do_early_abort_test);
1223 	g_test_add_func ("/misc/early-abort/req", do_early_abort_req_test);
1224 	g_test_add_func ("/misc/accept-language", do_accept_language_test);
1225 	g_test_add_func ("/misc/cancel-while-reading/msg", do_cancel_while_reading_test);
1226 	g_test_add_func ("/misc/cancel-while-reading/req/immediate", do_cancel_while_reading_immediate_req_test);
1227 	g_test_add_func ("/misc/cancel-while-reading/req/delayed", do_cancel_while_reading_delayed_req_test);
1228 	g_test_add_func ("/misc/cancel-while-reading/req/preemptive", do_cancel_while_reading_preemptive_req_test);
1229 	g_test_add_func ("/misc/aliases", do_aliases_test);
1230 	g_test_add_func ("/misc/idle-on-dispose", do_idle_on_dispose_test);
1231 	g_test_add_func ("/misc/pause-abort", do_pause_abort_test);
1232 	g_test_add_func ("/misc/pause-cancel", do_pause_cancel_test);
1233 	g_test_add_data_func ("/misc/stealing/async", GINT_TO_POINTER (FALSE), do_stealing_test);
1234 	g_test_add_data_func ("/misc/stealing/sync", GINT_TO_POINTER (TRUE), do_stealing_test);
1235 
1236 	ret = g_test_run ();
1237 
1238 	soup_uri_free (base_uri);
1239 	soup_test_server_quit_unref (server);
1240 
1241 	if (tls_available) {
1242 		soup_uri_free (ssl_base_uri);
1243 		soup_test_server_quit_unref (ssl_server);
1244 	}
1245 
1246 	test_cleanup ();
1247 	return ret;
1248 }
1249