1c08ee1836c10e9f38d4d266a998b249daaa547c
[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 /* We can't use timeout sources here because on slow or heavily-loaded
356  * machines, the test program might not get enough cycles to hit the
357  * timeouts at the expected times. So instead we define a source that
358  * is based on the number of GMainContext iterations.
359  */
360
361 static gint counter;
362 static gint64 last_counter_update;
363
364 typedef struct {
365   GSource source;
366   gint    interval;
367   gint    timeout;
368 } CounterSource;
369
370 static gboolean
371 counter_source_prepare (GSource *source,
372                         gint    *timeout)
373 {
374   CounterSource *csource = (CounterSource *)source;
375   gint64 now;
376
377   now = g_source_get_time (source);
378   if (now != last_counter_update)
379     {
380       last_counter_update = now;
381       counter++;
382     }
383
384   *timeout = 1;
385   return counter >= csource->timeout;
386 }
387
388 static gboolean
389 counter_source_dispatch (GSource    *source,
390                          GSourceFunc callback,
391                          gpointer    user_data)
392 {
393   CounterSource *csource = (CounterSource *) source;
394   gboolean again;
395
396   again = callback (user_data);
397
398   if (again)
399     csource->timeout = counter + csource->interval;
400
401   return again;
402 }
403
404 static GSourceFuncs counter_source_funcs = {
405   counter_source_prepare,
406   NULL,
407   counter_source_dispatch,
408   NULL,
409 };
410
411 static GSource *
412 counter_source_new (gint interval)
413 {
414   GSource *source = g_source_new (&counter_source_funcs, sizeof (CounterSource));
415   CounterSource *csource = (CounterSource *) source;
416
417   csource->interval = interval;
418   csource->timeout = counter + interval;
419
420   return source;
421 }
422
423
424 static gboolean
425 run_inner_loop (gpointer user_data)
426 {
427   GMainContext *ctx = user_data;
428   GMainLoop *inner;
429   GSource *timeout;
430
431   a++;
432
433   inner = g_main_loop_new (ctx, FALSE);
434   timeout = counter_source_new (100);
435   g_source_set_callback (timeout, quit_loop, inner, NULL);
436   g_source_attach (timeout, ctx);
437   g_source_unref (timeout);
438
439   g_main_loop_run (inner);
440   g_main_loop_unref (inner);
441
442   return G_SOURCE_CONTINUE;
443 }
444
445 static void
446 test_child_sources (void)
447 {
448   GMainContext *ctx;
449   GMainLoop *loop;
450   GSource *parent, *child_b, *child_c, *end;
451
452   ctx = g_main_context_new ();
453   loop = g_main_loop_new (ctx, FALSE);
454
455   a = b = c = 0;
456
457   parent = counter_source_new (2000);
458   g_source_set_callback (parent, run_inner_loop, ctx, NULL);
459   g_source_set_priority (parent, G_PRIORITY_LOW);
460   g_source_attach (parent, ctx);
461
462   child_b = counter_source_new (250);
463   g_source_set_callback (child_b, count_calls, &b, NULL);
464   g_source_add_child_source (parent, child_b);
465
466   child_c = counter_source_new (330);
467   g_source_set_callback (child_c, count_calls, &c, NULL);
468   g_source_set_priority (child_c, G_PRIORITY_HIGH);
469   g_source_add_child_source (parent, child_c);
470
471   /* Child sources always have the priority of the parent */
472   g_assert_cmpint (g_source_get_priority (parent), ==, G_PRIORITY_LOW);
473   g_assert_cmpint (g_source_get_priority (child_b), ==, G_PRIORITY_LOW);
474   g_assert_cmpint (g_source_get_priority (child_c), ==, G_PRIORITY_LOW);
475   g_source_set_priority (parent, G_PRIORITY_DEFAULT);
476   g_assert_cmpint (g_source_get_priority (parent), ==, G_PRIORITY_DEFAULT);
477   g_assert_cmpint (g_source_get_priority (child_b), ==, G_PRIORITY_DEFAULT);
478   g_assert_cmpint (g_source_get_priority (child_c), ==, G_PRIORITY_DEFAULT);
479
480   end = counter_source_new (1050);
481   g_source_set_callback (end, quit_loop, loop, NULL);
482   g_source_attach (end, ctx);
483   g_source_unref (end);
484
485   g_main_loop_run (loop);
486
487   /* The parent source's own timeout will never trigger, so "a" will
488    * only get incremented when "b" or "c" does. And when timeouts get
489    * blocked, they still wait the full interval next time rather than
490    * "catching up". So the timing is:
491    *
492    *  250 - b++ -> a++, run_inner_loop
493    *  330 - (c is blocked)
494    *  350 - inner_loop ends
495    *  350 - c++ belatedly -> a++, run_inner_loop
496    *  450 - inner loop ends
497    *  500 - b++ -> a++, run_inner_loop
498    *  600 - inner_loop ends
499    *  680 - c++ -> a++, run_inner_loop
500    *  750 - (b is blocked)
501    *  780 - inner loop ends
502    *  780 - b++ belatedly -> a++, run_inner_loop
503    *  880 - inner loop ends
504    * 1010 - c++ -> a++, run_inner_loop
505    * 1030 - (b is blocked)
506    * 1050 - end runs, quits outer loop, which has no effect yet
507    * 1110 - inner loop ends, a returns, outer loop exits
508    */
509
510   g_assert_cmpint (a, ==, 6);
511   g_assert_cmpint (b, ==, 3);
512   g_assert_cmpint (c, ==, 3);
513
514   g_source_destroy (parent);
515   g_source_unref (parent);
516   g_source_unref (child_b);
517   g_source_unref (child_c);
518
519   g_main_loop_unref (loop);
520   g_main_context_unref (ctx);
521 }
522
523 static void
524 test_recursive_child_sources (void)
525 {
526   GMainContext *ctx;
527   GMainLoop *loop;
528   GSource *parent, *child_b, *child_c, *end;
529
530   ctx = g_main_context_new ();
531   loop = g_main_loop_new (ctx, FALSE);
532
533   a = b = c = 0;
534
535   parent = counter_source_new (500);
536   g_source_set_callback (parent, count_calls, &a, NULL);
537
538   child_b = counter_source_new (220);
539   g_source_set_callback (child_b, count_calls, &b, NULL);
540   g_source_add_child_source (parent, child_b);
541
542   child_c = counter_source_new (430);
543   g_source_set_callback (child_c, count_calls, &c, NULL);
544   g_source_add_child_source (child_b, child_c);
545
546   g_source_attach (parent, ctx);
547
548   end = counter_source_new (2010);
549   g_source_set_callback (end, (GSourceFunc)g_main_loop_quit, loop, NULL);
550   g_source_attach (end, ctx);
551   g_source_unref (end);
552
553   g_main_loop_run (loop);
554
555   /* Sequence of events:
556    *  220 b (b -> 440, a -> 720)
557    *  430 c (c -> 860, b -> 650, a -> 930)
558    *  650 b (b -> 870, a -> 1150)
559    *  860 c (c -> 1290, b -> 1080, a -> 1360)
560    * 1080 b (b -> 1300, a -> 1580)
561    * 1290 c (c -> 1720, b -> 1510, a -> 1790)
562    * 1510 b (b -> 1730, a -> 2010)
563    * 1720 c (c -> 2150, b -> 1940, a -> 2220)
564    * 1940 b (b -> 2160, a -> 2440)
565    */
566
567   g_assert_cmpint (a, ==, 9);
568   g_assert_cmpint (b, ==, 9);
569   g_assert_cmpint (c, ==, 4);
570
571   g_source_destroy (parent);
572   g_source_unref (parent);
573   g_source_unref (child_b);
574   g_source_unref (child_c);
575
576   g_main_loop_unref (loop);
577   g_main_context_unref (ctx);
578 }
579
580 typedef struct {
581   GSource *parent, *old_child, *new_child;
582   GMainLoop *loop;
583 } SwappingTestData;
584
585 static gboolean
586 swap_sources (gpointer user_data)
587 {
588   SwappingTestData *data = user_data;
589
590   if (data->old_child)
591     {
592       g_source_remove_child_source (data->parent, data->old_child);
593       g_clear_pointer (&data->old_child, g_source_unref);
594     }
595
596   if (!data->new_child)
597     {
598       data->new_child = g_timeout_source_new (0);
599       g_source_set_callback (data->new_child, quit_loop, data->loop, NULL);
600       g_source_add_child_source (data->parent, data->new_child);
601     }
602
603   return G_SOURCE_CONTINUE;
604 }
605
606 static gboolean
607 assert_not_reached_callback (gpointer user_data)
608 {
609   g_assert_not_reached ();
610
611   return G_SOURCE_REMOVE;
612 }
613
614 static void
615 test_swapping_child_sources (void)
616 {
617   GMainContext *ctx;
618   GMainLoop *loop;
619   SwappingTestData data;
620
621   ctx = g_main_context_new ();
622   loop = g_main_loop_new (ctx, FALSE);
623
624   data.parent = counter_source_new (50);
625   data.loop = loop;
626   g_source_set_callback (data.parent, swap_sources, &data, NULL);
627   g_source_attach (data.parent, ctx);
628
629   data.old_child = counter_source_new (100);
630   g_source_add_child_source (data.parent, data.old_child);
631   g_source_set_callback (data.old_child, assert_not_reached_callback, NULL, NULL);
632
633   data.new_child = NULL;
634   g_main_loop_run (loop);
635
636   g_source_destroy (data.parent);
637   g_source_unref (data.parent);
638   g_source_unref (data.new_child);
639
640   g_main_loop_unref (loop);
641   g_main_context_unref (ctx);
642 }
643
644 static gboolean
645 add_source_callback (gpointer user_data)
646 {
647   GMainLoop *loop = user_data;
648   GSource *self = g_main_current_source (), *child;
649   GIOChannel *io;
650
651   /* It doesn't matter whether this is a valid fd or not; it never
652    * actually gets polled; the test is just checking that
653    * g_source_add_child_source() doesn't crash.
654    */
655   io = g_io_channel_unix_new (0);
656   child = g_io_create_watch (io, G_IO_IN);
657   g_source_add_child_source (self, child);
658   g_source_unref (child);
659   g_io_channel_unref (io);
660
661   g_main_loop_quit (loop);
662   return FALSE;
663 }
664
665 static void
666 test_blocked_child_sources (void)
667 {
668   GMainContext *ctx;
669   GMainLoop *loop;
670   GSource *source;
671
672   g_test_bug ("701283");
673
674   ctx = g_main_context_new ();
675   loop = g_main_loop_new (ctx, FALSE);
676
677   source = g_idle_source_new ();
678   g_source_set_callback (source, add_source_callback, loop, NULL);
679   g_source_attach (source, ctx);
680
681   g_main_loop_run (loop);
682
683   g_source_destroy (source);
684   g_source_unref (source);
685
686   g_main_loop_unref (loop);
687   g_main_context_unref (ctx);
688 }
689
690 typedef struct {
691   GMainContext *ctx;
692   GMainLoop *loop;
693
694   GSource *timeout1, *timeout2;
695   gint64 time1;
696 } TimeTestData;
697
698 static gboolean
699 timeout1_callback (gpointer user_data)
700 {
701   TimeTestData *data = user_data;
702   GSource *source;
703   gint64 mtime1, mtime2, time2;
704
705   source = g_main_current_source ();
706   g_assert (source == data->timeout1);
707
708   if (data->time1 == -1)
709     {
710       /* First iteration */
711       g_assert (!g_source_is_destroyed (data->timeout2));
712
713       mtime1 = g_get_monotonic_time ();
714       data->time1 = g_source_get_time (source);
715
716       /* g_source_get_time() does not change during a single callback */
717       g_usleep (1000000);
718       mtime2 = g_get_monotonic_time ();
719       time2 = g_source_get_time (source);
720
721       g_assert_cmpint (mtime1, <, mtime2);
722       g_assert_cmpint (data->time1, ==, time2);
723     }
724   else
725     {
726       /* Second iteration */
727       g_assert (g_source_is_destroyed (data->timeout2));
728
729       /* g_source_get_time() MAY change between iterations; in this
730        * case we know for sure that it did because of the g_usleep()
731        * last time.
732        */
733       time2 = g_source_get_time (source);
734       g_assert_cmpint (data->time1, <, time2);
735
736       g_main_loop_quit (data->loop);
737     }
738
739   return TRUE;
740 }
741
742 static gboolean
743 timeout2_callback (gpointer user_data)
744 {
745   TimeTestData *data = user_data;
746   GSource *source;
747   gint64 time2, time3;
748
749   source = g_main_current_source ();
750   g_assert (source == data->timeout2);
751
752   g_assert (!g_source_is_destroyed (data->timeout1));
753
754   /* g_source_get_time() does not change between different sources in
755    * a single iteration of the mainloop.
756    */
757   time2 = g_source_get_time (source);
758   g_assert_cmpint (data->time1, ==, time2);
759
760   /* The source should still have a valid time even after being
761    * destroyed, since it's currently running.
762    */
763   g_source_destroy (source);
764   time3 = g_source_get_time (source);
765   g_assert_cmpint (time2, ==, time3);
766
767   return FALSE;
768 }
769
770 static void
771 test_source_time (void)
772 {
773   TimeTestData data;
774
775   data.ctx = g_main_context_new ();
776   data.loop = g_main_loop_new (data.ctx, FALSE);
777
778   data.timeout1 = g_timeout_source_new (0);
779   g_source_set_callback (data.timeout1, timeout1_callback, &data, NULL);
780   g_source_attach (data.timeout1, data.ctx);
781
782   data.timeout2 = g_timeout_source_new (0);
783   g_source_set_callback (data.timeout2, timeout2_callback, &data, NULL);
784   g_source_attach (data.timeout2, data.ctx);
785
786   data.time1 = -1;
787
788   g_main_loop_run (data.loop);
789
790   g_assert (!g_source_is_destroyed (data.timeout1));
791   g_assert (g_source_is_destroyed (data.timeout2));
792
793   g_source_destroy (data.timeout1);
794   g_source_unref (data.timeout1);
795   g_source_unref (data.timeout2);
796
797   g_main_loop_unref (data.loop);
798   g_main_context_unref (data.ctx);
799 }
800
801 typedef struct {
802   guint outstanding_ops;
803   GMainLoop *loop;
804 } TestOverflowData;
805
806 static gboolean
807 on_source_fired_cb (gpointer user_data)
808 {
809   TestOverflowData *data = user_data;
810   GSource *current_source;
811   GMainContext *current_context;
812   guint source_id;
813
814   data->outstanding_ops--;
815
816   current_source = g_main_current_source ();
817   current_context = g_source_get_context (current_source);
818   source_id = g_source_get_id (current_source);
819   g_assert (g_main_context_find_source_by_id (current_context, source_id) != NULL);
820   g_source_destroy (current_source);
821   g_assert (g_main_context_find_source_by_id (current_context, source_id) == NULL);
822
823   if (data->outstanding_ops == 0)
824     g_main_loop_quit (data->loop);
825   return FALSE;
826 }
827
828 static GSource *
829 add_idle_source (GMainContext *ctx,
830                  TestOverflowData *data)
831 {
832   GSource *source;
833
834   source = g_idle_source_new ();
835   g_source_set_callback (source, on_source_fired_cb, data, NULL);
836   g_source_attach (source, ctx);
837   g_source_unref (source);
838   data->outstanding_ops++;
839
840   return source;
841 }
842
843 static void
844 test_mainloop_overflow (void)
845 {
846   GMainContext *ctx;
847   GMainLoop *loop;
848   GSource *source;
849   TestOverflowData data;
850   guint i;
851
852   g_test_bug ("687098");
853
854   memset (&data, 0, sizeof (data));
855
856   ctx = GLIB_PRIVATE_CALL (g_main_context_new_with_next_id) (G_MAXUINT-1);
857
858   loop = g_main_loop_new (ctx, TRUE);
859   data.outstanding_ops = 0;
860   data.loop = loop;
861
862   source = add_idle_source (ctx, &data);
863   g_assert_cmpint (source->source_id, ==, G_MAXUINT-1);
864
865   source = add_idle_source (ctx, &data);
866   g_assert_cmpint (source->source_id, ==, G_MAXUINT);
867
868   source = add_idle_source (ctx, &data);
869   g_assert_cmpint (source->source_id, !=, 0);
870
871   /* Now, a lot more sources */
872   for (i = 0; i < 50; i++)
873     {
874       source = add_idle_source (ctx, &data);
875       g_assert_cmpint (source->source_id, !=, 0);
876     }
877
878   g_main_loop_run (loop);
879   g_assert_cmpint (data.outstanding_ops, ==, 0);
880
881   g_main_loop_unref (loop);
882   g_main_context_unref (ctx);
883 }
884
885 static volatile gint ready_time_dispatched;
886
887 static gboolean
888 ready_time_dispatch (GSource     *source,
889                      GSourceFunc  callback,
890                      gpointer     user_data)
891 {
892   g_atomic_int_set (&ready_time_dispatched, TRUE);
893
894   g_source_set_ready_time (source, -1);
895
896   return TRUE;
897 }
898
899 static gpointer
900 run_context (gpointer user_data)
901 {
902   g_main_loop_run (user_data);
903
904   return NULL;
905 }
906
907 static void
908 test_ready_time (void)
909 {
910   GThread *thread;
911   GSource *source;
912   GSourceFuncs source_funcs = {
913     NULL, NULL, ready_time_dispatch
914   };
915   GMainLoop *loop;
916
917   source = g_source_new (&source_funcs, sizeof (GSource));
918   g_source_attach (source, NULL);
919   g_source_unref (source);
920
921   /* Unfortunately we can't do too many things with respect to timing
922    * without getting into trouble on slow systems or heavily loaded
923    * builders.
924    *
925    * We can test that the basics are working, though.
926    */
927
928   /* A source with no ready time set should not fire */
929   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
930   while (g_main_context_iteration (NULL, FALSE));
931   g_assert (!ready_time_dispatched);
932
933   /* The ready time should not have been changed */
934   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
935
936   /* Of course this shouldn't change anything either */
937   g_source_set_ready_time (source, -1);
938   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
939
940   /* A source with a ready time set to tomorrow should not fire on any
941    * builder, no matter how badly loaded...
942    */
943   g_source_set_ready_time (source, g_get_monotonic_time () + G_TIME_SPAN_DAY);
944   while (g_main_context_iteration (NULL, FALSE));
945   g_assert (!ready_time_dispatched);
946   /* Make sure it didn't get reset */
947   g_assert_cmpint (g_source_get_ready_time (source), !=, -1);
948
949   /* Ready time of -1 -> don't fire */
950   g_source_set_ready_time (source, -1);
951   while (g_main_context_iteration (NULL, FALSE));
952   g_assert (!ready_time_dispatched);
953   /* Not reset, but should still be -1 from above */
954   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
955
956   /* A ready time of the current time should fire immediately */
957   g_source_set_ready_time (source, g_get_monotonic_time ());
958   while (g_main_context_iteration (NULL, FALSE));
959   g_assert (ready_time_dispatched);
960   ready_time_dispatched = FALSE;
961   /* Should have gotten reset by the handler function */
962   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
963
964   /* As well as one in the recent past... */
965   g_source_set_ready_time (source, g_get_monotonic_time () - G_TIME_SPAN_SECOND);
966   while (g_main_context_iteration (NULL, FALSE));
967   g_assert (ready_time_dispatched);
968   ready_time_dispatched = FALSE;
969   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
970
971   /* Zero is the 'official' way to get a source to fire immediately */
972   g_source_set_ready_time (source, 0);
973   while (g_main_context_iteration (NULL, FALSE));
974   g_assert (ready_time_dispatched);
975   ready_time_dispatched = FALSE;
976   g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
977
978   /* Now do some tests of cross-thread wakeups.
979    *
980    * Make sure it wakes up right away from the start.
981    */
982   g_source_set_ready_time (source, 0);
983   loop = g_main_loop_new (NULL, FALSE);
984   thread = g_thread_new ("context thread", run_context, loop);
985   while (!g_atomic_int_get (&ready_time_dispatched));
986
987   /* Now let's see if it can wake up from sleeping. */
988   g_usleep (G_TIME_SPAN_SECOND / 2);
989   g_atomic_int_set (&ready_time_dispatched, FALSE);
990   g_source_set_ready_time (source, 0);
991   while (!g_atomic_int_get (&ready_time_dispatched));
992
993   /* kill the thread */
994   g_main_loop_quit (loop);
995   g_thread_join (thread);
996   g_main_loop_unref (loop);
997
998   g_source_destroy (source);
999 }
1000
1001 static void
1002 test_wakeup(void)
1003 {
1004   GMainContext *ctx;
1005   int i;
1006
1007   ctx = g_main_context_new ();
1008
1009   /* run a random large enough number of times because 
1010    * main contexts tend to wake up a few times after creation.
1011    */
1012   for (i = 0; i < 100; i++)
1013     {
1014       /* This is the invariant we care about:
1015        * g_main_context_wakeup(ctx,) ensures that the next call to
1016        * g_main_context_iteration (ctx, TRUE) returns and doesn't
1017        * block.
1018        * This is important in threaded apps where we might not know
1019        * if the thread calls g_main_context_wakeup() before or after
1020        * we enter g_main_context_iteration().
1021        */
1022       g_main_context_wakeup (ctx);
1023       g_main_context_iteration (ctx, TRUE);
1024     }
1025
1026   g_main_context_unref (ctx);
1027 }
1028
1029 #ifdef G_OS_UNIX
1030
1031 #include <glib-unix.h>
1032 #include <unistd.h>
1033
1034 static gchar zeros[1024];
1035
1036 static gsize
1037 fill_a_pipe (gint fd)
1038 {
1039   gsize written = 0;
1040   GPollFD pfd;
1041
1042   pfd.fd = fd;
1043   pfd.events = G_IO_OUT;
1044   while (g_poll (&pfd, 1, 0) == 1)
1045     /* we should never see -1 here */
1046     written += write (fd, zeros, sizeof zeros);
1047
1048   return written;
1049 }
1050
1051 static gboolean
1052 write_bytes (gint         fd,
1053              GIOCondition condition,
1054              gpointer     user_data)
1055 {
1056   gssize *to_write = user_data;
1057   gint limit;
1058
1059   if (*to_write == 0)
1060     return FALSE;
1061
1062   /* Detect if we run before we should */
1063   g_assert (*to_write >= 0);
1064
1065   limit = MIN (*to_write, sizeof zeros);
1066   *to_write -= write (fd, zeros, limit);
1067
1068   return TRUE;
1069 }
1070
1071 static gboolean
1072 read_bytes (gint         fd,
1073             GIOCondition condition,
1074             gpointer     user_data)
1075 {
1076   static gchar buffer[1024];
1077   gssize *to_read = user_data;
1078
1079   *to_read -= read (fd, buffer, sizeof buffer);
1080
1081   /* The loop will exit when there is nothing else to read, then we will
1082    * use g_source_remove() to destroy this source.
1083    */
1084   return TRUE;
1085 }
1086
1087 static void
1088 test_unix_fd (void)
1089 {
1090   gssize to_write = -1;
1091   gssize to_read;
1092   gint fds[2];
1093   gint a, b;
1094   gint s;
1095   GSource *source_a;
1096   GSource *source_b;
1097
1098   s = pipe (fds);
1099   g_assert (s == 0);
1100
1101   to_read = fill_a_pipe (fds[1]);
1102   /* write at higher priority to keep the pipe full... */
1103   a = g_unix_fd_add_full (G_PRIORITY_HIGH, fds[1], G_IO_OUT, write_bytes, &to_write, NULL);
1104   source_a = g_source_ref (g_main_context_find_source_by_id (NULL, a));
1105   /* make sure no 'writes' get dispatched yet */
1106   while (g_main_context_iteration (NULL, FALSE));
1107
1108   to_read += 128 * 1024 * 1024;
1109   to_write = 128 * 1024 * 1024;
1110   b = g_unix_fd_add (fds[0], G_IO_IN, read_bytes, &to_read);
1111   source_b = g_source_ref (g_main_context_find_source_by_id (NULL, b));
1112
1113   /* Assuming the kernel isn't internally 'laggy' then there will always
1114    * be either data to read or room in which to write.  That will keep
1115    * the loop running until all data has been read and written.
1116    */
1117   while (TRUE)
1118     {
1119       gssize to_write_was = to_write;
1120       gssize to_read_was = to_read;
1121
1122       if (!g_main_context_iteration (NULL, FALSE))
1123         break;
1124
1125       /* Since the sources are at different priority, only one of them
1126        * should possibly have run.
1127        */
1128       g_assert (to_write == to_write_was || to_read == to_read_was);
1129     }
1130
1131   g_assert (to_write == 0);
1132   g_assert (to_read == 0);
1133
1134   /* 'a' is already removed by itself */
1135   g_assert (g_source_is_destroyed (source_a));
1136   g_source_unref (source_a);
1137   g_source_remove (b);
1138   g_assert (g_source_is_destroyed (source_b));
1139   g_source_unref (source_b);
1140   close (fds[1]);
1141   close (fds[0]);
1142 }
1143
1144 static void
1145 assert_main_context_state (gint n_to_poll,
1146                            ...)
1147 {
1148   GMainContext *context;
1149   gboolean consumed[10] = { };
1150   GPollFD poll_fds[10];
1151   gboolean immediate;
1152   gint max_priority;
1153   gint timeout;
1154   gint n;
1155   gint i, j;
1156   va_list ap;
1157
1158   context = g_main_context_default ();
1159
1160   immediate = g_main_context_prepare (context, &max_priority);
1161   g_assert (!immediate);
1162   n = g_main_context_query (context, max_priority, &timeout, poll_fds, 10);
1163   g_assert_cmpint (n, ==, n_to_poll + 1); /* one will be the gwakeup */
1164
1165   va_start (ap, n_to_poll);
1166   for (i = 0; i < n_to_poll; i++)
1167     {
1168       gint expected_fd = va_arg (ap, gint);
1169       GIOCondition expected_events = va_arg (ap, GIOCondition);
1170       GIOCondition report_events = va_arg (ap, GIOCondition);
1171
1172       for (j = 0; j < n; j++)
1173         if (!consumed[j] && poll_fds[j].fd == expected_fd && poll_fds[j].events == expected_events)
1174           {
1175             poll_fds[j].revents = report_events;
1176             consumed[j] = TRUE;
1177             break;
1178           }
1179
1180       if (j == n)
1181         g_error ("Unable to find fd %d (index %d) with events 0x%x\n", expected_fd, i, (guint) expected_events);
1182     }
1183   va_end (ap);
1184
1185   /* find the gwakeup, flag as non-ready */
1186   for (i = 0; i < n; i++)
1187     if (!consumed[i])
1188       poll_fds[i].revents = 0;
1189
1190   if (g_main_context_check (context, max_priority, poll_fds, n))
1191     g_main_context_dispatch (context);
1192 }
1193
1194 static gboolean
1195 flag_bool (gint         fd,
1196            GIOCondition condition,
1197            gpointer     user_data)
1198 {
1199   gboolean *flag = user_data;
1200
1201   *flag = TRUE;
1202
1203   return TRUE;
1204 }
1205
1206 static void
1207 test_unix_fd_source (void)
1208 {
1209   GSource *out_source;
1210   GSource *in_source;
1211   GSource *source;
1212   gboolean out, in;
1213   gint fds[2];
1214   gint s;
1215
1216   assert_main_context_state (0);
1217
1218   s = pipe (fds);
1219   g_assert (s == 0);
1220
1221   source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1222   g_source_attach (source, NULL);
1223
1224   /* Check that a source with no callback gets successfully detached
1225    * with a warning printed.
1226    */
1227   g_test_expect_message ("GLib", G_LOG_LEVEL_WARNING, "*GUnixFDSource dispatched without callback*");
1228   while (g_main_context_iteration (NULL, FALSE));
1229   g_test_assert_expected_messages ();
1230   g_assert (g_source_is_destroyed (source));
1231   g_source_unref (source);
1232
1233   out = in = FALSE;
1234   out_source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1235   g_source_set_callback (out_source, (GSourceFunc) flag_bool, &out, NULL);
1236   g_source_attach (out_source, NULL);
1237   assert_main_context_state (1,
1238                              fds[1], G_IO_OUT, 0);
1239   g_assert (!in && !out);
1240
1241   in_source = g_unix_fd_source_new (fds[0], G_IO_IN);
1242   g_source_set_callback (in_source, (GSourceFunc) flag_bool, &in, NULL);
1243   g_source_set_priority (in_source, G_PRIORITY_DEFAULT_IDLE);
1244   g_source_attach (in_source, NULL);
1245   assert_main_context_state (2,
1246                              fds[0], G_IO_IN, G_IO_IN,
1247                              fds[1], G_IO_OUT, G_IO_OUT);
1248   /* out is higher priority so only it should fire */
1249   g_assert (!in && out);
1250
1251   /* raise the priority of the in source to higher than out*/
1252   in = out = FALSE;
1253   g_source_set_priority (in_source, G_PRIORITY_HIGH);
1254   assert_main_context_state (2,
1255                              fds[0], G_IO_IN, G_IO_IN,
1256                              fds[1], G_IO_OUT, G_IO_OUT);
1257   g_assert (in && !out);
1258
1259   /* now, let them be equal */
1260   in = out = FALSE;
1261   g_source_set_priority (in_source, G_PRIORITY_DEFAULT);
1262   assert_main_context_state (2,
1263                              fds[0], G_IO_IN, G_IO_IN,
1264                              fds[1], G_IO_OUT, G_IO_OUT);
1265   g_assert (in && out);
1266
1267   g_source_destroy (out_source);
1268   g_source_destroy (in_source);
1269   close (fds[1]);
1270   close (fds[0]);
1271 }
1272
1273 typedef struct
1274 {
1275   GSource parent;
1276   gboolean flagged;
1277 } FlagSource;
1278
1279 static gboolean
1280 return_true (GSource *source, GSourceFunc callback, gpointer user_data)
1281 {
1282   FlagSource *flag_source = (FlagSource *) source;
1283
1284   flag_source->flagged = TRUE;
1285
1286   return TRUE;
1287 }
1288
1289 #define assert_flagged(s) g_assert (((FlagSource *) (s))->flagged);
1290 #define assert_not_flagged(s) g_assert (!((FlagSource *) (s))->flagged);
1291 #define clear_flag(s) ((FlagSource *) (s))->flagged = 0
1292
1293 static void
1294 test_source_unix_fd_api (void)
1295 {
1296   GSourceFuncs no_funcs = {
1297     NULL, NULL, return_true
1298   };
1299   GSource *source_a;
1300   GSource *source_b;
1301   gpointer tag1, tag2;
1302   gint fds_a[2];
1303   gint fds_b[2];
1304
1305   pipe (fds_a);
1306   pipe (fds_b);
1307
1308   source_a = g_source_new (&no_funcs, sizeof (FlagSource));
1309   source_b = g_source_new (&no_funcs, sizeof (FlagSource));
1310
1311   /* attach a source with more than one fd */
1312   g_source_add_unix_fd (source_a, fds_a[0], G_IO_IN);
1313   g_source_add_unix_fd (source_a, fds_a[1], G_IO_OUT);
1314   g_source_attach (source_a, NULL);
1315   assert_main_context_state (2,
1316                              fds_a[0], G_IO_IN, 0,
1317                              fds_a[1], G_IO_OUT, 0);
1318   assert_not_flagged (source_a);
1319
1320   /* attach a higher priority source with no fds */
1321   g_source_set_priority (source_b, G_PRIORITY_HIGH);
1322   g_source_attach (source_b, NULL);
1323   assert_main_context_state (2,
1324                              fds_a[0], G_IO_IN, G_IO_IN,
1325                              fds_a[1], G_IO_OUT, 0);
1326   assert_flagged (source_a);
1327   assert_not_flagged (source_b);
1328   clear_flag (source_a);
1329
1330   /* add some fds to the second source, while attached */
1331   tag1 = g_source_add_unix_fd (source_b, fds_b[0], G_IO_IN);
1332   tag2 = g_source_add_unix_fd (source_b, fds_b[1], G_IO_OUT);
1333   assert_main_context_state (4,
1334                              fds_a[0], G_IO_IN, 0,
1335                              fds_a[1], G_IO_OUT, G_IO_OUT,
1336                              fds_b[0], G_IO_IN, 0,
1337                              fds_b[1], G_IO_OUT, G_IO_OUT);
1338   /* only 'b' (higher priority) should have dispatched */
1339   assert_not_flagged (source_a);
1340   assert_flagged (source_b);
1341   clear_flag (source_b);
1342
1343   /* change our events on b to the same as they were before */
1344   g_source_modify_unix_fd (source_b, tag1, G_IO_IN);
1345   g_source_modify_unix_fd (source_b, tag2, G_IO_OUT);
1346   assert_main_context_state (4,
1347                              fds_a[0], G_IO_IN, 0,
1348                              fds_a[1], G_IO_OUT, G_IO_OUT,
1349                              fds_b[0], G_IO_IN, 0,
1350                              fds_b[1], G_IO_OUT, G_IO_OUT);
1351   assert_not_flagged (source_a);
1352   assert_flagged (source_b);
1353   clear_flag (source_b);
1354
1355   /* now reverse them */
1356   g_source_modify_unix_fd (source_b, tag1, G_IO_OUT);
1357   g_source_modify_unix_fd (source_b, tag2, G_IO_IN);
1358   assert_main_context_state (4,
1359                              fds_a[0], G_IO_IN, 0,
1360                              fds_a[1], G_IO_OUT, G_IO_OUT,
1361                              fds_b[0], G_IO_OUT, 0,
1362                              fds_b[1], G_IO_IN, 0);
1363   /* 'b' had no events, so 'a' can go this time */
1364   assert_flagged (source_a);
1365   assert_not_flagged (source_b);
1366   clear_flag (source_a);
1367
1368   /* remove one of the fds from 'b' */
1369   g_source_remove_unix_fd (source_b, tag1);
1370   assert_main_context_state (3,
1371                              fds_a[0], G_IO_IN, 0,
1372                              fds_a[1], G_IO_OUT, 0,
1373                              fds_b[1], G_IO_IN, 0);
1374   assert_not_flagged (source_a);
1375   assert_not_flagged (source_b);
1376
1377   /* remove the other */
1378   g_source_remove_unix_fd (source_b, tag2);
1379   assert_main_context_state (2,
1380                              fds_a[0], G_IO_IN, 0,
1381                              fds_a[1], G_IO_OUT, 0);
1382   assert_not_flagged (source_a);
1383   assert_not_flagged (source_b);
1384
1385   /* destroy the sources */
1386   g_source_destroy (source_a);
1387   g_source_destroy (source_b);
1388   assert_main_context_state (0);
1389
1390   g_source_unref (source_a);
1391   g_source_unref (source_b);
1392   close (fds_a[0]);
1393   close (fds_a[1]);
1394   close (fds_b[0]);
1395   close (fds_b[1]);
1396 }
1397
1398 #endif
1399
1400 int
1401 main (int argc, char *argv[])
1402 {
1403   g_test_init (&argc, &argv, NULL);
1404   g_test_bug_base ("http://bugzilla.gnome.org/");
1405
1406   g_test_add_func ("/maincontext/basic", test_maincontext_basic);
1407   g_test_add_func ("/mainloop/basic", test_mainloop_basic);
1408   g_test_add_func ("/mainloop/timeouts", test_timeouts);
1409   g_test_add_func ("/mainloop/priorities", test_priorities);
1410   g_test_add_func ("/mainloop/invoke", test_invoke);
1411   g_test_add_func ("/mainloop/child_sources", test_child_sources);
1412   g_test_add_func ("/mainloop/recursive_child_sources", test_recursive_child_sources);
1413   g_test_add_func ("/mainloop/swapping_child_sources", test_swapping_child_sources);
1414   g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources);
1415   g_test_add_func ("/mainloop/source_time", test_source_time);
1416   g_test_add_func ("/mainloop/overflow", test_mainloop_overflow);
1417   g_test_add_func ("/mainloop/ready-time", test_ready_time);
1418   g_test_add_func ("/mainloop/wakeup", test_wakeup);
1419 #ifdef G_OS_UNIX
1420   g_test_add_func ("/mainloop/unix-fd", test_unix_fd);
1421   g_test_add_func ("/mainloop/unix-fd-source", test_unix_fd_source);
1422   g_test_add_func ("/mainloop/source-unix-fd-api", test_source_unix_fd_api);
1423 #endif
1424
1425   return g_test_run ();
1426 }