tests/mainloop: Fix assertions to really avoid race conditions
[platform/upstream/glib.git] / glib / tests / mainloop.c
1 /* Unit tests for GMainLoop
2  * Copyright (C) 2011 Red Hat, Inc
3  * Author: Matthias Clasen
4  *
5  * This work is provided "as is"; redistribution and modification
6  * in whole or in part, in any medium, physical or electronic is
7  * permitted without restriction.
8  *
9  * This work is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * In no event shall the authors or contributors be liable for any
14  * direct, indirect, incidental, special, exemplary, or consequential
15  * damages (including, but not limited to, procurement of substitute
16  * goods or services; loss of use, data, or profits; or business
17  * interruption) however caused and on any theory of liability, whether
18  * in contract, strict liability, or tort (including negligence or
19  * otherwise) arising in any way out of the use of this software, even
20  * if advised of the possibility of such damage.
21  */
22
23 #include <glib.h>
24 #include "glib-private.h"
25 #include <string.h>
26
27 static gboolean cb (gpointer data)
28 {
29   return FALSE;
30 }
31
32 static gboolean prepare (GSource *source, gint *time)
33 {
34   return FALSE;
35 }
36 static gboolean check (GSource *source)
37 {
38   return FALSE;
39 }
40 static gboolean dispatch (GSource *source, GSourceFunc cb, gpointer date)
41 {
42   return FALSE;
43 }
44
45 GSourceFuncs funcs = {
46   prepare,
47   check,
48   dispatch,
49   NULL
50 };
51
52 static void
53 test_maincontext_basic (void)
54 {
55   GMainContext *ctx;
56   GSource *source;
57   guint id;
58   gpointer data = &funcs;
59
60   ctx = g_main_context_new ();
61
62   g_assert (!g_main_context_pending (ctx));
63   g_assert (!g_main_context_iteration (ctx, FALSE));
64
65   source = g_source_new (&funcs, sizeof (GSource));
66   g_assert_cmpint (g_source_get_priority (source), ==, G_PRIORITY_DEFAULT);
67   g_assert (!g_source_is_destroyed (source));
68
69   g_assert (!g_source_get_can_recurse (source));
70   g_assert (g_source_get_name (source) == NULL);
71
72   g_source_set_can_recurse (source, TRUE);
73   g_source_set_name (source, "d");
74
75   g_assert (g_source_get_can_recurse (source));
76   g_assert_cmpstr (g_source_get_name (source), ==, "d");
77
78   g_assert (g_main_context_find_source_by_user_data (ctx, NULL) == NULL);
79   g_assert (g_main_context_find_source_by_funcs_user_data (ctx, &funcs, NULL) == NULL);
80
81   id = g_source_attach (source, ctx);
82   g_assert_cmpint (g_source_get_id (source), ==, id);
83   g_assert (g_main_context_find_source_by_id (ctx, id) == source);
84
85   g_source_set_priority (source, G_PRIORITY_HIGH);
86   g_assert_cmpint (g_source_get_priority (source), ==, G_PRIORITY_HIGH);
87
88   g_source_destroy (source);
89   g_assert (g_source_get_context (source) == ctx);
90   g_assert (g_main_context_find_source_by_id (ctx, id) == NULL);
91
92   g_main_context_unref (ctx);
93
94   if (g_test_undefined ())
95     {
96       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
97                              "*assertion*source->context != NULL*failed*");
98       g_assert (g_source_get_context (source) == NULL);
99       g_test_assert_expected_messages ();
100     }
101
102   g_source_unref (source);
103
104   ctx = g_main_context_default ();
105   source = g_source_new (&funcs, sizeof (GSource));
106   g_source_set_funcs (source, &funcs);
107   g_source_set_callback (source, cb, data, NULL);
108   id = g_source_attach (source, ctx);
109   g_source_unref (source);
110   g_source_set_name_by_id (id, "e");
111   g_assert_cmpstr (g_source_get_name (source), ==, "e");
112   g_assert (g_source_get_context (source) == ctx);
113   g_assert (g_source_remove_by_funcs_user_data (&funcs, data));
114
115   source = g_source_new (&funcs, sizeof (GSource));
116   g_source_set_funcs (source, &funcs);
117   g_source_set_callback (source, cb, data, NULL);
118   id = g_source_attach (source, ctx);
119   g_source_unref (source);
120   g_assert (g_source_remove_by_user_data (data));
121
122   g_idle_add (cb, data);
123   g_assert (g_idle_remove_by_data (data));
124 }
125
126 static void
127 test_mainloop_basic (void)
128 {
129   GMainLoop *loop;
130   GMainContext *ctx;
131
132   loop = g_main_loop_new (NULL, FALSE);
133
134   g_assert (!g_main_loop_is_running (loop));
135
136   g_main_loop_ref (loop);
137
138   ctx = g_main_loop_get_context (loop);
139   g_assert (ctx == g_main_context_default ());
140
141   g_main_loop_unref (loop);
142
143   g_assert_cmpint (g_main_depth (), ==, 0);
144
145   g_main_loop_unref (loop);
146 }
147
148 static gint a;
149 static gint b;
150 static gint c;
151
152 static gboolean
153 count_calls (gpointer data)
154 {
155   gint *i = data;
156
157   (*i)++;
158
159   return TRUE;
160 }
161
162 static void
163 test_timeouts (void)
164 {
165   GMainContext *ctx;
166   GMainLoop *loop;
167   GSource *source;
168
169   a = b = c = 0;
170
171   ctx = g_main_context_new ();
172   loop = g_main_loop_new (ctx, FALSE);
173
174   source = g_timeout_source_new (100);
175   g_source_set_callback (source, count_calls, &a, NULL);
176   g_source_attach (source, ctx);
177   g_source_unref (source);
178
179   source = g_timeout_source_new (250);
180   g_source_set_callback (source, count_calls, &b, NULL);
181   g_source_attach (source, ctx);
182   g_source_unref (source);
183
184   source = g_timeout_source_new (330);
185   g_source_set_callback (source, count_calls, &c, NULL);
186   g_source_attach (source, ctx);
187   g_source_unref (source);
188
189   source = g_timeout_source_new (1050);
190   g_source_set_callback (source, (GSourceFunc)g_main_loop_quit, loop, NULL);
191   g_source_attach (source, ctx);
192   g_source_unref (source);
193
194   g_main_loop_run (loop);
195
196   /* We may be delayed for an arbitrary amount of time - for example,
197    * it's possible for all timeouts to fire exactly once.
198    */
199   g_assert_cmpint (a, >, 0);
200   g_assert_cmpint (a, >=, b);
201   g_assert_cmpint (b, >=, c);
202
203   g_assert_cmpint (a, <=, 10);
204   g_assert_cmpint (b, <=, 4);
205   g_assert_cmpint (c, <=, 3);
206
207   g_main_loop_unref (loop);
208   g_main_context_unref (ctx);
209 }
210
211 static void
212 test_priorities (void)
213 {
214   GMainContext *ctx;
215   GSource *sourcea;
216   GSource *sourceb;
217
218   a = b = c = 0;
219
220   ctx = g_main_context_new ();
221
222   sourcea = g_idle_source_new ();
223   g_source_set_callback (sourcea, count_calls, &a, NULL);
224   g_source_set_priority (sourcea, 1);
225   g_source_attach (sourcea, ctx);
226   g_source_unref (sourcea);
227
228   sourceb = g_idle_source_new ();
229   g_source_set_callback (sourceb, count_calls, &b, NULL);
230   g_source_set_priority (sourceb, 0);
231   g_source_attach (sourceb, ctx);
232   g_source_unref (sourceb);
233
234   g_assert (g_main_context_pending (ctx));
235   g_assert (g_main_context_iteration (ctx, FALSE));
236   g_assert_cmpint (a, ==, 0);
237   g_assert_cmpint (b, ==, 1);
238
239   g_assert (g_main_context_iteration (ctx, FALSE));
240   g_assert_cmpint (a, ==, 0);
241   g_assert_cmpint (b, ==, 2);
242
243   g_source_destroy (sourceb);
244
245   g_assert (g_main_context_iteration (ctx, FALSE));
246   g_assert_cmpint (a, ==, 1);
247   g_assert_cmpint (b, ==, 2);
248
249   g_assert (g_main_context_pending (ctx));
250   g_source_destroy (sourcea);
251   g_assert (!g_main_context_pending (ctx));
252
253   g_main_context_unref (ctx);
254 }
255
256 static gboolean
257 quit_loop (gpointer data)
258 {
259   GMainLoop *loop = data;
260
261   g_main_loop_quit (loop);
262
263   return G_SOURCE_REMOVE;
264 }
265
266 static gint count;
267
268 static gboolean
269 func (gpointer data)
270 {
271   if (data != NULL)
272     g_assert (data == g_thread_self ());
273
274   count++;
275
276   return FALSE;
277 }
278
279 static gboolean
280 call_func (gpointer data)
281 {
282   func (g_thread_self ());
283
284   return G_SOURCE_REMOVE;
285 }
286
287 static GMutex mutex;
288 static GCond cond;
289 static gboolean thread_ready;
290
291 static gpointer
292 thread_func (gpointer data)
293 {
294   GMainContext *ctx = data;
295   GMainLoop *loop;
296   GSource *source;
297
298   g_main_context_push_thread_default (ctx);
299   loop = g_main_loop_new (ctx, FALSE);
300
301   g_mutex_lock (&mutex);
302   thread_ready = TRUE;
303   g_cond_signal (&cond);
304   g_mutex_unlock (&mutex);
305
306   source = g_timeout_source_new (500);
307   g_source_set_callback (source, quit_loop, loop, NULL);
308   g_source_attach (source, ctx);
309   g_source_unref (source);
310
311   g_main_loop_run (loop);
312
313   g_main_context_pop_thread_default (ctx);
314   g_main_loop_unref (loop);
315
316   return NULL;
317 }
318
319 static void
320 test_invoke (void)
321 {
322   GMainContext *ctx;
323   GThread *thread;
324
325   count = 0;
326
327   /* this one gets invoked directly */
328   g_main_context_invoke (NULL, func, g_thread_self ());
329   g_assert_cmpint (count, ==, 1);
330
331   /* invoking out of an idle works too */
332   g_idle_add (call_func, NULL);
333   g_main_context_iteration (g_main_context_default (), FALSE);
334   g_assert_cmpint (count, ==, 2);
335
336   /* test thread-default forcing the invocation to go
337    * to another thread
338    */
339   ctx = g_main_context_new ();
340   thread = g_thread_new ("worker", thread_func, ctx);
341
342   g_mutex_lock (&mutex);
343   while (!thread_ready)
344     g_cond_wait (&cond, &mutex);
345   g_mutex_unlock (&mutex);
346
347   g_main_context_invoke (ctx, func, thread);
348
349   g_thread_join (thread);
350   g_assert_cmpint (count, ==, 3);
351
352   g_main_context_unref (ctx);
353 }
354
355 static gboolean
356 run_inner_loop (gpointer user_data)
357 {
358   GMainContext *ctx = user_data;
359   GMainLoop *inner;
360   GSource *timeout;
361
362   a++;
363
364   inner = g_main_loop_new (ctx, FALSE);
365   timeout = g_timeout_source_new (100);
366   g_source_set_callback (timeout, quit_loop, inner, NULL);
367   g_source_attach (timeout, ctx);
368   g_source_unref (timeout);
369
370   g_main_loop_run (inner);
371   g_main_loop_unref (inner);
372
373   return G_SOURCE_CONTINUE;
374 }
375
376 static void
377 test_child_sources (void)
378 {
379   GMainContext *ctx;
380   GMainLoop *loop;
381   GSource *parent, *child_b, *child_c, *end;
382
383   ctx = g_main_context_new ();
384   loop = g_main_loop_new (ctx, FALSE);
385
386   a = b = c = 0;
387
388   parent = g_timeout_source_new (2000);
389   g_source_set_callback (parent, run_inner_loop, ctx, NULL);
390   g_source_set_priority (parent, G_PRIORITY_LOW);
391   g_source_attach (parent, ctx);
392
393   child_b = g_timeout_source_new (250);
394   g_source_set_callback (child_b, count_calls, &b, NULL);
395   g_source_add_child_source (parent, child_b);
396
397   child_c = g_timeout_source_new (330);
398   g_source_set_callback (child_c, count_calls, &c, NULL);
399   g_source_set_priority (child_c, G_PRIORITY_HIGH);
400   g_source_add_child_source (parent, child_c);
401
402   /* Child sources always have the priority of the parent */
403   g_assert_cmpint (g_source_get_priority (parent), ==, G_PRIORITY_LOW);
404   g_assert_cmpint (g_source_get_priority (child_b), ==, G_PRIORITY_LOW);
405   g_assert_cmpint (g_source_get_priority (child_c), ==, G_PRIORITY_LOW);
406   g_source_set_priority (parent, G_PRIORITY_DEFAULT);
407   g_assert_cmpint (g_source_get_priority (parent), ==, G_PRIORITY_DEFAULT);
408   g_assert_cmpint (g_source_get_priority (child_b), ==, G_PRIORITY_DEFAULT);
409   g_assert_cmpint (g_source_get_priority (child_c), ==, G_PRIORITY_DEFAULT);
410
411   end = g_timeout_source_new (1050);
412   g_source_set_callback (end, quit_loop, loop, NULL);
413   g_source_attach (end, ctx);
414   g_source_unref (end);
415
416   g_main_loop_run (loop);
417
418   /* The parent source's own timeout will never trigger, so "a" will
419    * only get incremented when "b" or "c" does. And when timeouts get
420    * blocked, they still wait the full interval next time rather than
421    * "catching up". So the timing is:
422    *
423    *  250 - b++ -> a++, run_inner_loop
424    *  330 - (c is blocked)
425    *  350 - inner_loop ends
426    *  350 - c++ belatedly -> a++, run_inner_loop
427    *  450 - inner loop ends
428    *  500 - b++ -> a++, run_inner_loop
429    *  600 - inner_loop ends
430    *  680 - c++ -> a++, run_inner_loop
431    *  750 - (b is blocked)
432    *  780 - inner loop ends
433    *  780 - b++ belatedly -> a++, run_inner_loop
434    *  880 - inner loop ends
435    * 1010 - c++ -> a++, run_inner_loop
436    * 1030 - (b is blocked)
437    * 1050 - end runs, quits outer loop, which has no effect yet
438    * 1110 - inner loop ends, a returns, outer loop exits
439    */
440
441   g_assert_cmpint (a, ==, 6);
442   g_assert_cmpint (b, ==, 3);
443   g_assert_cmpint (c, ==, 3);
444
445   g_source_destroy (parent);
446   g_source_unref (parent);
447   g_source_unref (child_b);
448   g_source_unref (child_c);
449
450   g_main_loop_unref (loop);
451   g_main_context_unref (ctx);
452 }
453
454 static void
455 test_recursive_child_sources (void)
456 {
457   GMainContext *ctx;
458   GMainLoop *loop;
459   GSource *parent, *child_b, *child_c, *end;
460
461   ctx = g_main_context_new ();
462   loop = g_main_loop_new (ctx, FALSE);
463
464   a = b = c = 0;
465
466   parent = g_timeout_source_new (500);
467   g_source_set_callback (parent, count_calls, &a, NULL);
468
469   child_b = g_timeout_source_new (220);
470   g_source_set_callback (child_b, count_calls, &b, NULL);
471   g_source_add_child_source (parent, child_b);
472
473   child_c = g_timeout_source_new (430);
474   g_source_set_callback (child_c, count_calls, &c, NULL);
475   g_source_add_child_source (child_b, child_c);
476
477   g_source_attach (parent, ctx);
478
479   end = g_timeout_source_new (2010);
480   g_source_set_callback (end, (GSourceFunc)g_main_loop_quit, loop, NULL);
481   g_source_attach (end, ctx);
482   g_source_unref (end);
483
484   g_main_loop_run (loop);
485
486   /* Sequence of events:
487    * 220 b (b = 440, a = 720)
488    * 430 c (c = 860, b = 650, a = 930)
489    * 650 b (b = 870, a = 1150)
490    * 860 c (c = 1290, b = 1080, a = 1360)
491    * 1080 b (b = 1300, a = 1580)
492    * 1290 c (c = 1720, b = 1510, a = 1790)
493    * 1510 b (b = 1730, a = 2010)
494    * 1720 c (c = 2150, b = 1940, a = 2220)
495    * 1940 b (b = 2160, a = 2440)
496    */
497
498   g_assert_cmpint (a, ==, 9);
499   g_assert_cmpint (b, ==, 9);
500   g_assert_cmpint (c, ==, 4);
501
502   g_source_destroy (parent);
503   g_source_unref (parent);
504   g_source_unref (child_b);
505   g_source_unref (child_c);
506
507   g_main_loop_unref (loop);
508   g_main_context_unref (ctx);
509 }
510
511 typedef struct {
512   GSource *parent, *old_child, *new_child;
513   GMainLoop *loop;
514 } SwappingTestData;
515
516 static gboolean
517 swap_sources (gpointer user_data)
518 {
519   SwappingTestData *data = user_data;
520
521   if (data->old_child)
522     {
523       g_source_remove_child_source (data->parent, data->old_child);
524       g_clear_pointer (&data->old_child, g_source_unref);
525     }
526
527   if (!data->new_child)
528     {
529       data->new_child = g_timeout_source_new (0);
530       g_source_set_callback (data->new_child, quit_loop, data->loop, NULL);
531       g_source_add_child_source (data->parent, data->new_child);
532     }
533
534   return G_SOURCE_CONTINUE;
535 }
536
537 static gboolean
538 assert_not_reached_callback (gpointer user_data)
539 {
540   g_assert_not_reached ();
541
542   return G_SOURCE_REMOVE;
543 }
544
545 static void
546 test_swapping_child_sources (void)
547 {
548   GMainContext *ctx;
549   GMainLoop *loop;
550   SwappingTestData data;
551
552   ctx = g_main_context_new ();
553   loop = g_main_loop_new (ctx, FALSE);
554
555   data.parent = g_timeout_source_new (50);
556   data.loop = loop;
557   g_source_set_callback (data.parent, swap_sources, &data, NULL);
558   g_source_attach (data.parent, ctx);
559
560   data.old_child = g_timeout_source_new (100);
561   g_source_add_child_source (data.parent, data.old_child);
562   g_source_set_callback (data.old_child, assert_not_reached_callback, NULL, NULL);
563
564   data.new_child = NULL;
565   g_main_loop_run (loop);
566
567   g_source_destroy (data.parent);
568   g_source_unref (data.parent);
569   g_source_unref (data.new_child);
570
571   g_main_loop_unref (loop);
572   g_main_context_unref (ctx);
573 }
574
575 static gboolean
576 add_source_callback (gpointer user_data)
577 {
578   GMainLoop *loop = user_data;
579   GSource *self = g_main_current_source (), *child;
580   GIOChannel *io;
581
582   /* It doesn't matter whether this is a valid fd or not; it never
583    * actually gets polled; the test is just checking that
584    * g_source_add_child_source() doesn't crash.
585    */
586   io = g_io_channel_unix_new (0);
587   child = g_io_create_watch (io, G_IO_IN);
588   g_source_add_child_source (self, child);
589   g_source_unref (child);
590   g_io_channel_unref (io);
591
592   g_main_loop_quit (loop);
593   return FALSE;
594 }
595
596 static void
597 test_blocked_child_sources (void)
598 {
599   GMainContext *ctx;
600   GMainLoop *loop;
601   GSource *source;
602
603   g_test_bug ("701283");
604
605   ctx = g_main_context_new ();
606   loop = g_main_loop_new (ctx, FALSE);
607
608   source = g_idle_source_new ();
609   g_source_set_callback (source, add_source_callback, loop, NULL);
610   g_source_attach (source, ctx);
611
612   g_main_loop_run (loop);
613
614   g_source_destroy (source);
615   g_source_unref (source);
616
617   g_main_loop_unref (loop);
618   g_main_context_unref (ctx);
619 }
620
621 typedef struct {
622   GMainContext *ctx;
623   GMainLoop *loop;
624
625   GSource *timeout1, *timeout2;
626   gint64 time1;
627 } TimeTestData;
628
629 static gboolean
630 timeout1_callback (gpointer user_data)
631 {
632   TimeTestData *data = user_data;
633   GSource *source;
634   gint64 mtime1, mtime2, time2;
635
636   source = g_main_current_source ();
637   g_assert (source == data->timeout1);
638
639   if (data->time1 == -1)
640     {
641       /* First iteration */
642       g_assert (!g_source_is_destroyed (data->timeout2));
643
644       mtime1 = g_get_monotonic_time ();
645       data->time1 = g_source_get_time (source);
646
647       /* g_source_get_time() does not change during a single callback */
648       g_usleep (1000000);
649       mtime2 = g_get_monotonic_time ();
650       time2 = g_source_get_time (source);
651
652       g_assert_cmpint (mtime1, <, mtime2);
653       g_assert_cmpint (data->time1, ==, time2);
654     }
655   else
656     {
657       /* Second iteration */
658       g_assert (g_source_is_destroyed (data->timeout2));
659
660       /* g_source_get_time() MAY change between iterations; in this
661        * case we know for sure that it did because of the g_usleep()
662        * last time.
663        */
664       time2 = g_source_get_time (source);
665       g_assert_cmpint (data->time1, <, time2);
666
667       g_main_loop_quit (data->loop);
668     }
669
670   return TRUE;
671 }
672
673 static gboolean
674 timeout2_callback (gpointer user_data)
675 {
676   TimeTestData *data = user_data;
677   GSource *source;
678   gint64 time2, time3;
679
680   source = g_main_current_source ();
681   g_assert (source == data->timeout2);
682
683   g_assert (!g_source_is_destroyed (data->timeout1));
684
685   /* g_source_get_time() does not change between different sources in
686    * a single iteration of the mainloop.
687    */
688   time2 = g_source_get_time (source);
689   g_assert_cmpint (data->time1, ==, time2);
690
691   /* The source should still have a valid time even after being
692    * destroyed, since it's currently running.
693    */
694   g_source_destroy (source);
695   time3 = g_source_get_time (source);
696   g_assert_cmpint (time2, ==, time3);
697
698   return FALSE;
699 }
700
701 static void
702 test_source_time (void)
703 {
704   TimeTestData data;
705
706   data.ctx = g_main_context_new ();
707   data.loop = g_main_loop_new (data.ctx, FALSE);
708
709   data.timeout1 = g_timeout_source_new (0);
710   g_source_set_callback (data.timeout1, timeout1_callback, &data, NULL);
711   g_source_attach (data.timeout1, data.ctx);
712
713   data.timeout2 = g_timeout_source_new (0);
714   g_source_set_callback (data.timeout2, timeout2_callback, &data, NULL);
715   g_source_attach (data.timeout2, data.ctx);
716
717   data.time1 = -1;
718
719   g_main_loop_run (data.loop);
720
721   g_assert (!g_source_is_destroyed (data.timeout1));
722   g_assert (g_source_is_destroyed (data.timeout2));
723
724   g_source_destroy (data.timeout1);
725   g_source_unref (data.timeout1);
726   g_source_unref (data.timeout2);
727
728   g_main_loop_unref (data.loop);
729   g_main_context_unref (data.ctx);
730 }
731
732 typedef struct {
733   guint outstanding_ops;
734   GMainLoop *loop;
735 } TestOverflowData;
736
737 static gboolean
738 on_source_fired_cb (gpointer user_data)
739 {
740   TestOverflowData *data = user_data;
741   GSource *current_source;
742   GMainContext *current_context;
743   guint source_id;
744
745   data->outstanding_ops--;
746
747   current_source = g_main_current_source ();
748   current_context = g_source_get_context (current_source);
749   source_id = g_source_get_id (current_source);
750   g_assert (g_main_context_find_source_by_id (current_context, source_id) != NULL);
751   g_source_destroy (current_source);
752   g_assert (g_main_context_find_source_by_id (current_context, source_id) == NULL);
753
754   if (data->outstanding_ops == 0)
755     g_main_loop_quit (data->loop);
756   return FALSE;
757 }
758
759 static GSource *
760 add_idle_source (GMainContext *ctx,
761                  TestOverflowData *data)
762 {
763   GSource *source;
764
765   source = g_idle_source_new ();
766   g_source_set_callback (source, on_source_fired_cb, data, NULL);
767   g_source_attach (source, ctx);
768   g_source_unref (source);
769   data->outstanding_ops++;
770
771   return source;
772 }
773
774 static void
775 test_mainloop_overflow (void)
776 {
777   GMainContext *ctx;
778   GMainLoop *loop;
779   GSource *source;
780   TestOverflowData data;
781   guint i;
782
783   g_test_bug ("687098");
784
785   memset (&data, 0, sizeof (data));
786
787   ctx = GLIB_PRIVATE_CALL (g_main_context_new_with_next_id) (G_MAXUINT-1);
788
789   loop = g_main_loop_new (ctx, TRUE);
790   data.outstanding_ops = 0;
791   data.loop = loop;
792
793   source = add_idle_source (ctx, &data);
794   g_assert_cmpint (source->source_id, ==, G_MAXUINT-1);
795
796   source = add_idle_source (ctx, &data);
797   g_assert_cmpint (source->source_id, ==, G_MAXUINT);
798
799   source = add_idle_source (ctx, &data);
800   g_assert_cmpint (source->source_id, !=, 0);
801
802   /* Now, a lot more sources */
803   for (i = 0; i < 50; i++)
804     {
805       source = add_idle_source (ctx, &data);
806       g_assert_cmpint (source->source_id, !=, 0);
807     }
808
809   g_main_loop_run (loop);
810   g_assert_cmpint (data.outstanding_ops, ==, 0);
811
812   g_main_loop_unref (loop);
813   g_main_context_unref (ctx);
814 }
815
816 static volatile gint ready_time_dispatched;
817
818 static gboolean
819 ready_time_dispatch (GSource     *source,
820                      GSourceFunc  callback,
821                      gpointer     user_data)
822 {
823   g_atomic_int_set (&ready_time_dispatched, TRUE);
824
825   g_source_set_ready_time (source, -1);
826
827   return TRUE;
828 }
829
830 static gpointer
831 run_context (gpointer user_data)
832 {
833   g_main_loop_run (user_data);
834
835   return NULL;
836 }
837
838 static void
839 test_ready_time (void)
840 {
841   GThread *thread;
842   GSource *source;
843   GSourceFuncs source_funcs = {
844     NULL, NULL, ready_time_dispatch
845   };
846   GMainLoop *loop;
847
848   source = g_source_new (&source_funcs, sizeof (GSource));
849   g_source_attach (source, NULL);
850   g_source_unref (source);
851
852   /* Unfortunately we can't do too many things with respect to timing
853    * without getting into trouble on slow systems or heavily loaded
854    * builders.
855    *
856    * We can test that the basics are working, though.
857    */
858
859   /* A source with no ready time set should not fire */
860   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
861   while (g_main_context_iteration (NULL, FALSE));
862   g_assert (!ready_time_dispatched);
863
864   /* The ready time should not have been changed */
865   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
866
867   /* Of course this shouldn't change anything either */
868   g_source_set_ready_time (source, -1);
869   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
870
871   /* A source with a ready time set to tomorrow should not fire on any
872    * builder, no matter how badly loaded...
873    */
874   g_source_set_ready_time (source, g_get_monotonic_time () + G_TIME_SPAN_DAY);
875   while (g_main_context_iteration (NULL, FALSE));
876   g_assert (!ready_time_dispatched);
877   /* Make sure it didn't get reset */
878   g_assert_cmpint (g_source_get_ready_time (source), !=, -1);
879
880   /* Ready time of -1 -> don't fire */
881   g_source_set_ready_time (source, -1);
882   while (g_main_context_iteration (NULL, FALSE));
883   g_assert (!ready_time_dispatched);
884   /* Not reset, but should still be -1 from above */
885   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
886
887   /* A ready time of the current time should fire immediately */
888   g_source_set_ready_time (source, g_get_monotonic_time ());
889   while (g_main_context_iteration (NULL, FALSE));
890   g_assert (ready_time_dispatched);
891   ready_time_dispatched = FALSE;
892   /* Should have gotten reset by the handler function */
893   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
894
895   /* As well as one in the recent past... */
896   g_source_set_ready_time (source, g_get_monotonic_time () - G_TIME_SPAN_SECOND);
897   while (g_main_context_iteration (NULL, FALSE));
898   g_assert (ready_time_dispatched);
899   ready_time_dispatched = FALSE;
900   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
901
902   /* Zero is the 'official' way to get a source to fire immediately */
903   g_source_set_ready_time (source, 0);
904   while (g_main_context_iteration (NULL, FALSE));
905   g_assert (ready_time_dispatched);
906   ready_time_dispatched = FALSE;
907   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
908
909   /* Now do some tests of cross-thread wakeups.
910    *
911    * Make sure it wakes up right away from the start.
912    */
913   g_source_set_ready_time (source, 0);
914   loop = g_main_loop_new (NULL, FALSE);
915   thread = g_thread_new ("context thread", run_context, loop);
916   while (!g_atomic_int_get (&ready_time_dispatched));
917
918   /* Now let's see if it can wake up from sleeping. */
919   g_usleep (G_TIME_SPAN_SECOND / 2);
920   g_atomic_int_set (&ready_time_dispatched, FALSE);
921   g_source_set_ready_time (source, 0);
922   while (!g_atomic_int_get (&ready_time_dispatched));
923
924   /* kill the thread */
925   g_main_loop_quit (loop);
926   g_thread_join (thread);
927   g_main_loop_unref (loop);
928
929   g_source_destroy (source);
930 }
931
932 static void
933 test_wakeup(void)
934 {
935   GMainContext *ctx;
936   int i;
937
938   ctx = g_main_context_new ();
939
940   /* run a random large enough number of times because 
941    * main contexts tend to wake up a few times after creation.
942    */
943   for (i = 0; i < 100; i++)
944     {
945       /* This is the invariant we care about:
946        * g_main_context_wakeup(ctx,) ensures that the next call to
947        * g_main_context_iteration (ctx, TRUE) returns and doesn't
948        * block.
949        * This is important in threaded apps where we might not know
950        * if the thread calls g_main_context_wakeup() before or after
951        * we enter g_main_context_iteration().
952        */
953       g_main_context_wakeup (ctx);
954       g_main_context_iteration (ctx, TRUE);
955     }
956
957   g_main_context_unref (ctx);
958 }
959
960 #ifdef G_OS_UNIX
961
962 #include <glib-unix.h>
963 #include <unistd.h>
964
965 static gchar zeros[1024];
966
967 static gsize
968 fill_a_pipe (gint fd)
969 {
970   gsize written = 0;
971   GPollFD pfd;
972
973   pfd.fd = fd;
974   pfd.events = G_IO_OUT;
975   while (g_poll (&pfd, 1, 0) == 1)
976     /* we should never see -1 here */
977     written += write (fd, zeros, sizeof zeros);
978
979   return written;
980 }
981
982 static gboolean
983 write_bytes (gint         fd,
984              GIOCondition condition,
985              gpointer     user_data)
986 {
987   gssize *to_write = user_data;
988   gint limit;
989
990   if (*to_write == 0)
991     return FALSE;
992
993   /* Detect if we run before we should */
994   g_assert (*to_write >= 0);
995
996   limit = MIN (*to_write, sizeof zeros);
997   *to_write -= write (fd, zeros, limit);
998
999   return TRUE;
1000 }
1001
1002 static gboolean
1003 read_bytes (gint         fd,
1004             GIOCondition condition,
1005             gpointer     user_data)
1006 {
1007   static gchar buffer[1024];
1008   gssize *to_read = user_data;
1009
1010   *to_read -= read (fd, buffer, sizeof buffer);
1011
1012   /* The loop will exit when there is nothing else to read, then we will
1013    * use g_source_remove() to destroy this source.
1014    */
1015   return TRUE;
1016 }
1017
1018 static void
1019 test_unix_fd (void)
1020 {
1021   gssize to_write = -1;
1022   gssize to_read;
1023   gint fds[2];
1024   gint a, b;
1025   gint s;
1026   GSource *source_a;
1027   GSource *source_b;
1028
1029   s = pipe (fds);
1030   g_assert (s == 0);
1031
1032   to_read = fill_a_pipe (fds[1]);
1033   /* write at higher priority to keep the pipe full... */
1034   a = g_unix_fd_add_full (G_PRIORITY_HIGH, fds[1], G_IO_OUT, write_bytes, &to_write, NULL);
1035   source_a = g_source_ref (g_main_context_find_source_by_id (NULL, a));
1036   /* make sure no 'writes' get dispatched yet */
1037   while (g_main_context_iteration (NULL, FALSE));
1038
1039   to_read += 128 * 1024 * 1024;
1040   to_write = 128 * 1024 * 1024;
1041   b = g_unix_fd_add (fds[0], G_IO_IN, read_bytes, &to_read);
1042   source_b = g_source_ref (g_main_context_find_source_by_id (NULL, b));
1043
1044   /* Assuming the kernel isn't internally 'laggy' then there will always
1045    * be either data to read or room in which to write.  That will keep
1046    * the loop running until all data has been read and written.
1047    */
1048   while (TRUE)
1049     {
1050       gssize to_write_was = to_write;
1051       gssize to_read_was = to_read;
1052
1053       if (!g_main_context_iteration (NULL, FALSE))
1054         break;
1055
1056       /* Since the sources are at different priority, only one of them
1057        * should possibly have run.
1058        */
1059       g_assert (to_write == to_write_was || to_read == to_read_was);
1060     }
1061
1062   g_assert (to_write == 0);
1063   g_assert (to_read == 0);
1064
1065   /* 'a' is already removed by itself */
1066   g_assert (g_source_is_destroyed (source_a));
1067   g_source_unref (source_a);
1068   g_source_remove (b);
1069   g_assert (g_source_is_destroyed (source_b));
1070   g_source_unref (source_b);
1071   close (fds[1]);
1072   close (fds[0]);
1073 }
1074
1075 static void
1076 assert_main_context_state (gint n_to_poll,
1077                            ...)
1078 {
1079   GMainContext *context;
1080   gboolean consumed[10] = { };
1081   GPollFD poll_fds[10];
1082   gboolean immediate;
1083   gint max_priority;
1084   gint timeout;
1085   gint n;
1086   gint i, j;
1087   va_list ap;
1088
1089   context = g_main_context_default ();
1090
1091   immediate = g_main_context_prepare (context, &max_priority);
1092   g_assert (!immediate);
1093   n = g_main_context_query (context, max_priority, &timeout, poll_fds, 10);
1094   g_assert_cmpint (n, ==, n_to_poll + 1); /* one will be the gwakeup */
1095
1096   va_start (ap, n_to_poll);
1097   for (i = 0; i < n_to_poll; i++)
1098     {
1099       gint expected_fd = va_arg (ap, gint);
1100       GIOCondition expected_events = va_arg (ap, GIOCondition);
1101       GIOCondition report_events = va_arg (ap, GIOCondition);
1102
1103       for (j = 0; j < n; j++)
1104         if (!consumed[j] && poll_fds[j].fd == expected_fd && poll_fds[j].events == expected_events)
1105           {
1106             poll_fds[j].revents = report_events;
1107             consumed[j] = TRUE;
1108             break;
1109           }
1110
1111       if (j == n)
1112         g_error ("Unable to find fd %d (index %d) with events 0x%x\n", expected_fd, i, (guint) expected_events);
1113     }
1114   va_end (ap);
1115
1116   /* find the gwakeup, flag as non-ready */
1117   for (i = 0; i < n; i++)
1118     if (!consumed[i])
1119       poll_fds[i].revents = 0;
1120
1121   if (g_main_context_check (context, max_priority, poll_fds, n))
1122     g_main_context_dispatch (context);
1123 }
1124
1125 static gboolean
1126 flag_bool (gint         fd,
1127            GIOCondition condition,
1128            gpointer     user_data)
1129 {
1130   gboolean *flag = user_data;
1131
1132   *flag = TRUE;
1133
1134   return TRUE;
1135 }
1136
1137 static void
1138 test_unix_fd_source (void)
1139 {
1140   GSource *out_source;
1141   GSource *in_source;
1142   GSource *source;
1143   gboolean out, in;
1144   gint fds[2];
1145   gint s;
1146
1147   assert_main_context_state (0);
1148
1149   s = pipe (fds);
1150   g_assert (s == 0);
1151
1152   source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1153   g_source_attach (source, NULL);
1154
1155   /* Check that a source with no callback gets successfully detached
1156    * with a warning printed.
1157    */
1158   g_test_expect_message ("GLib", G_LOG_LEVEL_WARNING, "*GUnixFDSource dispatched without callback*");
1159   while (g_main_context_iteration (NULL, FALSE));
1160   g_test_assert_expected_messages ();
1161   g_assert (g_source_is_destroyed (source));
1162   g_source_unref (source);
1163
1164   out = in = FALSE;
1165   out_source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1166   g_source_set_callback (out_source, (GSourceFunc) flag_bool, &out, NULL);
1167   g_source_attach (out_source, NULL);
1168   assert_main_context_state (1,
1169                              fds[1], G_IO_OUT, 0);
1170   g_assert (!in && !out);
1171
1172   in_source = g_unix_fd_source_new (fds[0], G_IO_IN);
1173   g_source_set_callback (in_source, (GSourceFunc) flag_bool, &in, NULL);
1174   g_source_set_priority (in_source, G_PRIORITY_DEFAULT_IDLE);
1175   g_source_attach (in_source, NULL);
1176   assert_main_context_state (2,
1177                              fds[0], G_IO_IN, G_IO_IN,
1178                              fds[1], G_IO_OUT, G_IO_OUT);
1179   /* out is higher priority so only it should fire */
1180   g_assert (!in && out);
1181
1182   /* raise the priority of the in source to higher than out*/
1183   in = out = FALSE;
1184   g_source_set_priority (in_source, G_PRIORITY_HIGH);
1185   assert_main_context_state (2,
1186                              fds[0], G_IO_IN, G_IO_IN,
1187                              fds[1], G_IO_OUT, G_IO_OUT);
1188   g_assert (in && !out);
1189
1190   /* now, let them be equal */
1191   in = out = FALSE;
1192   g_source_set_priority (in_source, G_PRIORITY_DEFAULT);
1193   assert_main_context_state (2,
1194                              fds[0], G_IO_IN, G_IO_IN,
1195                              fds[1], G_IO_OUT, G_IO_OUT);
1196   g_assert (in && out);
1197
1198   g_source_destroy (out_source);
1199   g_source_destroy (in_source);
1200   close (fds[1]);
1201   close (fds[0]);
1202 }
1203
1204 typedef struct
1205 {
1206   GSource parent;
1207   gboolean flagged;
1208 } FlagSource;
1209
1210 static gboolean
1211 return_true (GSource *source, GSourceFunc callback, gpointer user_data)
1212 {
1213   FlagSource *flag_source = (FlagSource *) source;
1214
1215   flag_source->flagged = TRUE;
1216
1217   return TRUE;
1218 }
1219
1220 #define assert_flagged(s) g_assert (((FlagSource *) (s))->flagged);
1221 #define assert_not_flagged(s) g_assert (!((FlagSource *) (s))->flagged);
1222 #define clear_flag(s) ((FlagSource *) (s))->flagged = 0
1223
1224 static void
1225 test_source_unix_fd_api (void)
1226 {
1227   GSourceFuncs no_funcs = {
1228     NULL, NULL, return_true
1229   };
1230   GSource *source_a;
1231   GSource *source_b;
1232   gpointer tag1, tag2;
1233   gint fds_a[2];
1234   gint fds_b[2];
1235
1236   pipe (fds_a);
1237   pipe (fds_b);
1238
1239   source_a = g_source_new (&no_funcs, sizeof (FlagSource));
1240   source_b = g_source_new (&no_funcs, sizeof (FlagSource));
1241
1242   /* attach a source with more than one fd */
1243   g_source_add_unix_fd (source_a, fds_a[0], G_IO_IN);
1244   g_source_add_unix_fd (source_a, fds_a[1], G_IO_OUT);
1245   g_source_attach (source_a, NULL);
1246   assert_main_context_state (2,
1247                              fds_a[0], G_IO_IN, 0,
1248                              fds_a[1], G_IO_OUT, 0);
1249   assert_not_flagged (source_a);
1250
1251   /* attach a higher priority source with no fds */
1252   g_source_set_priority (source_b, G_PRIORITY_HIGH);
1253   g_source_attach (source_b, NULL);
1254   assert_main_context_state (2,
1255                              fds_a[0], G_IO_IN, G_IO_IN,
1256                              fds_a[1], G_IO_OUT, 0);
1257   assert_flagged (source_a);
1258   assert_not_flagged (source_b);
1259   clear_flag (source_a);
1260
1261   /* add some fds to the second source, while attached */
1262   tag1 = g_source_add_unix_fd (source_b, fds_b[0], G_IO_IN);
1263   tag2 = g_source_add_unix_fd (source_b, fds_b[1], G_IO_OUT);
1264   assert_main_context_state (4,
1265                              fds_a[0], G_IO_IN, 0,
1266                              fds_a[1], G_IO_OUT, G_IO_OUT,
1267                              fds_b[0], G_IO_IN, 0,
1268                              fds_b[1], G_IO_OUT, G_IO_OUT);
1269   /* only 'b' (higher priority) should have dispatched */
1270   assert_not_flagged (source_a);
1271   assert_flagged (source_b);
1272   clear_flag (source_b);
1273
1274   /* change our events on b to the same as they were before */
1275   g_source_modify_unix_fd (source_b, tag1, G_IO_IN);
1276   g_source_modify_unix_fd (source_b, tag2, G_IO_OUT);
1277   assert_main_context_state (4,
1278                              fds_a[0], G_IO_IN, 0,
1279                              fds_a[1], G_IO_OUT, G_IO_OUT,
1280                              fds_b[0], G_IO_IN, 0,
1281                              fds_b[1], G_IO_OUT, G_IO_OUT);
1282   assert_not_flagged (source_a);
1283   assert_flagged (source_b);
1284   clear_flag (source_b);
1285
1286   /* now reverse them */
1287   g_source_modify_unix_fd (source_b, tag1, G_IO_OUT);
1288   g_source_modify_unix_fd (source_b, tag2, G_IO_IN);
1289   assert_main_context_state (4,
1290                              fds_a[0], G_IO_IN, 0,
1291                              fds_a[1], G_IO_OUT, G_IO_OUT,
1292                              fds_b[0], G_IO_OUT, 0,
1293                              fds_b[1], G_IO_IN, 0);
1294   /* 'b' had no events, so 'a' can go this time */
1295   assert_flagged (source_a);
1296   assert_not_flagged (source_b);
1297   clear_flag (source_a);
1298
1299   /* remove one of the fds from 'b' */
1300   g_source_remove_unix_fd (source_b, tag1);
1301   assert_main_context_state (3,
1302                              fds_a[0], G_IO_IN, 0,
1303                              fds_a[1], G_IO_OUT, 0,
1304                              fds_b[1], G_IO_IN, 0);
1305   assert_not_flagged (source_a);
1306   assert_not_flagged (source_b);
1307
1308   /* remove the other */
1309   g_source_remove_unix_fd (source_b, tag2);
1310   assert_main_context_state (2,
1311                              fds_a[0], G_IO_IN, 0,
1312                              fds_a[1], G_IO_OUT, 0);
1313   assert_not_flagged (source_a);
1314   assert_not_flagged (source_b);
1315
1316   /* destroy the sources */
1317   g_source_destroy (source_a);
1318   g_source_destroy (source_b);
1319   assert_main_context_state (0);
1320
1321   g_source_unref (source_a);
1322   g_source_unref (source_b);
1323   close (fds_a[0]);
1324   close (fds_a[1]);
1325   close (fds_b[0]);
1326   close (fds_b[1]);
1327 }
1328
1329 #endif
1330
1331 int
1332 main (int argc, char *argv[])
1333 {
1334   g_test_init (&argc, &argv, NULL);
1335   g_test_bug_base ("http://bugzilla.gnome.org/");
1336
1337   g_test_add_func ("/maincontext/basic", test_maincontext_basic);
1338   g_test_add_func ("/mainloop/basic", test_mainloop_basic);
1339   g_test_add_func ("/mainloop/timeouts", test_timeouts);
1340   g_test_add_func ("/mainloop/priorities", test_priorities);
1341   g_test_add_func ("/mainloop/invoke", test_invoke);
1342   g_test_add_func ("/mainloop/child_sources", test_child_sources);
1343   g_test_add_func ("/mainloop/recursive_child_sources", test_recursive_child_sources);
1344   g_test_add_func ("/mainloop/swapping_child_sources", test_swapping_child_sources);
1345   g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources);
1346   g_test_add_func ("/mainloop/source_time", test_source_time);
1347   g_test_add_func ("/mainloop/overflow", test_mainloop_overflow);
1348   g_test_add_func ("/mainloop/ready-time", test_ready_time);
1349   g_test_add_func ("/mainloop/wakeup", test_wakeup);
1350 #ifdef G_OS_UNIX
1351   g_test_add_func ("/mainloop/unix-fd", test_unix_fd);
1352   g_test_add_func ("/mainloop/unix-fd-source", test_unix_fd_source);
1353   g_test_add_func ("/mainloop/source-unix-fd-api", test_source_unix_fd_api);
1354 #endif
1355
1356   return g_test_run ();
1357 }