mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
gio/tests/task: Ensure that cancelled tasks are returned asynchronously
Closes https://gitlab.gnome.org/GNOME/glib/issues/1608
This commit is contained in:
parent
6f3d57d2ee
commit
381af21072
115
gio/tests/task.c
115
gio/tests/task.c
@ -654,6 +654,120 @@ 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.
|
||||
*/
|
||||
|
||||
static void
|
||||
asynchronous_cancellation_callback (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
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)));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
if (run_task_id != 0)
|
||||
g_source_remove (run_task_id);
|
||||
|
||||
g_task_return_boolean (task, FALSE);
|
||||
g_assert_false (g_task_get_completed (task));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
g_task_set_task_data (task, GUINT_TO_POINTER (0), NULL);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/* Test that cancellation is always asynchronous. The completion callback for
|
||||
* a #GTask must not be called from inside the cancellation handler. */
|
||||
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, ¬ification_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 +2300,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);
|
||||
|
Loading…
Reference in New Issue
Block a user