Remove g_type_init() calls
[platform/upstream/glib.git] / gio / tests / task.c
1 /*
2  * Copyright 2012 Red Hat, Inc.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2 of the licence or (at
7  * your option) any later version.
8  *
9  * See the included COPYING file for more information.
10  */
11
12 #include <gio/gio.h>
13
14 static GMainLoop *loop;
15 static GThread *main_thread;
16 static gssize magic;
17
18 /* We need objects for a few tests where we don't care what type
19  * they are, just that they're GObjects.
20  */
21 #define g_dummy_object_new g_socket_client_new
22
23 /* test_basic */
24
25 static void
26 basic_callback (GObject      *object,
27                 GAsyncResult *result,
28                 gpointer      user_data)
29 {
30   gssize *result_out = user_data;
31   GError *error = NULL;
32
33   g_assert (object == NULL);
34   g_assert (g_task_is_valid (result, object));
35   g_assert (g_async_result_get_user_data (result) == user_data);
36   g_assert (!g_task_had_error (G_TASK (result)));
37
38   *result_out = g_task_propagate_int (G_TASK (result), &error);
39   g_assert_no_error (error);
40
41   g_main_loop_quit (loop);
42 }
43
44 static gboolean
45 basic_return (gpointer user_data)
46 {
47   GTask *task = user_data;
48
49   g_task_return_int (task, magic);
50   g_object_unref (task);
51
52   return FALSE;
53 }
54
55 static void
56 basic_destroy_notify (gpointer user_data)
57 {
58   gboolean *destroyed = user_data;
59
60   *destroyed = TRUE;
61 }
62
63 static void
64 test_basic (void)
65 {
66   GTask *task;
67   gssize result;
68   gboolean task_data_destroyed = FALSE;
69
70   task = g_task_new (NULL, NULL, basic_callback, &result);
71   g_task_set_task_data (task, &task_data_destroyed, basic_destroy_notify);
72   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
73
74   g_idle_add (basic_return, task);
75   g_main_loop_run (loop);
76
77   g_assert_cmpint (result, ==, magic);
78   g_assert (task_data_destroyed == TRUE);
79   g_assert (task == NULL);
80 }
81
82 /* test_error */
83
84 static void
85 error_callback (GObject      *object,
86                 GAsyncResult *result,
87                 gpointer      user_data)
88 {
89   gssize *result_out = user_data;
90   GError *error = NULL;
91
92   g_assert (object == NULL);
93   g_assert (g_task_is_valid (result, object));
94   g_assert (g_async_result_get_user_data (result) == user_data);
95   g_assert (g_task_had_error (G_TASK (result)));
96
97   *result_out = g_task_propagate_int (G_TASK (result), &error);
98   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
99   g_error_free (error);
100
101   g_main_loop_quit (loop);
102 }
103
104 static gboolean
105 error_return (gpointer user_data)
106 {
107   GTask *task = user_data;
108
109   g_task_return_new_error (task,
110                            G_IO_ERROR, G_IO_ERROR_FAILED,
111                            "Failed");
112   g_object_unref (task);
113
114   return FALSE;
115 }
116
117 static void
118 error_destroy_notify (gpointer user_data)
119 {
120   gboolean *destroyed = user_data;
121
122   *destroyed = TRUE;
123 }
124
125 static void
126 test_error (void)
127 {
128   GTask *task;
129   gssize result;
130   gboolean first_task_data_destroyed = FALSE;
131   gboolean second_task_data_destroyed = FALSE;
132
133   task = g_task_new (NULL, NULL, error_callback, &result);
134   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
135
136   g_assert (first_task_data_destroyed == FALSE);
137   g_task_set_task_data (task, &first_task_data_destroyed, error_destroy_notify);
138   g_assert (first_task_data_destroyed == FALSE);
139
140   /* Calling g_task_set_task_data() again will destroy the first data */
141   g_task_set_task_data (task, &second_task_data_destroyed, error_destroy_notify);
142   g_assert (first_task_data_destroyed == TRUE);
143   g_assert (second_task_data_destroyed == FALSE);
144
145   g_idle_add (error_return, task);
146   g_main_loop_run (loop);
147
148   g_assert_cmpint (result, ==, -1);
149   g_assert (second_task_data_destroyed == TRUE);
150   g_assert (task == NULL);
151 }
152
153 /* test_return_from_same_iteration: calling g_task_return_* from the
154  * loop iteration the task was created in defers completion until the
155  * next iteration.
156  */
157 gboolean same_result = FALSE;
158
159 static void
160 same_callback (GObject      *object,
161                GAsyncResult *result,
162                gpointer      user_data)
163 {
164   gboolean *result_out = user_data;
165   GError *error = NULL;
166
167   g_assert (object == NULL);
168   g_assert (g_task_is_valid (result, object));
169   g_assert (g_async_result_get_user_data (result) == user_data);
170   g_assert (!g_task_had_error (G_TASK (result)));
171
172   *result_out = g_task_propagate_boolean (G_TASK (result), &error);
173   g_assert_no_error (error);
174
175   g_main_loop_quit (loop);
176 }
177
178 static gboolean
179 same_start (gpointer user_data)
180 {
181   gpointer *weak_pointer = user_data;
182   GTask *task;
183
184   task = g_task_new (NULL, NULL, same_callback, &same_result);
185   *weak_pointer = task;
186   g_object_add_weak_pointer (G_OBJECT (task), weak_pointer);
187
188   g_task_return_boolean (task, TRUE);
189   g_object_unref (task);
190
191   /* same_callback should not have been invoked yet */
192   g_assert (same_result == FALSE);
193   g_assert (*weak_pointer == task);
194
195   return FALSE;
196 }
197
198 static void
199 test_return_from_same_iteration (void)
200 {
201   gpointer weak_pointer;
202
203   g_idle_add (same_start, &weak_pointer);
204   g_main_loop_run (loop);
205
206   g_assert (same_result == TRUE);
207   g_assert (weak_pointer == NULL);
208 }
209
210 /* test_return_from_toplevel: calling g_task_return_* from outside any
211  * main loop completes the task inside the main loop.
212  */
213
214 static void
215 toplevel_callback (GObject      *object,
216               GAsyncResult *result,
217               gpointer      user_data)
218 {
219   gboolean *result_out = user_data;
220   GError *error = NULL;
221
222   g_assert (object == NULL);
223   g_assert (g_task_is_valid (result, object));
224   g_assert (g_async_result_get_user_data (result) == user_data);
225   g_assert (!g_task_had_error (G_TASK (result)));
226
227   *result_out = g_task_propagate_boolean (G_TASK (result), &error);
228   g_assert_no_error (error);
229
230   g_main_loop_quit (loop);
231 }
232
233 static void
234 test_return_from_toplevel (void)
235 {
236   GTask *task;
237   gboolean result = FALSE;
238
239   task = g_task_new (NULL, NULL, toplevel_callback, &result);
240   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
241
242   g_task_return_boolean (task, TRUE);
243   g_object_unref (task);
244
245   /* toplevel_callback should not have been invoked yet */
246   g_assert (result == FALSE);
247   g_assert (task != NULL);
248
249   g_main_loop_run (loop);
250
251   g_assert (result == TRUE);
252   g_assert (task == NULL);
253 }
254
255 /* test_return_from_anon_thread: calling g_task_return_* from a
256  * thread with no thread-default main context will complete the
257  * task in the task's context/thread.
258  */
259
260 GThread *anon_thread;
261
262 static void
263 anon_callback (GObject      *object,
264                GAsyncResult *result,
265                gpointer      user_data)
266 {
267   gssize *result_out = user_data;
268   GError *error = NULL;
269
270   g_assert (object == NULL);
271   g_assert (g_task_is_valid (result, object));
272   g_assert (g_async_result_get_user_data (result) == user_data);
273   g_assert (!g_task_had_error (G_TASK (result)));
274
275   g_assert (g_thread_self () == main_thread);
276
277   *result_out = g_task_propagate_int (G_TASK (result), &error);
278   g_assert_no_error (error);
279
280   g_main_loop_quit (loop);
281 }
282
283 static gpointer
284 anon_thread_func (gpointer user_data)
285 {
286   GTask *task = user_data;
287
288   g_task_return_int (task, magic);
289   g_object_unref (task);
290
291   return NULL;
292 }
293
294 static gboolean
295 anon_start (gpointer user_data)
296 {
297   GTask *task = user_data;
298
299   anon_thread = g_thread_new ("test_return_from_anon_thread",
300                               anon_thread_func, task);
301   return FALSE;
302 }
303
304 static void
305 test_return_from_anon_thread (void)
306 {
307   GTask *task;
308   gssize result = 0;
309
310   task = g_task_new (NULL, NULL, anon_callback, &result);
311   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
312
313   g_idle_add (anon_start, task);
314   g_main_loop_run (loop);
315
316   g_thread_join (anon_thread);
317
318   g_assert_cmpint (result, ==, magic);
319   g_assert (task == NULL);
320 }
321
322 /* test_return_from_wrong_thread: calling g_task_return_* from a
323  * thread with its own thread-default main context will complete the
324  * task in the task's context/thread.
325  */
326
327 GThread *wrong_thread;
328
329 static void
330 wrong_callback (GObject      *object,
331                GAsyncResult *result,
332                gpointer      user_data)
333 {
334   gssize *result_out = user_data;
335   GError *error = NULL;
336
337   g_assert (object == NULL);
338   g_assert (g_task_is_valid (result, object));
339   g_assert (g_async_result_get_user_data (result) == user_data);
340   g_assert (!g_task_had_error (G_TASK (result)));
341
342   g_assert (g_thread_self () == main_thread);
343
344   *result_out = g_task_propagate_int (G_TASK (result), &error);
345   g_assert_no_error (error);
346
347   g_main_loop_quit (loop);
348 }
349
350 static gpointer
351 wrong_thread_func (gpointer user_data)
352 {
353   GTask *task = user_data;
354   GMainContext *context;
355
356   context = g_main_context_new ();
357   g_main_context_push_thread_default (context);
358
359   g_assert (g_task_get_context (task) != context);
360
361   g_task_return_int (task, magic);
362   g_object_unref (task);
363
364   g_main_context_pop_thread_default (context);
365   g_main_context_unref (context);
366
367   return NULL;
368 }
369
370 static gboolean
371 wrong_start (gpointer user_data)
372 {
373   GTask *task = user_data;
374
375   wrong_thread = g_thread_new ("test_return_from_anon_thread",
376                                wrong_thread_func, task);
377   return FALSE;
378 }
379
380 static void
381 test_return_from_wrong_thread (void)
382 {
383   GTask *task;
384   gssize result = 0;
385
386   task = g_task_new (NULL, NULL, wrong_callback, &result);
387   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
388
389   g_idle_add (wrong_start, task);
390   g_main_loop_run (loop);
391
392   g_thread_join (wrong_thread);
393
394   g_assert_cmpint (result, ==, magic);
395   g_assert (task == NULL);
396 }
397
398 /* test_no_callback */
399
400 static void
401 test_no_callback (void)
402 {
403   GTask *task;
404
405   task = g_task_new (NULL, NULL, NULL, NULL);
406   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
407
408   g_task_return_boolean (task, TRUE);
409   g_object_unref (task);
410
411   /* Since there's no callback, g_task_return_boolean() will
412    * not have queued an idle source and taken a ref on task,
413    * so we just dropped the last ref.
414    */
415   g_assert (task == NULL);
416 }
417
418 /* test_report_error */
419
420 static void test_report_error (void);
421
422 static void
423 report_callback (GObject      *object,
424                  GAsyncResult *result,
425                  gpointer      user_data)
426 {
427   gpointer *weak_pointer = user_data;
428   GError *error = NULL;
429   gssize ret;
430
431   g_assert (object == NULL);
432   g_assert (g_task_is_valid (result, object));
433   g_assert (g_async_result_get_user_data (result) == user_data);
434   g_assert (g_async_result_is_tagged (result, test_report_error));
435   g_assert (g_task_get_source_tag (G_TASK (result)) == test_report_error);
436   g_assert (g_task_had_error (G_TASK (result)));
437
438   ret = g_task_propagate_int (G_TASK (result), &error);
439   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
440   g_assert_cmpint (ret, ==, -1);
441   g_error_free (error);
442
443   *weak_pointer = result;
444   g_object_add_weak_pointer (G_OBJECT (result), weak_pointer);
445
446   g_main_loop_quit (loop);
447 }
448
449 static void
450 test_report_error (void)
451 {
452   gpointer weak_pointer = (gpointer)-1;
453
454   g_task_report_new_error (NULL, report_callback, &weak_pointer,
455                            test_report_error,
456                            G_IO_ERROR, G_IO_ERROR_FAILED,
457                            "Failed");
458   g_main_loop_run (loop);
459
460   g_assert (weak_pointer == NULL);
461 }
462
463 /* test_priority: tasks complete in priority order */
464
465 static int counter = 0;
466
467 static void
468 priority_callback (GObject      *object,
469                    GAsyncResult *result,
470                    gpointer      user_data)
471 {
472   gssize *ret_out = user_data;
473   GError *error = NULL;
474
475   g_assert (object == NULL);
476   g_assert (g_task_is_valid (result, object));
477   g_assert (g_async_result_get_user_data (result) == user_data);
478   g_assert (!g_task_had_error (G_TASK (result)));
479
480   g_task_propagate_boolean (G_TASK (result), &error);
481   g_assert_no_error (error);
482
483   *ret_out = ++counter;
484
485   if (counter == 3)
486     g_main_loop_quit (loop);
487 }
488
489 static void
490 test_priority (void)
491 {
492   GTask *t1, *t2, *t3;
493   gssize ret1, ret2, ret3;
494
495   /* t2 has higher priority than either t1 or t3, so we can't
496    * accidentally pass the test just by completing the tasks in the
497    * order they were created (or in reverse order).
498    */
499
500   t1 = g_task_new (NULL, NULL, priority_callback, &ret1);
501   g_task_set_priority (t1, G_PRIORITY_DEFAULT);
502   g_task_return_boolean (t1, TRUE);
503   g_object_unref (t1);
504
505   t2 = g_task_new (NULL, NULL, priority_callback, &ret2);
506   g_task_set_priority (t2, G_PRIORITY_HIGH);
507   g_task_return_boolean (t2, TRUE);
508   g_object_unref (t2);
509
510   t3 = g_task_new (NULL, NULL, priority_callback, &ret3);
511   g_task_set_priority (t3, G_PRIORITY_LOW);
512   g_task_return_boolean (t3, TRUE);
513   g_object_unref (t3);
514
515   g_main_loop_run (loop);
516
517   g_assert_cmpint (ret2, ==, 1);
518   g_assert_cmpint (ret1, ==, 2);
519   g_assert_cmpint (ret3, ==, 3);
520 }
521
522 /* test_check_cancellable: cancellation overrides return value */
523
524 enum {
525   CANCEL_BEFORE     = (1 << 1),
526   CANCEL_AFTER      = (1 << 2),
527   CHECK_CANCELLABLE = (1 << 3)
528 };
529 #define NUM_CANCEL_TESTS (CANCEL_BEFORE | CANCEL_AFTER | CHECK_CANCELLABLE)
530
531 static void
532 cancel_callback (GObject      *object,
533                  GAsyncResult *result,
534                  gpointer      user_data)
535 {
536   int state = GPOINTER_TO_INT (user_data);
537   GTask *task;
538   GCancellable *cancellable;
539   GError *error = NULL;
540
541   g_assert (object == NULL);
542   g_assert (g_task_is_valid (result, object));
543   g_assert (g_async_result_get_user_data (result) == user_data);
544
545   task = G_TASK (result);
546   cancellable = g_task_get_cancellable (task);
547   g_assert (G_IS_CANCELLABLE (cancellable));
548
549   if (state & (CANCEL_BEFORE | CANCEL_AFTER))
550     g_assert (g_cancellable_is_cancelled (cancellable));
551   else
552     g_assert (!g_cancellable_is_cancelled (cancellable));
553
554   if (state & CHECK_CANCELLABLE)
555     g_assert (g_task_get_check_cancellable (task));
556   else
557     g_assert (!g_task_get_check_cancellable (task));
558
559   if (g_task_propagate_boolean (task, &error))
560     {
561       g_assert (!g_cancellable_is_cancelled (cancellable) ||
562                 !g_task_get_check_cancellable (task));
563     }
564   else
565     {
566       g_assert (g_cancellable_is_cancelled (cancellable) &&
567                 g_task_get_check_cancellable (task));
568       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
569       g_error_free (error);
570     }
571
572   g_main_loop_quit (loop);
573 }
574
575 static void
576 test_check_cancellable (void)
577 {
578   GTask *task;
579   GCancellable *cancellable;
580   int state;
581
582   cancellable = g_cancellable_new ();
583
584   for (state = 0; state <= NUM_CANCEL_TESTS; state++)
585     {
586       task = g_task_new (NULL, cancellable, cancel_callback,
587                          GINT_TO_POINTER (state));
588       g_task_set_check_cancellable (task, (state & CHECK_CANCELLABLE) != 0);
589
590       if (state & CANCEL_BEFORE)
591         g_cancellable_cancel (cancellable);
592       g_task_return_boolean (task, TRUE);
593       if (state & CANCEL_AFTER)
594         g_cancellable_cancel (cancellable);
595
596       g_main_loop_run (loop);
597       g_object_unref (task);
598       g_cancellable_reset (cancellable);
599     }
600
601   g_object_unref (cancellable);
602 }
603
604 /* test_return_if_cancelled */
605
606 static void
607 return_if_cancelled_callback (GObject      *object,
608                               GAsyncResult *result,
609                               gpointer      user_data)
610 {
611   GError *error = NULL;
612
613   g_assert (object == NULL);
614   g_assert (g_task_is_valid (result, object));
615   g_assert (g_async_result_get_user_data (result) == user_data);
616   g_assert (g_task_had_error (G_TASK (result)));
617
618   g_task_propagate_boolean (G_TASK (result), &error);
619   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
620   g_clear_error (&error);
621
622   g_main_loop_quit (loop);
623 }
624
625 static void
626 test_return_if_cancelled (void)
627 {
628   GTask *task;
629   GCancellable *cancellable;
630   gboolean cancelled;
631
632   cancellable = g_cancellable_new ();
633
634   task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
635   g_cancellable_cancel (cancellable);
636   cancelled = g_task_return_error_if_cancelled (task);
637   g_assert (cancelled);
638   g_main_loop_run (loop);
639   g_object_unref (task);
640   g_cancellable_reset (cancellable);
641
642   task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
643   g_task_set_check_cancellable (task, FALSE);
644   g_cancellable_cancel (cancellable);
645   cancelled = g_task_return_error_if_cancelled (task);
646   g_assert (cancelled);
647   g_main_loop_run (loop);
648   g_object_unref (task);
649   g_object_unref (cancellable);
650 }
651
652 /* test_run_in_thread */
653
654 static void
655 run_in_thread_callback (GObject      *object,
656                         GAsyncResult *result,
657                         gpointer      user_data)
658 {
659   gboolean *done = user_data;
660   GError *error = NULL;
661   gssize ret;
662
663   g_assert (g_thread_self () == main_thread);
664
665   g_assert (object == NULL);
666   g_assert (g_task_is_valid (result, object));
667   g_assert (g_async_result_get_user_data (result) == user_data);
668   g_assert (!g_task_had_error (G_TASK (result)));
669
670   ret = g_task_propagate_int (G_TASK (result), &error);
671   g_assert_no_error (error);
672   g_assert_cmpint (ret, ==, magic);
673
674   *done = TRUE;
675   g_main_loop_quit (loop);
676 }
677
678 static void
679 run_in_thread_thread (GTask        *task,
680                       gpointer      source_object,
681                       gpointer      task_data,
682                       GCancellable *cancellable)
683 {
684   gboolean *thread_ran = task_data;
685
686   g_assert (source_object == g_task_get_source_object (task));
687   g_assert (task_data == g_task_get_task_data (task));
688   g_assert (cancellable == g_task_get_cancellable (task));
689
690   g_assert (g_thread_self () != main_thread);
691
692   *thread_ran = TRUE;
693   g_task_return_int (task, magic);
694 }
695
696 static void
697 test_run_in_thread (void)
698 {
699   GTask *task;
700   volatile gboolean thread_ran = FALSE;
701   gboolean done = FALSE;
702
703   task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
704   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
705
706   g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
707   g_task_run_in_thread (task, run_in_thread_thread);
708   g_object_unref (task);
709
710   while (!thread_ran)
711     g_usleep (100);
712
713   g_assert (done == FALSE);
714   g_assert (task != NULL);
715
716   g_main_loop_run (loop);
717
718   g_assert (done == TRUE);
719   g_assert (task == NULL);
720 }
721
722 /* test_run_in_thread_sync */
723
724 static void
725 run_in_thread_sync_callback (GObject      *object,
726                              GAsyncResult *result,
727                              gpointer      user_data)
728 {
729   /* g_task_run_in_thread_sync() does not invoke the task's callback */
730   g_assert_not_reached ();
731 }
732
733 static void
734 run_in_thread_sync_thread (GTask        *task,
735                            gpointer      source_object,
736                            gpointer      task_data,
737                            GCancellable *cancellable)
738 {
739   gboolean *thread_ran = task_data;
740
741   g_assert (source_object == g_task_get_source_object (task));
742   g_assert (task_data == g_task_get_task_data (task));
743   g_assert (cancellable == g_task_get_cancellable (task));
744
745   g_assert (g_thread_self () != main_thread);
746
747   *thread_ran = TRUE;
748   g_task_return_int (task, magic);
749 }
750
751 static void
752 test_run_in_thread_sync (void)
753 {
754   GTask *task;
755   gboolean thread_ran = FALSE;
756   gssize ret;
757   GError *error = NULL;
758
759   task = g_task_new (NULL, NULL, run_in_thread_sync_callback, NULL);
760
761   g_task_set_task_data (task, &thread_ran, NULL);
762   g_task_run_in_thread_sync (task, run_in_thread_sync_thread);
763
764   g_assert (thread_ran == TRUE);
765   g_assert (task != NULL);
766   g_assert (!g_task_had_error (task));
767
768   ret = g_task_propagate_int (task, &error);
769   g_assert_no_error (error);
770   g_assert_cmpint (ret, ==, magic);
771
772   g_object_unref (task);
773 }
774
775 /* test_run_in_thread_priority */
776
777 static GMutex fake_task_mutex, last_fake_task_mutex;
778 static gint sequence_number = 0;
779
780 static void
781 quit_main_loop_callback (GObject      *object,
782                          GAsyncResult *result,
783                          gpointer      user_data)
784 {
785   GError *error = NULL;
786   gboolean ret;
787
788   g_assert (g_thread_self () == main_thread);
789
790   g_assert (object == NULL);
791   g_assert (g_task_is_valid (result, object));
792   g_assert (g_async_result_get_user_data (result) == user_data);
793   g_assert (!g_task_had_error (G_TASK (result)));
794
795   ret = g_task_propagate_boolean (G_TASK (result), &error);
796   g_assert_no_error (error);
797   g_assert_cmpint (ret, ==, TRUE);
798
799   g_main_loop_quit (loop);
800 }
801
802 static void
803 set_sequence_number_thread (GTask        *task,
804                             gpointer      source_object,
805                             gpointer      task_data,
806                             GCancellable *cancellable)
807 {
808   gint *seq_no_p = task_data;
809
810   *seq_no_p = ++sequence_number;
811   g_task_return_boolean (task, TRUE);
812 }
813
814 static void
815 fake_task_thread (GTask        *task,
816                   gpointer      source_object,
817                   gpointer      task_data,
818                   GCancellable *cancellable)
819 {
820   GMutex *mutex = task_data;
821
822   g_mutex_lock (mutex);
823   g_mutex_unlock (mutex);
824   g_task_return_boolean (task, TRUE);
825 }
826
827 #define G_TASK_THREAD_POOL_SIZE 10
828
829 static void
830 test_run_in_thread_priority (void)
831 {
832   GTask *task;
833   GCancellable *cancellable;
834   int seq_a, seq_b, seq_c, seq_d;
835   int i;
836
837   /* Flush the thread pool, then clog it up with junk tasks */
838   g_thread_pool_stop_unused_threads ();
839
840   g_mutex_lock (&fake_task_mutex);
841   for (i = 0; i < G_TASK_THREAD_POOL_SIZE - 1; i++)
842     {
843       task = g_task_new (NULL, NULL, NULL, NULL);
844       g_task_set_task_data (task, &fake_task_mutex, NULL);
845       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_DEFAULT);
846       g_task_set_priority (task, G_PRIORITY_HIGH * 2);
847       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_HIGH * 2);
848       g_task_run_in_thread (task, fake_task_thread);
849       g_object_unref (task);
850     }
851
852   g_mutex_lock (&last_fake_task_mutex);
853   task = g_task_new (NULL, NULL, NULL, NULL);
854   g_task_set_task_data (task, &last_fake_task_mutex, NULL);
855   g_task_set_priority (task, G_PRIORITY_HIGH * 2);
856   g_task_run_in_thread (task, fake_task_thread);
857   g_object_unref (task);
858
859   /* Queue three more tasks that we'll arrange to have run serially */
860   task = g_task_new (NULL, NULL, NULL, NULL);
861   g_task_set_task_data (task, &seq_a, NULL);
862   g_task_run_in_thread (task, set_sequence_number_thread);
863   g_object_unref (task);
864   
865   task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
866   g_task_set_task_data (task, &seq_b, NULL);
867   g_task_set_priority (task, G_PRIORITY_LOW);
868   g_task_run_in_thread (task, set_sequence_number_thread);
869   g_object_unref (task);
870   
871   task = g_task_new (NULL, NULL, NULL, NULL);
872   g_task_set_task_data (task, &seq_c, NULL);
873   g_task_set_priority (task, G_PRIORITY_HIGH);
874   g_task_run_in_thread (task, set_sequence_number_thread);
875   g_object_unref (task);
876   
877   cancellable = g_cancellable_new ();
878   task = g_task_new (NULL, cancellable, NULL, NULL);
879   g_task_set_task_data (task, &seq_d, NULL);
880   g_task_run_in_thread (task, set_sequence_number_thread);
881   g_cancellable_cancel (cancellable);
882   g_object_unref (cancellable);
883   g_object_unref (task);
884
885   /* Let the last fake task complete; the four other tasks will then
886    * complete serially, in the order D, C, A, B, and B will quit the
887    * main loop.
888    */
889   g_mutex_unlock (&last_fake_task_mutex);
890   g_main_loop_run (loop);
891
892   g_assert_cmpint (seq_d, ==, 1);
893   g_assert_cmpint (seq_c, ==, 2);
894   g_assert_cmpint (seq_a, ==, 3);
895   g_assert_cmpint (seq_b, ==, 4);
896
897   g_mutex_unlock (&fake_task_mutex);
898 }
899
900 /* test_return_on_cancel */
901
902 GMutex roc_init_mutex, roc_finish_mutex;
903 GCond roc_init_cond, roc_finish_cond;
904
905 typedef enum {
906   THREAD_STARTING,
907   THREAD_RUNNING,
908   THREAD_CANCELLED,
909   THREAD_COMPLETED
910 } ThreadState;
911
912 static void
913 return_on_cancel_callback (GObject      *object,
914                            GAsyncResult *result,
915                            gpointer      user_data)
916 {
917   gboolean *callback_ran = user_data;
918   GError *error = NULL;
919   gssize ret;
920
921   g_assert (g_thread_self () == main_thread);
922
923   g_assert (object == NULL);
924   g_assert (g_task_is_valid (result, object));
925   g_assert (g_async_result_get_user_data (result) == user_data);
926   g_assert (g_task_had_error (G_TASK (result)));
927
928   ret = g_task_propagate_int (G_TASK (result), &error);
929   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
930   g_clear_error (&error);
931   g_assert_cmpint (ret, ==, -1);
932
933   *callback_ran = TRUE;
934   g_main_loop_quit (loop);
935 }
936
937 static void
938 return_on_cancel_thread (GTask        *task,
939                          gpointer      source_object,
940                          gpointer      task_data,
941                          GCancellable *cancellable)
942 {
943   ThreadState *state = task_data;
944
945   g_assert (source_object == g_task_get_source_object (task));
946   g_assert (task_data == g_task_get_task_data (task));
947   g_assert (cancellable == g_task_get_cancellable (task));
948
949   g_assert (g_thread_self () != main_thread);
950
951   g_mutex_lock (&roc_init_mutex);
952   *state = THREAD_RUNNING;
953   g_cond_signal (&roc_init_cond);
954   g_mutex_unlock (&roc_init_mutex);
955
956   g_mutex_lock (&roc_finish_mutex);
957
958   if (!g_task_get_return_on_cancel (task) ||
959       g_task_set_return_on_cancel (task, FALSE))
960     {
961       *state = THREAD_COMPLETED;
962       g_task_return_int (task, magic);
963     }
964   else
965     *state = THREAD_CANCELLED;
966
967   g_cond_signal (&roc_finish_cond);
968   g_mutex_unlock (&roc_finish_mutex);
969 }
970
971 static void
972 test_return_on_cancel (void)
973 {
974   GTask *task;
975   GCancellable *cancellable;
976   volatile ThreadState thread_state;
977   gboolean callback_ran;
978
979   cancellable = g_cancellable_new ();
980
981   /* If return-on-cancel is FALSE (default), the task does not return
982    * early.
983    */
984   callback_ran = FALSE;
985   thread_state = THREAD_STARTING;
986   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
987
988   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
989   g_mutex_lock (&roc_init_mutex);
990   g_mutex_lock (&roc_finish_mutex);
991   g_task_run_in_thread (task, return_on_cancel_thread);
992   g_object_unref (task);
993
994   while (thread_state == THREAD_STARTING)
995     g_cond_wait (&roc_init_cond, &roc_init_mutex);
996   g_mutex_unlock (&roc_init_mutex);
997
998   g_assert (thread_state == THREAD_RUNNING);
999   g_assert (callback_ran == FALSE);
1000
1001   g_cancellable_cancel (cancellable);
1002   g_mutex_unlock (&roc_finish_mutex);
1003   g_main_loop_run (loop);
1004
1005   g_assert (thread_state == THREAD_COMPLETED);
1006   g_assert (callback_ran == TRUE);
1007
1008   g_cancellable_reset (cancellable);
1009
1010   /* If return-on-cancel is TRUE, it does return early */
1011   callback_ran = FALSE;
1012   thread_state = THREAD_STARTING;
1013   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1014   g_task_set_return_on_cancel (task, TRUE);
1015
1016   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1017   g_mutex_lock (&roc_init_mutex);
1018   g_mutex_lock (&roc_finish_mutex);
1019   g_task_run_in_thread (task, return_on_cancel_thread);
1020   g_object_unref (task);
1021
1022   while (thread_state == THREAD_STARTING)
1023     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1024   g_mutex_unlock (&roc_init_mutex);
1025
1026   g_assert (thread_state == THREAD_RUNNING);
1027   g_assert (callback_ran == FALSE);
1028
1029   g_cancellable_cancel (cancellable);
1030   g_main_loop_run (loop);
1031   g_assert (thread_state == THREAD_RUNNING);
1032   g_assert (callback_ran == TRUE);
1033
1034   while (thread_state == THREAD_RUNNING)
1035     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1036   g_mutex_unlock (&roc_finish_mutex);
1037
1038   g_assert (thread_state == THREAD_CANCELLED);
1039   /* We can't g_assert (task == NULL) here because it won't become NULL
1040    * until a little bit after roc_finish_cond is signaled.
1041    */
1042
1043   g_cancellable_reset (cancellable);
1044
1045   /* If the task is already cancelled before it starts, it returns
1046    * immediately, but the thread func still runs.
1047    */
1048   callback_ran = FALSE;
1049   thread_state = THREAD_STARTING;
1050   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1051   g_task_set_return_on_cancel (task, TRUE);
1052
1053   g_cancellable_cancel (cancellable);
1054
1055   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1056   g_mutex_lock (&roc_init_mutex);
1057   g_mutex_lock (&roc_finish_mutex);
1058   g_task_run_in_thread (task, return_on_cancel_thread);
1059   g_object_unref (task);
1060
1061   g_main_loop_run (loop);
1062   g_assert (callback_ran == TRUE);
1063
1064   while (thread_state == THREAD_STARTING)
1065     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1066   g_mutex_unlock (&roc_init_mutex);
1067
1068   g_assert (thread_state == THREAD_RUNNING);
1069
1070   while (thread_state == THREAD_RUNNING)
1071     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1072   g_mutex_unlock (&roc_finish_mutex);
1073
1074   g_assert (thread_state == THREAD_CANCELLED);
1075
1076   g_object_unref (cancellable);
1077 }
1078
1079 /* test_return_on_cancel_sync */
1080
1081 static gpointer
1082 cancel_sync_runner_thread (gpointer task)
1083 {
1084   g_task_run_in_thread_sync (task, return_on_cancel_thread);
1085   return NULL;
1086 }
1087
1088 static void
1089 test_return_on_cancel_sync (void)
1090 {
1091   GTask *task;
1092   GCancellable *cancellable;
1093   volatile ThreadState thread_state;
1094   GThread *runner_thread;
1095   gssize ret;
1096   GError *error = NULL;
1097
1098   cancellable = g_cancellable_new ();
1099
1100   /* If return-on-cancel is FALSE, the task does not return early.
1101    */
1102   thread_state = THREAD_STARTING;
1103   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1104
1105   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1106   g_mutex_lock (&roc_init_mutex);
1107   g_mutex_lock (&roc_finish_mutex);
1108   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1109                                 cancel_sync_runner_thread, task);
1110
1111   while (thread_state == THREAD_STARTING)
1112     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1113   g_mutex_unlock (&roc_init_mutex);
1114
1115   g_assert (thread_state == THREAD_RUNNING);
1116
1117   g_cancellable_cancel (cancellable);
1118   g_mutex_unlock (&roc_finish_mutex);
1119   g_thread_join (runner_thread);
1120   g_assert (thread_state == THREAD_COMPLETED);
1121
1122   ret = g_task_propagate_int (task, &error);
1123   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1124   g_clear_error (&error);
1125   g_assert_cmpint (ret, ==, -1);
1126
1127   g_object_unref (task);
1128
1129   g_cancellable_reset (cancellable);
1130
1131   /* If return-on-cancel is TRUE, it does return early */
1132   thread_state = THREAD_STARTING;
1133   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1134   g_task_set_return_on_cancel (task, TRUE);
1135
1136   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1137   g_mutex_lock (&roc_init_mutex);
1138   g_mutex_lock (&roc_finish_mutex);
1139   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1140                                 cancel_sync_runner_thread, task);
1141
1142   while (thread_state == THREAD_STARTING)
1143     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1144   g_mutex_unlock (&roc_init_mutex);
1145
1146   g_assert (thread_state == THREAD_RUNNING);
1147
1148   g_cancellable_cancel (cancellable);
1149   g_thread_join (runner_thread);
1150   g_assert (thread_state == THREAD_RUNNING);
1151
1152   ret = g_task_propagate_int (task, &error);
1153   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1154   g_clear_error (&error);
1155   g_assert_cmpint (ret, ==, -1);
1156
1157   g_object_unref (task);
1158
1159   while (thread_state == THREAD_RUNNING)
1160     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1161   g_mutex_unlock (&roc_finish_mutex);
1162
1163   g_assert (thread_state == THREAD_CANCELLED);
1164
1165   g_cancellable_reset (cancellable);
1166
1167   /* If the task is already cancelled before it starts, it returns
1168    * immediately, but the thread func still runs.
1169    */
1170   thread_state = THREAD_STARTING;
1171   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1172   g_task_set_return_on_cancel (task, TRUE);
1173
1174   g_cancellable_cancel (cancellable);
1175
1176   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1177   g_mutex_lock (&roc_init_mutex);
1178   g_mutex_lock (&roc_finish_mutex);
1179   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1180                                 cancel_sync_runner_thread, task);
1181
1182   g_thread_join (runner_thread);
1183   g_assert (thread_state == THREAD_STARTING);
1184
1185   ret = g_task_propagate_int (task, &error);
1186   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1187   g_clear_error (&error);
1188   g_assert_cmpint (ret, ==, -1);
1189
1190   g_object_unref (task);
1191
1192   while (thread_state == THREAD_STARTING)
1193     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1194   g_mutex_unlock (&roc_init_mutex);
1195
1196   g_assert (thread_state == THREAD_RUNNING);
1197
1198   while (thread_state == THREAD_RUNNING)
1199     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1200   g_mutex_unlock (&roc_finish_mutex);
1201
1202   g_assert (thread_state == THREAD_CANCELLED);
1203
1204   g_object_unref (cancellable);
1205 }
1206
1207 /* test_return_on_cancel_atomic: turning return-on-cancel on/off is
1208  * non-racy
1209  */
1210
1211 GMutex roca_mutex_1, roca_mutex_2;
1212 GCond roca_cond_1, roca_cond_2;
1213
1214 static void
1215 return_on_cancel_atomic_callback (GObject      *object,
1216                                   GAsyncResult *result,
1217                                   gpointer      user_data)
1218 {
1219   gboolean *callback_ran = user_data;
1220   GError *error = NULL;
1221   gssize ret;
1222
1223   g_assert (g_thread_self () == main_thread);
1224
1225   g_assert (object == NULL);
1226   g_assert (g_task_is_valid (result, object));
1227   g_assert (g_async_result_get_user_data (result) == user_data);
1228   g_assert (g_task_had_error (G_TASK (result)));
1229
1230   ret = g_task_propagate_int (G_TASK (result), &error);
1231   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1232   g_clear_error (&error);
1233   g_assert_cmpint (ret, ==, -1);
1234
1235   *callback_ran = TRUE;
1236   g_main_loop_quit (loop);
1237 }
1238
1239 static gboolean
1240 idle_quit_loop (gpointer user_data)
1241 {
1242   g_main_loop_quit (loop);
1243   return FALSE;
1244 }
1245
1246 static void
1247 return_on_cancel_atomic_thread (GTask        *task,
1248                                 gpointer      source_object,
1249                                 gpointer      task_data,
1250                                 GCancellable *cancellable)
1251 {
1252   gint *state = task_data;
1253
1254   g_assert (source_object == g_task_get_source_object (task));
1255   g_assert (task_data == g_task_get_task_data (task));
1256   g_assert (cancellable == g_task_get_cancellable (task));
1257
1258   g_assert (g_thread_self () != main_thread);
1259   g_assert_cmpint (*state, ==, 0);
1260
1261   g_mutex_lock (&roca_mutex_1);
1262   *state = 1;
1263   g_cond_signal (&roca_cond_1);
1264   g_mutex_unlock (&roca_mutex_1);
1265
1266   g_mutex_lock (&roca_mutex_2);
1267   if (g_task_set_return_on_cancel (task, FALSE))
1268     *state = 2;
1269   else
1270     *state = 3;
1271   g_cond_signal (&roca_cond_2);
1272   g_mutex_unlock (&roca_mutex_2);
1273
1274   g_mutex_lock (&roca_mutex_1);
1275   if (g_task_set_return_on_cancel (task, TRUE))
1276     *state = 4;
1277   else
1278     *state = 5;
1279   g_cond_signal (&roca_cond_1);
1280   g_mutex_unlock (&roca_mutex_1);
1281
1282   g_mutex_lock (&roca_mutex_2);
1283   if (g_task_set_return_on_cancel (task, TRUE))
1284     *state = 6;
1285   else
1286     *state = 7;
1287   g_cond_signal (&roca_cond_2);
1288   g_mutex_unlock (&roca_mutex_2);
1289
1290   g_task_return_int (task, magic);
1291 }
1292
1293 static void
1294 test_return_on_cancel_atomic (void)
1295 {
1296   GTask *task;
1297   GCancellable *cancellable;
1298   volatile gint state;
1299   gboolean callback_ran;
1300
1301   cancellable = g_cancellable_new ();
1302   g_mutex_lock (&roca_mutex_1);
1303   g_mutex_lock (&roca_mutex_2);
1304
1305   /* If we don't cancel it, each set_return_on_cancel() call will succeed */
1306   state = 0;
1307   callback_ran = FALSE;
1308   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1309   g_task_set_return_on_cancel (task, TRUE);
1310
1311   g_task_set_task_data (task, (gpointer)&state, NULL);
1312   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1313   g_object_unref (task);
1314
1315   g_assert_cmpint (state, ==, 0);
1316
1317   while (state == 0)
1318     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1319   g_assert (state == 1);
1320
1321   while (state == 1)
1322     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1323   g_assert (state == 2);
1324
1325   while (state == 2)
1326     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1327   g_assert (state == 4);
1328
1329   while (state == 4)
1330     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1331   g_assert (state == 6);
1332
1333   /* callback assumes there'll be a cancelled error */
1334   g_cancellable_cancel (cancellable);
1335
1336   g_assert (callback_ran == FALSE);
1337   g_main_loop_run (loop);
1338   g_assert (callback_ran == TRUE);
1339
1340   g_cancellable_reset (cancellable);
1341
1342
1343   /* If we cancel while it's temporarily not return-on-cancel, the
1344    * task won't complete right away, and further
1345    * g_task_set_return_on_cancel() calls will return FALSE.
1346    */
1347   state = 0;
1348   callback_ran = FALSE;
1349   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1350   g_task_set_return_on_cancel (task, TRUE);
1351
1352   g_task_set_task_data (task, (gpointer)&state, NULL);
1353   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1354   g_object_unref (task);
1355
1356   g_assert_cmpint (state, ==, 0);
1357
1358   while (state == 0)
1359     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1360   g_assert (state == 1);
1361   g_assert (g_task_get_return_on_cancel (task));
1362
1363   while (state == 1)
1364     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1365   g_assert (state == 2);
1366   g_assert (!g_task_get_return_on_cancel (task));
1367
1368   g_cancellable_cancel (cancellable);
1369   g_idle_add (idle_quit_loop, NULL);
1370   g_main_loop_run (loop);
1371   g_assert (callback_ran == FALSE);
1372
1373   while (state == 2)
1374     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1375   g_assert (state == 5);
1376   g_assert (!g_task_get_return_on_cancel (task));
1377
1378   g_main_loop_run (loop);
1379   g_assert (callback_ran == TRUE);
1380
1381   while (state == 5)
1382     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1383   g_assert (state == 7);
1384
1385   g_object_unref (cancellable);
1386   g_mutex_unlock (&roca_mutex_1);
1387   g_mutex_unlock (&roca_mutex_2);
1388 }
1389
1390 /* test_return_pointer: memory management of pointer returns */
1391
1392 static void
1393 test_return_pointer (void)
1394 {
1395   GObject *object, *ret;
1396   GTask *task;
1397   GCancellable *cancellable;
1398   GError *error = NULL;
1399
1400   /* If we don't read back the return value, the task will
1401    * run its destroy notify.
1402    */
1403   object = (GObject *)g_dummy_object_new ();
1404   g_assert_cmpint (object->ref_count, ==, 1);
1405   g_object_add_weak_pointer (object, (gpointer *)&object);
1406
1407   task = g_task_new (NULL, NULL, NULL, NULL);
1408   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1409   g_task_return_pointer (task, object, g_object_unref);
1410   g_assert_cmpint (object->ref_count, ==, 1);
1411
1412   g_object_unref (task);
1413   g_assert (task == NULL);
1414   g_assert (object == NULL);
1415
1416   /* Likewise, if the return value is overwritten by an error */
1417   object = (GObject *)g_dummy_object_new ();
1418   g_assert_cmpint (object->ref_count, ==, 1);
1419   g_object_add_weak_pointer (object, (gpointer *)&object);
1420
1421   cancellable = g_cancellable_new ();
1422   task = g_task_new (NULL, cancellable, NULL, NULL);
1423   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1424   g_task_return_pointer (task, object, g_object_unref);
1425   g_assert_cmpint (object->ref_count, ==, 1);
1426   g_cancellable_cancel (cancellable);
1427   g_assert_cmpint (object->ref_count, ==, 1);
1428
1429   ret = g_task_propagate_pointer (task, &error);
1430   g_assert (ret == NULL);
1431   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1432   g_clear_error (&error);
1433   g_assert_cmpint (object->ref_count, ==, 1);
1434
1435   g_object_unref (task);
1436   g_object_unref (cancellable);
1437   g_assert (task == NULL);
1438   g_assert (object == NULL);
1439   
1440   /* If we read back the return value, we steal its ref */
1441   object = (GObject *)g_dummy_object_new ();
1442   g_assert_cmpint (object->ref_count, ==, 1);
1443   g_object_add_weak_pointer (object, (gpointer *)&object);
1444
1445   task = g_task_new (NULL, NULL, NULL, NULL);
1446   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1447   g_task_return_pointer (task, object, g_object_unref);
1448   g_assert_cmpint (object->ref_count, ==, 1);
1449
1450   ret = g_task_propagate_pointer (task, &error);
1451   g_assert_no_error (error);
1452   g_assert (ret == object);
1453   g_assert_cmpint (object->ref_count, ==, 1);
1454
1455   g_object_unref (task);
1456   g_assert (task == NULL);
1457   g_assert_cmpint (object->ref_count, ==, 1);
1458   g_object_unref (object);
1459   g_assert (object == NULL);
1460 }
1461
1462 /* test_object_keepalive: GTask takes a ref on its source object */
1463
1464 static GObject *keepalive_object;
1465
1466 static void
1467 keepalive_callback (GObject      *object,
1468                     GAsyncResult *result,
1469                     gpointer      user_data)
1470 {
1471   gssize *result_out = user_data;
1472   GError *error = NULL;
1473
1474   g_assert (object == keepalive_object);
1475   g_assert (g_task_is_valid (result, object));
1476   g_assert (g_async_result_get_user_data (result) == user_data);
1477   g_assert (!g_task_had_error (G_TASK (result)));
1478
1479   *result_out = g_task_propagate_int (G_TASK (result), &error);
1480   g_assert_no_error (error);
1481
1482   g_main_loop_quit (loop);
1483 }
1484
1485 static void
1486 test_object_keepalive (void)
1487 {
1488   GObject *object;
1489   GTask *task;
1490   gssize result;
1491   int ref_count;
1492
1493   keepalive_object = object = (GObject *)g_dummy_object_new ();
1494   g_object_add_weak_pointer (object, (gpointer *)&object);
1495
1496   task = g_task_new (object, NULL, keepalive_callback, &result);
1497   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1498
1499   ref_count = object->ref_count;
1500   g_assert_cmpint (ref_count, >, 1);
1501
1502   g_assert (g_task_get_source_object (task) == object);
1503   g_assert (g_async_result_get_source_object (G_ASYNC_RESULT (task)) == object);
1504   g_assert_cmpint (object->ref_count, ==, ref_count + 1);
1505   g_object_unref (object);
1506
1507   g_object_unref (object);
1508   g_assert (object != NULL);
1509
1510   g_task_return_int (task, magic);
1511   g_main_loop_run (loop);
1512
1513   g_assert (object != NULL);
1514   g_assert_cmpint (result, ==, magic);
1515
1516   g_object_unref (task);
1517   g_assert (task == NULL);
1518   g_assert (object == NULL);
1519 }
1520
1521 /* test_legacy_error: legacy GSimpleAsyncResult handling */
1522 static void test_legacy_error (void);
1523
1524 static void
1525 legacy_error_callback (GObject      *object,
1526                        GAsyncResult *result,
1527                        gpointer      user_data)
1528 {
1529   gssize *result_out = user_data;
1530   GError *error = NULL;
1531
1532   g_assert (object == NULL);
1533   g_assert (g_async_result_is_tagged (result, test_legacy_error));
1534   g_assert (g_async_result_get_user_data (result) == user_data);
1535
1536   if (g_async_result_legacy_propagate_error (result, &error))
1537     {
1538       g_assert (!g_task_is_valid (result, object));
1539       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1540       g_assert (g_simple_async_result_is_valid (result, object, test_legacy_error));
1541       G_GNUC_END_IGNORE_DEPRECATIONS;
1542
1543       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
1544       *result_out = -2;
1545     }
1546   else
1547     {
1548       g_assert (g_task_is_valid (result, object));
1549
1550       *result_out = g_task_propagate_int (G_TASK (result), NULL);
1551       /* Might be error, might not */
1552     }
1553
1554   g_main_loop_quit (loop);
1555 }
1556
1557 static gboolean
1558 legacy_error_return (gpointer user_data)
1559 {
1560   if (G_IS_TASK (user_data))
1561     {
1562       GTask *task = user_data;
1563
1564       g_task_return_int (task, magic);
1565       g_object_unref (task);
1566     }
1567   else
1568     {
1569       GSimpleAsyncResult *simple = user_data;
1570
1571       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1572       g_simple_async_result_set_error (simple,
1573                                        G_IO_ERROR,
1574                                        G_IO_ERROR_FAILED,
1575                                        "Failed");
1576       g_simple_async_result_complete (simple);
1577       G_GNUC_END_IGNORE_DEPRECATIONS;
1578       g_object_unref (simple);
1579     }
1580
1581   return FALSE;
1582 }
1583
1584 static void
1585 test_legacy_error (void)
1586 {
1587   GTask *task;
1588   GSimpleAsyncResult *simple;
1589   gssize result;
1590
1591   /* GTask success */
1592   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1593   g_task_set_source_tag (task, test_legacy_error);
1594   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1595
1596   g_idle_add (legacy_error_return, task);
1597   g_main_loop_run (loop);
1598
1599   g_assert_cmpint (result, ==, magic);
1600   g_assert (task == NULL);
1601
1602   /* GTask error */
1603   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1604   g_task_set_source_tag (task, test_legacy_error);
1605   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1606
1607   g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
1608                            "Failed");
1609   g_object_unref (task);
1610   g_main_loop_run (loop);
1611
1612   g_assert_cmpint (result, ==, -1);
1613   g_assert (task == NULL);
1614
1615   /* GSimpleAsyncResult error */
1616   G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1617   simple = g_simple_async_result_new (NULL, legacy_error_callback, &result,
1618                                       test_legacy_error);
1619   G_GNUC_END_IGNORE_DEPRECATIONS;
1620   g_object_add_weak_pointer (G_OBJECT (simple), (gpointer *)&simple);
1621
1622   g_idle_add (legacy_error_return, simple);
1623   g_main_loop_run (loop);
1624
1625   g_assert_cmpint (result, ==, -2);
1626   g_assert (simple == NULL);
1627 }
1628
1629
1630 int
1631 main (int argc, char **argv)
1632 {
1633   int ret;
1634
1635   g_test_init (&argc, &argv, NULL);
1636
1637   loop = g_main_loop_new (NULL, FALSE);
1638   main_thread = g_thread_self ();
1639   magic = g_get_monotonic_time ();
1640
1641   g_test_add_func ("/gtask/basic", test_basic);
1642   g_test_add_func ("/gtask/error", test_error);
1643   g_test_add_func ("/gtask/return-from-same-iteration", test_return_from_same_iteration);
1644   g_test_add_func ("/gtask/return-from-toplevel", test_return_from_toplevel);
1645   g_test_add_func ("/gtask/return-from-anon-thread", test_return_from_anon_thread);
1646   g_test_add_func ("/gtask/return-from-wrong-thread", test_return_from_wrong_thread);
1647   g_test_add_func ("/gtask/no-callback", test_no_callback);
1648   g_test_add_func ("/gtask/report-error", test_report_error);
1649   g_test_add_func ("/gtask/priority", test_priority);
1650   g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
1651   g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
1652   g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
1653   g_test_add_func ("/gtask/run-in-thread-sync", test_run_in_thread_sync);
1654   g_test_add_func ("/gtask/run-in-thread-priority", test_run_in_thread_priority);
1655   g_test_add_func ("/gtask/return-on-cancel", test_return_on_cancel);
1656   g_test_add_func ("/gtask/return-on-cancel-sync", test_return_on_cancel_sync);
1657   g_test_add_func ("/gtask/return-on-cancel-atomic", test_return_on_cancel_atomic);
1658   g_test_add_func ("/gtask/return-pointer", test_return_pointer);
1659   g_test_add_func ("/gtask/object-keepalive", test_object_keepalive);
1660   g_test_add_func ("/gtask/legacy-error", test_legacy_error);
1661
1662   ret = g_test_run();
1663
1664   g_main_loop_unref (loop);
1665
1666   return ret;
1667 }