gmain: test g_source_remove() with invalid ID
[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 static void
1030 test_remove_invalid (void)
1031 {
1032   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "Source ID 3000000000 was not found*");
1033   g_source_remove (3000000000u);
1034   g_test_assert_expected_messages ();
1035 }
1036
1037 #ifdef G_OS_UNIX
1038
1039 #include <glib-unix.h>
1040 #include <unistd.h>
1041
1042 static gchar zeros[1024];
1043
1044 static gsize
1045 fill_a_pipe (gint fd)
1046 {
1047   gsize written = 0;
1048   GPollFD pfd;
1049
1050   pfd.fd = fd;
1051   pfd.events = G_IO_OUT;
1052   while (g_poll (&pfd, 1, 0) == 1)
1053     /* we should never see -1 here */
1054     written += write (fd, zeros, sizeof zeros);
1055
1056   return written;
1057 }
1058
1059 static gboolean
1060 write_bytes (gint         fd,
1061              GIOCondition condition,
1062              gpointer     user_data)
1063 {
1064   gssize *to_write = user_data;
1065   gint limit;
1066
1067   if (*to_write == 0)
1068     return FALSE;
1069
1070   /* Detect if we run before we should */
1071   g_assert (*to_write >= 0);
1072
1073   limit = MIN (*to_write, sizeof zeros);
1074   *to_write -= write (fd, zeros, limit);
1075
1076   return TRUE;
1077 }
1078
1079 static gboolean
1080 read_bytes (gint         fd,
1081             GIOCondition condition,
1082             gpointer     user_data)
1083 {
1084   static gchar buffer[1024];
1085   gssize *to_read = user_data;
1086
1087   *to_read -= read (fd, buffer, sizeof buffer);
1088
1089   /* The loop will exit when there is nothing else to read, then we will
1090    * use g_source_remove() to destroy this source.
1091    */
1092   return TRUE;
1093 }
1094
1095 static void
1096 test_unix_fd (void)
1097 {
1098   gssize to_write = -1;
1099   gssize to_read;
1100   gint fds[2];
1101   gint a, b;
1102   gint s;
1103   GSource *source_a;
1104   GSource *source_b;
1105
1106   s = pipe (fds);
1107   g_assert (s == 0);
1108
1109   to_read = fill_a_pipe (fds[1]);
1110   /* write at higher priority to keep the pipe full... */
1111   a = g_unix_fd_add_full (G_PRIORITY_HIGH, fds[1], G_IO_OUT, write_bytes, &to_write, NULL);
1112   source_a = g_source_ref (g_main_context_find_source_by_id (NULL, a));
1113   /* make sure no 'writes' get dispatched yet */
1114   while (g_main_context_iteration (NULL, FALSE));
1115
1116   to_read += 128 * 1024 * 1024;
1117   to_write = 128 * 1024 * 1024;
1118   b = g_unix_fd_add (fds[0], G_IO_IN, read_bytes, &to_read);
1119   source_b = g_source_ref (g_main_context_find_source_by_id (NULL, b));
1120
1121   /* Assuming the kernel isn't internally 'laggy' then there will always
1122    * be either data to read or room in which to write.  That will keep
1123    * the loop running until all data has been read and written.
1124    */
1125   while (TRUE)
1126     {
1127       gssize to_write_was = to_write;
1128       gssize to_read_was = to_read;
1129
1130       if (!g_main_context_iteration (NULL, FALSE))
1131         break;
1132
1133       /* Since the sources are at different priority, only one of them
1134        * should possibly have run.
1135        */
1136       g_assert (to_write == to_write_was || to_read == to_read_was);
1137     }
1138
1139   g_assert (to_write == 0);
1140   g_assert (to_read == 0);
1141
1142   /* 'a' is already removed by itself */
1143   g_assert (g_source_is_destroyed (source_a));
1144   g_source_unref (source_a);
1145   g_source_remove (b);
1146   g_assert (g_source_is_destroyed (source_b));
1147   g_source_unref (source_b);
1148   close (fds[1]);
1149   close (fds[0]);
1150 }
1151
1152 static void
1153 assert_main_context_state (gint n_to_poll,
1154                            ...)
1155 {
1156   GMainContext *context;
1157   gboolean consumed[10] = { };
1158   GPollFD poll_fds[10];
1159   gboolean immediate;
1160   gint max_priority;
1161   gint timeout;
1162   gint n;
1163   gint i, j;
1164   va_list ap;
1165
1166   context = g_main_context_default ();
1167
1168   immediate = g_main_context_prepare (context, &max_priority);
1169   g_assert (!immediate);
1170   n = g_main_context_query (context, max_priority, &timeout, poll_fds, 10);
1171   g_assert_cmpint (n, ==, n_to_poll + 1); /* one will be the gwakeup */
1172
1173   va_start (ap, n_to_poll);
1174   for (i = 0; i < n_to_poll; i++)
1175     {
1176       gint expected_fd = va_arg (ap, gint);
1177       GIOCondition expected_events = va_arg (ap, GIOCondition);
1178       GIOCondition report_events = va_arg (ap, GIOCondition);
1179
1180       for (j = 0; j < n; j++)
1181         if (!consumed[j] && poll_fds[j].fd == expected_fd && poll_fds[j].events == expected_events)
1182           {
1183             poll_fds[j].revents = report_events;
1184             consumed[j] = TRUE;
1185             break;
1186           }
1187
1188       if (j == n)
1189         g_error ("Unable to find fd %d (index %d) with events 0x%x\n", expected_fd, i, (guint) expected_events);
1190     }
1191   va_end (ap);
1192
1193   /* find the gwakeup, flag as non-ready */
1194   for (i = 0; i < n; i++)
1195     if (!consumed[i])
1196       poll_fds[i].revents = 0;
1197
1198   if (g_main_context_check (context, max_priority, poll_fds, n))
1199     g_main_context_dispatch (context);
1200 }
1201
1202 static gboolean
1203 flag_bool (gint         fd,
1204            GIOCondition condition,
1205            gpointer     user_data)
1206 {
1207   gboolean *flag = user_data;
1208
1209   *flag = TRUE;
1210
1211   return TRUE;
1212 }
1213
1214 static void
1215 test_unix_fd_source (void)
1216 {
1217   GSource *out_source;
1218   GSource *in_source;
1219   GSource *source;
1220   gboolean out, in;
1221   gint fds[2];
1222   gint s;
1223
1224   assert_main_context_state (0);
1225
1226   s = pipe (fds);
1227   g_assert (s == 0);
1228
1229   source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1230   g_source_attach (source, NULL);
1231
1232   /* Check that a source with no callback gets successfully detached
1233    * with a warning printed.
1234    */
1235   g_test_expect_message ("GLib", G_LOG_LEVEL_WARNING, "*GUnixFDSource dispatched without callback*");
1236   while (g_main_context_iteration (NULL, FALSE));
1237   g_test_assert_expected_messages ();
1238   g_assert (g_source_is_destroyed (source));
1239   g_source_unref (source);
1240
1241   out = in = FALSE;
1242   out_source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1243   g_source_set_callback (out_source, (GSourceFunc) flag_bool, &out, NULL);
1244   g_source_attach (out_source, NULL);
1245   assert_main_context_state (1,
1246                              fds[1], G_IO_OUT, 0);
1247   g_assert (!in && !out);
1248
1249   in_source = g_unix_fd_source_new (fds[0], G_IO_IN);
1250   g_source_set_callback (in_source, (GSourceFunc) flag_bool, &in, NULL);
1251   g_source_set_priority (in_source, G_PRIORITY_DEFAULT_IDLE);
1252   g_source_attach (in_source, NULL);
1253   assert_main_context_state (2,
1254                              fds[0], G_IO_IN, G_IO_IN,
1255                              fds[1], G_IO_OUT, G_IO_OUT);
1256   /* out is higher priority so only it should fire */
1257   g_assert (!in && out);
1258
1259   /* raise the priority of the in source to higher than out*/
1260   in = out = FALSE;
1261   g_source_set_priority (in_source, G_PRIORITY_HIGH);
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   /* now, let them be equal */
1268   in = out = FALSE;
1269   g_source_set_priority (in_source, G_PRIORITY_DEFAULT);
1270   assert_main_context_state (2,
1271                              fds[0], G_IO_IN, G_IO_IN,
1272                              fds[1], G_IO_OUT, G_IO_OUT);
1273   g_assert (in && out);
1274
1275   g_source_destroy (out_source);
1276   g_source_destroy (in_source);
1277   close (fds[1]);
1278   close (fds[0]);
1279 }
1280
1281 typedef struct
1282 {
1283   GSource parent;
1284   gboolean flagged;
1285 } FlagSource;
1286
1287 static gboolean
1288 return_true (GSource *source, GSourceFunc callback, gpointer user_data)
1289 {
1290   FlagSource *flag_source = (FlagSource *) source;
1291
1292   flag_source->flagged = TRUE;
1293
1294   return TRUE;
1295 }
1296
1297 #define assert_flagged(s) g_assert (((FlagSource *) (s))->flagged);
1298 #define assert_not_flagged(s) g_assert (!((FlagSource *) (s))->flagged);
1299 #define clear_flag(s) ((FlagSource *) (s))->flagged = 0
1300
1301 static void
1302 test_source_unix_fd_api (void)
1303 {
1304   GSourceFuncs no_funcs = {
1305     NULL, NULL, return_true
1306   };
1307   GSource *source_a;
1308   GSource *source_b;
1309   gpointer tag1, tag2;
1310   gint fds_a[2];
1311   gint fds_b[2];
1312
1313   pipe (fds_a);
1314   pipe (fds_b);
1315
1316   source_a = g_source_new (&no_funcs, sizeof (FlagSource));
1317   source_b = g_source_new (&no_funcs, sizeof (FlagSource));
1318
1319   /* attach a source with more than one fd */
1320   g_source_add_unix_fd (source_a, fds_a[0], G_IO_IN);
1321   g_source_add_unix_fd (source_a, fds_a[1], G_IO_OUT);
1322   g_source_attach (source_a, NULL);
1323   assert_main_context_state (2,
1324                              fds_a[0], G_IO_IN, 0,
1325                              fds_a[1], G_IO_OUT, 0);
1326   assert_not_flagged (source_a);
1327
1328   /* attach a higher priority source with no fds */
1329   g_source_set_priority (source_b, G_PRIORITY_HIGH);
1330   g_source_attach (source_b, NULL);
1331   assert_main_context_state (2,
1332                              fds_a[0], G_IO_IN, G_IO_IN,
1333                              fds_a[1], G_IO_OUT, 0);
1334   assert_flagged (source_a);
1335   assert_not_flagged (source_b);
1336   clear_flag (source_a);
1337
1338   /* add some fds to the second source, while attached */
1339   tag1 = g_source_add_unix_fd (source_b, fds_b[0], G_IO_IN);
1340   tag2 = g_source_add_unix_fd (source_b, fds_b[1], G_IO_OUT);
1341   assert_main_context_state (4,
1342                              fds_a[0], G_IO_IN, 0,
1343                              fds_a[1], G_IO_OUT, G_IO_OUT,
1344                              fds_b[0], G_IO_IN, 0,
1345                              fds_b[1], G_IO_OUT, G_IO_OUT);
1346   /* only 'b' (higher priority) should have dispatched */
1347   assert_not_flagged (source_a);
1348   assert_flagged (source_b);
1349   clear_flag (source_b);
1350
1351   /* change our events on b to the same as they were before */
1352   g_source_modify_unix_fd (source_b, tag1, G_IO_IN);
1353   g_source_modify_unix_fd (source_b, tag2, G_IO_OUT);
1354   assert_main_context_state (4,
1355                              fds_a[0], G_IO_IN, 0,
1356                              fds_a[1], G_IO_OUT, G_IO_OUT,
1357                              fds_b[0], G_IO_IN, 0,
1358                              fds_b[1], G_IO_OUT, G_IO_OUT);
1359   assert_not_flagged (source_a);
1360   assert_flagged (source_b);
1361   clear_flag (source_b);
1362
1363   /* now reverse them */
1364   g_source_modify_unix_fd (source_b, tag1, G_IO_OUT);
1365   g_source_modify_unix_fd (source_b, tag2, G_IO_IN);
1366   assert_main_context_state (4,
1367                              fds_a[0], G_IO_IN, 0,
1368                              fds_a[1], G_IO_OUT, G_IO_OUT,
1369                              fds_b[0], G_IO_OUT, 0,
1370                              fds_b[1], G_IO_IN, 0);
1371   /* 'b' had no events, so 'a' can go this time */
1372   assert_flagged (source_a);
1373   assert_not_flagged (source_b);
1374   clear_flag (source_a);
1375
1376   /* remove one of the fds from 'b' */
1377   g_source_remove_unix_fd (source_b, tag1);
1378   assert_main_context_state (3,
1379                              fds_a[0], G_IO_IN, 0,
1380                              fds_a[1], G_IO_OUT, 0,
1381                              fds_b[1], G_IO_IN, 0);
1382   assert_not_flagged (source_a);
1383   assert_not_flagged (source_b);
1384
1385   /* remove the other */
1386   g_source_remove_unix_fd (source_b, tag2);
1387   assert_main_context_state (2,
1388                              fds_a[0], G_IO_IN, 0,
1389                              fds_a[1], G_IO_OUT, 0);
1390   assert_not_flagged (source_a);
1391   assert_not_flagged (source_b);
1392
1393   /* destroy the sources */
1394   g_source_destroy (source_a);
1395   g_source_destroy (source_b);
1396   assert_main_context_state (0);
1397
1398   g_source_unref (source_a);
1399   g_source_unref (source_b);
1400   close (fds_a[0]);
1401   close (fds_a[1]);
1402   close (fds_b[0]);
1403   close (fds_b[1]);
1404 }
1405
1406 #endif
1407
1408 int
1409 main (int argc, char *argv[])
1410 {
1411   g_test_init (&argc, &argv, NULL);
1412   g_test_bug_base ("http://bugzilla.gnome.org/");
1413
1414   g_test_add_func ("/maincontext/basic", test_maincontext_basic);
1415   g_test_add_func ("/mainloop/basic", test_mainloop_basic);
1416   g_test_add_func ("/mainloop/timeouts", test_timeouts);
1417   g_test_add_func ("/mainloop/priorities", test_priorities);
1418   g_test_add_func ("/mainloop/invoke", test_invoke);
1419   g_test_add_func ("/mainloop/child_sources", test_child_sources);
1420   g_test_add_func ("/mainloop/recursive_child_sources", test_recursive_child_sources);
1421   g_test_add_func ("/mainloop/swapping_child_sources", test_swapping_child_sources);
1422   g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources);
1423   g_test_add_func ("/mainloop/source_time", test_source_time);
1424   g_test_add_func ("/mainloop/overflow", test_mainloop_overflow);
1425   g_test_add_func ("/mainloop/ready-time", test_ready_time);
1426   g_test_add_func ("/mainloop/wakeup", test_wakeup);
1427   g_test_add_func ("/mainloop/remove-invalid", test_remove_invalid);
1428 #ifdef G_OS_UNIX
1429   g_test_add_func ("/mainloop/unix-fd", test_unix_fd);
1430   g_test_add_func ("/mainloop/unix-fd-source", test_unix_fd_source);
1431   g_test_add_func ("/mainloop/source-unix-fd-api", test_source_unix_fd_api);
1432 #endif
1433
1434   return g_test_run ();
1435 }