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