diff options
Diffstat (limited to 'tests/test-utils.c')
-rw-r--r-- | tests/test-utils.c | 224 |
1 files changed, 180 insertions, 44 deletions
diff --git a/tests/test-utils.c b/tests/test-utils.c index f4632a9b..650a5eb6 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -268,77 +268,209 @@ soup_test_session_abort_unref (SoupSession *session) } } -static gpointer run_server_thread (gpointer user_data); +static void +server_listen (SoupServer *server) +{ + GError *error = NULL; + SoupServerListenOptions options = + GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (server), "listen-options")); -static SoupServer * -test_server_new (gboolean in_own_thread, gboolean ssl) + soup_server_listen_local (server, 0, options, &error); + if (error) { + g_printerr ("Unable to create server: %s\n", error->message); + exit (1); + } +} + +static GMutex server_start_mutex; +static GCond server_start_cond; + +static gpointer +run_server_thread (gpointer user_data) { - SoupServer *server; - GMainContext *async_context; - const char *ssl_cert_file, *ssl_key_file; - SoupAddress *addr; + SoupServer *server = user_data; + GMainContext *context; + GMainLoop *loop; - async_context = in_own_thread ? g_main_context_new () : NULL; + context = g_main_context_new (); + g_main_context_push_thread_default (context); + loop = g_main_loop_new (context, FALSE); + g_object_set_data (G_OBJECT (server), "GMainLoop", loop); - if (ssl) { - ssl_cert_file = SRCDIR "/test-cert.pem"; - ssl_key_file = SRCDIR "/test-key.pem"; - } else - ssl_cert_file = ssl_key_file = NULL; + server_listen (server); - addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT); - soup_address_resolve_sync (addr, NULL); + g_mutex_lock (&server_start_mutex); + g_cond_signal (&server_start_cond); + g_mutex_unlock (&server_start_mutex); - server = soup_server_new (SOUP_SERVER_INTERFACE, addr, - SOUP_SERVER_ASYNC_CONTEXT, async_context, - SOUP_SERVER_SSL_CERT_FILE, ssl_cert_file, - SOUP_SERVER_SSL_KEY_FILE, ssl_key_file, - NULL); - g_object_unref (addr); - if (async_context) - g_main_context_unref (async_context); + g_main_loop_run (loop); + g_main_loop_unref (loop); - if (!server) { - g_printerr ("Unable to create server\n"); - exit (1); + soup_server_disconnect (server); + + g_main_context_pop_thread_default (context); + g_main_context_unref (context); + + return NULL; +} + +SoupServer * +soup_test_server_new (SoupTestServerOptions options) +{ + SoupServer *server; + GTlsCertificate *cert = NULL; + GError *error = NULL; + + if (tls_available) { + cert = g_tls_certificate_new_from_files (SRCDIR "/test-cert.pem", + SRCDIR "/test-key.pem", + &error); + if (error) { + g_printerr ("Unable to create server: %s\n", error->message); + exit (1); + } } + + server = soup_server_new (SOUP_SERVER_TLS_CERTIFICATE, cert, + NULL); + g_clear_object (&cert); - if (in_own_thread) { + g_object_set_data (G_OBJECT (server), "options", GUINT_TO_POINTER (options)); + + if (options & SOUP_TEST_SERVER_IN_THREAD) { GThread *thread; + g_mutex_lock (&server_start_mutex); + thread = g_thread_new ("server_thread", run_server_thread, server); g_object_set_data (G_OBJECT (server), "thread", thread); + + /* We have to call soup_server_listen() from the server's + * thread, but want to be sure we don't return from here + * until it happens, hence the locking. + */ + g_cond_wait (&server_start_cond, &server_start_mutex); + g_mutex_unlock (&server_start_mutex); } else - soup_server_run_async (server); + server_listen (server); return server; } -SoupServer * -soup_test_server_new (gboolean in_own_thread) +static SoupURI * +find_server_uri (SoupServer *server, const char *scheme, const char *host) +{ + GSList *uris, *u; + SoupURI *uri, *ret_uri = NULL; + + uris = soup_server_get_uris (server); + for (u = uris; u; u = u->next) { + uri = u->data; + + if (scheme && strcmp (uri->scheme, scheme) != 0) + continue; + if (host && strcmp (uri->host, host) != 0) + continue; + + ret_uri = soup_uri_copy (uri); + break; + } + g_slist_free_full (uris, (GDestroyNotify)soup_uri_free); + + return ret_uri; +} + +static SoupURI * +add_listener (SoupServer *server, const char *scheme, const char *host) { - return test_server_new (in_own_thread, FALSE); + SoupServerListenOptions options = 0; + GError *error = NULL; + + if (!g_strcmp0 (scheme, SOUP_URI_SCHEME_HTTPS)) + options |= SOUP_SERVER_LISTEN_HTTPS; + if (!g_strcmp0 (host, "127.0.0.1")) + options |= SOUP_SERVER_LISTEN_IPV4_ONLY; + else if (!g_strcmp0 (host, "::1")) + options |= SOUP_SERVER_LISTEN_IPV6_ONLY; + + soup_server_listen_local (server, 0, options, &error); + g_assert_no_error (error); + + return find_server_uri (server, scheme, host); } -SoupServer * -soup_test_server_new_ssl (gboolean in_own_thread) +typedef struct { + GMutex mutex; + GCond cond; + + SoupServer *server; + const char *scheme; + const char *host; + + SoupURI *uri; +} AddListenerData; + +static gboolean +add_listener_in_thread (gpointer user_data) { - return test_server_new (in_own_thread, TRUE); + AddListenerData *data = user_data; + + data->uri = add_listener (data->server, data->scheme, data->host); + g_mutex_lock (&data->mutex); + g_cond_signal (&data->cond); + g_mutex_unlock (&data->mutex); + + return FALSE; } -static gpointer -run_server_thread (gpointer user_data) +SoupURI * +soup_test_server_get_uri (SoupServer *server, + const char *scheme, + const char *host) { - SoupServer *server = user_data; + SoupURI *uri; + GMainLoop *loop; - soup_server_run (server); - return NULL; + uri = find_server_uri (server, scheme, host); + if (uri) + return uri; + + /* Need to add a new listener */ + uri = soup_uri_new (NULL); + soup_uri_set_scheme (uri, scheme); + soup_uri_set_host (uri, host); + + loop = g_object_get_data (G_OBJECT (server), "GMainLoop"); + if (loop) { + GMainContext *context = g_main_loop_get_context (loop); + AddListenerData data; + + g_mutex_init (&data.mutex); + g_cond_init (&data.cond); + data.server = server; + data.scheme = scheme; + data.host = host; + data.uri = NULL; + + g_mutex_lock (&data.mutex); + soup_add_completion (context, add_listener_in_thread, &data); + + while (!data.uri) + g_cond_wait (&data.cond, &data.mutex); + + g_mutex_clear (&data.mutex); + g_cond_clear (&data.cond); + uri = data.uri; + } else + uri = add_listener (server, scheme, host); + + return uri; } static gboolean -idle_quit_server (gpointer server) +idle_quit_server (gpointer loop) { - soup_server_quit (server); + g_main_loop_quit (loop); return FALSE; } @@ -352,11 +484,15 @@ soup_test_server_quit_unref (SoupServer *server) thread = g_object_get_data (G_OBJECT (server), "thread"); if (thread) { - soup_add_completion (soup_server_get_async_context (server), - idle_quit_server, server); + GMainLoop *loop; + GMainContext *context; + + loop = g_object_get_data (G_OBJECT (server), "GMainLoop"); + context = g_main_loop_get_context (loop); + soup_add_completion (context, idle_quit_server, loop); g_thread_join (thread); } else - soup_server_quit (server); + soup_server_disconnect (server); g_object_unref (server); if (server) { |