summaryrefslogtreecommitdiff
path: root/gio
diff options
context:
space:
mode:
Diffstat (limited to 'gio')
-rw-r--r--gio/gdbusprivate.c6
-rw-r--r--gio/gnetworkaddress.c147
-rw-r--r--gio/gpollableoutputstream.h2
-rw-r--r--gio/gresource.c8
-rw-r--r--gio/gsocket.c16
-rw-r--r--gio/gsocketclient.c2
-rw-r--r--gio/gsocketlistener.c32
-rw-r--r--gio/gtask.c17
-rw-r--r--gio/gwin32volumemonitor.c10
-rw-r--r--gio/tests/autoptr.c2
-rw-r--r--gio/tests/gsettings.c287
-rw-r--r--gio/tests/gsubprocess.c46
-rw-r--r--gio/tests/meson.build20
-rw-r--r--gio/tests/network-address.c103
-rw-r--r--gio/tests/task.c148
-rw-r--r--gio/win32/gwinhttpvfs.c2
16 files changed, 591 insertions, 257 deletions
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index c2a04ae12..1e8e1d64b 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -809,11 +809,11 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
out:
g_mutex_unlock (&worker->read_lock);
- /* gives up the reference acquired when calling g_input_stream_read_async() */
- _g_dbus_worker_unref (worker);
-
/* check if there is any pending close */
schedule_pending_close (worker);
+
+ /* gives up the reference acquired when calling g_input_stream_read_async() */
+ _g_dbus_worker_unref (worker);
}
/* called in private thread shared by all GDBusConnection instances (with read-lock held) */
diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c
index 60736874e..24af25c2c 100644
--- a/gio/gnetworkaddress.c
+++ b/gio/gnetworkaddress.c
@@ -38,6 +38,10 @@
#include <string.h>
+/* As recommended by RFC 8305 this is the time it waits for a following
+ DNS response to come in (ipv4 waiting on ipv6 generally)
+ */
+#define HAPPY_EYEBALLS_RESOLUTION_DELAY_MS 50
/**
* SECTION:gnetworkaddress
@@ -879,6 +883,12 @@ g_network_address_get_scheme (GNetworkAddress *addr)
#define G_TYPE_NETWORK_ADDRESS_ADDRESS_ENUMERATOR (_g_network_address_address_enumerator_get_type ())
#define G_NETWORK_ADDRESS_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_NETWORK_ADDRESS_ADDRESS_ENUMERATOR, GNetworkAddressAddressEnumerator))
+typedef enum {
+ RESOLVE_STATE_NONE = 0,
+ RESOLVE_STATE_WAITING_ON_IPV4 = 1 << 0,
+ RESOLVE_STATE_WAITING_ON_IPV6 = 1 << 1,
+} ResolveState;
+
typedef struct {
GSocketAddressEnumerator parent_instance;
@@ -887,9 +897,11 @@ typedef struct {
GList *last_tail; /* (unowned) (nullable) */
GList *current_item; /* (unowned) (nullable) */
GTask *queued_task; /* (owned) (nullable) */
+ GTask *waiting_task; /* (owned) (nullable) */
GError *last_error; /* (owned) (nullable) */
GSource *wait_source; /* (owned) (nullable) */
GMainContext *context; /* (owned) (nullable) */
+ ResolveState state;
} GNetworkAddressAddressEnumerator;
typedef struct {
@@ -912,6 +924,7 @@ g_network_address_address_enumerator_finalize (GObject *object)
g_clear_pointer (&addr_enum->wait_source, g_source_unref);
}
g_clear_object (&addr_enum->queued_task);
+ g_clear_object (&addr_enum->waiting_task);
g_clear_error (&addr_enum->last_error);
g_object_unref (addr_enum->addr);
g_clear_pointer (&addr_enum->addresses, g_list_free);
@@ -1093,20 +1106,54 @@ g_network_address_address_enumerator_next (GSocketAddressEnumerator *enumerator
return g_object_ref (sockaddr);
}
+/*
+ * Each enumeration lazily initializes the internal address list from the
+ * master list. It does this since addresses come in asynchronously and
+ * they need to be resorted into the list already in use.
+ */
+static GSocketAddress *
+init_and_query_next_address (GNetworkAddressAddressEnumerator *addr_enum)
+{
+ GNetworkAddress *addr = addr_enum->addr;
+ GSocketAddress *sockaddr;
+
+ if (addr_enum->addresses == NULL)
+ {
+ addr_enum->current_item = addr_enum->addresses = list_copy_interleaved (addr->priv->sockaddrs);
+ addr_enum->last_tail = g_list_last (addr_enum->addr->priv->sockaddrs);
+ if (addr_enum->current_item)
+ sockaddr = g_object_ref (addr_enum->current_item->data);
+ else
+ sockaddr = NULL;
+ }
+ else
+ {
+ GList *parent_tail = g_list_last (addr_enum->addr->priv->sockaddrs);
+
+ if (addr_enum->last_tail != parent_tail)
+ {
+ addr_enum->current_item = list_concat_interleaved (addr_enum->current_item, g_list_next (addr_enum->last_tail));
+ addr_enum->last_tail = parent_tail;
+ }
+
+ if (addr_enum->current_item->next)
+ {
+ addr_enum->current_item = g_list_next (addr_enum->current_item);
+ sockaddr = g_object_ref (addr_enum->current_item->data);
+ }
+ else
+ sockaddr = NULL;
+ }
+
+ return sockaddr;
+}
+
static void
complete_queued_task (GNetworkAddressAddressEnumerator *addr_enum,
GTask *task,
GError *error)
{
- GSocketAddress *sockaddr;
-
- addr_enum->current_item = addr_enum->addresses = list_copy_interleaved (addr_enum->addr->priv->sockaddrs);
- addr_enum->last_tail = g_list_last (addr_enum->addr->priv->sockaddrs);
-
- if (addr_enum->current_item)
- sockaddr = g_object_ref (addr_enum->current_item->data);
- else
- sockaddr = NULL;
+ GSocketAddress *sockaddr = init_and_query_next_address (addr_enum);
if (error)
g_task_return_error (task, error);
@@ -1123,10 +1170,12 @@ on_address_timeout (gpointer user_data)
/* Upon completion it may get unref'd by the owner */
g_object_ref (addr_enum);
- /* If ipv6 didn't come in yet, just complete the task */
if (addr_enum->queued_task != NULL)
- complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->queued_task),
- g_steal_pointer (&addr_enum->last_error));
+ complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->queued_task),
+ g_steal_pointer (&addr_enum->last_error));
+ else if (addr_enum->waiting_task != NULL)
+ complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->waiting_task),
+ NULL);
g_clear_pointer (&addr_enum->wait_source, g_source_unref);
g_object_unref (addr_enum);
@@ -1144,6 +1193,8 @@ got_ipv6_addresses (GObject *source_object,
GList *addresses;
GError *error = NULL;
+ addr_enum->state ^= RESOLVE_STATE_WAITING_ON_IPV6;
+
addresses = g_resolver_lookup_by_name_with_flags_finish (resolver, result, &error);
if (!error)
{
@@ -1163,30 +1214,39 @@ got_ipv6_addresses (GObject *source_object,
g_clear_pointer (&addr_enum->wait_source, g_source_unref);
}
- /* If we got an error before ipv4 then let it handle it.
+ /* If we got an error before ipv4 then let its response handle it.
* If we get ipv6 response first or error second then
* immediately complete the task.
*/
- if (error != NULL && !addr_enum->last_error)
+ if (error != NULL && !addr_enum->last_error && (addr_enum->state & RESOLVE_STATE_WAITING_ON_IPV4))
{
addr_enum->last_error = g_steal_pointer (&error);
- /* This shouldn't happen often but avoid never responding. */
- addr_enum->wait_source = g_timeout_source_new_seconds (1);
+ addr_enum->wait_source = g_timeout_source_new (HAPPY_EYEBALLS_RESOLUTION_DELAY_MS);
g_source_set_callback (addr_enum->wait_source,
on_address_timeout,
addr_enum, NULL);
g_source_attach (addr_enum->wait_source, addr_enum->context);
}
+ else if (addr_enum->waiting_task != NULL)
+ {
+ complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->waiting_task), NULL);
+ }
else if (addr_enum->queued_task != NULL)
{
+ GError *task_error = NULL;
+
+ /* If both errored just use the ipv6 one,
+ but if ipv6 errored and ipv4 didn't we don't error */
+ if (error != NULL && addr_enum->last_error)
+ task_error = g_steal_pointer (&error);
+
g_clear_error (&addr_enum->last_error);
complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->queued_task),
- g_steal_pointer (&error));
+ g_steal_pointer (&task_error));
}
- else if (error != NULL)
- g_clear_error (&error);
+ g_clear_error (&error);
g_object_unref (addr_enum);
}
@@ -1200,6 +1260,8 @@ got_ipv4_addresses (GObject *source_object,
GList *addresses;
GError *error = NULL;
+ addr_enum->state ^= RESOLVE_STATE_WAITING_ON_IPV4;
+
addresses = g_resolver_lookup_by_name_with_flags_finish (resolver, result, &error);
if (!error)
{
@@ -1216,8 +1278,9 @@ got_ipv4_addresses (GObject *source_object,
}
/* If ipv6 already came in and errored then we return.
- * If ipv6 returned successfully then we don't need to do anything.
- * Otherwise we should wait a short while for ipv6 as RFC 8305 suggests.
+ * If ipv6 returned successfully then we don't need to do anything unless
+ * another enumeration was waiting on us.
+ * If ipv6 hasn't come we should wait a short while for it as RFC 8305 suggests.
*/
if (addr_enum->last_error)
{
@@ -1226,18 +1289,21 @@ got_ipv4_addresses (GObject *source_object,
complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->queued_task),
g_steal_pointer (&error));
}
+ else if (addr_enum->waiting_task != NULL)
+ {
+ complete_queued_task (addr_enum, g_steal_pointer (&addr_enum->waiting_task), NULL);
+ }
else if (addr_enum->queued_task != NULL)
{
addr_enum->last_error = g_steal_pointer (&error);
- addr_enum->wait_source = g_timeout_source_new (50);
+ addr_enum->wait_source = g_timeout_source_new (HAPPY_EYEBALLS_RESOLUTION_DELAY_MS);
g_source_set_callback (addr_enum->wait_source,
on_address_timeout,
addr_enum, NULL);
g_source_attach (addr_enum->wait_source, addr_enum->context);
}
- else if (error != NULL)
- g_clear_error (&error);
+ g_clear_error (&error);
g_object_unref (addr_enum);
}
@@ -1251,12 +1317,11 @@ g_network_address_address_enumerator_next_async (GSocketAddressEnumerator *enum
G_NETWORK_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
GSocketAddress *sockaddr;
GTask *task;
- GNetworkAddress *addr = addr_enum->addr;
task = g_task_new (addr_enum, cancellable, callback, user_data);
g_task_set_source_tag (task, g_network_address_address_enumerator_next_async);
- if (addr_enum->addresses == NULL)
+ if (addr_enum->addresses == NULL && addr_enum->state == RESOLVE_STATE_NONE)
{
GNetworkAddress *addr = addr_enum->addr;
GResolver *resolver = g_resolver_get_default ();
@@ -1280,6 +1345,7 @@ g_network_address_address_enumerator_next_async (GSocketAddressEnumerator *enum
* times before the initial callback has been called */
g_assert (addr_enum->queued_task == NULL);
+ addr_enum->state = RESOLVE_STATE_WAITING_ON_IPV4 | RESOLVE_STATE_WAITING_ON_IPV6;
addr_enum->queued_task = g_steal_pointer (&task);
/* Lookup in parallel as per RFC 8305 */
g_resolver_lookup_by_name_with_flags_async (resolver,
@@ -1300,34 +1366,17 @@ g_network_address_address_enumerator_next_async (GSocketAddressEnumerator *enum
g_object_unref (resolver);
}
- if (addr_enum->addresses == NULL)
+ sockaddr = init_and_query_next_address (addr_enum);
+ if (sockaddr == NULL && (addr_enum->state & RESOLVE_STATE_WAITING_ON_IPV4 ||
+ addr_enum->state & RESOLVE_STATE_WAITING_ON_IPV6))
{
- g_assert (addr->priv->sockaddrs);
-
- addr_enum->current_item = addr_enum->addresses = list_copy_interleaved (addr->priv->sockaddrs);
- sockaddr = g_object_ref (addr_enum->current_item->data);
+ addr_enum->waiting_task = task;
}
else
{
- GList *parent_tail = g_list_last (addr_enum->addr->priv->sockaddrs);
-
- if (addr_enum->last_tail != parent_tail)
- {
- addr_enum->current_item = list_concat_interleaved (addr_enum->current_item, g_list_next (addr_enum->last_tail));
- addr_enum->last_tail = parent_tail;
- }
-
- if (addr_enum->current_item->next)
- {
- addr_enum->current_item = g_list_next (addr_enum->current_item);
- sockaddr = g_object_ref (addr_enum->current_item->data);
- }
- else
- sockaddr = NULL;
+ g_task_return_pointer (task, sockaddr, g_object_unref);
+ g_object_unref (task);
}
-
- g_task_return_pointer (task, sockaddr, g_object_unref);
- g_object_unref (task);
}
static GSocketAddress *
diff --git a/gio/gpollableoutputstream.h b/gio/gpollableoutputstream.h
index 1ef830b57..c1e7ad889 100644
--- a/gio/gpollableoutputstream.h
+++ b/gio/gpollableoutputstream.h
@@ -35,7 +35,7 @@ G_BEGIN_DECLS
/**
* GPollableOutputStream:
*
- * An interface for a #GOutputStream that can be polled for readability.
+ * An interface for a #GOutputStream that can be polled for writeability.
*
* Since: 2.28
*/
diff --git a/gio/gresource.c b/gio/gresource.c
index e71db43ed..9aaae8b53 100644
--- a/gio/gresource.c
+++ b/gio/gresource.c
@@ -151,7 +151,7 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
* When debugging a program or testing a change to an installed version, it is often useful to be able to
* replace resources in the program or library, without recompiling, for debugging or quick hacking and testing
* purposes. Since GLib 2.50, it is possible to use the `G_RESOURCE_OVERLAYS` environment variable to selectively overlay
- * resources with replacements from the filesystem. It is a colon-separated list of substitutions to perform
+ * resources with replacements from the filesystem. It is a %G_SEARCHPATH_SEPARATOR-separated list of substitutions to perform
* during resource lookups.
*
* A substitution has the form
@@ -332,7 +332,7 @@ g_resource_find_overlay (const gchar *path,
gchar **parts;
gint i, j;
- parts = g_strsplit (envvar, ":", 0);
+ parts = g_strsplit (envvar, G_SEARCHPATH_SEPARATOR_S, 0);
/* Sanity check the parts, dropping those that are invalid.
* 'i' may grow faster than 'j'.
@@ -378,9 +378,9 @@ g_resource_find_overlay (const gchar *path,
continue;
}
- if (eq[1] != '/')
+ if (!g_path_is_absolute (eq + 1))
{
- g_critical ("G_RESOURCE_OVERLAYS segment '%s' lacks leading '/' after '='. Ignoring", part);
+ g_critical ("G_RESOURCE_OVERLAYS segment '%s' does not have an absolute path after '='. Ignoring", part);
g_free (part);
continue;
}
diff --git a/gio/gsocket.c b/gio/gsocket.c
index b1db8e645..92baa62ea 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -4609,7 +4609,13 @@ g_socket_send_message (GSocket *socket,
cancellable, error);
if (res == G_POLLABLE_RETURN_WOULD_BLOCK)
- socket_set_error_lazy (error, EWOULDBLOCK, _("Error sending message: %s"));
+ {
+#ifndef G_OS_WIN32
+ socket_set_error_lazy (error, EWOULDBLOCK, _("Error sending message: %s"));
+#else
+ socket_set_error_lazy (error, WSAEWOULDBLOCK, _("Error sending message: %s"));
+#endif
+ }
return res == G_POLLABLE_RETURN_OK ? bytes_written : -1;
}
@@ -5056,7 +5062,13 @@ g_socket_send_messages_with_timeout (GSocket *socket,
cancellable, &msg_error);
if (pollable_result == G_POLLABLE_RETURN_WOULD_BLOCK)
- socket_set_error_lazy (&msg_error, EWOULDBLOCK, _("Error sending message: %s"));
+ {
+#ifndef G_OS_WIN32
+ socket_set_error_lazy (&msg_error, EWOULDBLOCK, _("Error sending message: %s"));
+#else
+ socket_set_error_lazy (&msg_error, WSAEWOULDBLOCK, _("Error sending message: %s"));
+#endif
+ }
result = pollable_result == G_POLLABLE_RETURN_OK ? bytes_written : -1;
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index 29a5e5598..11e92e909 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -1567,7 +1567,7 @@ g_socket_client_connected_callback (GObject *source,
GProxy *proxy;
const gchar *protocol;
- if (g_cancellable_is_cancelled (attempt->cancellable) || task_completed_or_cancelled (data->task))
+ if (task_completed_or_cancelled (data->task) || g_cancellable_is_cancelled (attempt->cancellable))
{
g_object_unref (data->task);
connection_attempt_unref (attempt);
diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c
index ab17678a9..a2c879d9c 100644
--- a/gio/gsocketlistener.c
+++ b/gio/gsocketlistener.c
@@ -773,6 +773,19 @@ g_socket_listener_accept (GSocketListener *listener,
return connection;
}
+typedef struct
+{
+ GList *sources; /* (element-type GSource) */
+ gboolean returned_yet;
+} AcceptSocketAsyncData;
+
+static void
+accept_socket_async_data_free (AcceptSocketAsyncData *data)
+{
+ free_sources (data->sources);
+ g_free (data);
+}
+
static gboolean
accept_ready (GSocket *accept_socket,
GIOCondition condition,
@@ -782,6 +795,12 @@ accept_ready (GSocket *accept_socket,
GError *error = NULL;
GSocket *socket;
GObject *source_object;
+ AcceptSocketAsyncData *data = g_task_get_task_data (task);
+
+ /* Don’t call g_task_return_*() multiple times if we have multiple incoming
+ * connections in the same #GMainContext iteration. */
+ if (data->returned_yet)
+ return G_SOURCE_REMOVE;
socket = g_socket_accept (accept_socket, g_task_get_cancellable (task), &error);
if (socket)
@@ -798,8 +817,10 @@ accept_ready (GSocket *accept_socket,
g_task_return_error (task, error);
}
+ data->returned_yet = TRUE;
g_object_unref (task);
- return FALSE;
+
+ return G_SOURCE_REMOVE;
}
/**
@@ -824,8 +845,8 @@ g_socket_listener_accept_socket_async (GSocketListener *listener,
gpointer user_data)
{
GTask *task;
- GList *sources;
GError *error = NULL;
+ AcceptSocketAsyncData *data = NULL;
task = g_task_new (listener, cancellable, callback, user_data);
g_task_set_source_tag (task, g_socket_listener_accept_socket_async);
@@ -837,12 +858,15 @@ g_socket_listener_accept_socket_async (GSocketListener *listener,
return;
}
- sources = add_sources (listener,
+ data = g_new0 (AcceptSocketAsyncData, 1);
+ data->returned_yet = FALSE;
+ data->sources = add_sources (listener,
accept_ready,
task,
cancellable,
g_main_context_get_thread_default ());
- g_task_set_task_data (task, sources, (GDestroyNotify) free_sources);
+ g_task_set_task_data (task, g_steal_pointer (&data),
+ (GDestroyNotify) accept_socket_async_data_free);
}
/**
diff --git a/gio/gtask.c b/gio/gtask.c
index aa98f752c..346d2ec5b 100644
--- a/gio/gtask.c
+++ b/gio/gtask.c
@@ -1,6 +1,6 @@
/* GIO - GLib Input, Output and Streaming Library
*
- * Copyright 2011 Red Hat, Inc.
+ * Copyright 2011-2018 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1260,9 +1260,18 @@ g_task_return (GTask *task,
*/
if (g_source_get_time (source) > task->creation_time)
{
- g_task_return_now (task);
- g_object_unref (task);
- return;
+ /* Finally, if the task has been cancelled, we shouldn't
+ * return synchronously from inside the
+ * GCancellable::cancelled handler. It's easier to run
+ * another iteration of the main loop than tracking how the
+ * cancellation was handled.
+ */
+ if (!g_cancellable_is_cancelled (task->cancellable))
+ {
+ g_task_return_now (task);
+ g_object_unref (task);
+ return;
+ }
}
}
diff --git a/gio/gwin32volumemonitor.c b/gio/gwin32volumemonitor.c
index c9db68a8a..512471834 100644
--- a/gio/gwin32volumemonitor.c
+++ b/gio/gwin32volumemonitor.c
@@ -111,7 +111,7 @@ get_mounts (GVolumeMonitor *volume_monitor)
{
DWORD drives;
gchar drive[4] = "A:\\";
- GList *list = NULL;
+ GQueue queue = G_QUEUE_INIT;
drives = get_viewable_logical_drives ();
@@ -121,13 +121,13 @@ get_mounts (GVolumeMonitor *volume_monitor)
while (drives && drive[0] <= 'Z')
{
if (drives & 1)
- {
- list = g_list_prepend (list, _g_win32_mount_new (volume_monitor, drive, NULL));
- }
+ g_queue_push_tail (&queue, _g_win32_mount_new (volume_monitor, drive, NULL));
+
drives >>= 1;
drive[0]++;
}
- return list;
+
+ return g_steal_pointer (&queue.head);
}
/* actually 'mounting' volumes is out of GIOs business on win32, so no volumes are delivered either */
diff --git a/gio/tests/autoptr.c b/gio/tests/autoptr.c
index 9ff1428ea..55a1c91fb 100644
--- a/gio/tests/autoptr.c
+++ b/gio/tests/autoptr.c
@@ -8,7 +8,7 @@ test_autoptr (void)
g_autofree gchar *path = g_file_get_path (p);
g_autofree gchar *istr = g_inet_address_to_string (a);
- g_assert_cmpstr (path, ==, "/blah");
+ g_assert_cmpstr (path, ==, G_DIR_SEPARATOR_S "blah");
g_assert_cmpstr (istr, ==, "127.0.0.1");
}
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
index f254c3195..640f3a31c 100644
--- a/gio/tests/gsettings.c
+++ b/gio/tests/gsettings.c
@@ -1,6 +1,8 @@
#include <stdlib.h>
#include <locale.h>
#include <libintl.h>
+#include <unistd.h>
+#include <sys/types.h>
#include <gio/gio.h>
#include <gstdio.h>
#define G_SETTINGS_ENABLE_BACKEND
@@ -53,10 +55,10 @@ test_basic (void)
"delay-apply", &delay_apply,
NULL);
g_assert_cmpstr (str, ==, "org.gtk.test");
- g_assert (b != NULL);
+ g_assert_nonnull (b);
g_assert_cmpstr (path, ==, "/tests/");
- g_assert (!has_unapplied);
- g_assert (!delay_apply);
+ g_assert_false (has_unapplied);
+ g_assert_false (delay_apply);
g_free (str);
g_object_unref (b);
g_free (path);
@@ -114,7 +116,7 @@ test_unknown_key (void)
settings = g_settings_new ("org.gtk.test");
value = g_settings_get_value (settings, "no_such_key");
- g_assert (value == NULL);
+ g_assert_null (value);
g_object_unref (settings);
return;
@@ -139,7 +141,7 @@ test_no_schema (void)
settings = g_settings_new ("no.such.schema");
- g_assert (settings == NULL);
+ g_assert_null (settings);
return;
}
g_test_trap_subprocess (NULL, 0, 0);
@@ -168,7 +170,7 @@ test_wrong_type (void)
g_settings_get (settings, "greeting", "o", &str);
g_test_assert_expected_messages ();
- g_assert (str == NULL);
+ g_assert_null (str);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*expects type 's'*");
@@ -358,28 +360,28 @@ test_complex_types (void)
g_settings_get (settings, "test-array", "ai", &iter);
g_assert_cmpint (g_variant_iter_n_children (iter), ==, 6);
- g_assert (g_variant_iter_next (iter, "i", &i1));
+ g_assert_true (g_variant_iter_next (iter, "i", &i1));
g_assert_cmpint (i1, ==, 0);
- g_assert (g_variant_iter_next (iter, "i", &i1));
+ g_assert_true (g_variant_iter_next (iter, "i", &i1));
g_assert_cmpint (i1, ==, 1);
- g_assert (g_variant_iter_next (iter, "i", &i1));
+ g_assert_true (g_variant_iter_next (iter, "i", &i1));
g_assert_cmpint (i1, ==, 2);
- g_assert (g_variant_iter_next (iter, "i", &i1));
+ g_assert_true (g_variant_iter_next (iter, "i", &i1));
g_assert_cmpint (i1, ==, 3);
- g_assert (g_variant_iter_next (iter, "i", &i1));
+ g_assert_true (g_variant_iter_next (iter, "i", &i1));
g_assert_cmpint (i1, ==, 4);
- g_assert (g_variant_iter_next (iter, "i", &i1));
+ g_assert_true (g_variant_iter_next (iter, "i", &i1));
g_assert_cmpint (i1, ==, 5);
- g_assert (!g_variant_iter_next (iter, "i", &i1));
+ g_assert_false (g_variant_iter_next (iter, "i", &i1));
g_variant_iter_free (iter);
g_settings_get (settings, "test-dict", "a{sau}", &iter);
g_assert_cmpint (g_variant_iter_n_children (iter), ==, 2);
- g_assert (g_variant_iter_next (iter, "{&s@au}", &s, &v));
+ g_assert_true (g_variant_iter_next (iter, "{&s@au}", &s, &v));
g_assert_cmpstr (s, ==, "AC");
g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "au");
g_variant_unref (v);
- g_assert (g_variant_iter_next (iter, "{&s@au}", &s, &v));
+ g_assert_true (g_variant_iter_next (iter, "{&s@au}", &s, &v));
g_assert_cmpstr (s, ==, "IV");
g_assert_cmpstr ((char *)g_variant_get_type (v), ==, "au");
g_variant_unref (v);
@@ -420,14 +422,14 @@ test_changes (void)
changed_cb_called = FALSE;
g_settings_set (settings, "greeting", "s", "new greeting");
- g_assert (changed_cb_called);
+ g_assert_true (changed_cb_called);
settings2 = g_settings_new ("org.gtk.test");
changed_cb_called = FALSE;
g_settings_set (settings2, "greeting", "s", "hi");
- g_assert (changed_cb_called);
+ g_assert_true (changed_cb_called);
g_object_unref (settings2);
g_object_unref (settings);
@@ -479,11 +481,11 @@ test_delay_apply (void)
g_settings_set (settings, "greeting", "s", "greetings from test_delay_apply");
- g_assert (changed_cb_called);
- g_assert (!changed_cb_called2);
+ g_assert_true (changed_cb_called);
+ g_assert_false (changed_cb_called2);
writable = g_settings_is_writable (settings, "greeting");
- g_assert (writable);
+ g_assert_true (writable);
g_settings_get (settings, "greeting", "s", &str);
g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
@@ -500,16 +502,16 @@ test_delay_apply (void)
g_free (str);
str = NULL;
- g_assert (g_settings_get_has_unapplied (settings));
- g_assert (!g_settings_get_has_unapplied (settings2));
+ g_assert_true (g_settings_get_has_unapplied (settings));
+ g_assert_false (g_settings_get_has_unapplied (settings2));
changed_cb_called = FALSE;
changed_cb_called2 = FALSE;
g_settings_apply (settings);
- g_assert (!changed_cb_called);
- g_assert (changed_cb_called2);
+ g_assert_false (changed_cb_called);
+ g_assert_true (changed_cb_called2);
g_settings_get (settings, "greeting", "s", &str);
g_assert_cmpstr (str, ==, "greetings from test_delay_apply");
@@ -521,8 +523,8 @@ test_delay_apply (void)
g_free (str);
str = NULL;
- g_assert (!g_settings_get_has_unapplied (settings));
- g_assert (!g_settings_get_has_unapplied (settings2));
+ g_assert_false (g_settings_get_has_unapplied (settings));
+ g_assert_false (g_settings_get_has_unapplied (settings2));
g_settings_reset (settings, "greeting");
g_settings_apply (settings);
@@ -568,11 +570,11 @@ test_delay_revert (void)
g_free (str);
str = NULL;
- g_assert (g_settings_get_has_unapplied (settings));
+ g_assert_true (g_settings_get_has_unapplied (settings));
g_settings_revert (settings);
- g_assert (!g_settings_get_has_unapplied (settings));
+ g_assert_false (g_settings_get_has_unapplied (settings));
g_settings_get (settings, "greeting", "s", &str);
g_assert_cmpstr (str, ==, "top o' the morning");
@@ -603,13 +605,13 @@ test_delay_child (void)
settings = g_settings_new ("org.gtk.test");
g_settings_delay (settings);
g_object_get (settings, "delay-apply", &delay, NULL);
- g_assert (delay);
+ g_assert_true (delay);
child = g_settings_get_child (settings, "basic-types");
- g_assert (child != NULL);
+ g_assert_nonnull (child);
g_object_get (child, "delay-apply", &delay, NULL);
- g_assert (!delay);
+ g_assert_false (delay);
g_settings_get (child, "test-byte", "y", &byte);
g_assert_cmpuint (byte, ==, 36);
@@ -634,10 +636,10 @@ keys_changed_cb (GSettings *settings,
g_assert_cmpint (n_keys, ==, 2);
- g_assert ((keys[0] == g_quark_from_static_string ("greeting") &&
- keys[1] == g_quark_from_static_string ("farewell")) ||
- (keys[1] == g_quark_from_static_string ("greeting") &&
- keys[0] == g_quark_from_static_string ("farewell")));
+ g_assert_true ((keys[0] == g_quark_from_static_string ("greeting") &&
+ keys[1] == g_quark_from_static_string ("farewell")) ||
+ (keys[1] == g_quark_from_static_string ("greeting") &&
+ keys[0] == g_quark_from_static_string ("farewell")));
g_settings_get (settings, "greeting", "s", &str);
g_assert_cmpstr (str, ==, "greetings from test_atomic");
@@ -1297,7 +1299,7 @@ test_simple_binding (void)
g_free (s);
g_settings_set_strv (settings, "strv", NULL);
g_object_get (obj, "strv", &strv, NULL);
- g_assert (strv != NULL);
+ g_assert_nonnull (strv);
g_assert_cmpint (g_strv_length (strv), ==, 0);
g_strfreev (strv);
@@ -1401,14 +1403,14 @@ test_bind_writable (void)
g_settings_bind_writable (settings, "int", obj, "bool", FALSE);
g_object_get (obj, "bool", &b, NULL);
- g_assert (b);
+ g_assert_true (b);
g_settings_unbind (obj, "bool");
g_settings_bind_writable (settings, "int", obj, "bool", TRUE);
g_object_get (obj, "bool", &b, NULL);
- g_assert (!b);
+ g_assert_false (b);
g_object_unref (obj);
g_object_unref (settings);
@@ -1724,7 +1726,7 @@ test_keyfile (void)
g_free (str);
writable = g_settings_is_writable (settings, "greeting");
- g_assert (writable);
+ g_assert_true (writable);
g_settings_set (settings, "greeting", "s", "see if this works");
str = g_settings_get_string (settings, "greeting");
@@ -1736,7 +1738,7 @@ test_keyfile (void)
g_settings_apply (settings);
keyfile = g_key_file_new ();
- g_assert (g_key_file_load_from_file (keyfile, "keyfile/gsettings.store", 0, NULL));
+ g_assert_true (g_key_file_load_from_file (keyfile, "keyfile/gsettings.store", 0, NULL));
str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
g_assert_cmpstr (str, ==, "'see if this works'");
@@ -1750,10 +1752,10 @@ test_keyfile (void)
g_settings_reset (settings, "greeting");
g_settings_apply (settings);
keyfile = g_key_file_new ();
- g_assert (g_key_file_load_from_file (keyfile, "keyfile/gsettings.store", 0, NULL));
+ g_assert_true (g_key_file_load_from_file (keyfile, "keyfile/gsettings.store", 0, NULL));
str = g_key_file_get_string (keyfile, "tests", "greeting", NULL);
- g_assert (str == NULL);
+ g_assert_null (str);
called = FALSE;
g_signal_connect (settings, "changed::greeting", G_CALLBACK (key_changed_cb), &called);
@@ -1789,16 +1791,23 @@ test_keyfile (void)
g_settings_set (settings, "farewell", "s", "cheerio");
- called = FALSE;
- g_signal_connect (settings, "writable-changed::greeting", G_CALLBACK (key_changed_cb), &called);
+ /* When executing as root, changing the mode of the keyfile will have
+ * no effect on the writability of the settings.
+ */
+ if (geteuid () != 0)
+ {
+ called = FALSE;
+ g_signal_connect (settings, "writable-changed::greeting",
+ G_CALLBACK (key_changed_cb), &called);
- g_chmod ("keyfile", 0500);
- while (!called)
- g_main_context_iteration (NULL, FALSE);
- g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
+ g_chmod ("keyfile", 0500);
+ while (!called)
+ g_main_context_iteration (NULL, FALSE);
+ g_signal_handlers_disconnect_by_func (settings, key_changed_cb, &called);
- writable = g_settings_is_writable (settings, "greeting");
- g_assert (!writable);
+ writable = g_settings_is_writable (settings, "greeting");
+ g_assert_false (writable);
+ }
g_key_file_free (keyfile);
g_free (data);
@@ -1827,7 +1836,7 @@ test_child_schema (void)
settings = g_settings_new ("org.gtk.test");
child = g_settings_get_child (settings, "basic-types");
- g_assert (child != NULL);
+ g_assert_nonnull (child);
g_settings_get (child, "test-byte", "y", &byte);
g_assert_cmpint (byte, ==, 36);
@@ -1860,7 +1869,7 @@ test_strinfo (void)
builder = g_string_new (NULL);
strinfo_builder_append_item (builder, "foo", 1);
strinfo_builder_append_item (builder, "bar", 2);
- g_assert (strinfo_builder_append_alias (builder, "baz", "bar"));
+ g_assert_true (strinfo_builder_append_alias (builder, "baz", "bar"));
g_assert_cmpmem (builder->str, builder->len, strinfo, length * 4);
g_string_free (builder, TRUE);
}
@@ -1874,22 +1883,22 @@ test_strinfo (void)
g_assert_cmpstr (strinfo_string_from_alias (strinfo, length, "quux"),
==, NULL);
- g_assert (strinfo_enum_from_string (strinfo, length, "foo", &result));
+ g_assert_true (strinfo_enum_from_string (strinfo, length, "foo", &result));
g_assert_cmpint (result, ==, 1);
- g_assert (strinfo_enum_from_string (strinfo, length, "bar", &result));
+ g_assert_true (strinfo_enum_from_string (strinfo, length, "bar", &result));
g_assert_cmpint (result, ==, 2);
- g_assert (!strinfo_enum_from_string (strinfo, length, "baz", &result));
- g_assert (!strinfo_enum_from_string (strinfo, length, "quux", &result));
+ g_assert_false (strinfo_enum_from_string (strinfo, length, "baz", &result));
+ g_assert_false (strinfo_enum_from_string (strinfo, length, "quux", &result));
g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 0), ==, NULL);
g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 1), ==, "foo");
g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 2), ==, "bar");
g_assert_cmpstr (strinfo_string_from_enum (strinfo, length, 3), ==, NULL);
- g_assert (strinfo_is_string_valid (strinfo, length, "foo"));
- g_assert (strinfo_is_string_valid (strinfo, length, "bar"));
- g_assert (!strinfo_is_string_valid (strinfo, length, "baz"));
- g_assert (!strinfo_is_string_valid (strinfo, length, "quux"));
+ g_assert_true (strinfo_is_string_valid (strinfo, length, "foo"));
+ g_assert_true (strinfo_is_string_valid (strinfo, length, "bar"));
+ g_assert_false (strinfo_is_string_valid (strinfo, length, "baz"));
+ g_assert_false (strinfo_is_string_valid (strinfo, length, "quux"));
}
static void
@@ -2152,13 +2161,13 @@ test_range (void)
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
value = g_variant_new_int32 (1);
- g_assert (!g_settings_range_check (settings, "val", value));
+ g_assert_false (g_settings_range_check (settings, "val", value));
g_variant_unref (value);
value = g_variant_new_int32 (33);
- g_assert (g_settings_range_check (settings, "val", value));
+ g_assert_true (g_settings_range_check (settings, "val", value));
g_variant_unref (value);
value = g_variant_new_int32 (45);
- g_assert (!g_settings_range_check (settings, "val", value));
+ g_assert_false (g_settings_range_check (settings, "val", value));
g_variant_unref (value);
G_GNUC_END_IGNORE_DEPRECATIONS
@@ -2224,8 +2233,8 @@ test_list_items (void)
children = g_settings_list_children (settings);
keys = g_settings_schema_list_keys (schema);
- g_assert (strv_set_equal (children, "basic-types", "complex-types", "localized", NULL));
- g_assert (strv_set_equal (keys, "greeting", "farewell", NULL));
+ g_assert_true (strv_set_equal (children, "basic-types", "complex-types", "localized", NULL));
+ g_assert_true (strv_set_equal (keys, "greeting", "farewell", NULL));
g_strfreev (children);
g_strfreev (keys);
@@ -2245,26 +2254,26 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
schemas = g_settings_list_schemas ();
G_GNUC_END_IGNORE_DEPRECATIONS
- g_assert (strv_set_equal ((gchar **)relocs,
- "org.gtk.test.no-path",
- "org.gtk.test.extends.base",
- "org.gtk.test.extends.extended",
- NULL));
-
- g_assert (strv_set_equal ((gchar **)schemas,
- "org.gtk.test",
- "org.gtk.test.basic-types",
- "org.gtk.test.complex-types",
- "org.gtk.test.localized",
- "org.gtk.test.binding",
- "org.gtk.test.enums",
- "org.gtk.test.enums.direct",
- "org.gtk.test.range",
- "org.gtk.test.range.direct",
- "org.gtk.test.mapped",
- "org.gtk.test.descriptions",
- "org.gtk.test.per-desktop",
- NULL));
+ g_assert_true (strv_set_equal ((gchar **)relocs,
+ "org.gtk.test.no-path",
+ "org.gtk.test.extends.base",
+ "org.gtk.test.extends.extended",
+ NULL));
+
+ g_assert_true (strv_set_equal ((gchar **)schemas,
+ "org.gtk.test",
+ "org.gtk.test.basic-types",
+ "org.gtk.test.complex-types",
+ "org.gtk.test.localized",
+ "org.gtk.test.binding",
+ "org.gtk.test.enums",
+ "org.gtk.test.enums.direct",
+ "org.gtk.test.range",
+ "org.gtk.test.range.direct",
+ "org.gtk.test.mapped",
+ "org.gtk.test.descriptions",
+ "org.gtk.test.per-desktop",
+ NULL));
}
static gboolean
@@ -2294,7 +2303,7 @@ map_func (GVariant *value,
}
else
{
- g_assert (value == NULL);
+ g_assert_null (value);
*result = g_variant_new_int32 (5);
return TRUE;
}
@@ -2366,7 +2375,7 @@ test_schema_source (void)
/* make sure it fails properly */
parent = g_settings_schema_source_get_default ();
source = g_settings_schema_source_new_from_directory ("/path/that/does/not/exist", parent, TRUE, &error);
- g_assert (source == NULL);
+ g_assert_null (source);
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
g_clear_error (&error);
@@ -2385,60 +2394,60 @@ test_schema_source (void)
/* create a source with the parent */
source = g_settings_schema_source_new_from_directory ("schema-source", parent, TRUE, &error);
g_assert_no_error (error);
- g_assert (source != NULL);
+ g_assert_nonnull (source);
/* check recursive lookups are working */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
- g_assert (schema != NULL);
+ g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive lookups for non-existent schemas */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", TRUE);
- g_assert (schema == NULL);
+ g_assert_null (schema);
/* check non-recursive for schema that only exists in lower layers */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
- g_assert (schema == NULL);
+ g_assert_null (schema);
/* check non-recursive lookup for non-existent */
schema = g_settings_schema_source_lookup (source, "org.gtk.doesnotexist", FALSE);
- g_assert (schema == NULL);
+ g_assert_null (schema);
/* check non-recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
- g_assert (schema != NULL);
+ g_assert_nonnull (schema);
g_settings_schema_unref (schema);
/* check recursive for schema that exists in toplevel */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
- g_assert (schema != NULL);
+ g_assert_nonnull (schema);
/* try to use it for something */
settings = g_settings_new_full (schema, backend, g_settings_schema_get_path (schema));
g_settings_schema_unref (schema);
enabled = FALSE;
g_settings_get (settings, "enabled", "b", &enabled);
- g_assert (enabled);
+ g_assert_true (enabled);
g_object_unref (settings);
g_settings_schema_source_unref (source);
/* try again, but with no parent */
source = g_settings_schema_source_new_from_directory ("schema-source", NULL, FALSE, NULL);
- g_assert (source != NULL);
+ g_assert_nonnull (source);
/* should not find it this time, even if recursive... */
schema = g_settings_schema_source_lookup (source, "org.gtk.test", FALSE);
- g_assert (schema == NULL);
+ g_assert_null (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.test", TRUE);
- g_assert (schema == NULL);
+ g_assert_null (schema);
/* should still find our own... */
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", TRUE);
- g_assert (schema != NULL);
+ g_assert_nonnull (schema);
g_settings_schema_unref (schema);
schema = g_settings_schema_source_lookup (source, "org.gtk.schemasourcecheck", FALSE);
- g_assert (schema != NULL);
+ g_assert_nonnull (schema);
g_settings_schema_unref (schema);
g_settings_schema_source_unref (source);
@@ -2451,14 +2460,14 @@ test_schema_list_keys (void)
gchar **keys;
GSettingsSchemaSource *src = g_settings_schema_source_get_default ();
GSettingsSchema *schema = g_settings_schema_source_lookup (src, "org.gtk.test", TRUE);
- g_assert (schema != NULL);
+ g_assert_nonnull (schema);
keys = g_settings_schema_list_keys (schema);
- g_assert (strv_set_equal ((gchar **)keys,
- "greeting",
- "farewell",
- NULL));
+ g_assert_true (strv_set_equal ((gchar **)keys,
+ "greeting",
+ "farewell",
+ NULL));
g_strfreev (keys);
g_settings_schema_unref (schema);
@@ -2488,27 +2497,27 @@ test_actions (void)
c1 = c2 = c3 = FALSE;
g_settings_set_string (settings, "test-string", "hello world");
check_and_free (g_action_get_state (string), "'hello world'");
- g_assert (c1 && c2 && !c3);
+ g_assert_true (c1 && c2 && !c3);
c1 = c2 = c3 = FALSE;
g_action_activate (string, g_variant_new_string ("hihi"));
check_and_free (g_settings_get_value (settings, "test-string"), "'hihi'");
- g_assert (c1 && c2 && !c3);
+ g_assert_true (c1 && c2 && !c3);
c1 = c2 = c3 = FALSE;
g_action_change_state (string, g_variant_new_string ("kthxbye"));
check_and_free (g_settings_get_value (settings, "test-string"), "'kthxbye'");
- g_assert (c1 && c2 && !c3);
+ g_assert_true (c1 && c2 && !c3);
c1 = c2 = c3 = FALSE;
g_action_change_state (toggle, g_variant_new_boolean (TRUE));
- g_assert (g_settings_get_boolean (settings, "test-boolean"));
- g_assert (c1 && !c2 && c3);
+ g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
+ g_assert_true (c1 && !c2 && c3);
c1 = c2 = c3 = FALSE;
g_action_activate (toggle, NULL);
- g_assert (!g_settings_get_boolean (settings, "test-boolean"));
- g_assert (c1 && !c2 && c3);
+ g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
+ g_assert_true (c1 && !c2 && c3);
g_object_get (string,
"name", &name,
@@ -2519,9 +2528,9 @@ test_actions (void)
NULL);
g_assert_cmpstr (name, ==, "test-string");
- g_assert (g_variant_type_equal (param_type, G_VARIANT_TYPE_STRING));
- g_assert (enabled);
- g_assert (g_variant_type_equal (state_type, G_VARIANT_TYPE_STRING));
+ g_assert_true (g_variant_type_equal (param_type, G_VARIANT_TYPE_STRING));
+ g_assert_true (enabled);
+ g_assert_true (g_variant_type_equal (state_type, G_VARIANT_TYPE_STRING));
g_assert_cmpstr (g_variant_get_string (state, NULL), ==, "kthxbye");
g_free (name);
@@ -2558,7 +2567,7 @@ test_null_backend (void)
g_free (str);
writable = g_settings_is_writable (settings, "greeting");
- g_assert (!writable);
+ g_assert_false (writable);
g_settings_reset (settings, "greeting");
@@ -2579,7 +2588,7 @@ test_memory_backend (void)
GSettingsBackend *backend;
backend = g_memory_settings_backend_new ();
- g_assert (G_IS_SETTINGS_BACKEND (backend));
+ g_assert_true (G_IS_SETTINGS_BACKEND (backend));
g_object_unref (backend);
}
@@ -2634,7 +2643,7 @@ test_default_value (void)
g_settings_schema_unref (schema);
g_settings_schema_key_ref (key);
- g_assert (g_variant_type_equal (g_settings_schema_key_get_value_type (key), G_VARIANT_TYPE_STRING));
+ g_assert_true (g_variant_type_equal (g_settings_schema_key_get_value_type (key), G_VARIANT_TYPE_STRING));
v = g_settings_schema_key_get_default_value (key);
str = g_variant_get_string (v, NULL);
@@ -2772,7 +2781,7 @@ test_extended_schema (void)
settings = g_settings_new_with_path ("org.gtk.test.extends.extended", "/test/extendes/");
g_object_get (settings, "settings-schema", &schema, NULL);
keys = g_settings_schema_list_keys (schema);
- g_assert (strv_set_equal (keys, "int32", "string", "another-int32", NULL));
+ g_assert_true (strv_set_equal (keys, "int32", "string", "another-int32", NULL));
g_strfreev (keys);
g_object_unref (settings);
g_settings_schema_unref (schema);
@@ -2818,37 +2827,37 @@ main (int argc, char *argv[])
g_remove ("org.gtk.test.enums.xml");
/* #GLIB_MKENUMS is defined in meson.build */
- g_assert (g_spawn_command_line_sync (GLIB_MKENUMS " "
- "--template " SRCDIR "/enums.xml.template "
- SRCDIR "/testenum.h",
- &enums, NULL, &result, NULL));
- g_assert (result == 0);
- g_assert (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
+ g_assert_true (g_spawn_command_line_sync (GLIB_MKENUMS " "
+ "--template " SRCDIR "/enums.xml.template "
+ SRCDIR "/testenum.h",
+ &enums, NULL, &result, NULL));
+ g_assert_cmpint (result, ==, 0);
+ g_assert_true (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
g_free (enums);
- g_assert (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.xml.orig", &schema_text, NULL, NULL));
- g_assert (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL));
+ g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.xml.orig", &schema_text, NULL, NULL));
+ g_assert_true (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL));
g_free (schema_text);
- g_assert (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL));
- g_assert (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL));
+ g_assert_true (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL));
+ g_assert_true (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL));
g_free (override_text);
g_remove ("gschemas.compiled");
/* #GLIB_COMPILE_SCHEMAS is defined in meson.build */
- g_assert (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. "
- "--schema-file=org.gtk.test.enums.xml "
- "--schema-file=org.gtk.test.gschema.xml "
- "--override-file=org.gtk.test.gschema.override",
- NULL, NULL, &result, NULL));
- g_assert (result == 0);
+ g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. "
+ "--schema-file=org.gtk.test.enums.xml "
+ "--schema-file=org.gtk.test.gschema.xml "
+ "--override-file=org.gtk.test.gschema.override",
+ NULL, NULL, &result, NULL));
+ g_assert_cmpint (result, ==, 0);
g_remove ("schema-source/gschemas.compiled");
g_mkdir ("schema-source", 0777);
- g_assert (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=schema-source "
- "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
- NULL, NULL, &result, NULL));
- g_assert (result == 0);
+ g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=schema-source "
+ "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
+ NULL, NULL, &result, NULL));
+ g_assert_cmpint (result, ==, 0);
g_remove ("schema-source-corrupt/gschemas.compiled");
g_mkdir ("schema-source-corrupt", 0777);
diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c
index 431828384..f0b36b764 100644
--- a/gio/tests/gsubprocess.c
+++ b/gio/tests/gsubprocess.c
@@ -8,12 +8,20 @@
#include <gio/gfiledescriptorbased.h>
#endif
+/* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
+ * ultimately
+ */
+#define TOTAL_HELLOS 2047
+#define HELLO_WORLD "hello world!\n"
+
#ifdef G_OS_WIN32
#define LINEEND "\r\n"
#define EXEEXT ".exe"
+#define SPLICELEN (TOTAL_HELLOS * (strlen (HELLO_WORLD) + 1)) /* because \r */
#else
#define LINEEND "\n"
#define EXEEXT
+#define SPLICELEN (TOTAL_HELLOS * strlen (HELLO_WORLD))
#endif
static GPtrArray *
@@ -557,10 +565,7 @@ on_idle_multisplice (gpointer user_data)
{
TestMultiSpliceData *data = user_data;
- /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
- * ultimately
- */
- if (data->counter >= 2047 || data->caught_error)
+ if (data->counter >= TOTAL_HELLOS || data->caught_error)
{
if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
data->caught_error = TRUE;
@@ -577,8 +582,8 @@ on_idle_multisplice (gpointer user_data)
for (i = 0; i < data->counter; i++)
{
gsize bytes_written;
- if (!g_output_stream_write_all (data->first_stdin, "hello world!\n",
- strlen ("hello world!\n"), &bytes_written,
+ if (!g_output_stream_write_all (data->first_stdin, HELLO_WORLD,
+ strlen (HELLO_WORLD), &bytes_written,
NULL, &data->error))
{
data->caught_error = TRUE;
@@ -684,7 +689,7 @@ test_multi_1 (void)
g_assert (!data.caught_error);
g_assert_no_error (data.error);
- g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, 26611);
+ g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, SPLICELEN);
g_main_loop_unref (data.loop);
g_object_unref (membuf);
@@ -732,7 +737,7 @@ on_communicate_complete (GObject *proc,
else
stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
- g_assert_cmpmem (stdout_data, stdout_len, "# hello world\n", 14);
+ g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
}
else
{
@@ -834,7 +839,7 @@ test_communicate (gconstpointer test_data)
if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
{
stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
- g_assert_cmpmem (stdout_data, stdout_len, "# hello world\n", 14);
+ g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
}
else
g_assert_null (stdout_bytes);
@@ -1110,7 +1115,7 @@ test_communicate_utf8 (gconstpointer test_data)
g_assert_no_error (error);
if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
- g_assert_cmpstr (stdout_buf, ==, "# hello world\n");
+ g_assert_cmpstr (stdout_buf, ==, "# hello world" LINEEND);
else
g_assert_null (stdout_buf);
if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
@@ -1358,9 +1363,10 @@ test_env (void)
GPtrArray *args;
GInputStream *stdout_stream;
gchar *result;
- gchar *envp[] = { "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
+ gchar *envp[] = { NULL, "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
gchar **split;
+ envp[0] = g_strdup_printf ("PATH=%s", g_getenv ("PATH"));
args = get_test_subprocess_args ("env", NULL);
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
@@ -1374,11 +1380,12 @@ test_env (void)
proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
g_ptr_array_free (args, TRUE);
g_assert_no_error (local_error);
+ g_free (envp[0]);
stdout_stream = g_subprocess_get_stdout_pipe (proc);
result = splice_to_string (stdout_stream, error);
- split = g_strsplit (result, "\n", -1);
+ split = g_strsplit (result, LINEEND, -1);
g_assert_cmpstr (g_environ_getenv (split, "ONE"), ==, "1");
g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
g_assert_cmpstr (g_environ_getenv (split, "THREE"), ==, "3");
@@ -1425,7 +1432,7 @@ test_env_inherit (void)
stdout_stream = g_subprocess_get_stdout_pipe (proc);
result = splice_to_string (stdout_stream, error);
- split = g_strsplit (result, "\n", -1);
+ split = g_strsplit (result, LINEEND, -1);
g_assert_null (g_environ_getenv (split, "TEST_ENV_INHERIT1"));
g_assert_cmpstr (g_environ_getenv (split, "TEST_ENV_INHERIT2"), ==, "2");
g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
@@ -1447,11 +1454,15 @@ test_cwd (void)
GInputStream *stdout_stream;
gchar *result;
const char *basename;
+ gchar *tmp_lineend;
+ const gchar *tmp_lineend_basename;
args = get_test_subprocess_args ("cwd", NULL);
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
- g_subprocess_launcher_set_cwd (launcher, "/tmp");
+ g_subprocess_launcher_set_cwd (launcher, g_get_tmp_dir ());
+ tmp_lineend = g_strdup_printf ("%s%s", g_get_tmp_dir (), LINEEND);
+ tmp_lineend_basename = g_strrstr (tmp_lineend, G_DIR_SEPARATOR_S);
proc = g_subprocess_launcher_spawnv (launcher, (const char * const *)args->pdata, error);
g_ptr_array_free (args, TRUE);
@@ -1461,9 +1472,10 @@ test_cwd (void)
result = splice_to_string (stdout_stream, error);
- basename = g_strrstr (result, "/");
+ basename = g_strrstr (result, G_DIR_SEPARATOR_S);
g_assert (basename != NULL);
- g_assert_cmpstr (basename, ==, "/tmp" LINEEND);
+ g_assert_cmpstr (basename, ==, tmp_lineend_basename);
+ g_free (tmp_lineend);
g_free (result);
g_object_unref (proc);
@@ -1719,7 +1731,7 @@ test_launcher_environment (void)
g_subprocess_communicate_utf8 (proc, NULL, NULL, &out, NULL, &error);
g_assert_no_error (error);
- g_assert_cmpstr (out, ==, "C=D\nE=F\n");
+ g_assert_cmpstr (out, ==, "C=D" LINEEND "E=F" LINEEND);
g_free (out);
g_object_unref (proc);
diff --git a/gio/tests/meson.build b/gio/tests/meson.build
index 8bf555cf2..a1b41872d 100644
--- a/gio/tests/meson.build
+++ b/gio/tests/meson.build
@@ -55,7 +55,7 @@ gio_tests = {
'memory-output-stream' : {},
'monitor' : {},
'mount-operation' : {},
- 'network-address' : {'extra_sources': ['mock-resolver.c'], 'suite': ['flaky']},
+ 'network-address' : {'extra_sources': ['mock-resolver.c']},
'network-monitor' : {},
'network-monitor-race' : {},
'permission' : {},
@@ -67,7 +67,7 @@ gio_tests = {
'sleepy-stream' : {},
'socket' : {},
'socket-listener' : {},
- 'socket-service' : {},
+ 'socket-service' : { 'suite': ['flaky'] },
'srvtarget' : {},
'task' : {},
'vfs' : {},
@@ -140,11 +140,16 @@ if host_machine.system() != 'windows'
'slow-connect-preload.c',
name_prefix : '',
dependencies: cc.find_library('dl'),
+ install_dir : installed_tests_execdir,
+ install: installed_tests_enabled,
)
],
'env' : {
'LD_PRELOAD': '@0@/slow-connect-preload.so'.format(meson.current_build_dir())
},
+ 'installed_tests_env' : {
+ 'LD_PRELOAD': '@0@/slow-connect-preload.so'.format(installed_tests_execdir),
+ },
'suite': ['flaky'],
},
'gschema-compile' : {'install' : false},
@@ -428,6 +433,7 @@ if installed_tests_enabled
'appinfo-test-static.desktop',
'file.c',
'org.gtk.test.dbusappinfo.desktop',
+ 'test1.overlay',
install_dir : installed_tests_execdir,
)
install_subdir('x-content', install_dir : installed_tests_execdir)
@@ -592,11 +598,21 @@ foreach test_name, extra_args : gio_tests
source = extra_args.get('source', test_name + '.c')
extra_sources = extra_args.get('extra_sources', [])
install = installed_tests_enabled and extra_args.get('install', true)
+ installed_tests_env = extra_args.get('installed_tests_env', {})
if install
test_conf = configuration_data()
test_conf.set('installed_tests_dir', installed_tests_execdir)
test_conf.set('program', test_name)
+ test_env_override = ''
+ if installed_tests_env != {}
+ envs = []
+ foreach var, value : installed_tests_env
+ envs += '@0@=@1@'.format(var, value)
+ endforeach
+ test_env_override = '@0@ @1@ '.format(env_program.path(), ' '.join(envs))
+ endif
+ test_conf.set('env', test_env_override)
configure_file(
input: installed_tests_template_tap,
output: test_name + '.test',
diff --git a/gio/tests/network-address.c b/gio/tests/network-address.c
index 4a2718e24..c62afccd2 100644
--- a/gio/tests/network-address.c
+++ b/gio/tests/network-address.c
@@ -271,6 +271,7 @@ find_ifname_and_index (void)
static void
test_scope_id (GSocketConnectable *addr)
{
+#ifndef G_OS_WIN32
GSocketAddressEnumerator *addr_enum;
GSocketAddress *saddr;
GInetSocketAddress *isaddr;
@@ -300,6 +301,9 @@ test_scope_id (GSocketConnectable *addr)
g_assert (saddr == NULL);
g_object_unref (addr_enum);
+#else
+ g_test_skip ("winsock2 getaddrinfo() can’t understand scope IDs");
+#endif
}
static void
@@ -622,13 +626,16 @@ happy_eyeballs_teardown (HappyEyeballsFixture *fixture,
g_main_loop_unref (fixture->loop);
}
+static const guint FAST_DELAY_LESS_THAN_TIMEOUT = 25;
+static const guint SLOW_DELAY_MORE_THAN_TIMEOUT = 100;
+
static void
test_happy_eyeballs_basic (HappyEyeballsFixture *fixture,
gconstpointer user_data)
{
AsyncData data = { 0 };
- data.delay_ms = 10;
+ data.delay_ms = FAST_DELAY_LESS_THAN_TIMEOUT;
data.loop = fixture->loop;
/* This just tests in the common case it gets all results */
@@ -645,15 +652,15 @@ test_happy_eyeballs_slow_ipv4 (HappyEyeballsFixture *fixture,
{
AsyncData data = { 0 };
- /* If ipv4 dns response is a bit slow we just don't get them */
+ /* If ipv4 dns response is a bit slow we still get everything */
data.loop = fixture->loop;
- mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, 25);
+ mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
- assert_list_matches_expected (data.addrs, fixture->input_ipv6_results);
+ assert_list_matches_expected (data.addrs, fixture->input_all_results);
}
static void
@@ -665,7 +672,7 @@ test_happy_eyeballs_slow_ipv6 (HappyEyeballsFixture *fixture,
/* If ipv6 is a bit slow it waits for them */
data.loop = fixture->loop;
- mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, 25);
+ mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
@@ -679,15 +686,15 @@ test_happy_eyeballs_very_slow_ipv6 (HappyEyeballsFixture *fixture,
{
AsyncData data = { 0 };
- /* If ipv6 is very slow we don't get them */
+ /* If ipv6 is very slow we still get everything */
data.loop = fixture->loop;
- mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, 200);
+ mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, SLOW_DELAY_MORE_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
- assert_list_matches_expected (data.addrs, fixture->input_ipv4_results);
+ assert_list_matches_expected (data.addrs, fixture->input_all_results);
}
static void
@@ -700,8 +707,8 @@ test_happy_eyeballs_slow_connection_and_ipv4 (HappyEyeballsFixture *fixture,
* take long enough. */
data.loop = fixture->loop;
- data.delay_ms = 500;
- mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, 200);
+ data.delay_ms = SLOW_DELAY_MORE_THAN_TIMEOUT * 2;
+ mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, SLOW_DELAY_MORE_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
@@ -710,17 +717,18 @@ test_happy_eyeballs_slow_connection_and_ipv4 (HappyEyeballsFixture *fixture,
}
static void
-test_happy_eyeballs_ipv6_error (HappyEyeballsFixture *fixture,
- gconstpointer user_data)
+test_happy_eyeballs_ipv6_error_ipv4_first (HappyEyeballsFixture *fixture,
+ gconstpointer user_data)
{
AsyncData data = { 0 };
GError *ipv6_error;
- /* If ipv6 fails we still get ipv4. */
+ /* If ipv6 fails, ensuring that ipv4 finishes before ipv6 errors, we still get ipv4. */
data.loop = fixture->loop;
ipv6_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
+ mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
@@ -731,17 +739,62 @@ test_happy_eyeballs_ipv6_error (HappyEyeballsFixture *fixture,
}
static void
-test_happy_eyeballs_ipv4_error (HappyEyeballsFixture *fixture,
- gconstpointer user_data)
+test_happy_eyeballs_ipv6_error_ipv6_first (HappyEyeballsFixture *fixture,
+ gconstpointer user_data)
+{
+ AsyncData data = { 0 };
+ GError *ipv6_error;
+
+ /* If ipv6 fails, ensuring that ipv6 errors before ipv4 finishes, we still get ipv4. */
+
+ data.loop = fixture->loop;
+ ipv6_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
+ mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
+ mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
+
+ g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
+ g_main_loop_run (fixture->loop);
+
+ assert_list_matches_expected (data.addrs, fixture->input_ipv4_results);
+
+ g_error_free (ipv6_error);
+}
+
+static void
+test_happy_eyeballs_ipv4_error_ipv4_first (HappyEyeballsFixture *fixture,
+ gconstpointer user_data)
+{
+ AsyncData data = { 0 };
+ GError *ipv4_error;
+
+ /* If ipv4 fails, ensuring that ipv4 errors before ipv6 finishes, we still get ipv6. */
+
+ data.loop = fixture->loop;
+ ipv4_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
+ mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
+ mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
+
+ g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
+ g_main_loop_run (fixture->loop);
+
+ assert_list_matches_expected (data.addrs, fixture->input_ipv6_results);
+
+ g_error_free (ipv4_error);
+}
+
+static void
+test_happy_eyeballs_ipv4_error_ipv6_first (HappyEyeballsFixture *fixture,
+ gconstpointer user_data)
{
AsyncData data = { 0 };
GError *ipv4_error;
- /* If ipv4 fails we still get ipv6. */
+ /* If ipv4 fails, ensuring that ipv6 finishes before ipv4 errors, we still get ipv6. */
data.loop = fixture->loop;
ipv4_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
+ mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
@@ -792,7 +845,7 @@ test_happy_eyeballs_both_error_delays_1 (HappyEyeballsFixture *fixture,
ipv6_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
- mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, 25);
+ mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
@@ -820,7 +873,7 @@ test_happy_eyeballs_both_error_delays_2 (HappyEyeballsFixture *fixture,
mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
- mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, 25);
+ mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
@@ -847,7 +900,7 @@ test_happy_eyeballs_both_error_delays_3 (HappyEyeballsFixture *fixture,
mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
- mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, 200);
+ mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, SLOW_DELAY_MORE_THAN_TIMEOUT);
g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
g_main_loop_run (fixture->loop);
@@ -913,10 +966,14 @@ main (int argc, char *argv[])
happy_eyeballs_setup, test_happy_eyeballs_very_slow_ipv6, happy_eyeballs_teardown);
g_test_add ("/network-address/happy-eyeballs/slow-connection-and-ipv4", HappyEyeballsFixture, NULL,
happy_eyeballs_setup, test_happy_eyeballs_slow_connection_and_ipv4, happy_eyeballs_teardown);
- g_test_add ("/network-address/happy-eyeballs/ipv6-error", HappyEyeballsFixture, NULL,
- happy_eyeballs_setup, test_happy_eyeballs_ipv6_error, happy_eyeballs_teardown);
- g_test_add ("/network-address/happy-eyeballs/ipv4-error", HappyEyeballsFixture, NULL,
- happy_eyeballs_setup, test_happy_eyeballs_ipv4_error, happy_eyeballs_teardown);
+ g_test_add ("/network-address/happy-eyeballs/ipv6-error-ipv4-first", HappyEyeballsFixture, NULL,
+ happy_eyeballs_setup, test_happy_eyeballs_ipv6_error_ipv4_first, happy_eyeballs_teardown);
+ g_test_add ("/network-address/happy-eyeballs/ipv6-error-ipv6-first", HappyEyeballsFixture, NULL,
+ happy_eyeballs_setup, test_happy_eyeballs_ipv6_error_ipv6_first, happy_eyeballs_teardown);
+ g_test_add ("/network-address/happy-eyeballs/ipv4-error-ipv6-first", HappyEyeballsFixture, NULL,
+ happy_eyeballs_setup, test_happy_eyeballs_ipv4_error_ipv6_first, happy_eyeballs_teardown);
+ g_test_add ("/network-address/happy-eyeballs/ipv4-error-ipv4-first", HappyEyeballsFixture, NULL,
+ happy_eyeballs_setup, test_happy_eyeballs_ipv4_error_ipv4_first, happy_eyeballs_teardown);
g_test_add ("/network-address/happy-eyeballs/both-error", HappyEyeballsFixture, NULL,
happy_eyeballs_setup, test_happy_eyeballs_both_error, happy_eyeballs_teardown);
g_test_add ("/network-address/happy-eyeballs/both-error-delays-1", HappyEyeballsFixture, NULL,
diff --git a/gio/tests/task.c b/gio/tests/task.c
index db1b2d4fe..9f7ae2563 100644
--- a/gio/tests/task.c
+++ b/gio/tests/task.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Red Hat, Inc.
+ * Copyright 2012-2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -654,6 +654,151 @@ name_callback (GObject *object,
g_main_loop_quit (loop);
}
+/* test_asynchronous_cancellation: cancelled tasks are returned
+ * asynchronously, i.e. not from inside the GCancellable::cancelled
+ * handler.
+ *
+ * The test is set up further below in test_asynchronous_cancellation.
+ */
+
+/* asynchronous_cancellation_callback represents the callback that the
+ * caller of a typical asynchronous API would have passed. See
+ * test_asynchronous_cancellation.
+ */
+static void
+asynchronous_cancellation_callback (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ guint run_task_id;
+
+ g_assert_null (object);
+ g_assert_true (g_task_is_valid (result, object));
+ g_assert_true (g_async_result_get_user_data (result) == user_data);
+ g_assert_true (g_task_had_error (G_TASK (result)));
+ g_assert_false (g_task_get_completed (G_TASK (result)));
+
+ run_task_id = GPOINTER_TO_UINT (g_task_get_task_data (G_TASK (result)));
+ g_assert_cmpuint (run_task_id, ==, 0);
+
+ g_task_propagate_boolean (G_TASK (result), &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_clear_error (&error);
+
+ g_assert_true (g_task_had_error (G_TASK (result)));
+
+ g_main_loop_quit (loop);
+}
+
+/* asynchronous_cancellation_cancel_task represents a user cancelling
+ * the ongoing operation. To make it somewhat realistic it is delayed
+ * by 50ms via a timeout GSource. See test_asynchronous_cancellation.
+ */
+static gboolean
+asynchronous_cancellation_cancel_task (gpointer user_data)
+{
+ GCancellable *cancellable;
+ GTask *task = G_TASK (user_data);
+
+ cancellable = g_task_get_cancellable (task);
+ g_assert_true (G_IS_CANCELLABLE (cancellable));
+
+ g_cancellable_cancel (cancellable);
+ g_assert_false (g_task_get_completed (task));
+
+ return G_SOURCE_REMOVE;
+}
+
+/* asynchronous_cancellation_cancelled is the GCancellable::cancelled
+ * handler that's used by the asynchronous implementation for
+ * cancelling itself.
+ */
+static void
+asynchronous_cancellation_cancelled (GCancellable *cancellable,
+ gpointer user_data)
+{
+ GTask *task = G_TASK (user_data);
+ guint run_task_id;
+
+ g_assert_true (cancellable == g_task_get_cancellable (task));
+
+ run_task_id = GPOINTER_TO_UINT (g_task_get_task_data (task));
+ g_assert_cmpuint (run_task_id, !=, 0);
+
+ g_source_remove (run_task_id);
+ g_task_set_task_data (task, GUINT_TO_POINTER (0), NULL);
+
+ g_task_return_boolean (task, FALSE);
+ g_assert_false (g_task_get_completed (task));
+}
+
+/* asynchronous_cancellation_run_task represents the actual
+ * asynchronous work being done in an idle GSource as was mentioned
+ * above. This is effectively meant to be an infinite loop so that
+ * the only way to break out of it is via cancellation.
+ */
+static gboolean
+asynchronous_cancellation_run_task (gpointer user_data)
+{
+ GCancellable *cancellable;
+ GTask *task = G_TASK (user_data);
+
+ cancellable = g_task_get_cancellable (task);
+ g_assert_true (G_IS_CANCELLABLE (cancellable));
+ g_assert_false (g_cancellable_is_cancelled (cancellable));
+
+ return G_SOURCE_CONTINUE;
+}
+
+/* Test that cancellation is always asynchronous. The completion callback for
+ * a #GTask must not be called from inside the cancellation handler.
+ *
+ * The body of the loop inside test_asynchronous_cancellation
+ * represents what would have been a typical asynchronous API call,
+ * and its implementation. They are fused together without an API
+ * boundary. The actual work done by this asynchronous API is
+ * represented by an idle GSource.
+ */
+static void
+test_asynchronous_cancellation (void)
+{
+ guint i;
+
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1608");
+
+ /* Run a few times to shake out any timing issues between the
+ * cancellation and task sources.
+ */
+ for (i = 0; i < 5; i++)
+ {
+ GCancellable *cancellable;
+ GTask *task;
+ gboolean notification_emitted = FALSE;
+ guint run_task_id;
+
+ cancellable = g_cancellable_new ();
+
+ task = g_task_new (NULL, cancellable, asynchronous_cancellation_callback, NULL);
+ g_cancellable_connect (cancellable, (GCallback) asynchronous_cancellation_cancelled, task, NULL);
+ g_signal_connect (task, "notify::completed", (GCallback) completed_cb, &notification_emitted);
+
+ run_task_id = g_idle_add (asynchronous_cancellation_run_task, task);
+ g_source_set_name_by_id (run_task_id, "[test_asynchronous_cancellation] run_task");
+ g_task_set_task_data (task, GUINT_TO_POINTER (run_task_id), NULL);
+
+ g_timeout_add (50, asynchronous_cancellation_cancel_task, task);
+
+ g_main_loop_run (loop);
+
+ g_assert_true (g_task_get_completed (task));
+ g_assert_true (notification_emitted);
+
+ g_object_unref (cancellable);
+ g_object_unref (task);
+ }
+}
+
/* test_check_cancellable: cancellation overrides return value */
enum {
@@ -2186,6 +2331,7 @@ main (int argc, char **argv)
g_test_add_func ("/gtask/report-error", test_report_error);
g_test_add_func ("/gtask/priority", test_priority);
g_test_add_func ("/gtask/name", test_name);
+ g_test_add_func ("/gtask/asynchronous-cancellation", test_asynchronous_cancellation);
g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
diff --git a/gio/win32/gwinhttpvfs.c b/gio/win32/gwinhttpvfs.c
index d32a4cbe1..038368f81 100644
--- a/gio/win32/gwinhttpvfs.c
+++ b/gio/win32/gwinhttpvfs.c
@@ -173,7 +173,7 @@ g_winhttp_vfs_get_file_for_uri (GVfs *vfs,
return _g_winhttp_file_new (winhttp_vfs, uri);
/* For other URIs fallback to the wrapped GVfs */
- return g_vfs_parse_name (winhttp_vfs->wrapped_vfs, uri);
+ return g_vfs_get_file_for_uri (winhttp_vfs->wrapped_vfs, uri);
}
static const gchar * const *