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