gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / gio / tests / task.c
1 /*
2  * Copyright 2012-2019 Red Hat, Inc.
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * See the included COPYING file for more information.
12  */
13
14 #include <gio/gio.h>
15 #include <string.h>
16
17 static GMainLoop *loop;
18 static GThread *main_thread;
19 static gssize magic;
20
21 /* We need objects for a few tests where we don't care what type
22  * they are, just that they're GObjects.
23  */
24 #define g_dummy_object_new g_socket_client_new
25
26 static gboolean
27 idle_quit_loop (gpointer user_data)
28 {
29   g_main_loop_quit (loop);
30   return FALSE;
31 }
32
33 static void
34 completed_cb (GObject    *gobject,
35               GParamSpec *pspec,
36               gpointer    user_data)
37 {
38         gboolean *notification_emitted = user_data;
39         *notification_emitted = TRUE;
40 }
41
42 static void
43 wait_for_completed_notification (GTask *task)
44 {
45   gboolean notification_emitted = FALSE;
46   gboolean is_completed = FALSE;
47
48   /* Hold a ref. so we can check the :completed property afterwards. */
49   g_object_ref (task);
50
51   g_signal_connect (task, "notify::completed",
52                     (GCallback) completed_cb, &notification_emitted);
53   g_idle_add (idle_quit_loop, NULL);
54   g_main_loop_run (loop);
55   g_assert_true (notification_emitted);
56
57   g_assert_true (g_task_get_completed (task));
58   g_object_get (G_OBJECT (task), "completed", &is_completed, NULL);
59   g_assert_true (is_completed);
60
61   g_object_unref (task);
62 }
63
64 /* test_basic */
65
66 static void
67 basic_callback (GObject      *object,
68                 GAsyncResult *result,
69                 gpointer      user_data)
70 {
71   gssize *result_out = user_data;
72   GError *error = NULL;
73
74   g_assert (object == NULL);
75   g_assert (g_task_is_valid (result, object));
76   g_assert (g_async_result_get_user_data (result) == user_data);
77   g_assert (!g_task_had_error (G_TASK (result)));
78   g_assert_false (g_task_get_completed (G_TASK (result)));
79
80   *result_out = g_task_propagate_int (G_TASK (result), &error);
81   g_assert_no_error (error);
82
83   g_assert (!g_task_had_error (G_TASK (result)));
84
85   g_main_loop_quit (loop);
86 }
87
88 static gboolean
89 basic_return (gpointer user_data)
90 {
91   GTask *task = user_data;
92
93   g_task_return_int (task, magic);
94   g_object_unref (task);
95
96   return FALSE;
97 }
98
99 static void
100 basic_destroy_notify (gpointer user_data)
101 {
102   gboolean *destroyed = user_data;
103
104   *destroyed = TRUE;
105 }
106
107 static void
108 test_basic (void)
109 {
110   GTask *task;
111   gssize result;
112   gboolean task_data_destroyed = FALSE;
113   gboolean notification_emitted = FALSE;
114
115   task = g_task_new (NULL, NULL, basic_callback, &result);
116   g_task_set_task_data (task, &task_data_destroyed, basic_destroy_notify);
117   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
118   g_signal_connect (task, "notify::completed",
119                     (GCallback) completed_cb, &notification_emitted);
120
121   g_idle_add (basic_return, task);
122   g_main_loop_run (loop);
123
124   g_assert_cmpint (result, ==, magic);
125   g_assert (task_data_destroyed == TRUE);
126   g_assert_true (notification_emitted);
127   g_assert (task == NULL);
128 }
129
130 /* test_error */
131
132 static void
133 error_callback (GObject      *object,
134                 GAsyncResult *result,
135                 gpointer      user_data)
136 {
137   gssize *result_out = user_data;
138   GError *error = NULL;
139
140   g_assert (object == NULL);
141   g_assert (g_task_is_valid (result, object));
142   g_assert (g_async_result_get_user_data (result) == user_data);
143   g_assert (g_task_had_error (G_TASK (result)));
144   g_assert_false (g_task_get_completed (G_TASK (result)));
145
146   *result_out = g_task_propagate_int (G_TASK (result), &error);
147   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
148   g_error_free (error);
149
150   g_assert (g_task_had_error (G_TASK (result)));
151
152   g_main_loop_quit (loop);
153 }
154
155 static gboolean
156 error_return (gpointer user_data)
157 {
158   GTask *task = user_data;
159
160   g_task_return_new_error (task,
161                            G_IO_ERROR, G_IO_ERROR_FAILED,
162                            "Failed");
163   g_object_unref (task);
164
165   return FALSE;
166 }
167
168 static void
169 error_destroy_notify (gpointer user_data)
170 {
171   gboolean *destroyed = user_data;
172
173   *destroyed = TRUE;
174 }
175
176 static void
177 test_error (void)
178 {
179   GTask *task;
180   gssize result;
181   gboolean first_task_data_destroyed = FALSE;
182   gboolean second_task_data_destroyed = FALSE;
183   gboolean notification_emitted = FALSE;
184
185   task = g_task_new (NULL, NULL, error_callback, &result);
186   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
187   g_signal_connect (task, "notify::completed",
188                     (GCallback) completed_cb, &notification_emitted);
189
190   g_assert (first_task_data_destroyed == FALSE);
191   g_task_set_task_data (task, &first_task_data_destroyed, error_destroy_notify);
192   g_assert (first_task_data_destroyed == FALSE);
193
194   /* Calling g_task_set_task_data() again will destroy the first data */
195   g_task_set_task_data (task, &second_task_data_destroyed, error_destroy_notify);
196   g_assert (first_task_data_destroyed == TRUE);
197   g_assert (second_task_data_destroyed == FALSE);
198
199   g_idle_add (error_return, task);
200   g_main_loop_run (loop);
201
202   g_assert_cmpint (result, ==, -1);
203   g_assert (second_task_data_destroyed == TRUE);
204   g_assert_true (notification_emitted);
205   g_assert (task == NULL);
206 }
207
208 /* test_return_from_same_iteration: calling g_task_return_* from the
209  * loop iteration the task was created in defers completion until the
210  * next iteration.
211  */
212 gboolean same_result = FALSE;
213 gboolean same_notification_emitted = FALSE;
214
215 static void
216 same_callback (GObject      *object,
217                GAsyncResult *result,
218                gpointer      user_data)
219 {
220   gboolean *result_out = user_data;
221   GError *error = NULL;
222
223   g_assert (object == NULL);
224   g_assert (g_task_is_valid (result, object));
225   g_assert (g_async_result_get_user_data (result) == user_data);
226   g_assert (!g_task_had_error (G_TASK (result)));
227   g_assert_false (g_task_get_completed (G_TASK (result)));
228
229   *result_out = g_task_propagate_boolean (G_TASK (result), &error);
230   g_assert_no_error (error);
231
232   g_assert (!g_task_had_error (G_TASK (result)));
233
234   g_main_loop_quit (loop);
235 }
236
237 static gboolean
238 same_start (gpointer user_data)
239 {
240   gpointer *weak_pointer = user_data;
241   GTask *task;
242
243   task = g_task_new (NULL, NULL, same_callback, &same_result);
244   *weak_pointer = task;
245   g_object_add_weak_pointer (G_OBJECT (task), weak_pointer);
246   g_signal_connect (task, "notify::completed",
247                     (GCallback) completed_cb, &same_notification_emitted);
248
249   g_task_return_boolean (task, TRUE);
250   g_object_unref (task);
251
252   /* same_callback should not have been invoked yet */
253   g_assert (same_result == FALSE);
254   g_assert (*weak_pointer == task);
255   g_assert_false (same_notification_emitted);
256
257   return FALSE;
258 }
259
260 static void
261 test_return_from_same_iteration (void)
262 {
263   gpointer weak_pointer;
264
265   g_idle_add (same_start, &weak_pointer);
266   g_main_loop_run (loop);
267
268   g_assert (same_result == TRUE);
269   g_assert (weak_pointer == NULL);
270   g_assert_true (same_notification_emitted);
271 }
272
273 /* test_return_from_toplevel: calling g_task_return_* from outside any
274  * main loop completes the task inside the main loop.
275  */
276 gboolean toplevel_notification_emitted = FALSE;
277
278 static void
279 toplevel_callback (GObject      *object,
280               GAsyncResult *result,
281               gpointer      user_data)
282 {
283   gboolean *result_out = user_data;
284   GError *error = NULL;
285
286   g_assert (object == NULL);
287   g_assert (g_task_is_valid (result, object));
288   g_assert (g_async_result_get_user_data (result) == user_data);
289   g_assert (!g_task_had_error (G_TASK (result)));
290   g_assert_false (g_task_get_completed (G_TASK (result)));
291
292   *result_out = g_task_propagate_boolean (G_TASK (result), &error);
293   g_assert_no_error (error);
294
295   g_assert (!g_task_had_error (G_TASK (result)));
296
297   g_main_loop_quit (loop);
298 }
299
300 static void
301 test_return_from_toplevel (void)
302 {
303   GTask *task;
304   gboolean result = FALSE;
305
306   task = g_task_new (NULL, NULL, toplevel_callback, &result);
307   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
308   g_signal_connect (task, "notify::completed",
309                     (GCallback) completed_cb, &toplevel_notification_emitted);
310
311   g_task_return_boolean (task, TRUE);
312   g_object_unref (task);
313
314   /* toplevel_callback should not have been invoked yet */
315   g_assert (result == FALSE);
316   g_assert (task != NULL);
317   g_assert_false (toplevel_notification_emitted);
318
319   g_main_loop_run (loop);
320
321   g_assert (result == TRUE);
322   g_assert (task == NULL);
323   g_assert_true (toplevel_notification_emitted);
324 }
325
326 /* test_return_from_anon_thread: calling g_task_return_* from a
327  * thread with no thread-default main context will complete the
328  * task in the task's context/thread.
329  */
330
331 gboolean anon_thread_notification_emitted = FALSE;
332 GThread *anon_thread;
333
334 static void
335 anon_callback (GObject      *object,
336                GAsyncResult *result,
337                gpointer      user_data)
338 {
339   gssize *result_out = user_data;
340   GError *error = NULL;
341
342   g_assert (object == NULL);
343   g_assert (g_task_is_valid (result, object));
344   g_assert (g_async_result_get_user_data (result) == user_data);
345   g_assert (!g_task_had_error (G_TASK (result)));
346   g_assert_false (g_task_get_completed (G_TASK (result)));
347
348   g_assert (g_thread_self () == main_thread);
349
350   *result_out = g_task_propagate_int (G_TASK (result), &error);
351   g_assert_no_error (error);
352
353   g_assert (!g_task_had_error (G_TASK (result)));
354
355   g_main_loop_quit (loop);
356 }
357
358 static gpointer
359 anon_thread_func (gpointer user_data)
360 {
361   GTask *task = user_data;
362
363   g_task_return_int (task, magic);
364   g_object_unref (task);
365
366   return NULL;
367 }
368
369 static gboolean
370 anon_start (gpointer user_data)
371 {
372   GTask *task = user_data;
373
374   anon_thread = g_thread_new ("test_return_from_anon_thread",
375                               anon_thread_func, task);
376   return FALSE;
377 }
378
379 static void
380 test_return_from_anon_thread (void)
381 {
382   GTask *task;
383   gssize result = 0;
384
385   task = g_task_new (NULL, NULL, anon_callback, &result);
386   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
387   g_signal_connect (task, "notify::completed",
388                     (GCallback) completed_cb,
389                     &anon_thread_notification_emitted);
390
391   g_idle_add (anon_start, task);
392   g_main_loop_run (loop);
393
394   g_thread_join (anon_thread);
395
396   g_assert_cmpint (result, ==, magic);
397   g_assert (task == NULL);
398   g_assert_true (anon_thread_notification_emitted);
399 }
400
401 /* test_return_from_wrong_thread: calling g_task_return_* from a
402  * thread with its own thread-default main context will complete the
403  * task in the task's context/thread.
404  */
405
406 gboolean wrong_thread_notification_emitted = FALSE;
407 GThread *wrong_thread;
408
409 static void
410 wrong_callback (GObject      *object,
411                GAsyncResult *result,
412                gpointer      user_data)
413 {
414   gssize *result_out = user_data;
415   GError *error = NULL;
416
417   g_assert (object == NULL);
418   g_assert (g_task_is_valid (result, object));
419   g_assert (g_async_result_get_user_data (result) == user_data);
420   g_assert (!g_task_had_error (G_TASK (result)));
421   g_assert_false (g_task_get_completed (G_TASK (result)));
422
423   g_assert (g_thread_self () == main_thread);
424
425   *result_out = g_task_propagate_int (G_TASK (result), &error);
426   g_assert_no_error (error);
427
428   g_assert (!g_task_had_error (G_TASK (result)));
429
430   g_main_loop_quit (loop);
431 }
432
433 static gpointer
434 wrong_thread_func (gpointer user_data)
435 {
436   GTask *task = user_data;
437   GMainContext *context;
438
439   context = g_main_context_new ();
440   g_main_context_push_thread_default (context);
441
442   g_assert (g_task_get_context (task) != context);
443
444   g_task_return_int (task, magic);
445   g_object_unref (task);
446
447   g_main_context_pop_thread_default (context);
448   g_main_context_unref (context);
449
450   return NULL;
451 }
452
453 static gboolean
454 wrong_start (gpointer user_data)
455 {
456   GTask *task = user_data;
457
458   wrong_thread = g_thread_new ("test_return_from_anon_thread",
459                                wrong_thread_func, task);
460   return FALSE;
461 }
462
463 static void
464 test_return_from_wrong_thread (void)
465 {
466   GTask *task;
467   gssize result = 0;
468
469   task = g_task_new (NULL, NULL, wrong_callback, &result);
470   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
471   g_signal_connect (task, "notify::completed",
472                     (GCallback) completed_cb,
473                     &wrong_thread_notification_emitted);
474
475   g_idle_add (wrong_start, task);
476   g_main_loop_run (loop);
477
478   g_thread_join (wrong_thread);
479
480   g_assert_cmpint (result, ==, magic);
481   g_assert (task == NULL);
482   g_assert_true (wrong_thread_notification_emitted);
483 }
484
485 /* test_no_callback */
486
487 static void
488 test_no_callback (void)
489 {
490   GTask *task;
491
492   task = g_task_new (NULL, NULL, NULL, NULL);
493   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
494
495   g_task_return_boolean (task, TRUE);
496   g_object_unref (task);
497
498   /* Even though there’s no callback, the :completed notification has to
499    * happen in an idle handler. */
500   g_assert_nonnull (task);
501   wait_for_completed_notification (task);
502   g_assert_null (task);
503 }
504
505 /* test_report_error */
506
507 static void test_report_error (void);
508 gboolean error_notification_emitted = FALSE;
509
510 static void
511 report_callback (GObject      *object,
512                  GAsyncResult *result,
513                  gpointer      user_data)
514 {
515   gpointer *weak_pointer = user_data;
516   GError *error = NULL;
517   gssize ret;
518
519   g_assert (object == NULL);
520   g_assert (g_task_is_valid (result, object));
521   g_assert (g_async_result_get_user_data (result) == user_data);
522   g_assert (g_async_result_is_tagged (result, test_report_error));
523   g_assert (g_task_get_source_tag (G_TASK (result)) == test_report_error);
524   g_assert (g_task_had_error (G_TASK (result)));
525   g_assert_false (g_task_get_completed (G_TASK (result)));
526
527   ret = g_task_propagate_int (G_TASK (result), &error);
528   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
529   g_assert_cmpint (ret, ==, -1);
530   g_error_free (error);
531
532   g_assert (g_task_had_error (G_TASK (result)));
533
534   *weak_pointer = result;
535   g_object_add_weak_pointer (G_OBJECT (result), weak_pointer);
536   g_signal_connect (result, "notify::completed",
537                     (GCallback) completed_cb, &error_notification_emitted);
538
539   g_main_loop_quit (loop);
540 }
541
542 static void
543 test_report_error (void)
544 {
545   gpointer weak_pointer = (gpointer)-1;
546
547   g_task_report_new_error (NULL, report_callback, &weak_pointer,
548                            test_report_error,
549                            G_IO_ERROR, G_IO_ERROR_FAILED,
550                            "Failed");
551   g_main_loop_run (loop);
552
553   g_assert (weak_pointer == NULL);
554   g_assert_true (error_notification_emitted);
555 }
556
557 /* test_priority: tasks complete in priority order */
558
559 static int counter = 0;
560
561 static void
562 priority_callback (GObject      *object,
563                    GAsyncResult *result,
564                    gpointer      user_data)
565 {
566   gssize *ret_out = user_data;
567   GError *error = NULL;
568
569   g_assert (object == NULL);
570   g_assert (g_task_is_valid (result, object));
571   g_assert (g_async_result_get_user_data (result) == user_data);
572   g_assert (!g_task_had_error (G_TASK (result)));
573   g_assert_false (g_task_get_completed (G_TASK (result)));
574
575   g_task_propagate_boolean (G_TASK (result), &error);
576   g_assert_no_error (error);
577
578   g_assert (!g_task_had_error (G_TASK (result)));
579
580   *ret_out = ++counter;
581
582   if (counter == 3)
583     g_main_loop_quit (loop);
584 }
585
586 static void
587 test_priority (void)
588 {
589   GTask *t1, *t2, *t3;
590   gssize ret1, ret2, ret3;
591
592   /* t2 has higher priority than either t1 or t3, so we can't
593    * accidentally pass the test just by completing the tasks in the
594    * order they were created (or in reverse order).
595    */
596
597   t1 = g_task_new (NULL, NULL, priority_callback, &ret1);
598   g_task_set_priority (t1, G_PRIORITY_DEFAULT);
599   g_task_return_boolean (t1, TRUE);
600   g_object_unref (t1);
601
602   t2 = g_task_new (NULL, NULL, priority_callback, &ret2);
603   g_task_set_priority (t2, G_PRIORITY_HIGH);
604   g_task_return_boolean (t2, TRUE);
605   g_object_unref (t2);
606
607   t3 = g_task_new (NULL, NULL, priority_callback, &ret3);
608   g_task_set_priority (t3, G_PRIORITY_LOW);
609   g_task_return_boolean (t3, TRUE);
610   g_object_unref (t3);
611
612   g_main_loop_run (loop);
613
614   g_assert_cmpint (ret2, ==, 1);
615   g_assert_cmpint (ret1, ==, 2);
616   g_assert_cmpint (ret3, ==, 3);
617 }
618
619 /* Test that getting and setting the task name works. */
620 static void name_callback (GObject      *object,
621                            GAsyncResult *result,
622                            gpointer      user_data);
623
624 static void
625 test_name (void)
626 {
627   GTask *t1 = NULL;
628   char *orig = g_strdup ("some task");
629   gchar *name1 = NULL;
630
631   t1 = g_task_new (NULL, NULL, name_callback, &name1);
632   (g_task_set_name) (t1, orig);
633   g_task_return_boolean (t1, TRUE);
634   g_object_unref (t1);
635
636   g_main_loop_run (loop);
637
638   g_assert_cmpstr (name1, ==, orig);
639
640   g_free (name1);
641   g_free (orig);
642 }
643
644 static void
645 test_name_macro_wrapper (void)
646 {
647   GTask *t1 = NULL;
648   char *orig = g_strdup ("some task");
649   gchar *name1 = NULL;
650
651   t1 = g_task_new (NULL, NULL, name_callback, &name1);
652   g_task_set_name (t1, orig);
653   g_task_return_boolean (t1, TRUE);
654   g_object_unref (t1);
655
656   g_main_loop_run (loop);
657
658   g_assert_cmpstr (name1, ==, orig);
659
660   g_free (name1);
661   g_free (orig);
662 }
663
664 static void
665 name_callback (GObject      *object,
666                GAsyncResult *result,
667                gpointer      user_data)
668 {
669   gchar **name_out = user_data;
670   GError *local_error = NULL;
671
672   g_assert_null (*name_out);
673   *name_out = g_strdup (g_task_get_name (G_TASK (result)));
674
675   g_task_propagate_boolean (G_TASK (result), &local_error);
676   g_assert_no_error (local_error);
677
678   g_main_loop_quit (loop);
679 }
680
681 static void static_name_callback (GObject      *object,
682                                   GAsyncResult *result,
683                                   gpointer      user_data);
684
685 static void
686 test_static_name (void)
687 {
688   GTask *t1 = NULL;
689   char *orig = "some task";
690   char *name1 = NULL;
691
692   t1 = g_task_new (NULL, NULL, static_name_callback, &name1);
693   g_task_set_static_name (t1, orig);
694   g_task_return_boolean (t1, TRUE);
695   g_object_unref (t1);
696
697   g_main_loop_run (loop);
698
699   g_assert_true (name1 == orig);
700 }
701
702 static void
703 static_name_callback (GObject      *object,
704                       GAsyncResult *result,
705                       gpointer      user_data)
706 {
707   const char **name_out = user_data;
708   GError *local_error = NULL;
709
710   g_assert_null (*name_out);
711   *name_out = g_task_get_name (G_TASK (result));
712
713   g_task_propagate_boolean (G_TASK (result), &local_error);
714   g_assert_no_error (local_error);
715
716   g_main_loop_quit (loop);
717 }
718
719 /* test_asynchronous_cancellation: cancelled tasks are returned
720  * asynchronously, i.e. not from inside the GCancellable::cancelled
721  * handler.
722  *
723  * The test is set up further below in test_asynchronous_cancellation.
724  */
725
726 /* asynchronous_cancellation_callback represents the callback that the
727  * caller of a typical asynchronous API would have passed. See
728  * test_asynchronous_cancellation.
729  */
730 static void
731 asynchronous_cancellation_callback (GObject      *object,
732                                     GAsyncResult *result,
733                                     gpointer      user_data)
734 {
735   GError *error = NULL;
736   guint run_task_id;
737
738   g_assert_null (object);
739   g_assert_true (g_task_is_valid (result, object));
740   g_assert_true (g_async_result_get_user_data (result) == user_data);
741   g_assert_true (g_task_had_error (G_TASK (result)));
742   g_assert_false (g_task_get_completed (G_TASK (result)));
743
744   run_task_id = GPOINTER_TO_UINT (g_task_get_task_data (G_TASK (result)));
745   g_assert_cmpuint (run_task_id, ==, 0);
746
747   g_task_propagate_boolean (G_TASK (result), &error);
748   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
749   g_clear_error (&error);
750
751   g_assert_true (g_task_had_error (G_TASK (result)));
752
753   g_main_loop_quit (loop);
754 }
755
756 /* asynchronous_cancellation_cancel_task represents a user cancelling
757  * the ongoing operation. To make it somewhat realistic it is delayed
758  * by 50ms via a timeout GSource. See test_asynchronous_cancellation.
759  */
760 static gboolean
761 asynchronous_cancellation_cancel_task (gpointer user_data)
762 {
763   GCancellable *cancellable;
764   GTask *task = G_TASK (user_data);
765
766   cancellable = g_task_get_cancellable (task);
767   g_assert_true (G_IS_CANCELLABLE (cancellable));
768
769   g_cancellable_cancel (cancellable);
770   g_assert_false (g_task_get_completed (task));
771
772   return G_SOURCE_REMOVE;
773 }
774
775 /* asynchronous_cancellation_cancelled is the GCancellable::cancelled
776  * handler that's used by the asynchronous implementation for
777  * cancelling itself.
778  */
779 static void
780 asynchronous_cancellation_cancelled (GCancellable *cancellable,
781                                      gpointer      user_data)
782 {
783   GTask *task = G_TASK (user_data);
784   guint run_task_id;
785
786   g_assert_true (cancellable == g_task_get_cancellable (task));
787
788   run_task_id = GPOINTER_TO_UINT (g_task_get_task_data (task));
789   g_assert_cmpuint (run_task_id, !=, 0);
790
791   g_source_remove (run_task_id);
792   g_task_set_task_data (task, GUINT_TO_POINTER (0), NULL);
793
794   g_task_return_boolean (task, FALSE);
795   g_assert_false (g_task_get_completed (task));
796 }
797
798 /* asynchronous_cancellation_run_task represents the actual
799  * asynchronous work being done in an idle GSource as was mentioned
800  * above. This is effectively meant to be an infinite loop so that
801  * the only way to break out of it is via cancellation.
802  */
803 static gboolean
804 asynchronous_cancellation_run_task (gpointer user_data)
805 {
806   GCancellable *cancellable;
807   GTask *task = G_TASK (user_data);
808
809   cancellable = g_task_get_cancellable (task);
810   g_assert_true (G_IS_CANCELLABLE (cancellable));
811   g_assert_false (g_cancellable_is_cancelled (cancellable));
812
813   return G_SOURCE_CONTINUE;
814 }
815
816 /* Test that cancellation is always asynchronous. The completion callback for
817  * a #GTask must not be called from inside the cancellation handler.
818  *
819  * The body of the loop inside test_asynchronous_cancellation
820  * represents what would have been a typical asynchronous API call,
821  * and its implementation. They are fused together without an API
822  * boundary. The actual work done by this asynchronous API is
823  * represented by an idle GSource.
824  */
825 static void
826 test_asynchronous_cancellation (void)
827 {
828   guint i;
829
830   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1608");
831
832   /* Run a few times to shake out any timing issues between the
833    * cancellation and task sources.
834    */
835   for (i = 0; i < 5; i++)
836     {
837       GCancellable *cancellable;
838       GTask *task;
839       gboolean notification_emitted = FALSE;
840       guint run_task_id;
841
842       cancellable = g_cancellable_new ();
843
844       task = g_task_new (NULL, cancellable, asynchronous_cancellation_callback, NULL);
845       g_cancellable_connect (cancellable, (GCallback) asynchronous_cancellation_cancelled, task, NULL);
846       g_signal_connect (task, "notify::completed", (GCallback) completed_cb, &notification_emitted);
847
848       run_task_id = g_idle_add (asynchronous_cancellation_run_task, task);
849       g_source_set_name_by_id (run_task_id, "[test_asynchronous_cancellation] run_task");
850       g_task_set_task_data (task, GUINT_TO_POINTER (run_task_id), NULL);
851
852       g_timeout_add (50, asynchronous_cancellation_cancel_task, task);
853
854       g_main_loop_run (loop);
855
856       g_assert_true (g_task_get_completed (task));
857       g_assert_true (notification_emitted);
858
859       g_object_unref (cancellable);
860       g_object_unref (task);
861     }
862 }
863
864 /* test_check_cancellable: cancellation overrides return value */
865
866 enum {
867   CANCEL_BEFORE     = (1 << 1),
868   CANCEL_AFTER      = (1 << 2),
869   CHECK_CANCELLABLE = (1 << 3)
870 };
871 #define NUM_CANCEL_TESTS (CANCEL_BEFORE | CANCEL_AFTER | CHECK_CANCELLABLE)
872
873 static void
874 cancel_callback (GObject      *object,
875                  GAsyncResult *result,
876                  gpointer      user_data)
877 {
878   int state = GPOINTER_TO_INT (user_data);
879   GTask *task;
880   GCancellable *cancellable;
881   GError *error = NULL;
882
883   g_assert (object == NULL);
884   g_assert (g_task_is_valid (result, object));
885   g_assert (g_async_result_get_user_data (result) == user_data);
886
887   task = G_TASK (result);
888   cancellable = g_task_get_cancellable (task);
889   g_assert (G_IS_CANCELLABLE (cancellable));
890
891   if (state & (CANCEL_BEFORE | CANCEL_AFTER))
892     g_assert (g_cancellable_is_cancelled (cancellable));
893   else
894     g_assert (!g_cancellable_is_cancelled (cancellable));
895
896   if (state & CHECK_CANCELLABLE)
897     g_assert (g_task_get_check_cancellable (task));
898   else
899     g_assert (!g_task_get_check_cancellable (task));
900
901   if (g_task_propagate_boolean (task, &error))
902     {
903       g_assert (!g_cancellable_is_cancelled (cancellable) ||
904                 !g_task_get_check_cancellable (task));
905     }
906   else
907     {
908       g_assert (g_cancellable_is_cancelled (cancellable) &&
909                 g_task_get_check_cancellable (task));
910       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
911       g_error_free (error);
912     }
913
914   g_main_loop_quit (loop);
915 }
916
917 static void
918 test_check_cancellable (void)
919 {
920   GTask *task;
921   GCancellable *cancellable;
922   int state;
923
924   cancellable = g_cancellable_new ();
925
926   for (state = 0; state <= NUM_CANCEL_TESTS; state++)
927     {
928       task = g_task_new (NULL, cancellable, cancel_callback,
929                          GINT_TO_POINTER (state));
930       g_task_set_check_cancellable (task, (state & CHECK_CANCELLABLE) != 0);
931
932       if (state & CANCEL_BEFORE)
933         g_cancellable_cancel (cancellable);
934       g_task_return_boolean (task, TRUE);
935       if (state & CANCEL_AFTER)
936         g_cancellable_cancel (cancellable);
937
938       g_main_loop_run (loop);
939       g_object_unref (task);
940       g_cancellable_reset (cancellable);
941     }
942
943   g_object_unref (cancellable);
944 }
945
946 /* test_return_if_cancelled */
947
948 static void
949 return_if_cancelled_callback (GObject      *object,
950                               GAsyncResult *result,
951                               gpointer      user_data)
952 {
953   GError *error = NULL;
954
955   g_assert (object == NULL);
956   g_assert (g_task_is_valid (result, object));
957   g_assert (g_async_result_get_user_data (result) == user_data);
958   g_assert (g_task_had_error (G_TASK (result)));
959   g_assert_false (g_task_get_completed (G_TASK (result)));
960
961   g_task_propagate_boolean (G_TASK (result), &error);
962   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
963   g_clear_error (&error);
964
965   g_assert (g_task_had_error (G_TASK (result)));
966
967   g_main_loop_quit (loop);
968 }
969
970 static void
971 test_return_if_cancelled (void)
972 {
973   GTask *task;
974   GCancellable *cancellable;
975   gboolean cancelled;
976   gboolean notification_emitted = FALSE;
977
978   cancellable = g_cancellable_new ();
979
980   task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
981   g_signal_connect (task, "notify::completed",
982                     (GCallback) completed_cb, &notification_emitted);
983
984   g_cancellable_cancel (cancellable);
985   cancelled = g_task_return_error_if_cancelled (task);
986   g_assert (cancelled);
987   g_assert_false (notification_emitted);
988   g_main_loop_run (loop);
989   g_object_unref (task);
990   g_assert_true (notification_emitted);
991   g_cancellable_reset (cancellable);
992
993   notification_emitted = FALSE;
994
995   task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
996   g_signal_connect (task, "notify::completed",
997                     (GCallback) completed_cb, &notification_emitted);
998
999   g_task_set_check_cancellable (task, FALSE);
1000   g_cancellable_cancel (cancellable);
1001   cancelled = g_task_return_error_if_cancelled (task);
1002   g_assert (cancelled);
1003   g_assert_false (notification_emitted);
1004   g_main_loop_run (loop);
1005   g_object_unref (task);
1006   g_assert_true (notification_emitted);
1007   g_object_unref (cancellable);
1008 }
1009
1010 /* test_run_in_thread */
1011
1012 static GMutex run_in_thread_mutex;
1013 static GCond run_in_thread_cond;
1014
1015 static void
1016 task_weak_notify (gpointer  user_data,
1017                   GObject  *ex_task)
1018 {
1019   gboolean *weak_notify_ran = user_data;
1020
1021   g_mutex_lock (&run_in_thread_mutex);
1022   g_atomic_int_set (weak_notify_ran, TRUE);
1023   g_cond_signal (&run_in_thread_cond);
1024   g_mutex_unlock (&run_in_thread_mutex);
1025 }
1026
1027 static void
1028 run_in_thread_callback (GObject      *object,
1029                         GAsyncResult *result,
1030                         gpointer      user_data)
1031 {
1032   gboolean *done = user_data;
1033   GError *error = NULL;
1034   gssize ret;
1035
1036   g_assert (g_thread_self () == main_thread);
1037
1038   g_assert (object == NULL);
1039   g_assert (g_task_is_valid (result, object));
1040   g_assert (g_async_result_get_user_data (result) == user_data);
1041   g_assert (!g_task_had_error (G_TASK (result)));
1042   g_assert_false (g_task_get_completed (G_TASK (result)));
1043   g_assert_cmpstr (g_task_get_name (G_TASK (result)), ==, "test_run_in_thread name");
1044
1045   ret = g_task_propagate_int (G_TASK (result), &error);
1046   g_assert_no_error (error);
1047   g_assert_cmpint (ret, ==, magic);
1048
1049   g_assert (!g_task_had_error (G_TASK (result)));
1050
1051   *done = TRUE;
1052   g_main_loop_quit (loop);
1053 }
1054
1055 static void
1056 run_in_thread_thread (GTask        *task,
1057                       gpointer      source_object,
1058                       gpointer      task_data,
1059                       GCancellable *cancellable)
1060 {
1061   gboolean *thread_ran = task_data;
1062
1063   g_assert (source_object == g_task_get_source_object (task));
1064   g_assert (task_data == g_task_get_task_data (task));
1065   g_assert (cancellable == g_task_get_cancellable (task));
1066   g_assert_false (g_task_get_completed (task));
1067   g_assert_cmpstr (g_task_get_name (task), ==, "test_run_in_thread name");
1068
1069   g_assert (g_thread_self () != main_thread);
1070
1071   g_mutex_lock (&run_in_thread_mutex);
1072   g_atomic_int_set (thread_ran, TRUE);
1073   g_cond_signal (&run_in_thread_cond);
1074   g_mutex_unlock (&run_in_thread_mutex);
1075
1076   g_task_return_int (task, magic);
1077 }
1078
1079 static void
1080 test_run_in_thread (void)
1081 {
1082   GTask *task;
1083   gboolean thread_ran = FALSE;  /* (atomic) */
1084   gboolean weak_notify_ran = FALSE;  /* (atomic) */
1085   gboolean notification_emitted = FALSE;
1086   gboolean done = FALSE;
1087
1088   task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
1089   g_task_set_name (task, "test_run_in_thread name");
1090   g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
1091   g_signal_connect (task, "notify::completed",
1092                     (GCallback) completed_cb, &notification_emitted);
1093
1094   g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
1095   g_task_run_in_thread (task, run_in_thread_thread);
1096
1097   g_mutex_lock (&run_in_thread_mutex);
1098   while (!g_atomic_int_get (&thread_ran))
1099     g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
1100   g_mutex_unlock (&run_in_thread_mutex);
1101
1102   g_assert (done == FALSE);
1103   g_assert_false (g_atomic_int_get (&weak_notify_ran));
1104
1105   g_main_loop_run (loop);
1106
1107   g_assert (done == TRUE);
1108   g_assert_true (notification_emitted);
1109
1110   g_assert_cmpstr (g_task_get_name (task), ==, "test_run_in_thread name");
1111
1112   g_object_unref (task);
1113
1114   g_mutex_lock (&run_in_thread_mutex);
1115   while (!g_atomic_int_get (&weak_notify_ran))
1116     g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
1117   g_mutex_unlock (&run_in_thread_mutex);
1118 }
1119
1120 /* test_run_in_thread_sync */
1121
1122 static void
1123 run_in_thread_sync_callback (GObject      *object,
1124                              GAsyncResult *result,
1125                              gpointer      user_data)
1126 {
1127   /* g_task_run_in_thread_sync() does not invoke the task's callback */
1128   g_assert_not_reached ();
1129 }
1130
1131 static void
1132 run_in_thread_sync_thread (GTask        *task,
1133                            gpointer      source_object,
1134                            gpointer      task_data,
1135                            GCancellable *cancellable)
1136 {
1137   gboolean *thread_ran = task_data;
1138
1139   g_assert (source_object == g_task_get_source_object (task));
1140   g_assert (task_data == g_task_get_task_data (task));
1141   g_assert (cancellable == g_task_get_cancellable (task));
1142   g_assert_false (g_task_get_completed (task));
1143
1144   g_assert (g_thread_self () != main_thread);
1145
1146   g_atomic_int_set (thread_ran, TRUE);
1147   g_task_return_int (task, magic);
1148 }
1149
1150 static void
1151 test_run_in_thread_sync (void)
1152 {
1153   GTask *task;
1154   gboolean thread_ran = FALSE;
1155   gssize ret;
1156   gboolean notification_emitted = FALSE;
1157   GError *error = NULL;
1158
1159   task = g_task_new (NULL, NULL, run_in_thread_sync_callback, NULL);
1160   g_signal_connect (task, "notify::completed",
1161                     (GCallback) completed_cb,
1162                     &notification_emitted);
1163
1164   g_task_set_task_data (task, &thread_ran, NULL);
1165   g_task_run_in_thread_sync (task, run_in_thread_sync_thread);
1166
1167   g_assert_true (g_atomic_int_get (&thread_ran));
1168   g_assert (task != NULL);
1169   g_assert (!g_task_had_error (task));
1170   g_assert_true (g_task_get_completed (task));
1171   g_assert_true (notification_emitted);
1172
1173   ret = g_task_propagate_int (task, &error);
1174   g_assert_no_error (error);
1175   g_assert_cmpint (ret, ==, magic);
1176
1177   g_assert (!g_task_had_error (task));
1178
1179   g_object_unref (task);
1180 }
1181
1182 /* test_run_in_thread_priority */
1183
1184 static GMutex fake_task_mutex, last_fake_task_mutex;
1185 static gint sequence_number = 0;
1186
1187 static void
1188 quit_main_loop_callback (GObject      *object,
1189                          GAsyncResult *result,
1190                          gpointer      user_data)
1191 {
1192   GError *error = NULL;
1193   gboolean ret;
1194
1195   g_assert (g_thread_self () == main_thread);
1196
1197   g_assert (object == NULL);
1198   g_assert (g_task_is_valid (result, object));
1199   g_assert (g_async_result_get_user_data (result) == user_data);
1200   g_assert (!g_task_had_error (G_TASK (result)));
1201   g_assert_false (g_task_get_completed (G_TASK (result)));
1202
1203   ret = g_task_propagate_boolean (G_TASK (result), &error);
1204   g_assert_no_error (error);
1205   g_assert_cmpint (ret, ==, TRUE);
1206
1207   g_assert (!g_task_had_error (G_TASK (result)));
1208
1209   g_main_loop_quit (loop);
1210 }
1211
1212 static void
1213 set_sequence_number_thread (GTask        *task,
1214                             gpointer      source_object,
1215                             gpointer      task_data,
1216                             GCancellable *cancellable)
1217 {
1218   gint *seq_no_p = task_data;
1219
1220   *seq_no_p = ++sequence_number;
1221   g_task_return_boolean (task, TRUE);
1222 }
1223
1224 static void
1225 fake_task_thread (GTask        *task,
1226                   gpointer      source_object,
1227                   gpointer      task_data,
1228                   GCancellable *cancellable)
1229 {
1230   GMutex *mutex = task_data;
1231
1232   g_mutex_lock (mutex);
1233   g_mutex_unlock (mutex);
1234   g_task_return_boolean (task, TRUE);
1235 }
1236
1237 #define G_TASK_THREAD_POOL_SIZE 10
1238 static int fake_tasks_running;
1239
1240 static void
1241 fake_task_callback (GObject      *source,
1242                     GAsyncResult *result,
1243                     gpointer      user_data)
1244 {
1245   if (--fake_tasks_running == 0)
1246     g_main_loop_quit (loop);
1247 }
1248
1249 static void
1250 clog_up_thread_pool (void)
1251 {
1252   GTask *task;
1253   int i;
1254
1255   g_thread_pool_stop_unused_threads ();
1256
1257   g_mutex_lock (&fake_task_mutex);
1258   for (i = 0; i < G_TASK_THREAD_POOL_SIZE - 1; i++)
1259     {
1260       task = g_task_new (NULL, NULL, fake_task_callback, NULL);
1261       g_task_set_task_data (task, &fake_task_mutex, NULL);
1262       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_DEFAULT);
1263       g_task_set_priority (task, G_PRIORITY_HIGH * 2);
1264       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_HIGH * 2);
1265       g_task_run_in_thread (task, fake_task_thread);
1266       g_object_unref (task);
1267       fake_tasks_running++;
1268     }
1269
1270   g_mutex_lock (&last_fake_task_mutex);
1271   task = g_task_new (NULL, NULL, NULL, NULL);
1272   g_task_set_task_data (task, &last_fake_task_mutex, NULL);
1273   g_task_set_priority (task, G_PRIORITY_HIGH * 2);
1274   g_task_run_in_thread (task, fake_task_thread);
1275   g_object_unref (task);
1276 }
1277
1278 static void
1279 unclog_thread_pool (void)
1280 {
1281   g_mutex_unlock (&fake_task_mutex);
1282   g_main_loop_run (loop);
1283 }
1284
1285 static void
1286 test_run_in_thread_priority (void)
1287 {
1288   GTask *task;
1289   GCancellable *cancellable;
1290   int seq_a, seq_b, seq_c, seq_d;
1291
1292   clog_up_thread_pool ();
1293
1294   /* Queue three more tasks that we'll arrange to have run serially */
1295   task = g_task_new (NULL, NULL, NULL, NULL);
1296   g_task_set_task_data (task, &seq_a, NULL);
1297   g_task_run_in_thread (task, set_sequence_number_thread);
1298   g_object_unref (task);
1299   
1300   task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
1301   g_task_set_task_data (task, &seq_b, NULL);
1302   g_task_set_priority (task, G_PRIORITY_LOW);
1303   g_task_run_in_thread (task, set_sequence_number_thread);
1304   g_object_unref (task);
1305   
1306   task = g_task_new (NULL, NULL, NULL, NULL);
1307   g_task_set_task_data (task, &seq_c, NULL);
1308   g_task_set_priority (task, G_PRIORITY_HIGH);
1309   g_task_run_in_thread (task, set_sequence_number_thread);
1310   g_object_unref (task);
1311   
1312   cancellable = g_cancellable_new ();
1313   task = g_task_new (NULL, cancellable, NULL, NULL);
1314   g_task_set_task_data (task, &seq_d, NULL);
1315   g_task_run_in_thread (task, set_sequence_number_thread);
1316   g_cancellable_cancel (cancellable);
1317   g_object_unref (cancellable);
1318   g_object_unref (task);
1319
1320   /* Let the last fake task complete; the four other tasks will then
1321    * complete serially, in the order D, C, A, B, and B will quit the
1322    * main loop.
1323    */
1324   g_mutex_unlock (&last_fake_task_mutex);
1325   g_main_loop_run (loop);
1326
1327   g_assert_cmpint (seq_d, ==, 1);
1328   g_assert_cmpint (seq_c, ==, 2);
1329   g_assert_cmpint (seq_a, ==, 3);
1330   g_assert_cmpint (seq_b, ==, 4);
1331
1332   unclog_thread_pool ();
1333 }
1334
1335 /* test_run_in_thread_nested: task threads that block waiting on
1336  * other task threads will not cause the thread pool to starve.
1337  */
1338
1339 static void
1340 run_nested_task_thread (GTask        *task,
1341                         gpointer      source_object,
1342                         gpointer      task_data,
1343                         GCancellable *cancellable)
1344 {
1345   GTask *nested;
1346   int *nested_tasks_left = task_data;
1347
1348   if ((*nested_tasks_left)--)
1349     {
1350       nested = g_task_new (NULL, NULL, NULL, NULL);
1351       g_task_set_task_data (nested, nested_tasks_left, NULL);
1352       g_task_run_in_thread_sync (nested, run_nested_task_thread);
1353       g_object_unref (nested);
1354     }
1355
1356   g_task_return_boolean (task, TRUE);
1357 }
1358
1359 static void
1360 test_run_in_thread_nested (void)
1361 {
1362   GTask *task;
1363   int nested_tasks_left = 2;
1364
1365   clog_up_thread_pool ();
1366
1367   task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
1368   g_task_set_task_data (task, &nested_tasks_left, NULL);
1369   g_task_run_in_thread (task, run_nested_task_thread);
1370   g_object_unref (task);
1371
1372   g_mutex_unlock (&last_fake_task_mutex);
1373   g_main_loop_run (loop);
1374
1375   unclog_thread_pool ();
1376 }
1377
1378 /* test_run_in_thread_overflow: if you queue lots and lots and lots of
1379  * tasks, they won't all run at once.
1380  */
1381 static GMutex overflow_mutex;
1382 static guint overflow_completed;
1383
1384 static void
1385 run_overflow_task_thread (GTask        *task,
1386                           gpointer      source_object,
1387                           gpointer      task_data,
1388                           GCancellable *cancellable)
1389 {
1390   gchar *result = task_data;
1391
1392   if (g_task_return_error_if_cancelled (task))
1393     {
1394       *result = 'X';
1395     }
1396   else
1397     {
1398       /* Block until the main thread is ready. */
1399       g_mutex_lock (&overflow_mutex);
1400       g_mutex_unlock (&overflow_mutex);
1401
1402       *result = '.';
1403
1404       g_task_return_boolean (task, TRUE);
1405     }
1406
1407   g_atomic_int_inc (&overflow_completed);
1408 }
1409
1410 #define NUM_OVERFLOW_TASKS 1024
1411
1412 static void
1413 test_run_in_thread_overflow (void)
1414 {
1415   GCancellable *cancellable;
1416   GTask *task;
1417   gchar buf[NUM_OVERFLOW_TASKS + 1];
1418   gint i;
1419
1420   /* Queue way too many tasks and then sleep for a bit. The first 10
1421    * tasks will be dispatched to threads and will then block on
1422    * overflow_mutex, so more threads will be created while this thread
1423    * is sleeping. Then we cancel the cancellable, unlock the mutex,
1424    * wait for all of the tasks to complete, and make sure that we got
1425    * the behavior we expected.
1426    */
1427
1428   memset (buf, 0, sizeof (buf));
1429   cancellable = g_cancellable_new ();
1430
1431   g_mutex_lock (&overflow_mutex);
1432
1433   for (i = 0; i < NUM_OVERFLOW_TASKS; i++)
1434     {
1435       task = g_task_new (NULL, cancellable, NULL, NULL);
1436       g_task_set_task_data (task, buf + i, NULL);
1437       g_task_run_in_thread (task, run_overflow_task_thread);
1438       g_object_unref (task);
1439     }
1440
1441   if (g_test_slow ())
1442     g_usleep (5000000); /* 5 s */
1443   else
1444     g_usleep (500000);  /* 0.5 s */
1445   g_cancellable_cancel (cancellable);
1446   g_object_unref (cancellable);
1447
1448   g_mutex_unlock (&overflow_mutex);
1449
1450   /* Wait for all tasks to complete. */
1451   while (g_atomic_int_get (&overflow_completed) != NUM_OVERFLOW_TASKS)
1452     g_usleep (1000);
1453
1454   g_assert_cmpint (strlen (buf), ==, NUM_OVERFLOW_TASKS);
1455
1456   i = strspn (buf, ".");
1457   /* Given the sleep times above, i should be 14 for normal, 40 for
1458    * slow. But if the machine is too slow/busy then the scheduling
1459    * might get messed up and we'll get more or fewer threads than
1460    * expected. But there are limits to how messed up it could
1461    * plausibly get (and we hope that if gtask is actually broken then
1462    * it will exceed those limits).
1463    */
1464   g_assert_cmpint (i, >=, 10);
1465   if (g_test_slow ())
1466     g_assert_cmpint (i, <, 50);
1467   else
1468     g_assert_cmpint (i, <, 20);
1469
1470   g_assert_cmpint (i + strspn (buf + i, "X"), ==, NUM_OVERFLOW_TASKS);
1471 }
1472
1473 /* test_return_on_cancel */
1474
1475 GMutex roc_init_mutex, roc_finish_mutex;
1476 GCond roc_init_cond, roc_finish_cond;
1477
1478 typedef enum {
1479   THREAD_STARTING,
1480   THREAD_RUNNING,
1481   THREAD_CANCELLED,
1482   THREAD_COMPLETED
1483 } ThreadState;
1484
1485 static void
1486 return_on_cancel_callback (GObject      *object,
1487                            GAsyncResult *result,
1488                            gpointer      user_data)
1489 {
1490   gboolean *callback_ran = user_data;
1491   GError *error = NULL;
1492   gssize ret;
1493
1494   g_assert (g_thread_self () == main_thread);
1495
1496   g_assert (object == NULL);
1497   g_assert (g_task_is_valid (result, object));
1498   g_assert (g_async_result_get_user_data (result) == user_data);
1499   g_assert (g_task_had_error (G_TASK (result)));
1500   g_assert_false (g_task_get_completed (G_TASK (result)));
1501
1502   ret = g_task_propagate_int (G_TASK (result), &error);
1503   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1504   g_clear_error (&error);
1505   g_assert_cmpint (ret, ==, -1);
1506
1507   g_assert (g_task_had_error (G_TASK (result)));
1508
1509   *callback_ran = TRUE;
1510   g_main_loop_quit (loop);
1511 }
1512
1513 static void
1514 return_on_cancel_thread (GTask        *task,
1515                          gpointer      source_object,
1516                          gpointer      task_data,
1517                          GCancellable *cancellable)
1518 {
1519   ThreadState *state = task_data;
1520
1521   g_assert (source_object == g_task_get_source_object (task));
1522   g_assert (task_data == g_task_get_task_data (task));
1523   g_assert (cancellable == g_task_get_cancellable (task));
1524
1525   g_assert (g_thread_self () != main_thread);
1526
1527   g_mutex_lock (&roc_init_mutex);
1528   *state = THREAD_RUNNING;
1529   g_cond_signal (&roc_init_cond);
1530   g_mutex_unlock (&roc_init_mutex);
1531
1532   g_mutex_lock (&roc_finish_mutex);
1533
1534   if (!g_task_get_return_on_cancel (task) ||
1535       g_task_set_return_on_cancel (task, FALSE))
1536     {
1537       *state = THREAD_COMPLETED;
1538       g_task_return_int (task, magic);
1539     }
1540   else
1541     *state = THREAD_CANCELLED;
1542
1543   g_cond_signal (&roc_finish_cond);
1544   g_mutex_unlock (&roc_finish_mutex);
1545 }
1546
1547 static void
1548 test_return_on_cancel (void)
1549 {
1550   GTask *task;
1551   GCancellable *cancellable;
1552   ThreadState thread_state;  /* (atomic) */
1553   gboolean weak_notify_ran = FALSE;  /* (atomic) */
1554   gboolean callback_ran;
1555   gboolean notification_emitted = FALSE;
1556
1557   cancellable = g_cancellable_new ();
1558
1559   /* If return-on-cancel is FALSE (default), the task does not return
1560    * early.
1561    */
1562   callback_ran = FALSE;
1563   g_atomic_int_set (&thread_state, THREAD_STARTING);
1564   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1565   g_signal_connect (task, "notify::completed",
1566                     (GCallback) completed_cb, &notification_emitted);
1567
1568   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1569   g_mutex_lock (&roc_init_mutex);
1570   g_mutex_lock (&roc_finish_mutex);
1571   g_task_run_in_thread (task, return_on_cancel_thread);
1572   g_object_unref (task);
1573
1574   while (g_atomic_int_get (&thread_state) == THREAD_STARTING)
1575     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1576   g_mutex_unlock (&roc_init_mutex);
1577
1578   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1579   g_assert (callback_ran == FALSE);
1580
1581   g_cancellable_cancel (cancellable);
1582   g_mutex_unlock (&roc_finish_mutex);
1583   g_main_loop_run (loop);
1584
1585   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_COMPLETED);
1586   g_assert (callback_ran == TRUE);
1587   g_assert_true (notification_emitted);
1588
1589   g_cancellable_reset (cancellable);
1590
1591   /* If return-on-cancel is TRUE, it does return early */
1592   callback_ran = FALSE;
1593   notification_emitted = FALSE;
1594   g_atomic_int_set (&thread_state, THREAD_STARTING);
1595   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1596   g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
1597   g_signal_connect (task, "notify::completed",
1598                     (GCallback) completed_cb, &notification_emitted);
1599   g_task_set_return_on_cancel (task, TRUE);
1600
1601   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1602   g_mutex_lock (&roc_init_mutex);
1603   g_mutex_lock (&roc_finish_mutex);
1604   g_task_run_in_thread (task, return_on_cancel_thread);
1605   g_object_unref (task);
1606
1607   while (g_atomic_int_get (&thread_state) == THREAD_STARTING)
1608     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1609   g_mutex_unlock (&roc_init_mutex);
1610
1611   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1612   g_assert (callback_ran == FALSE);
1613
1614   g_cancellable_cancel (cancellable);
1615   g_main_loop_run (loop);
1616   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1617   g_assert (callback_ran == TRUE);
1618
1619   g_assert_false (g_atomic_int_get (&weak_notify_ran));
1620
1621   while (g_atomic_int_get (&thread_state) == THREAD_RUNNING)
1622     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1623   g_mutex_unlock (&roc_finish_mutex);
1624
1625   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED);
1626   g_mutex_lock (&run_in_thread_mutex);
1627   while (!g_atomic_int_get (&weak_notify_ran))
1628     g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
1629   g_mutex_unlock (&run_in_thread_mutex);
1630
1631   g_assert_true (notification_emitted);
1632   g_cancellable_reset (cancellable);
1633
1634   /* If the task is already cancelled before it starts, it returns
1635    * immediately, but the thread func still runs.
1636    */
1637   callback_ran = FALSE;
1638   notification_emitted = FALSE;
1639   g_atomic_int_set (&thread_state, THREAD_STARTING);
1640   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1641   g_signal_connect (task, "notify::completed",
1642                     (GCallback) completed_cb, &notification_emitted);
1643   g_task_set_return_on_cancel (task, TRUE);
1644
1645   g_cancellable_cancel (cancellable);
1646
1647   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1648   g_mutex_lock (&roc_init_mutex);
1649   g_mutex_lock (&roc_finish_mutex);
1650   g_task_run_in_thread (task, return_on_cancel_thread);
1651   g_object_unref (task);
1652
1653   g_main_loop_run (loop);
1654   g_assert (callback_ran == TRUE);
1655
1656   while (g_atomic_int_get (&thread_state) == THREAD_STARTING)
1657     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1658   g_mutex_unlock (&roc_init_mutex);
1659
1660   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1661
1662   while (g_atomic_int_get (&thread_state) == THREAD_RUNNING)
1663     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1664   g_mutex_unlock (&roc_finish_mutex);
1665
1666   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED);
1667   g_assert_true (notification_emitted);
1668
1669   g_object_unref (cancellable);
1670 }
1671
1672 /* test_return_on_cancel_sync */
1673
1674 static gpointer
1675 cancel_sync_runner_thread (gpointer task)
1676 {
1677   g_task_run_in_thread_sync (task, return_on_cancel_thread);
1678   return NULL;
1679 }
1680
1681 static void
1682 test_return_on_cancel_sync (void)
1683 {
1684   GTask *task;
1685   GCancellable *cancellable;
1686   ThreadState thread_state;  /* (atomic) */
1687   GThread *runner_thread;
1688   gssize ret;
1689   GError *error = NULL;
1690
1691   cancellable = g_cancellable_new ();
1692
1693   /* If return-on-cancel is FALSE, the task does not return early.
1694    */
1695   g_atomic_int_set (&thread_state, THREAD_STARTING);
1696   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1697
1698   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1699   g_mutex_lock (&roc_init_mutex);
1700   g_mutex_lock (&roc_finish_mutex);
1701   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1702                                 cancel_sync_runner_thread, task);
1703
1704   while (g_atomic_int_get (&thread_state) == THREAD_STARTING)
1705     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1706   g_mutex_unlock (&roc_init_mutex);
1707
1708   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1709
1710   g_cancellable_cancel (cancellable);
1711   g_mutex_unlock (&roc_finish_mutex);
1712   g_thread_join (runner_thread);
1713   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_COMPLETED);
1714
1715   ret = g_task_propagate_int (task, &error);
1716   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1717   g_clear_error (&error);
1718   g_assert_cmpint (ret, ==, -1);
1719
1720   g_object_unref (task);
1721
1722   g_cancellable_reset (cancellable);
1723
1724   /* If return-on-cancel is TRUE, it does return early */
1725   g_atomic_int_set (&thread_state, THREAD_STARTING);
1726   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1727   g_task_set_return_on_cancel (task, TRUE);
1728
1729   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1730   g_mutex_lock (&roc_init_mutex);
1731   g_mutex_lock (&roc_finish_mutex);
1732   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1733                                 cancel_sync_runner_thread, task);
1734
1735   while (g_atomic_int_get (&thread_state) == THREAD_STARTING)
1736     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1737   g_mutex_unlock (&roc_init_mutex);
1738
1739   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1740
1741   g_cancellable_cancel (cancellable);
1742   g_thread_join (runner_thread);
1743   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1744
1745   ret = g_task_propagate_int (task, &error);
1746   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1747   g_clear_error (&error);
1748   g_assert_cmpint (ret, ==, -1);
1749
1750   g_object_unref (task);
1751
1752   while (g_atomic_int_get (&thread_state) == THREAD_RUNNING)
1753     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1754   g_mutex_unlock (&roc_finish_mutex);
1755
1756   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED);
1757
1758   g_cancellable_reset (cancellable);
1759
1760   /* If the task is already cancelled before it starts, it returns
1761    * immediately, but the thread func still runs.
1762    */
1763   g_atomic_int_set (&thread_state, THREAD_STARTING);
1764   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1765   g_task_set_return_on_cancel (task, TRUE);
1766
1767   g_cancellable_cancel (cancellable);
1768
1769   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1770   g_mutex_lock (&roc_init_mutex);
1771   g_mutex_lock (&roc_finish_mutex);
1772   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1773                                 cancel_sync_runner_thread, task);
1774
1775   g_thread_join (runner_thread);
1776   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_STARTING);
1777
1778   ret = g_task_propagate_int (task, &error);
1779   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1780   g_clear_error (&error);
1781   g_assert_cmpint (ret, ==, -1);
1782
1783   g_object_unref (task);
1784
1785   while (g_atomic_int_get (&thread_state) == THREAD_STARTING)
1786     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1787   g_mutex_unlock (&roc_init_mutex);
1788
1789   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_RUNNING);
1790
1791   while (g_atomic_int_get (&thread_state) == THREAD_RUNNING)
1792     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1793   g_mutex_unlock (&roc_finish_mutex);
1794
1795   g_assert_cmpint (g_atomic_int_get (&thread_state), ==, THREAD_CANCELLED);
1796
1797   g_object_unref (cancellable);
1798 }
1799
1800 /* test_return_on_cancel_atomic: turning return-on-cancel on/off is
1801  * non-racy
1802  */
1803
1804 GMutex roca_mutex_1, roca_mutex_2;
1805 GCond roca_cond_1, roca_cond_2;
1806
1807 static void
1808 return_on_cancel_atomic_callback (GObject      *object,
1809                                   GAsyncResult *result,
1810                                   gpointer      user_data)
1811 {
1812   gboolean *callback_ran = user_data;
1813   GError *error = NULL;
1814   gssize ret;
1815
1816   g_assert (g_thread_self () == main_thread);
1817
1818   g_assert (object == NULL);
1819   g_assert (g_task_is_valid (result, object));
1820   g_assert (g_async_result_get_user_data (result) == user_data);
1821   g_assert (g_task_had_error (G_TASK (result)));
1822   g_assert_false (g_task_get_completed (G_TASK (result)));
1823
1824   ret = g_task_propagate_int (G_TASK (result), &error);
1825   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1826   g_clear_error (&error);
1827   g_assert_cmpint (ret, ==, -1);
1828
1829   g_assert (g_task_had_error (G_TASK (result)));
1830
1831   *callback_ran = TRUE;
1832   g_main_loop_quit (loop);
1833 }
1834
1835 static void
1836 return_on_cancel_atomic_thread (GTask        *task,
1837                                 gpointer      source_object,
1838                                 gpointer      task_data,
1839                                 GCancellable *cancellable)
1840 {
1841   gint *state = task_data;  /* (atomic) */
1842
1843   g_assert (source_object == g_task_get_source_object (task));
1844   g_assert (task_data == g_task_get_task_data (task));
1845   g_assert (cancellable == g_task_get_cancellable (task));
1846   g_assert_false (g_task_get_completed (task));
1847
1848   g_assert (g_thread_self () != main_thread);
1849   g_assert_cmpint (g_atomic_int_get (state), ==, 0);
1850
1851   g_mutex_lock (&roca_mutex_1);
1852   g_atomic_int_set (state, 1);
1853   g_cond_signal (&roca_cond_1);
1854   g_mutex_unlock (&roca_mutex_1);
1855
1856   g_mutex_lock (&roca_mutex_2);
1857   if (g_task_set_return_on_cancel (task, FALSE))
1858     g_atomic_int_set (state, 2);
1859   else
1860     g_atomic_int_set (state, 3);
1861   g_cond_signal (&roca_cond_2);
1862   g_mutex_unlock (&roca_mutex_2);
1863
1864   g_mutex_lock (&roca_mutex_1);
1865   if (g_task_set_return_on_cancel (task, TRUE))
1866     g_atomic_int_set (state, 4);
1867   else
1868     g_atomic_int_set (state, 5);
1869   g_cond_signal (&roca_cond_1);
1870   g_mutex_unlock (&roca_mutex_1);
1871
1872   g_mutex_lock (&roca_mutex_2);
1873   if (g_task_set_return_on_cancel (task, TRUE))
1874     g_atomic_int_set (state, 6);
1875   else
1876     g_atomic_int_set (state, 7);
1877   g_cond_signal (&roca_cond_2);
1878   g_mutex_unlock (&roca_mutex_2);
1879
1880   g_task_return_int (task, magic);
1881 }
1882
1883 static void
1884 test_return_on_cancel_atomic (void)
1885 {
1886   GTask *task;
1887   GCancellable *cancellable;
1888   gint state;  /* (atomic) */
1889   gboolean notification_emitted = FALSE;
1890   gboolean callback_ran;
1891
1892   cancellable = g_cancellable_new ();
1893   g_mutex_lock (&roca_mutex_1);
1894   g_mutex_lock (&roca_mutex_2);
1895
1896   /* If we don't cancel it, each set_return_on_cancel() call will succeed */
1897   g_atomic_int_set (&state, 0);
1898   callback_ran = FALSE;
1899   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1900   g_task_set_return_on_cancel (task, TRUE);
1901   g_signal_connect (task, "notify::completed",
1902                     (GCallback) completed_cb, &notification_emitted);
1903
1904   g_task_set_task_data (task, (gpointer)&state, NULL);
1905   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1906   g_object_unref (task);
1907
1908   g_assert_cmpint (g_atomic_int_get (&state), ==, 0);
1909
1910   while (g_atomic_int_get (&state) == 0)
1911     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1912   g_assert_cmpint (g_atomic_int_get (&state), ==, 1);
1913
1914   while (g_atomic_int_get (&state) == 1)
1915     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1916   g_assert_cmpint (g_atomic_int_get (&state), ==, 2);
1917
1918   while (g_atomic_int_get (&state) == 2)
1919     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1920   g_assert_cmpint (g_atomic_int_get (&state), ==, 4);
1921
1922   while (g_atomic_int_get (&state) == 4)
1923     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1924   g_assert_cmpint (g_atomic_int_get (&state), ==, 6);
1925
1926   /* callback assumes there'll be a cancelled error */
1927   g_cancellable_cancel (cancellable);
1928
1929   g_assert (callback_ran == FALSE);
1930   g_main_loop_run (loop);
1931   g_assert (callback_ran == TRUE);
1932   g_assert_true (notification_emitted);
1933
1934   g_cancellable_reset (cancellable);
1935
1936
1937   /* If we cancel while it's temporarily not return-on-cancel, the
1938    * task won't complete right away, and further
1939    * g_task_set_return_on_cancel() calls will return FALSE.
1940    */
1941   g_atomic_int_set (&state, 0);
1942   callback_ran = FALSE;
1943   notification_emitted = FALSE;
1944   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1945   g_task_set_return_on_cancel (task, TRUE);
1946   g_signal_connect (task, "notify::completed",
1947                     (GCallback) completed_cb, &notification_emitted);
1948
1949   g_task_set_task_data (task, (gpointer)&state, NULL);
1950   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1951
1952   g_assert_cmpint (g_atomic_int_get (&state), ==, 0);
1953
1954   while (g_atomic_int_get (&state) == 0)
1955     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1956   g_assert_cmpint (g_atomic_int_get (&state), ==, 1);
1957   g_assert (g_task_get_return_on_cancel (task));
1958
1959   while (g_atomic_int_get (&state) == 1)
1960     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1961   g_assert_cmpint (g_atomic_int_get (&state), ==, 2);
1962   g_assert (!g_task_get_return_on_cancel (task));
1963
1964   g_cancellable_cancel (cancellable);
1965   g_idle_add (idle_quit_loop, NULL);
1966   g_main_loop_run (loop);
1967   g_assert (callback_ran == FALSE);
1968
1969   while (g_atomic_int_get (&state) == 2)
1970     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1971   g_assert_cmpint (g_atomic_int_get (&state), ==, 5);
1972   g_assert (!g_task_get_return_on_cancel (task));
1973
1974   g_main_loop_run (loop);
1975   g_assert (callback_ran == TRUE);
1976   g_assert_true (notification_emitted);
1977
1978   while (g_atomic_int_get (&state) == 5)
1979     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1980   g_assert_cmpint (g_atomic_int_get (&state), ==, 7);
1981
1982   g_object_unref (cancellable);
1983   g_mutex_unlock (&roca_mutex_1);
1984   g_mutex_unlock (&roca_mutex_2);
1985   g_object_unref (task);
1986 }
1987
1988 /* test_return_pointer: memory management of pointer returns */
1989
1990 static void
1991 test_return_pointer (void)
1992 {
1993   GObject *object, *ret;
1994   GTask *task;
1995   GCancellable *cancellable;
1996   GError *error = NULL;
1997
1998   /* If we don't read back the return value, the task will
1999    * run its destroy notify.
2000    */
2001   object = (GObject *)g_dummy_object_new ();
2002   g_assert_cmpint (object->ref_count, ==, 1);
2003   g_object_add_weak_pointer (object, (gpointer *)&object);
2004
2005   task = g_task_new (NULL, NULL, NULL, NULL);
2006   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
2007   g_task_return_pointer (task, object, g_object_unref);
2008   g_assert_cmpint (object->ref_count, ==, 1);
2009
2010   /* Task and object are reffed until the :completed notification in idle. */
2011   g_object_unref (task);
2012   g_assert_nonnull (task);
2013   g_assert_nonnull (object);
2014
2015   wait_for_completed_notification (task);
2016
2017   g_assert_null (task);
2018   g_assert_null (object);
2019
2020   /* Likewise, if the return value is overwritten by an error */
2021   object = (GObject *)g_dummy_object_new ();
2022   g_assert_cmpint (object->ref_count, ==, 1);
2023   g_object_add_weak_pointer (object, (gpointer *)&object);
2024
2025   cancellable = g_cancellable_new ();
2026   task = g_task_new (NULL, cancellable, NULL, NULL);
2027   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
2028   g_task_return_pointer (task, object, g_object_unref);
2029   g_assert_cmpint (object->ref_count, ==, 1);
2030   g_cancellable_cancel (cancellable);
2031   g_assert_cmpint (object->ref_count, ==, 1);
2032
2033   ret = g_task_propagate_pointer (task, &error);
2034   g_assert (ret == NULL);
2035   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
2036   g_clear_error (&error);
2037   g_assert_cmpint (object->ref_count, ==, 1);
2038
2039   g_object_unref (task);
2040   g_object_unref (cancellable);
2041   g_assert_nonnull (task);
2042   g_assert_nonnull (object);
2043
2044   wait_for_completed_notification (task);
2045
2046   g_assert_null (task);
2047   g_assert_null (object);
2048   
2049   /* If we read back the return value, we steal its ref */
2050   object = (GObject *)g_dummy_object_new ();
2051   g_assert_cmpint (object->ref_count, ==, 1);
2052   g_object_add_weak_pointer (object, (gpointer *)&object);
2053
2054   task = g_task_new (NULL, NULL, NULL, NULL);
2055   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
2056   g_task_return_pointer (task, object, g_object_unref);
2057   g_assert_cmpint (object->ref_count, ==, 1);
2058
2059   ret = g_task_propagate_pointer (task, &error);
2060   g_assert_no_error (error);
2061   g_assert (ret == object);
2062   g_assert_cmpint (object->ref_count, ==, 1);
2063
2064   g_object_unref (task);
2065   g_assert_nonnull (task);
2066   g_assert_cmpint (object->ref_count, ==, 1);
2067   g_object_unref (object);
2068   g_assert (object == NULL);
2069
2070   wait_for_completed_notification (task);
2071   g_assert_null (task);
2072 }
2073
2074 static void
2075 test_return_value (void)
2076 {
2077   GObject *object;
2078   GValue value = G_VALUE_INIT;
2079   GValue ret = G_VALUE_INIT;
2080   GTask *task;
2081   GError *error = NULL;
2082
2083   object = (GObject *)g_dummy_object_new ();
2084   g_assert_cmpint (object->ref_count, ==, 1);
2085   g_object_add_weak_pointer (object, (gpointer *)&object);
2086
2087   g_value_init (&value, G_TYPE_OBJECT);
2088   g_value_set_object (&value, object);
2089   g_assert_cmpint (object->ref_count, ==, 2);
2090
2091   task = g_task_new (NULL, NULL, NULL, NULL);
2092   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
2093   g_task_return_value (task, &value);
2094   g_assert_cmpint (object->ref_count, ==, 3);
2095
2096   g_assert_true (g_task_propagate_value (task, &ret, &error));
2097   g_assert_no_error (error);
2098   g_assert_true (g_value_get_object (&ret) == object);
2099   g_assert_cmpint (object->ref_count, ==, 3);
2100
2101   g_object_unref (task);
2102   g_assert_nonnull (task);
2103   wait_for_completed_notification (task);
2104   g_assert_null (task);
2105
2106   g_assert_cmpint (object->ref_count, ==, 3);
2107   g_value_unset (&ret);
2108   g_assert_cmpint (object->ref_count, ==, 2);
2109   g_value_unset (&value);
2110   g_assert_cmpint (object->ref_count, ==, 1);
2111   g_object_unref (object);
2112   g_assert_null (object);
2113 }
2114
2115 /* test_object_keepalive: GTask takes a ref on its source object */
2116
2117 static GObject *keepalive_object;
2118
2119 static void
2120 keepalive_callback (GObject      *object,
2121                     GAsyncResult *result,
2122                     gpointer      user_data)
2123 {
2124   gssize *result_out = user_data;
2125   GError *error = NULL;
2126
2127   g_assert (object == keepalive_object);
2128   g_assert (g_task_is_valid (result, object));
2129   g_assert (g_async_result_get_user_data (result) == user_data);
2130   g_assert (!g_task_had_error (G_TASK (result)));
2131   g_assert_false (g_task_get_completed (G_TASK (result)));
2132
2133   *result_out = g_task_propagate_int (G_TASK (result), &error);
2134   g_assert_no_error (error);
2135
2136   g_assert (!g_task_had_error (G_TASK (result)));
2137
2138   g_main_loop_quit (loop);
2139 }
2140
2141 static void
2142 test_object_keepalive (void)
2143 {
2144   GObject *object;
2145   GTask *task;
2146   gssize result;
2147   int ref_count;
2148   gboolean notification_emitted = FALSE;
2149
2150   keepalive_object = object = (GObject *)g_dummy_object_new ();
2151   g_object_add_weak_pointer (object, (gpointer *)&object);
2152
2153   task = g_task_new (object, NULL, keepalive_callback, &result);
2154   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
2155   g_signal_connect (task, "notify::completed",
2156                     (GCallback) completed_cb, &notification_emitted);
2157
2158   ref_count = object->ref_count;
2159   g_assert_cmpint (ref_count, >, 1);
2160
2161   g_assert (g_task_get_source_object (task) == object);
2162   g_assert (g_async_result_get_source_object (G_ASYNC_RESULT (task)) == object);
2163   g_assert_cmpint (object->ref_count, ==, ref_count + 1);
2164   g_object_unref (object);
2165
2166   g_object_unref (object);
2167   g_assert (object != NULL);
2168
2169   g_task_return_int (task, magic);
2170   g_main_loop_run (loop);
2171
2172   g_assert (object != NULL);
2173   g_assert_cmpint (result, ==, magic);
2174   g_assert_true (notification_emitted);
2175
2176   g_object_unref (task);
2177   g_assert (task == NULL);
2178   g_assert (object == NULL);
2179 }
2180
2181 /* test_legacy_error: legacy GSimpleAsyncResult handling */
2182 static void test_legacy_error (void);
2183
2184 static void
2185 legacy_error_callback (GObject      *object,
2186                        GAsyncResult *result,
2187                        gpointer      user_data)
2188 {
2189   gssize *result_out = user_data;
2190   GError *error = NULL;
2191
2192   g_assert (object == NULL);
2193   g_assert (g_async_result_is_tagged (result, test_legacy_error));
2194   g_assert (g_async_result_get_user_data (result) == user_data);
2195
2196   if (g_async_result_legacy_propagate_error (result, &error))
2197     {
2198       g_assert (!g_task_is_valid (result, object));
2199       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
2200       g_assert (g_simple_async_result_is_valid (result, object, test_legacy_error));
2201       G_GNUC_END_IGNORE_DEPRECATIONS;
2202
2203       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
2204       *result_out = -2;
2205       g_clear_error (&error);
2206     }
2207   else
2208     {
2209       g_assert (g_task_is_valid (result, object));
2210
2211       *result_out = g_task_propagate_int (G_TASK (result), NULL);
2212       /* Might be error, might not */
2213     }
2214
2215   g_main_loop_quit (loop);
2216 }
2217
2218 static gboolean
2219 legacy_error_return (gpointer user_data)
2220 {
2221   if (G_IS_TASK (user_data))
2222     {
2223       GTask *task = user_data;
2224
2225       g_task_return_int (task, magic);
2226       g_object_unref (task);
2227     }
2228   else
2229     {
2230       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
2231
2232       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
2233       g_simple_async_result_set_error (simple,
2234                                        G_IO_ERROR,
2235                                        G_IO_ERROR_FAILED,
2236                                        "Failed");
2237       g_simple_async_result_complete (simple);
2238       G_GNUC_END_IGNORE_DEPRECATIONS;
2239       g_object_unref (simple);
2240     }
2241
2242   return FALSE;
2243 }
2244
2245 static void
2246 test_legacy_error (void)
2247 {
2248   GTask *task;
2249   GSimpleAsyncResult *simple;
2250   gssize result;
2251
2252   /* GTask success */
2253   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
2254   g_task_set_source_tag (task, test_legacy_error);
2255   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
2256
2257   g_idle_add (legacy_error_return, task);
2258   g_main_loop_run (loop);
2259
2260   g_assert_cmpint (result, ==, magic);
2261   g_assert (task == NULL);
2262
2263   /* GTask error */
2264   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
2265   g_task_set_source_tag (task, test_legacy_error);
2266   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
2267
2268   g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
2269                            "Failed");
2270   g_object_unref (task);
2271   g_main_loop_run (loop);
2272
2273   g_assert_cmpint (result, ==, -1);
2274   g_assert (task == NULL);
2275
2276   /* GSimpleAsyncResult error */
2277   G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
2278   simple = g_simple_async_result_new (NULL, legacy_error_callback, &result,
2279                                       test_legacy_error);
2280   G_GNUC_END_IGNORE_DEPRECATIONS;
2281   g_object_add_weak_pointer (G_OBJECT (simple), (gpointer *)&simple);
2282
2283   g_idle_add (legacy_error_return, simple);
2284   g_main_loop_run (loop);
2285
2286   g_assert_cmpint (result, ==, -2);
2287   g_assert (simple == NULL);
2288 }
2289
2290 /* Various helper functions for the return tests below. */
2291 static void
2292 task_complete_cb (GObject *source,
2293                   GAsyncResult *result,
2294                   gpointer user_data)
2295 {
2296   GTask *task = G_TASK (result);
2297   guint *calls = user_data;
2298
2299   g_assert_cmpint (++*calls, <=, 1);
2300
2301   /* Propagate the result, so it’s removed from the task’s internal state. */
2302   g_task_propagate_boolean (task, NULL);
2303 }
2304
2305 static void
2306 return_twice (GTask *task)
2307 {
2308   gboolean error_first = GPOINTER_TO_UINT (g_task_get_task_data (task));
2309
2310   if (error_first)
2311     {
2312       g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "oh no");
2313       g_task_return_boolean (task, TRUE);
2314     }
2315   else
2316     {
2317       g_task_return_boolean (task, TRUE);
2318       g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "oh no");
2319     }
2320 }
2321
2322 static gboolean
2323 idle_cb (gpointer user_data)
2324 {
2325   GTask *task = user_data;
2326   return_twice (task);
2327   g_object_unref (task);
2328
2329   return G_SOURCE_REMOVE;
2330 }
2331
2332 static void
2333 test_return_permutation (gboolean error_first,
2334                          gboolean return_in_idle)
2335 {
2336   guint calls = 0;
2337   GTask *task = NULL;
2338
2339   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1525");
2340
2341   task = g_task_new (NULL, NULL, task_complete_cb, &calls);
2342   g_task_set_task_data (task, GUINT_TO_POINTER (error_first), NULL);
2343
2344   if (return_in_idle)
2345     g_idle_add (idle_cb, g_object_ref (task));
2346   else
2347     return_twice (task);
2348
2349   while (calls == 0)
2350     g_main_context_iteration (NULL, TRUE);
2351
2352   g_assert_cmpint (calls, ==, 1);
2353
2354   g_object_unref (task);
2355 }
2356
2357 /* Test that calling g_task_return_boolean() after g_task_return_error(), when
2358  * returning in an idle callback, correctly results in a critical warning. */
2359 static void
2360 test_return_in_idle_error_first (void)
2361 {
2362   if (g_test_subprocess ())
2363     {
2364       test_return_permutation (TRUE, TRUE);
2365       return;
2366     }
2367
2368   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
2369   g_test_trap_assert_failed ();
2370   g_test_trap_assert_stderr ("*CRITICAL*assertion '!task->ever_returned' failed*");
2371 }
2372
2373 /* Test that calling g_task_return_error() after g_task_return_boolean(), when
2374  * returning in an idle callback, correctly results in a critical warning. */
2375 static void
2376 test_return_in_idle_value_first (void)
2377 {
2378   if (g_test_subprocess ())
2379     {
2380       test_return_permutation (FALSE, TRUE);
2381       return;
2382     }
2383
2384   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
2385   g_test_trap_assert_failed ();
2386   g_test_trap_assert_stderr ("*CRITICAL*assertion '!task->ever_returned' failed*");
2387 }
2388
2389 /* Test that calling g_task_return_boolean() after g_task_return_error(), when
2390  * returning synchronously, correctly results in a critical warning. */
2391 static void
2392 test_return_error_first (void)
2393 {
2394   if (g_test_subprocess ())
2395     {
2396       test_return_permutation (TRUE, FALSE);
2397       return;
2398     }
2399
2400   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
2401   g_test_trap_assert_failed ();
2402   g_test_trap_assert_stderr ("*CRITICAL*assertion '!task->ever_returned' failed*");
2403 }
2404
2405 /* Test that calling g_task_return_error() after g_task_return_boolean(), when
2406  * returning synchronously, correctly results in a critical warning. */
2407 static void
2408 test_return_value_first (void)
2409 {
2410   if (g_test_subprocess ())
2411     {
2412       test_return_permutation (FALSE, FALSE);
2413       return;
2414     }
2415
2416   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
2417   g_test_trap_assert_failed ();
2418   g_test_trap_assert_stderr ("*CRITICAL*assertion '!task->ever_returned' failed*");
2419 }
2420
2421 static gboolean
2422 source_cb (gpointer user_data)
2423 {
2424   return G_SOURCE_REMOVE;
2425 }
2426
2427 static void
2428 test_attach_source_set_name (void)
2429 {
2430   guint calls = 0;
2431   GTask *task = NULL;
2432   GSource *source = NULL;
2433   GSourceFuncs source_funcs = { NULL, NULL, NULL, NULL, NULL, NULL };
2434
2435   g_test_summary ("Test that attaching a source to a task will set the source’s name if unset");
2436
2437   task = g_task_new (NULL, NULL, task_complete_cb, &calls);
2438   g_task_set_name (task, "test name");
2439
2440   source = g_source_new (&source_funcs, sizeof (GSource));
2441   g_task_attach_source (task, source, source_cb);
2442   g_assert_cmpstr (g_source_get_name (source), ==, "test name");
2443   g_source_unref (source);
2444
2445   source = g_source_new (&source_funcs, sizeof (GSource));
2446   g_source_set_name (source, "not the task name");
2447   g_task_attach_source (task, source, source_cb);
2448   g_assert_cmpstr (g_source_get_name (source), ==, "not the task name");
2449   g_source_unref (source);
2450
2451   g_object_unref (task);
2452 }
2453
2454 static void
2455 test_finalize_without_return (void)
2456 {
2457   GTask *task = NULL;
2458   guint n_calls = 0;
2459
2460   /* With a callback set. */
2461   task = g_task_new (NULL, NULL, task_complete_cb, &n_calls);
2462
2463   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2464                          "GTask * (source object: *, source tag: *) finalized without "
2465                          "ever returning (using g_task_return_*()). This potentially "
2466                          "indicates a bug in the program.");
2467   g_object_unref (task);
2468   g_test_assert_expected_messages ();
2469
2470   /* With a callback and task name set. */
2471   task = g_task_new (NULL, NULL, task_complete_cb, &n_calls);
2472   g_task_set_static_name (task, "oogly boogly");
2473
2474   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2475                          "GTask oogly boogly (source object: *, source tag: *) finalized without "
2476                          "ever returning (using g_task_return_*()). This potentially "
2477                          "indicates a bug in the program.");
2478   g_object_unref (task);
2479   g_test_assert_expected_messages ();
2480
2481   /* Without a callback set. */
2482   task = g_task_new (NULL, NULL, NULL, NULL);
2483
2484   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
2485                          "GTask * (source object: *, source tag: *) finalized without "
2486                          "ever returning (using g_task_return_*()). This potentially "
2487                          "indicates a bug in the program.");
2488   g_object_unref (task);
2489   g_test_assert_expected_messages ();
2490 }
2491
2492 int
2493 main (int argc, char **argv)
2494 {
2495   int ret;
2496
2497   g_test_init (&argc, &argv, NULL);
2498
2499   loop = g_main_loop_new (NULL, FALSE);
2500   main_thread = g_thread_self ();
2501   magic = g_get_monotonic_time ();
2502
2503   g_test_add_func ("/gtask/basic", test_basic);
2504   g_test_add_func ("/gtask/error", test_error);
2505   g_test_add_func ("/gtask/return-from-same-iteration", test_return_from_same_iteration);
2506   g_test_add_func ("/gtask/return-from-toplevel", test_return_from_toplevel);
2507   g_test_add_func ("/gtask/return-from-anon-thread", test_return_from_anon_thread);
2508   g_test_add_func ("/gtask/return-from-wrong-thread", test_return_from_wrong_thread);
2509   g_test_add_func ("/gtask/no-callback", test_no_callback);
2510   g_test_add_func ("/gtask/report-error", test_report_error);
2511   g_test_add_func ("/gtask/priority", test_priority);
2512   g_test_add_func ("/gtask/name", test_name);
2513   g_test_add_func ("/gtask/name/macro-wrapper", test_name_macro_wrapper);
2514   g_test_add_func ("/gtask/static-name", test_static_name);
2515   g_test_add_func ("/gtask/asynchronous-cancellation", test_asynchronous_cancellation);
2516   g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
2517   g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
2518   g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
2519   g_test_add_func ("/gtask/run-in-thread-sync", test_run_in_thread_sync);
2520   g_test_add_func ("/gtask/run-in-thread-priority", test_run_in_thread_priority);
2521   g_test_add_func ("/gtask/run-in-thread-nested", test_run_in_thread_nested);
2522   g_test_add_func ("/gtask/run-in-thread-overflow", test_run_in_thread_overflow);
2523   g_test_add_func ("/gtask/return-on-cancel", test_return_on_cancel);
2524   g_test_add_func ("/gtask/return-on-cancel-sync", test_return_on_cancel_sync);
2525   g_test_add_func ("/gtask/return-on-cancel-atomic", test_return_on_cancel_atomic);
2526   g_test_add_func ("/gtask/return-pointer", test_return_pointer);
2527   g_test_add_func ("/gtask/return-value", test_return_value);
2528   g_test_add_func ("/gtask/object-keepalive", test_object_keepalive);
2529   g_test_add_func ("/gtask/legacy-error", test_legacy_error);
2530   g_test_add_func ("/gtask/return/in-idle/error-first", test_return_in_idle_error_first);
2531   g_test_add_func ("/gtask/return/in-idle/value-first", test_return_in_idle_value_first);
2532   g_test_add_func ("/gtask/return/error-first", test_return_error_first);
2533   g_test_add_func ("/gtask/return/value-first", test_return_value_first);
2534   g_test_add_func ("/gtask/attach-source/set-name", test_attach_source_set_name);
2535   g_test_add_func ("/gtask/finalize-without-return", test_finalize_without_return);
2536
2537   ret = g_test_run();
2538
2539   g_main_loop_unref (loop);
2540
2541   return ret;
2542 }