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