Update German translation
[glib.git] / glib / tests / mainloop.c
blobf5d672a6320ac03dbe36d440858c91c7ff7ad18c
1 /* Unit tests for GMainLoop
2 * Copyright (C) 2011 Red Hat, Inc
3 * Author: Matthias Clasen
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.
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.
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.
23 #include <glib.h>
24 #include "glib-private.h"
25 #include <stdio.h>
26 #include <string.h>
28 static gboolean cb (gpointer data)
30 return FALSE;
33 static gboolean prepare (GSource *source, gint *time)
35 return FALSE;
37 static gboolean check (GSource *source)
39 return FALSE;
41 static gboolean dispatch (GSource *source, GSourceFunc cb, gpointer date)
43 return FALSE;
46 GSourceFuncs funcs = {
47 prepare,
48 check,
49 dispatch,
50 NULL
53 static void
54 test_maincontext_basic (void)
56 GMainContext *ctx;
57 GSource *source;
58 guint id;
59 gpointer data = &funcs;
61 ctx = g_main_context_new ();
63 g_assert (!g_main_context_pending (ctx));
64 g_assert (!g_main_context_iteration (ctx, FALSE));
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));
70 g_assert (!g_source_get_can_recurse (source));
71 g_assert (g_source_get_name (source) == NULL);
73 g_source_set_can_recurse (source, TRUE);
74 g_source_set_name (source, "d");
76 g_assert (g_source_get_can_recurse (source));
77 g_assert_cmpstr (g_source_get_name (source), ==, "d");
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);
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);
86 g_source_set_priority (source, G_PRIORITY_HIGH);
87 g_assert_cmpint (g_source_get_priority (source), ==, G_PRIORITY_HIGH);
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);
93 g_main_context_unref (ctx);
95 if (g_test_undefined ())
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 ();
103 g_source_unref (source);
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));
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));
124 g_idle_add (cb, data);
125 g_assert (g_idle_remove_by_data (data));
128 static void
129 test_mainloop_basic (void)
131 GMainLoop *loop;
132 GMainContext *ctx;
134 loop = g_main_loop_new (NULL, FALSE);
136 g_assert (!g_main_loop_is_running (loop));
138 g_main_loop_ref (loop);
140 ctx = g_main_loop_get_context (loop);
141 g_assert (ctx == g_main_context_default ());
143 g_main_loop_unref (loop);
145 g_assert_cmpint (g_main_depth (), ==, 0);
147 g_main_loop_unref (loop);
150 static gint a;
151 static gint b;
152 static gint c;
154 static gboolean
155 count_calls (gpointer data)
157 gint *i = data;
159 (*i)++;
161 return TRUE;
164 static void
165 test_timeouts (void)
167 GMainContext *ctx;
168 GMainLoop *loop;
169 GSource *source;
171 a = b = c = 0;
173 ctx = g_main_context_new ();
174 loop = g_main_loop_new (ctx, FALSE);
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);
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);
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);
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);
196 g_main_loop_run (loop);
198 /* We may be delayed for an arbitrary amount of time - for example,
199 * it's possible for all timeouts to fire exactly once.
201 g_assert_cmpint (a, >, 0);
202 g_assert_cmpint (a, >=, b);
203 g_assert_cmpint (b, >=, c);
205 g_assert_cmpint (a, <=, 10);
206 g_assert_cmpint (b, <=, 4);
207 g_assert_cmpint (c, <=, 3);
209 g_main_loop_unref (loop);
210 g_main_context_unref (ctx);
213 static void
214 test_priorities (void)
216 GMainContext *ctx;
217 GSource *sourcea;
218 GSource *sourceb;
220 a = b = c = 0;
222 ctx = g_main_context_new ();
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);
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);
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);
241 g_assert (g_main_context_iteration (ctx, FALSE));
242 g_assert_cmpint (a, ==, 0);
243 g_assert_cmpint (b, ==, 2);
245 g_source_destroy (sourceb);
247 g_assert (g_main_context_iteration (ctx, FALSE));
248 g_assert_cmpint (a, ==, 1);
249 g_assert_cmpint (b, ==, 2);
251 g_assert (g_main_context_pending (ctx));
252 g_source_destroy (sourcea);
253 g_assert (!g_main_context_pending (ctx));
255 g_main_context_unref (ctx);
258 static gboolean
259 quit_loop (gpointer data)
261 GMainLoop *loop = data;
263 g_main_loop_quit (loop);
265 return G_SOURCE_REMOVE;
268 static gint count;
270 static gboolean
271 func (gpointer data)
273 if (data != NULL)
274 g_assert (data == g_thread_self ());
276 count++;
278 return FALSE;
281 static gboolean
282 call_func (gpointer data)
284 func (g_thread_self ());
286 return G_SOURCE_REMOVE;
289 static GMutex mutex;
290 static GCond cond;
291 static gboolean thread_ready;
293 static gpointer
294 thread_func (gpointer data)
296 GMainContext *ctx = data;
297 GMainLoop *loop;
298 GSource *source;
300 g_main_context_push_thread_default (ctx);
301 loop = g_main_loop_new (ctx, FALSE);
303 g_mutex_lock (&mutex);
304 thread_ready = TRUE;
305 g_cond_signal (&cond);
306 g_mutex_unlock (&mutex);
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);
313 g_main_loop_run (loop);
315 g_main_context_pop_thread_default (ctx);
316 g_main_loop_unref (loop);
318 return NULL;
321 static void
322 test_invoke (void)
324 GMainContext *ctx;
325 GThread *thread;
327 count = 0;
329 /* this one gets invoked directly */
330 g_main_context_invoke (NULL, func, g_thread_self ());
331 g_assert_cmpint (count, ==, 1);
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);
338 /* test thread-default forcing the invocation to go
339 * to another thread
341 ctx = g_main_context_new ();
342 thread = g_thread_new ("worker", thread_func, ctx);
344 g_mutex_lock (&mutex);
345 while (!thread_ready)
346 g_cond_wait (&cond, &mutex);
347 g_mutex_unlock (&mutex);
349 g_main_context_invoke (ctx, func, thread);
351 g_thread_join (thread);
352 g_assert_cmpint (count, ==, 3);
354 g_main_context_unref (ctx);
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.
363 static gint counter;
364 static gint64 last_counter_update;
366 typedef struct {
367 GSource source;
368 gint interval;
369 gint timeout;
370 } CounterSource;
372 static gboolean
373 counter_source_prepare (GSource *source,
374 gint *timeout)
376 CounterSource *csource = (CounterSource *)source;
377 gint64 now;
379 now = g_source_get_time (source);
380 if (now != last_counter_update)
382 last_counter_update = now;
383 counter++;
386 *timeout = 1;
387 return counter >= csource->timeout;
390 static gboolean
391 counter_source_dispatch (GSource *source,
392 GSourceFunc callback,
393 gpointer user_data)
395 CounterSource *csource = (CounterSource *) source;
396 gboolean again;
398 again = callback (user_data);
400 if (again)
401 csource->timeout = counter + csource->interval;
403 return again;
406 static GSourceFuncs counter_source_funcs = {
407 counter_source_prepare,
408 NULL,
409 counter_source_dispatch,
410 NULL,
413 static GSource *
414 counter_source_new (gint interval)
416 GSource *source = g_source_new (&counter_source_funcs, sizeof (CounterSource));
417 CounterSource *csource = (CounterSource *) source;
419 csource->interval = interval;
420 csource->timeout = counter + interval;
422 return source;
426 static gboolean
427 run_inner_loop (gpointer user_data)
429 GMainContext *ctx = user_data;
430 GMainLoop *inner;
431 GSource *timeout;
433 a++;
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);
441 g_main_loop_run (inner);
442 g_main_loop_unref (inner);
444 return G_SOURCE_CONTINUE;
447 static void
448 test_child_sources (void)
450 GMainContext *ctx;
451 GMainLoop *loop;
452 GSource *parent, *child_b, *child_c, *end;
454 ctx = g_main_context_new ();
455 loop = g_main_loop_new (ctx, FALSE);
457 a = b = c = 0;
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);
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);
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);
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);
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);
487 g_main_loop_run (loop);
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:
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
512 g_assert_cmpint (a, ==, 6);
513 g_assert_cmpint (b, ==, 3);
514 g_assert_cmpint (c, ==, 3);
516 g_source_destroy (parent);
517 g_source_unref (parent);
518 g_source_unref (child_b);
519 g_source_unref (child_c);
521 g_main_loop_unref (loop);
522 g_main_context_unref (ctx);
525 static void
526 test_recursive_child_sources (void)
528 GMainContext *ctx;
529 GMainLoop *loop;
530 GSource *parent, *child_b, *child_c, *end;
532 ctx = g_main_context_new ();
533 loop = g_main_loop_new (ctx, FALSE);
535 a = b = c = 0;
537 parent = counter_source_new (500);
538 g_source_set_callback (parent, count_calls, &a, NULL);
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);
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);
548 g_source_attach (parent, ctx);
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);
555 g_main_loop_run (loop);
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)
569 g_assert_cmpint (a, ==, 9);
570 g_assert_cmpint (b, ==, 9);
571 g_assert_cmpint (c, ==, 4);
573 g_source_destroy (parent);
574 g_source_unref (parent);
575 g_source_unref (child_b);
576 g_source_unref (child_c);
578 g_main_loop_unref (loop);
579 g_main_context_unref (ctx);
582 typedef struct {
583 GSource *parent, *old_child, *new_child;
584 GMainLoop *loop;
585 } SwappingTestData;
587 static gboolean
588 swap_sources (gpointer user_data)
590 SwappingTestData *data = user_data;
592 if (data->old_child)
594 g_source_remove_child_source (data->parent, data->old_child);
595 g_clear_pointer (&data->old_child, g_source_unref);
598 if (!data->new_child)
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);
605 return G_SOURCE_CONTINUE;
608 static gboolean
609 assert_not_reached_callback (gpointer user_data)
611 g_assert_not_reached ();
613 return G_SOURCE_REMOVE;
616 static void
617 test_swapping_child_sources (void)
619 GMainContext *ctx;
620 GMainLoop *loop;
621 SwappingTestData data;
623 ctx = g_main_context_new ();
624 loop = g_main_loop_new (ctx, FALSE);
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);
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);
635 data.new_child = NULL;
636 g_main_loop_run (loop);
638 g_source_destroy (data.parent);
639 g_source_unref (data.parent);
640 g_source_unref (data.new_child);
642 g_main_loop_unref (loop);
643 g_main_context_unref (ctx);
646 static gboolean
647 add_source_callback (gpointer user_data)
649 GMainLoop *loop = user_data;
650 GSource *self = g_main_current_source (), *child;
651 GIOChannel *io;
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.
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);
663 g_main_loop_quit (loop);
664 return FALSE;
667 static void
668 test_blocked_child_sources (void)
670 GMainContext *ctx;
671 GMainLoop *loop;
672 GSource *source;
674 g_test_bug ("701283");
676 ctx = g_main_context_new ();
677 loop = g_main_loop_new (ctx, FALSE);
679 source = g_idle_source_new ();
680 g_source_set_callback (source, add_source_callback, loop, NULL);
681 g_source_attach (source, ctx);
683 g_main_loop_run (loop);
685 g_source_destroy (source);
686 g_source_unref (source);
688 g_main_loop_unref (loop);
689 g_main_context_unref (ctx);
692 typedef struct {
693 GMainContext *ctx;
694 GMainLoop *loop;
696 GSource *timeout1, *timeout2;
697 gint64 time1;
698 GTimeVal tv;
699 } TimeTestData;
701 static gboolean
702 timeout1_callback (gpointer user_data)
704 TimeTestData *data = user_data;
705 GSource *source;
706 gint64 mtime1, mtime2, time2;
708 source = g_main_current_source ();
709 g_assert (source == data->timeout1);
711 if (data->time1 == -1)
713 /* First iteration */
714 g_assert (!g_source_is_destroyed (data->timeout2));
716 mtime1 = g_get_monotonic_time ();
717 data->time1 = g_source_get_time (source);
719 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
720 g_source_get_current_time (source, &data->tv);
721 G_GNUC_END_IGNORE_DEPRECATIONS
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);
728 g_assert_cmpint (mtime1, <, mtime2);
729 g_assert_cmpint (data->time1, ==, time2);
731 else
733 GTimeVal tv;
735 /* Second iteration */
736 g_assert (g_source_is_destroyed (data->timeout2));
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.
742 time2 = g_source_get_time (source);
743 g_assert_cmpint (data->time1, <, time2);
745 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
746 g_source_get_current_time (source, &tv);
747 G_GNUC_END_IGNORE_DEPRECATIONS
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));
753 g_main_loop_quit (data->loop);
756 return TRUE;
759 static gboolean
760 timeout2_callback (gpointer user_data)
762 TimeTestData *data = user_data;
763 GSource *source;
764 gint64 time2, time3;
766 source = g_main_current_source ();
767 g_assert (source == data->timeout2);
769 g_assert (!g_source_is_destroyed (data->timeout1));
771 /* g_source_get_time() does not change between different sources in
772 * a single iteration of the mainloop.
774 time2 = g_source_get_time (source);
775 g_assert_cmpint (data->time1, ==, time2);
777 /* The source should still have a valid time even after being
778 * destroyed, since it's currently running.
780 g_source_destroy (source);
781 time3 = g_source_get_time (source);
782 g_assert_cmpint (time2, ==, time3);
784 return FALSE;
787 static void
788 test_source_time (void)
790 TimeTestData data;
792 data.ctx = g_main_context_new ();
793 data.loop = g_main_loop_new (data.ctx, FALSE);
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);
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);
803 data.time1 = -1;
805 g_main_loop_run (data.loop);
807 g_assert (!g_source_is_destroyed (data.timeout1));
808 g_assert (g_source_is_destroyed (data.timeout2));
810 g_source_destroy (data.timeout1);
811 g_source_unref (data.timeout1);
812 g_source_unref (data.timeout2);
814 g_main_loop_unref (data.loop);
815 g_main_context_unref (data.ctx);
818 typedef struct {
819 guint outstanding_ops;
820 GMainLoop *loop;
821 } TestOverflowData;
823 static gboolean
824 on_source_fired_cb (gpointer user_data)
826 TestOverflowData *data = user_data;
827 GSource *current_source;
828 GMainContext *current_context;
829 guint source_id;
831 data->outstanding_ops--;
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);
840 if (data->outstanding_ops == 0)
841 g_main_loop_quit (data->loop);
842 return FALSE;
845 static GSource *
846 add_idle_source (GMainContext *ctx,
847 TestOverflowData *data)
849 GSource *source;
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++;
857 return source;
860 static void
861 test_mainloop_overflow (void)
863 GMainContext *ctx;
864 GMainLoop *loop;
865 GSource *source;
866 TestOverflowData data;
867 guint i;
869 g_test_bug ("687098");
871 memset (&data, 0, sizeof (data));
873 ctx = GLIB_PRIVATE_CALL (g_main_context_new_with_next_id) (G_MAXUINT-1);
875 loop = g_main_loop_new (ctx, TRUE);
876 data.outstanding_ops = 0;
877 data.loop = loop;
879 source = add_idle_source (ctx, &data);
880 g_assert_cmpint (source->source_id, ==, G_MAXUINT-1);
882 source = add_idle_source (ctx, &data);
883 g_assert_cmpint (source->source_id, ==, G_MAXUINT);
885 source = add_idle_source (ctx, &data);
886 g_assert_cmpint (source->source_id, !=, 0);
888 /* Now, a lot more sources */
889 for (i = 0; i < 50; i++)
891 source = add_idle_source (ctx, &data);
892 g_assert_cmpint (source->source_id, !=, 0);
895 g_main_loop_run (loop);
896 g_assert_cmpint (data.outstanding_ops, ==, 0);
898 g_main_loop_unref (loop);
899 g_main_context_unref (ctx);
902 static volatile gint ready_time_dispatched;
904 static gboolean
905 ready_time_dispatch (GSource *source,
906 GSourceFunc callback,
907 gpointer user_data)
909 g_atomic_int_set (&ready_time_dispatched, TRUE);
911 g_source_set_ready_time (source, -1);
913 return TRUE;
916 static gpointer
917 run_context (gpointer user_data)
919 g_main_loop_run (user_data);
921 return NULL;
924 static void
925 test_ready_time (void)
927 GThread *thread;
928 GSource *source;
929 GSourceFuncs source_funcs = {
930 NULL, NULL, ready_time_dispatch
932 GMainLoop *loop;
934 source = g_source_new (&source_funcs, sizeof (GSource));
935 g_source_attach (source, NULL);
936 g_source_unref (source);
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.
942 * We can test that the basics are working, though.
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);
950 /* The ready time should not have been changed */
951 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
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);
957 /* A source with a ready time set to tomorrow should not fire on any
958 * builder, no matter how badly loaded...
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);
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);
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);
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);
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);
995 /* Now do some tests of cross-thread wakeups.
997 * Make sure it wakes up right away from the start.
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));
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));
1010 /* kill the thread */
1011 g_main_loop_quit (loop);
1012 g_thread_join (thread);
1013 g_main_loop_unref (loop);
1015 g_source_destroy (source);
1018 static void
1019 test_wakeup(void)
1021 GMainContext *ctx;
1022 int i;
1024 ctx = g_main_context_new ();
1026 /* run a random large enough number of times because
1027 * main contexts tend to wake up a few times after creation.
1029 for (i = 0; i < 100; i++)
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().
1039 g_main_context_wakeup (ctx);
1040 g_main_context_iteration (ctx, TRUE);
1043 g_main_context_unref (ctx);
1046 static void
1047 test_remove_invalid (void)
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 ();
1054 static gboolean
1055 trivial_prepare (GSource *source,
1056 gint *timeout)
1058 *timeout = 0;
1059 return TRUE;
1062 static gint n_finalized;
1064 static void
1065 trivial_finalize (GSource *source)
1067 n_finalized++;
1070 static void
1071 test_unref_while_pending (void)
1073 static GSourceFuncs funcs = { trivial_prepare, NULL, NULL, trivial_finalize };
1074 GMainContext *context;
1075 GSource *source;
1077 context = g_main_context_new ();
1079 source = g_source_new (&funcs, sizeof (GSource));
1080 g_source_attach (source, context);
1081 g_source_unref (source);
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);
1088 /* Destroy the context */
1089 g_main_context_unref (context);
1091 /* Make sure we didn't leak the source */
1092 g_assert_cmpint (n_finalized, ==, 1);
1095 #ifdef G_OS_UNIX
1097 #include <glib-unix.h>
1098 #include <unistd.h>
1100 static gchar zeros[1024];
1102 static gsize
1103 fill_a_pipe (gint fd)
1105 gsize written = 0;
1106 GPollFD pfd;
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);
1114 return written;
1117 static gboolean
1118 write_bytes (gint fd,
1119 GIOCondition condition,
1120 gpointer user_data)
1122 gssize *to_write = user_data;
1123 gint limit;
1125 if (*to_write == 0)
1126 return FALSE;
1128 /* Detect if we run before we should */
1129 g_assert (*to_write >= 0);
1131 limit = MIN (*to_write, sizeof zeros);
1132 *to_write -= write (fd, zeros, limit);
1134 return TRUE;
1137 static gboolean
1138 read_bytes (gint fd,
1139 GIOCondition condition,
1140 gpointer user_data)
1142 static gchar buffer[1024];
1143 gssize *to_read = user_data;
1145 *to_read -= read (fd, buffer, sizeof buffer);
1147 /* The loop will exit when there is nothing else to read, then we will
1148 * use g_source_remove() to destroy this source.
1150 return TRUE;
1153 static void
1154 test_unix_fd (void)
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;
1164 s = pipe (fds);
1165 g_assert (s == 0);
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));
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));
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.
1183 while (TRUE)
1185 gssize to_write_was = to_write;
1186 gssize to_read_was = to_read;
1188 if (!g_main_context_iteration (NULL, FALSE))
1189 break;
1191 /* Since the sources are at different priority, only one of them
1192 * should possibly have run.
1194 g_assert (to_write == to_write_was || to_read == to_read_was);
1197 g_assert (to_write == 0);
1198 g_assert (to_read == 0);
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]);
1210 static void
1211 assert_main_context_state (gint n_to_poll,
1212 ...)
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;
1225 context = g_main_context_default ();
1227 acquired = g_main_context_acquire (context);
1228 g_assert (acquired);
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 */
1235 va_start (ap, n_to_poll);
1236 for (i = 0; i < n_to_poll; i++)
1238 gint expected_fd = va_arg (ap, gint);
1239 GIOCondition expected_events = va_arg (ap, GIOCondition);
1240 GIOCondition report_events = va_arg (ap, GIOCondition);
1242 for (j = 0; j < n; j++)
1243 if (!consumed[j] && poll_fds[j].fd == expected_fd && poll_fds[j].events == expected_events)
1245 poll_fds[j].revents = report_events;
1246 consumed[j] = TRUE;
1247 break;
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);
1253 va_end (ap);
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;
1260 if (g_main_context_check (context, max_priority, poll_fds, n))
1261 g_main_context_dispatch (context);
1263 g_main_context_release (context);
1266 static gboolean
1267 flag_bool (gint fd,
1268 GIOCondition condition,
1269 gpointer user_data)
1271 gboolean *flag = user_data;
1273 *flag = TRUE;
1275 return TRUE;
1278 static void
1279 test_unix_fd_source (void)
1281 GSource *out_source;
1282 GSource *in_source;
1283 GSource *source;
1284 gboolean out, in;
1285 gint fds[2];
1286 gint s;
1288 assert_main_context_state (0);
1290 s = pipe (fds);
1291 g_assert (s == 0);
1293 source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1294 g_source_attach (source, NULL);
1296 /* Check that a source with no callback gets successfully detached
1297 * with a warning printed.
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);
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);
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);
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);
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);
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]);
1347 typedef struct
1349 GSource parent;
1350 gboolean flagged;
1351 } FlagSource;
1353 static gboolean
1354 return_true (GSource *source, GSourceFunc callback, gpointer user_data)
1356 FlagSource *flag_source = (FlagSource *) source;
1358 flag_source->flagged = TRUE;
1360 return TRUE;
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
1367 static void
1368 test_source_unix_fd_api (void)
1370 GSourceFuncs no_funcs = {
1371 NULL, NULL, return_true
1373 GSource *source_a;
1374 GSource *source_b;
1375 gpointer tag1, tag2;
1376 gint fds_a[2];
1377 gint fds_b[2];
1379 pipe (fds_a);
1380 pipe (fds_b);
1382 source_a = g_source_new (&no_funcs, sizeof (FlagSource));
1383 source_b = g_source_new (&no_funcs, sizeof (FlagSource));
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);
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);
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);
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);
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);
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);
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);
1459 /* destroy the sources */
1460 g_source_destroy (source_a);
1461 g_source_destroy (source_b);
1462 assert_main_context_state (0);
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]);
1472 static gboolean
1473 unixfd_quit_loop (gint fd,
1474 GIOCondition condition,
1475 gpointer user_data)
1477 GMainLoop *loop = user_data;
1479 g_main_loop_quit (loop);
1481 return FALSE;
1484 static void
1485 test_unix_file_poll (void)
1487 gint fd;
1488 GSource *source;
1489 GMainLoop *loop;
1491 fd = open ("/dev/null", O_RDONLY);
1492 g_assert (fd >= 0);
1494 loop = g_main_loop_new (NULL, FALSE);
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);
1500 /* Should not block */
1501 g_main_loop_run (loop);
1503 g_source_destroy (source);
1505 assert_main_context_state (0);
1507 g_source_unref (source);
1509 g_main_loop_unref (loop);
1511 close (fd);
1514 #endif
1516 static gboolean
1517 timeout_cb (gpointer data)
1519 GMainLoop *loop = data;
1520 GMainContext *context;
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));
1526 g_main_loop_quit (loop);
1528 return G_SOURCE_REMOVE;
1531 static gpointer
1532 threadf (gpointer data)
1534 GMainContext *context = data;
1535 GMainLoop *loop;
1536 GSource *source;
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);
1544 g_main_loop_run (loop);
1546 g_main_loop_unref (loop);
1548 return NULL;
1551 static void
1552 test_mainloop_wait (void)
1554 GMainContext *context;
1555 GThread *t1, *t2;
1557 context = g_main_context_new ();
1559 t1 = g_thread_new ("t1", threadf, context);
1560 t2 = g_thread_new ("t2", threadf, context);
1562 g_thread_join (t1);
1563 g_thread_join (t2);
1565 g_main_context_unref (context);
1568 static gboolean
1569 nfds_in_cb (GIOChannel *io,
1570 GIOCondition condition,
1571 gpointer user_data)
1573 gboolean *in_cb_ran = user_data;
1575 *in_cb_ran = TRUE;
1576 g_assert_cmpint (condition, ==, G_IO_IN);
1577 return FALSE;
1580 static gboolean
1581 nfds_out_cb (GIOChannel *io,
1582 GIOCondition condition,
1583 gpointer user_data)
1585 gboolean *out_cb_ran = user_data;
1587 *out_cb_ran = TRUE;
1588 g_assert_cmpint (condition, ==, G_IO_OUT);
1589 return FALSE;
1592 static gboolean
1593 nfds_out_low_cb (GIOChannel *io,
1594 GIOCondition condition,
1595 gpointer user_data)
1597 g_assert_not_reached ();
1598 return FALSE;
1601 static void
1602 test_nfds (void)
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;
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.
1619 g_assert_cmpint (nfds, ==, 1);
1621 fd = g_file_open_tmp (NULL, &tmpfile, &error);
1622 g_assert_no_error (error);
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
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);
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 ();
1648 /* Add a second pollfd with the same fd but different event, and
1649 * lower priority.
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);
1657 /* g_main_context_query() should still return only 2 pollfds,
1658 * one of which has our fd, and a combined events field.
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 ();
1670 /* But if we query with a max priority, we won't see the
1671 * lower-priority one.
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 ();
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);
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 ();
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...)
1706 g_main_context_iteration (ctx, FALSE);
1708 g_assert (source1_ran);
1709 #ifndef G_OS_WIN32
1710 g_assert (source3_ran);
1711 #endif
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);
1720 g_io_channel_unref (io);
1721 remove (tmpfile);
1722 g_free (tmpfile);
1724 g_main_context_unref (ctx);
1728 main (int argc, char *argv[])
1730 g_test_init (&argc, &argv, NULL);
1731 g_test_bug_base ("http://bugzilla.gnome.org/");
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);
1757 return g_test_run ();