summaryrefslogtreecommitdiff
path: root/tests/test-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-utils.c')
-rw-r--r--tests/test-utils.c405
1 files changed, 312 insertions, 93 deletions
diff --git a/tests/test-utils.c b/tests/test-utils.c
index f040b738..bc160aea 100644
--- a/tests/test-utils.c
+++ b/tests/test-utils.c
@@ -12,8 +12,9 @@ static gboolean apache_running;
#endif
static SoupLogger *logger;
+static SoupBuffer *index_buffer;
-int debug_level, errors;
+int debug_level;
gboolean expect_warning, tls_available;
static int http_debug_level;
@@ -37,7 +38,7 @@ static GOptionEntry debug_entry[] = {
{ "debug", 'd', G_OPTION_FLAG_NO_ARG,
G_OPTION_ARG_CALLBACK, increment_debug_level,
"Enable (or increase) test-specific debugging", NULL },
- { "http-debug", 'h', G_OPTION_FLAG_NO_ARG,
+ { "http-debug", 'H', G_OPTION_FLAG_NO_ARG,
G_OPTION_ARG_CALLBACK, increment_http_debug_level,
"Enable (or increase) HTTP-level debugging", NULL },
{ NULL }
@@ -54,21 +55,6 @@ quit (int sig)
exit (1);
}
-static void
-test_log_handler (const char *log_domain, GLogLevelFlags log_level,
- const char *message, gpointer user_data)
-{
- if (log_level & (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL)) {
- if (expect_warning) {
- expect_warning = FALSE;
- debug_printf (2, "Got expected warning: %s\n", message);
- return;
- } else
- errors++;
- }
- g_log_default_handler (log_domain, log_level, message, user_data);
-}
-
void
test_init (int argc, char **argv, GOptionEntry *entries)
{
@@ -78,7 +64,8 @@ test_init (int argc, char **argv, GOptionEntry *entries)
GTlsBackend *tls_backend;
setlocale (LC_ALL, "");
- g_type_init ();
+ g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
+ g_setenv ("GIO_USE_PROXY_RESOLVER", "dummy", TRUE);
name = strrchr (argv[0], '/');
if (!name++)
@@ -87,6 +74,10 @@ test_init (int argc, char **argv, GOptionEntry *entries)
name += 3;
g_set_prgname (name);
+ g_test_init (&argc, &argv, NULL);
+ g_test_set_nonfatal_assertions ();
+ g_test_bug_base ("https://bugzilla.gnome.org/");
+
opts = g_option_context_new (NULL);
g_option_context_add_main_entries (opts, debug_entry, NULL);
if (entries)
@@ -104,8 +95,6 @@ test_init (int argc, char **argv, GOptionEntry *entries)
/* Exit cleanly on ^C in case we're valgrinding. */
signal (SIGINT, quit);
- g_log_set_default_handler (test_log_handler, NULL);
-
tls_backend = g_tls_backend_get_default ();
tls_available = g_tls_backend_supports_tls (tls_backend);
}
@@ -120,16 +109,12 @@ test_cleanup (void)
if (logger)
g_object_unref (logger);
+ if (index_buffer)
+ soup_buffer_free (index_buffer);
g_main_context_unref (g_main_context_default ());
debug_printf (1, "\n");
- if (errors) {
- g_print ("%s: %d error(s).%s\n",
- g_get_prgname (), errors,
- debug_level == 0 ? " Run with '-d' for details" : "");
- } else
- g_print ("%s: OK\n", g_get_prgname ());
}
void
@@ -150,30 +135,52 @@ debug_printf (int level, const char *format, ...)
static gboolean
apache_cmd (const char *cmd)
{
- const char *argv[8];
- char *cwd, *conf;
+ GPtrArray *argv;
+ char *server_root, *cwd, *pid_file;
+#ifdef HAVE_APACHE_2_4
+ char *default_runtime_dir;
+#endif
int status;
gboolean ok;
+ server_root = g_test_build_filename (G_TEST_BUILT, "", NULL);
+
cwd = g_get_current_dir ();
- conf = g_build_filename (cwd, "httpd.conf", NULL);
-
- argv[0] = APACHE_HTTPD;
- argv[1] = "-d";
- argv[2] = cwd;
- argv[3] = "-f";
- argv[4] = conf;
- argv[5] = "-k";
- argv[6] = cmd;
- argv[7] = NULL;
-
- ok = g_spawn_sync (cwd, (char **)argv, NULL, 0, NULL, NULL,
+#ifdef HAVE_APACHE_2_4
+ default_runtime_dir = g_strdup_printf ("DefaultRuntimeDir %s", cwd);
+#endif
+ pid_file = g_strdup_printf ("PidFile %s/httpd.pid", cwd);
+
+ argv = g_ptr_array_new ();
+ g_ptr_array_add (argv, APACHE_HTTPD);
+ g_ptr_array_add (argv, "-d");
+ g_ptr_array_add (argv, server_root);
+ g_ptr_array_add (argv, "-f");
+ g_ptr_array_add (argv, "httpd.conf");
+
+#ifdef HAVE_APACHE_2_4
+ g_ptr_array_add (argv, "-c");
+ g_ptr_array_add (argv, default_runtime_dir);
+#endif
+ g_ptr_array_add (argv, "-c");
+ g_ptr_array_add (argv, pid_file);
+
+ g_ptr_array_add (argv, "-k");
+ g_ptr_array_add (argv, (char *)cmd);
+ g_ptr_array_add (argv, NULL);
+
+ ok = g_spawn_sync (cwd, (char **)argv->pdata, NULL, 0, NULL, NULL,
NULL, NULL, &status, NULL);
if (ok)
ok = (status == 0);
+ g_free (server_root);
g_free (cwd);
- g_free (conf);
+ g_free (pid_file);
+#ifdef HAVE_APACHE_2_4
+ g_free (default_runtime_dir);
+#endif
+ g_ptr_array_free (argv, TRUE);
return ok;
}
@@ -181,6 +188,9 @@ apache_cmd (const char *cmd)
void
apache_init (void)
{
+ if (g_getenv ("SOUP_TESTS_IN_MAKE_CHECK"))
+ return;
+
if (!apache_cmd ("start")) {
g_printerr ("Could not start apache\n");
exit (1);
@@ -218,15 +228,18 @@ soup_test_session_new (GType type, ...)
va_list args;
const char *propname;
SoupSession *session;
+ char *cafile;
va_start (args, type);
propname = va_arg (args, const char *);
session = (SoupSession *)g_object_new_valist (type, propname, args);
va_end (args);
+ cafile = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL);
g_object_set (G_OBJECT (session),
- SOUP_SESSION_SSL_CA_FILE, SRCDIR "/test-cert.pem",
+ SOUP_SESSION_SSL_CA_FILE, cafile,
NULL);
+ g_free (cafile);
if (http_debug_level && !logger) {
SoupLoggerLogLevel level = MIN ((SoupLoggerLogLevel)http_debug_level, SOUP_LOGGER_LOG_BODY);
@@ -243,16 +256,10 @@ soup_test_session_new (GType type, ...)
void
soup_test_session_abort_unref (SoupSession *session)
{
- g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session);
-
soup_session_abort (session);
- g_object_unref (session);
- if (session) {
- errors++;
- debug_printf (1, "leaked SoupSession!\n");
- g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session);
- }
+ g_assert_cmpint (G_OBJECT (session)->ref_count, ==, 1);
+ g_object_unref (session);
}
static gpointer run_server_thread (gpointer user_data);
@@ -262,14 +269,14 @@ test_server_new (gboolean in_own_thread, gboolean ssl)
{
SoupServer *server;
GMainContext *async_context;
- const char *ssl_cert_file, *ssl_key_file;
+ char *ssl_cert_file, *ssl_key_file;
SoupAddress *addr;
async_context = in_own_thread ? g_main_context_new () : NULL;
if (ssl) {
- ssl_cert_file = SRCDIR "/test-cert.pem";
- ssl_key_file = SRCDIR "/test-key.pem";
+ ssl_cert_file = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL);
+ ssl_key_file = g_test_build_filename (G_TEST_DIST, "test-key.pem", NULL);
} else
ssl_cert_file = ssl_key_file = NULL;
@@ -284,6 +291,8 @@ test_server_new (gboolean in_own_thread, gboolean ssl)
g_object_unref (addr);
if (async_context)
g_main_context_unref (async_context);
+ g_free (ssl_cert_file);
+ g_free (ssl_key_file);
if (!server) {
g_printerr ("Unable to create server\n");
@@ -334,9 +343,6 @@ soup_test_server_quit_unref (SoupServer *server)
{
GThread *thread;
- g_object_add_weak_pointer (G_OBJECT (server),
- (gpointer *)&server);
-
thread = g_object_get_data (G_OBJECT (server), "thread");
if (thread) {
soup_add_completion (soup_server_get_async_context (server),
@@ -344,19 +350,14 @@ soup_test_server_quit_unref (SoupServer *server)
g_thread_join (thread);
} else
soup_server_quit (server);
- g_object_unref (server);
- if (server) {
- errors++;
- debug_printf (1, "leaked SoupServer!\n");
- g_object_remove_weak_pointer (G_OBJECT (server),
- (gpointer *)&server);
- }
+ g_assert_cmpint (G_OBJECT (server)->ref_count, ==, 1);
+ g_object_unref (server);
}
typedef struct {
- GMainLoop *loop;
- GAsyncResult *result;
+ GMainLoop *loop;
+ GAsyncResult *result;
} AsyncAsSyncData;
static void
@@ -364,51 +365,269 @@ async_as_sync_callback (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- AsyncAsSyncData *data = user_data;
+ AsyncAsSyncData *data = user_data;
+ GMainContext *context;
+
+ data->result = g_object_ref (result);
+ context = g_main_loop_get_context (data->loop);
+ while (g_main_context_pending (context))
+ g_main_context_iteration (context, FALSE);
+ g_main_loop_quit (data->loop);
+}
+
+typedef struct {
+ SoupRequest *req;
+ GCancellable *cancellable;
+ SoupTestRequestFlags flags;
+} CancelData;
+
+static CancelData *
+create_cancel_data (SoupRequest *req,
+ GCancellable *cancellable,
+ SoupTestRequestFlags flags)
+{
+ CancelData *cancel_data;
+
+ if (!flags)
+ return NULL;
+
+ cancel_data = g_slice_new0 (CancelData);
+ cancel_data->flags = flags;
+ if (flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE && SOUP_IS_REQUEST_HTTP (req))
+ cancel_data->req = g_object_ref (req);
+ else if (flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE)
+ cancel_data->cancellable = g_object_ref (cancellable);
+ return cancel_data;
+}
- data->result = g_object_ref (result);
- g_main_loop_quit (data->loop);
+static void inline
+cancel_message_or_cancellable (CancelData *cancel_data)
+{
+ if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE) {
+ SoupRequest *req = cancel_data->req;
+ SoupMessage *msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req));
+ soup_session_cancel_message (soup_request_get_session (req), msg,
+ SOUP_STATUS_CANCELLED);
+ g_object_unref (msg);
+ g_object_unref (req);
+ } else if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE) {
+ g_cancellable_cancel (cancel_data->cancellable);
+ g_object_unref (cancel_data->cancellable);
+ }
+ g_slice_free (CancelData, cancel_data);
+}
+
+static gboolean
+cancel_request_timeout (gpointer data)
+{
+ cancel_message_or_cancellable ((CancelData *) data);
+ return FALSE;
+}
+
+static gpointer
+cancel_request_thread (gpointer data)
+{
+ g_usleep (100000); /* .1s */
+ cancel_message_or_cancellable ((CancelData *) data);
+ return NULL;
}
GInputStream *
-soup_test_request_send_async_as_sync (SoupRequest *req,
- GCancellable *cancellable,
- GError **error)
+soup_test_request_send (SoupRequest *req,
+ GCancellable *cancellable,
+ guint flags,
+ GError **error)
{
- AsyncAsSyncData data;
- GInputStream *stream;
+ AsyncAsSyncData data;
+ GInputStream *stream;
+ CancelData *cancel_data = create_cancel_data (req, cancellable, flags);
- data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+ if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) {
+ GThread *thread;
- soup_request_send_async (req, cancellable, async_as_sync_callback, &data);
- g_main_loop_run (data.loop);
+ if (cancel_data)
+ thread = g_thread_new ("cancel_request_thread", cancel_request_thread,
+ cancel_data);
+ stream = soup_request_send (req, cancellable, error);
+ if (cancel_data)
+ g_thread_unref (thread);
+ return stream;
+ }
+
+ data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+ if (cancel_data &&
+ (flags & SOUP_TEST_REQUEST_CANCEL_SOON || flags & SOUP_TEST_REQUEST_CANCEL_IMMEDIATE)) {
+ guint interval = flags & SOUP_TEST_REQUEST_CANCEL_SOON ? 100 : 0;
+ g_timeout_add_full (G_PRIORITY_HIGH, interval, cancel_request_timeout, cancel_data, NULL);
+ }
+ if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE))
+ g_cancellable_cancel (cancellable);
+ soup_request_send_async (req, cancellable, async_as_sync_callback, &data);
+ g_main_loop_run (data.loop);
- stream = soup_request_send_finish (req, data.result, error);
+ stream = soup_request_send_finish (req, data.result, error);
- g_main_loop_unref (data.loop);
- g_object_unref (data.result);
+ if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH)) {
+ GMainContext *context;
- return stream;
+ cancel_message_or_cancellable (cancel_data);
+
+ context = g_main_loop_get_context (data.loop);
+ while (g_main_context_pending (context))
+ g_main_context_iteration (context, FALSE);
+ }
+
+ g_main_loop_unref (data.loop);
+ g_object_unref (data.result);
+
+ return stream;
+}
+
+gboolean
+soup_test_request_read_all (SoupRequest *req,
+ GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ char buf[8192];
+ AsyncAsSyncData data;
+ gsize nread;
+
+ if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req)))
+ data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+
+ do {
+ if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) {
+ nread = g_input_stream_read (stream, buf, sizeof (buf),
+ cancellable, error);
+ } else {
+ g_input_stream_read_async (stream, buf, sizeof (buf),
+ G_PRIORITY_DEFAULT, cancellable,
+ async_as_sync_callback, &data);
+ g_main_loop_run (data.loop);
+ nread = g_input_stream_read_finish (stream, data.result, error);
+ g_object_unref (data.result);
+ }
+ } while (nread > 0);
+
+ if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req)))
+ g_main_loop_unref (data.loop);
+
+ return nread == 0;
}
gboolean
-soup_test_stream_close_async_as_sync (GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
+soup_test_request_close_stream (SoupRequest *req,
+ GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
{
- AsyncAsSyncData data;
- gboolean ok;
+ AsyncAsSyncData data;
+ gboolean ok;
- data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+ if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req)))
+ return g_input_stream_close (stream, cancellable, error);
- g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, cancellable,
- async_as_sync_callback, &data);
- g_main_loop_run (data.loop);
+ data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
- ok = g_input_stream_close_finish (stream, data.result, error);
+ g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, cancellable,
+ async_as_sync_callback, &data);
+ g_main_loop_run (data.loop);
- g_main_loop_unref (data.loop);
- g_object_unref (data.result);
+ ok = g_input_stream_close_finish (stream, data.result, error);
- return ok;
+ g_main_loop_unref (data.loop);
+ g_object_unref (data.result);
+
+ return ok;
}
+
+void
+soup_test_register_resources (void)
+{
+ static gboolean registered = FALSE;
+ GResource *resource;
+ char *path;
+ GError *error = NULL;
+
+ if (registered)
+ return;
+
+ path = g_test_build_filename (G_TEST_BUILT, "soup-tests.gresource", NULL);
+ resource = g_resource_load (path, &error);
+ if (!resource) {
+ g_printerr ("Could not load resource soup-tests.gresource: %s\n",
+ error->message);
+ exit (1);
+ }
+ g_free (path);
+
+ g_resources_register (resource);
+ g_resource_unref (resource);
+
+ registered = TRUE;
+}
+
+SoupBuffer *
+soup_test_load_resource (const char *name,
+ GError **error)
+{
+ GBytes *bytes;
+ char *path;
+
+ soup_test_register_resources ();
+
+ path = g_build_path ("/", "/org/gnome/libsoup/tests/resources", name, NULL);
+ bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, error);
+ g_free (path);
+
+ if (!bytes)
+ return NULL;
+
+ return soup_buffer_new_with_owner (g_bytes_get_data (bytes, NULL),
+ g_bytes_get_size (bytes),
+ bytes,
+ (GDestroyNotify) g_bytes_unref);
+}
+
+SoupBuffer *
+soup_test_get_index (void)
+{
+ if (!index_buffer) {
+ char *path, *contents;
+ gsize length;
+ GError *error = NULL;
+
+ path = g_test_build_filename (G_TEST_DIST, "index.txt", NULL);
+ if (!g_file_get_contents (path, &contents, &length, &error)) {
+ g_printerr ("Could not read index.txt: %s\n",
+ error->message);
+ exit (1);
+ }
+ g_free (path);
+
+ index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length);
+ }
+
+ return index_buffer;
+}
+
+#ifndef G_HAVE_ISO_VARARGS
+void
+soup_test_assert (gboolean expr, const char *fmt, ...)
+{
+ char *message;
+ va_list args;
+
+ if (G_UNLIKELY (!expr)) {
+ va_start (args, fmt);
+ message = g_strdup_vprintf (fmt, args);
+ va_end (args);
+
+ g_assertion_message (G_LOG_DOMAIN,
+ "???", 0, "???"
+ message);
+ g_free (message);
+ }
+}
+#endif