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.
24 #include "glib-private.h"
27 static gboolean cb (gpointer data)
32 static gboolean prepare (GSource *source, gint *time)
36 static gboolean check (GSource *source)
40 static gboolean dispatch (GSource *source, GSourceFunc cb, gpointer date)
45 GSourceFuncs funcs = {
53 test_maincontext_basic (void)
58 gpointer data = &funcs;
60 ctx = g_main_context_new ();
62 g_assert (!g_main_context_pending (ctx));
63 g_assert (!g_main_context_iteration (ctx, FALSE));
65 source = g_source_new (&funcs, sizeof (GSource));
66 g_assert_cmpint (g_source_get_priority (source), ==, G_PRIORITY_DEFAULT);
67 g_assert (!g_source_is_destroyed (source));
69 g_assert (!g_source_get_can_recurse (source));
70 g_assert (g_source_get_name (source) == NULL);
72 g_source_set_can_recurse (source, TRUE);
73 g_source_set_name (source, "d");
75 g_assert (g_source_get_can_recurse (source));
76 g_assert_cmpstr (g_source_get_name (source), ==, "d");
78 g_assert (g_main_context_find_source_by_user_data (ctx, NULL) == NULL);
79 g_assert (g_main_context_find_source_by_funcs_user_data (ctx, &funcs, NULL) == NULL);
81 id = g_source_attach (source, ctx);
82 g_assert_cmpint (g_source_get_id (source), ==, id);
83 g_assert (g_main_context_find_source_by_id (ctx, id) == source);
85 g_source_set_priority (source, G_PRIORITY_HIGH);
86 g_assert_cmpint (g_source_get_priority (source), ==, G_PRIORITY_HIGH);
88 g_source_destroy (source);
89 g_assert (g_source_get_context (source) == ctx);
90 g_assert (g_main_context_find_source_by_id (ctx, id) == NULL);
92 g_main_context_unref (ctx);
94 if (g_test_undefined ())
96 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
97 "*assertion*source->context != NULL*failed*");
98 g_assert (g_source_get_context (source) == NULL);
99 g_test_assert_expected_messages ();
102 g_source_unref (source);
104 ctx = g_main_context_default ();
105 source = g_source_new (&funcs, sizeof (GSource));
106 g_source_set_funcs (source, &funcs);
107 g_source_set_callback (source, cb, data, NULL);
108 id = g_source_attach (source, ctx);
109 g_source_unref (source);
110 g_source_set_name_by_id (id, "e");
111 g_assert_cmpstr (g_source_get_name (source), ==, "e");
112 g_assert (g_source_get_context (source) == ctx);
113 g_assert (g_source_remove_by_funcs_user_data (&funcs, data));
115 source = g_source_new (&funcs, sizeof (GSource));
116 g_source_set_funcs (source, &funcs);
117 g_source_set_callback (source, cb, data, NULL);
118 id = g_source_attach (source, ctx);
119 g_source_unref (source);
120 g_assert (g_source_remove_by_user_data (data));
121 g_assert (!g_source_remove_by_user_data ((gpointer)0x1234));
123 g_idle_add (cb, data);
124 g_assert (g_idle_remove_by_data (data));
128 test_mainloop_basic (void)
133 loop = g_main_loop_new (NULL, FALSE);
135 g_assert (!g_main_loop_is_running (loop));
137 g_main_loop_ref (loop);
139 ctx = g_main_loop_get_context (loop);
140 g_assert (ctx == g_main_context_default ());
142 g_main_loop_unref (loop);
144 g_assert_cmpint (g_main_depth (), ==, 0);
146 g_main_loop_unref (loop);
154 count_calls (gpointer data)
172 ctx = g_main_context_new ();
173 loop = g_main_loop_new (ctx, FALSE);
175 source = g_timeout_source_new (100);
176 g_source_set_callback (source, count_calls, &a, NULL);
177 g_source_attach (source, ctx);
178 g_source_unref (source);
180 source = g_timeout_source_new (250);
181 g_source_set_callback (source, count_calls, &b, NULL);
182 g_source_attach (source, ctx);
183 g_source_unref (source);
185 source = g_timeout_source_new (330);
186 g_source_set_callback (source, count_calls, &c, NULL);
187 g_source_attach (source, ctx);
188 g_source_unref (source);
190 source = g_timeout_source_new (1050);
191 g_source_set_callback (source, (GSourceFunc)g_main_loop_quit, loop, NULL);
192 g_source_attach (source, ctx);
193 g_source_unref (source);
195 g_main_loop_run (loop);
197 /* We may be delayed for an arbitrary amount of time - for example,
198 * it's possible for all timeouts to fire exactly once.
200 g_assert_cmpint (a, >, 0);
201 g_assert_cmpint (a, >=, b);
202 g_assert_cmpint (b, >=, c);
204 g_assert_cmpint (a, <=, 10);
205 g_assert_cmpint (b, <=, 4);
206 g_assert_cmpint (c, <=, 3);
208 g_main_loop_unref (loop);
209 g_main_context_unref (ctx);
213 test_priorities (void)
221 ctx = g_main_context_new ();
223 sourcea = g_idle_source_new ();
224 g_source_set_callback (sourcea, count_calls, &a, NULL);
225 g_source_set_priority (sourcea, 1);
226 g_source_attach (sourcea, ctx);
227 g_source_unref (sourcea);
229 sourceb = g_idle_source_new ();
230 g_source_set_callback (sourceb, count_calls, &b, NULL);
231 g_source_set_priority (sourceb, 0);
232 g_source_attach (sourceb, ctx);
233 g_source_unref (sourceb);
235 g_assert (g_main_context_pending (ctx));
236 g_assert (g_main_context_iteration (ctx, FALSE));
237 g_assert_cmpint (a, ==, 0);
238 g_assert_cmpint (b, ==, 1);
240 g_assert (g_main_context_iteration (ctx, FALSE));
241 g_assert_cmpint (a, ==, 0);
242 g_assert_cmpint (b, ==, 2);
244 g_source_destroy (sourceb);
246 g_assert (g_main_context_iteration (ctx, FALSE));
247 g_assert_cmpint (a, ==, 1);
248 g_assert_cmpint (b, ==, 2);
250 g_assert (g_main_context_pending (ctx));
251 g_source_destroy (sourcea);
252 g_assert (!g_main_context_pending (ctx));
254 g_main_context_unref (ctx);
258 quit_loop (gpointer data)
260 GMainLoop *loop = data;
262 g_main_loop_quit (loop);
264 return G_SOURCE_REMOVE;
273 g_assert (data == g_thread_self ());
281 call_func (gpointer data)
283 func (g_thread_self ());
285 return G_SOURCE_REMOVE;
290 static gboolean thread_ready;
293 thread_func (gpointer data)
295 GMainContext *ctx = data;
299 g_main_context_push_thread_default (ctx);
300 loop = g_main_loop_new (ctx, FALSE);
302 g_mutex_lock (&mutex);
304 g_cond_signal (&cond);
305 g_mutex_unlock (&mutex);
307 source = g_timeout_source_new (500);
308 g_source_set_callback (source, quit_loop, loop, NULL);
309 g_source_attach (source, ctx);
310 g_source_unref (source);
312 g_main_loop_run (loop);
314 g_main_context_pop_thread_default (ctx);
315 g_main_loop_unref (loop);
328 /* this one gets invoked directly */
329 g_main_context_invoke (NULL, func, g_thread_self ());
330 g_assert_cmpint (count, ==, 1);
332 /* invoking out of an idle works too */
333 g_idle_add (call_func, NULL);
334 g_main_context_iteration (g_main_context_default (), FALSE);
335 g_assert_cmpint (count, ==, 2);
337 /* test thread-default forcing the invocation to go
340 ctx = g_main_context_new ();
341 thread = g_thread_new ("worker", thread_func, ctx);
343 g_mutex_lock (&mutex);
344 while (!thread_ready)
345 g_cond_wait (&cond, &mutex);
346 g_mutex_unlock (&mutex);
348 g_main_context_invoke (ctx, func, thread);
350 g_thread_join (thread);
351 g_assert_cmpint (count, ==, 3);
353 g_main_context_unref (ctx);
356 /* We can't use timeout sources here because on slow or heavily-loaded
357 * machines, the test program might not get enough cycles to hit the
358 * timeouts at the expected times. So instead we define a source that
359 * is based on the number of GMainContext iterations.
363 static gint64 last_counter_update;
372 counter_source_prepare (GSource *source,
375 CounterSource *csource = (CounterSource *)source;
378 now = g_source_get_time (source);
379 if (now != last_counter_update)
381 last_counter_update = now;
386 return counter >= csource->timeout;
390 counter_source_dispatch (GSource *source,
391 GSourceFunc callback,
394 CounterSource *csource = (CounterSource *) source;
397 again = callback (user_data);
400 csource->timeout = counter + csource->interval;
405 static GSourceFuncs counter_source_funcs = {
406 counter_source_prepare,
408 counter_source_dispatch,
413 counter_source_new (gint interval)
415 GSource *source = g_source_new (&counter_source_funcs, sizeof (CounterSource));
416 CounterSource *csource = (CounterSource *) source;
418 csource->interval = interval;
419 csource->timeout = counter + interval;
426 run_inner_loop (gpointer user_data)
428 GMainContext *ctx = user_data;
434 inner = g_main_loop_new (ctx, FALSE);
435 timeout = counter_source_new (100);
436 g_source_set_callback (timeout, quit_loop, inner, NULL);
437 g_source_attach (timeout, ctx);
438 g_source_unref (timeout);
440 g_main_loop_run (inner);
441 g_main_loop_unref (inner);
443 return G_SOURCE_CONTINUE;
447 test_child_sources (void)
451 GSource *parent, *child_b, *child_c, *end;
453 ctx = g_main_context_new ();
454 loop = g_main_loop_new (ctx, FALSE);
458 parent = counter_source_new (2000);
459 g_source_set_callback (parent, run_inner_loop, ctx, NULL);
460 g_source_set_priority (parent, G_PRIORITY_LOW);
461 g_source_attach (parent, ctx);
463 child_b = counter_source_new (250);
464 g_source_set_callback (child_b, count_calls, &b, NULL);
465 g_source_add_child_source (parent, child_b);
467 child_c = counter_source_new (330);
468 g_source_set_callback (child_c, count_calls, &c, NULL);
469 g_source_set_priority (child_c, G_PRIORITY_HIGH);
470 g_source_add_child_source (parent, child_c);
472 /* Child sources always have the priority of the parent */
473 g_assert_cmpint (g_source_get_priority (parent), ==, G_PRIORITY_LOW);
474 g_assert_cmpint (g_source_get_priority (child_b), ==, G_PRIORITY_LOW);
475 g_assert_cmpint (g_source_get_priority (child_c), ==, G_PRIORITY_LOW);
476 g_source_set_priority (parent, G_PRIORITY_DEFAULT);
477 g_assert_cmpint (g_source_get_priority (parent), ==, G_PRIORITY_DEFAULT);
478 g_assert_cmpint (g_source_get_priority (child_b), ==, G_PRIORITY_DEFAULT);
479 g_assert_cmpint (g_source_get_priority (child_c), ==, G_PRIORITY_DEFAULT);
481 end = counter_source_new (1050);
482 g_source_set_callback (end, quit_loop, loop, NULL);
483 g_source_attach (end, ctx);
484 g_source_unref (end);
486 g_main_loop_run (loop);
488 /* The parent source's own timeout will never trigger, so "a" will
489 * only get incremented when "b" or "c" does. And when timeouts get
490 * blocked, they still wait the full interval next time rather than
491 * "catching up". So the timing is:
493 * 250 - b++ -> a++, run_inner_loop
494 * 330 - (c is blocked)
495 * 350 - inner_loop ends
496 * 350 - c++ belatedly -> a++, run_inner_loop
497 * 450 - inner loop ends
498 * 500 - b++ -> a++, run_inner_loop
499 * 600 - inner_loop ends
500 * 680 - c++ -> a++, run_inner_loop
501 * 750 - (b is blocked)
502 * 780 - inner loop ends
503 * 780 - b++ belatedly -> a++, run_inner_loop
504 * 880 - inner loop ends
505 * 1010 - c++ -> a++, run_inner_loop
506 * 1030 - (b is blocked)
507 * 1050 - end runs, quits outer loop, which has no effect yet
508 * 1110 - inner loop ends, a returns, outer loop exits
511 g_assert_cmpint (a, ==, 6);
512 g_assert_cmpint (b, ==, 3);
513 g_assert_cmpint (c, ==, 3);
515 g_source_destroy (parent);
516 g_source_unref (parent);
517 g_source_unref (child_b);
518 g_source_unref (child_c);
520 g_main_loop_unref (loop);
521 g_main_context_unref (ctx);
525 test_recursive_child_sources (void)
529 GSource *parent, *child_b, *child_c, *end;
531 ctx = g_main_context_new ();
532 loop = g_main_loop_new (ctx, FALSE);
536 parent = counter_source_new (500);
537 g_source_set_callback (parent, count_calls, &a, NULL);
539 child_b = counter_source_new (220);
540 g_source_set_callback (child_b, count_calls, &b, NULL);
541 g_source_add_child_source (parent, child_b);
543 child_c = counter_source_new (430);
544 g_source_set_callback (child_c, count_calls, &c, NULL);
545 g_source_add_child_source (child_b, child_c);
547 g_source_attach (parent, ctx);
549 end = counter_source_new (2010);
550 g_source_set_callback (end, (GSourceFunc)g_main_loop_quit, loop, NULL);
551 g_source_attach (end, ctx);
552 g_source_unref (end);
554 g_main_loop_run (loop);
556 /* Sequence of events:
557 * 220 b (b -> 440, a -> 720)
558 * 430 c (c -> 860, b -> 650, a -> 930)
559 * 650 b (b -> 870, a -> 1150)
560 * 860 c (c -> 1290, b -> 1080, a -> 1360)
561 * 1080 b (b -> 1300, a -> 1580)
562 * 1290 c (c -> 1720, b -> 1510, a -> 1790)
563 * 1510 b (b -> 1730, a -> 2010)
564 * 1720 c (c -> 2150, b -> 1940, a -> 2220)
565 * 1940 b (b -> 2160, a -> 2440)
568 g_assert_cmpint (a, ==, 9);
569 g_assert_cmpint (b, ==, 9);
570 g_assert_cmpint (c, ==, 4);
572 g_source_destroy (parent);
573 g_source_unref (parent);
574 g_source_unref (child_b);
575 g_source_unref (child_c);
577 g_main_loop_unref (loop);
578 g_main_context_unref (ctx);
582 GSource *parent, *old_child, *new_child;
587 swap_sources (gpointer user_data)
589 SwappingTestData *data = user_data;
593 g_source_remove_child_source (data->parent, data->old_child);
594 g_clear_pointer (&data->old_child, g_source_unref);
597 if (!data->new_child)
599 data->new_child = g_timeout_source_new (0);
600 g_source_set_callback (data->new_child, quit_loop, data->loop, NULL);
601 g_source_add_child_source (data->parent, data->new_child);
604 return G_SOURCE_CONTINUE;
608 assert_not_reached_callback (gpointer user_data)
610 g_assert_not_reached ();
612 return G_SOURCE_REMOVE;
616 test_swapping_child_sources (void)
620 SwappingTestData data;
622 ctx = g_main_context_new ();
623 loop = g_main_loop_new (ctx, FALSE);
625 data.parent = counter_source_new (50);
627 g_source_set_callback (data.parent, swap_sources, &data, NULL);
628 g_source_attach (data.parent, ctx);
630 data.old_child = counter_source_new (100);
631 g_source_add_child_source (data.parent, data.old_child);
632 g_source_set_callback (data.old_child, assert_not_reached_callback, NULL, NULL);
634 data.new_child = NULL;
635 g_main_loop_run (loop);
637 g_source_destroy (data.parent);
638 g_source_unref (data.parent);
639 g_source_unref (data.new_child);
641 g_main_loop_unref (loop);
642 g_main_context_unref (ctx);
646 add_source_callback (gpointer user_data)
648 GMainLoop *loop = user_data;
649 GSource *self = g_main_current_source (), *child;
652 /* It doesn't matter whether this is a valid fd or not; it never
653 * actually gets polled; the test is just checking that
654 * g_source_add_child_source() doesn't crash.
656 io = g_io_channel_unix_new (0);
657 child = g_io_create_watch (io, G_IO_IN);
658 g_source_add_child_source (self, child);
659 g_source_unref (child);
660 g_io_channel_unref (io);
662 g_main_loop_quit (loop);
667 test_blocked_child_sources (void)
673 g_test_bug ("701283");
675 ctx = g_main_context_new ();
676 loop = g_main_loop_new (ctx, FALSE);
678 source = g_idle_source_new ();
679 g_source_set_callback (source, add_source_callback, loop, NULL);
680 g_source_attach (source, ctx);
682 g_main_loop_run (loop);
684 g_source_destroy (source);
685 g_source_unref (source);
687 g_main_loop_unref (loop);
688 g_main_context_unref (ctx);
695 GSource *timeout1, *timeout2;
701 timeout1_callback (gpointer user_data)
703 TimeTestData *data = user_data;
705 gint64 mtime1, mtime2, time2;
707 source = g_main_current_source ();
708 g_assert (source == data->timeout1);
710 if (data->time1 == -1)
712 /* First iteration */
713 g_assert (!g_source_is_destroyed (data->timeout2));
715 mtime1 = g_get_monotonic_time ();
716 data->time1 = g_source_get_time (source);
718 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
719 g_source_get_current_time (source, &data->tv);
720 G_GNUC_END_IGNORE_DEPRECATIONS
722 /* g_source_get_time() does not change during a single callback */
724 mtime2 = g_get_monotonic_time ();
725 time2 = g_source_get_time (source);
727 g_assert_cmpint (mtime1, <, mtime2);
728 g_assert_cmpint (data->time1, ==, time2);
734 /* Second iteration */
735 g_assert (g_source_is_destroyed (data->timeout2));
737 /* g_source_get_time() MAY change between iterations; in this
738 * case we know for sure that it did because of the g_usleep()
741 time2 = g_source_get_time (source);
742 g_assert_cmpint (data->time1, <, time2);
744 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
745 g_source_get_current_time (source, &tv);
746 G_GNUC_END_IGNORE_DEPRECATIONS
748 g_assert (tv.tv_sec > data->tv.tv_sec ||
749 (tv.tv_sec == data->tv.tv_sec &&
750 tv.tv_usec > data->tv.tv_usec));
752 g_main_loop_quit (data->loop);
759 timeout2_callback (gpointer user_data)
761 TimeTestData *data = user_data;
765 source = g_main_current_source ();
766 g_assert (source == data->timeout2);
768 g_assert (!g_source_is_destroyed (data->timeout1));
770 /* g_source_get_time() does not change between different sources in
771 * a single iteration of the mainloop.
773 time2 = g_source_get_time (source);
774 g_assert_cmpint (data->time1, ==, time2);
776 /* The source should still have a valid time even after being
777 * destroyed, since it's currently running.
779 g_source_destroy (source);
780 time3 = g_source_get_time (source);
781 g_assert_cmpint (time2, ==, time3);
787 test_source_time (void)
791 data.ctx = g_main_context_new ();
792 data.loop = g_main_loop_new (data.ctx, FALSE);
794 data.timeout1 = g_timeout_source_new (0);
795 g_source_set_callback (data.timeout1, timeout1_callback, &data, NULL);
796 g_source_attach (data.timeout1, data.ctx);
798 data.timeout2 = g_timeout_source_new (0);
799 g_source_set_callback (data.timeout2, timeout2_callback, &data, NULL);
800 g_source_attach (data.timeout2, data.ctx);
804 g_main_loop_run (data.loop);
806 g_assert (!g_source_is_destroyed (data.timeout1));
807 g_assert (g_source_is_destroyed (data.timeout2));
809 g_source_destroy (data.timeout1);
810 g_source_unref (data.timeout1);
811 g_source_unref (data.timeout2);
813 g_main_loop_unref (data.loop);
814 g_main_context_unref (data.ctx);
818 guint outstanding_ops;
823 on_source_fired_cb (gpointer user_data)
825 TestOverflowData *data = user_data;
826 GSource *current_source;
827 GMainContext *current_context;
830 data->outstanding_ops--;
832 current_source = g_main_current_source ();
833 current_context = g_source_get_context (current_source);
834 source_id = g_source_get_id (current_source);
835 g_assert (g_main_context_find_source_by_id (current_context, source_id) != NULL);
836 g_source_destroy (current_source);
837 g_assert (g_main_context_find_source_by_id (current_context, source_id) == NULL);
839 if (data->outstanding_ops == 0)
840 g_main_loop_quit (data->loop);
845 add_idle_source (GMainContext *ctx,
846 TestOverflowData *data)
850 source = g_idle_source_new ();
851 g_source_set_callback (source, on_source_fired_cb, data, NULL);
852 g_source_attach (source, ctx);
853 g_source_unref (source);
854 data->outstanding_ops++;
860 test_mainloop_overflow (void)
865 TestOverflowData data;
868 g_test_bug ("687098");
870 memset (&data, 0, sizeof (data));
872 ctx = GLIB_PRIVATE_CALL (g_main_context_new_with_next_id) (G_MAXUINT-1);
874 loop = g_main_loop_new (ctx, TRUE);
875 data.outstanding_ops = 0;
878 source = add_idle_source (ctx, &data);
879 g_assert_cmpint (source->source_id, ==, G_MAXUINT-1);
881 source = add_idle_source (ctx, &data);
882 g_assert_cmpint (source->source_id, ==, G_MAXUINT);
884 source = add_idle_source (ctx, &data);
885 g_assert_cmpint (source->source_id, !=, 0);
887 /* Now, a lot more sources */
888 for (i = 0; i < 50; i++)
890 source = add_idle_source (ctx, &data);
891 g_assert_cmpint (source->source_id, !=, 0);
894 g_main_loop_run (loop);
895 g_assert_cmpint (data.outstanding_ops, ==, 0);
897 g_main_loop_unref (loop);
898 g_main_context_unref (ctx);
901 static volatile gint ready_time_dispatched;
904 ready_time_dispatch (GSource *source,
905 GSourceFunc callback,
908 g_atomic_int_set (&ready_time_dispatched, TRUE);
910 g_source_set_ready_time (source, -1);
916 run_context (gpointer user_data)
918 g_main_loop_run (user_data);
924 test_ready_time (void)
928 GSourceFuncs source_funcs = {
929 NULL, NULL, ready_time_dispatch
933 source = g_source_new (&source_funcs, sizeof (GSource));
934 g_source_attach (source, NULL);
935 g_source_unref (source);
937 /* Unfortunately we can't do too many things with respect to timing
938 * without getting into trouble on slow systems or heavily loaded
941 * We can test that the basics are working, though.
944 /* A source with no ready time set should not fire */
945 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
946 while (g_main_context_iteration (NULL, FALSE));
947 g_assert (!ready_time_dispatched);
949 /* The ready time should not have been changed */
950 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
952 /* Of course this shouldn't change anything either */
953 g_source_set_ready_time (source, -1);
954 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
956 /* A source with a ready time set to tomorrow should not fire on any
957 * builder, no matter how badly loaded...
959 g_source_set_ready_time (source, g_get_monotonic_time () + G_TIME_SPAN_DAY);
960 while (g_main_context_iteration (NULL, FALSE));
961 g_assert (!ready_time_dispatched);
962 /* Make sure it didn't get reset */
963 g_assert_cmpint (g_source_get_ready_time (source), !=, -1);
965 /* Ready time of -1 -> don't fire */
966 g_source_set_ready_time (source, -1);
967 while (g_main_context_iteration (NULL, FALSE));
968 g_assert (!ready_time_dispatched);
969 /* Not reset, but should still be -1 from above */
970 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
972 /* A ready time of the current time should fire immediately */
973 g_source_set_ready_time (source, g_get_monotonic_time ());
974 while (g_main_context_iteration (NULL, FALSE));
975 g_assert (ready_time_dispatched);
976 ready_time_dispatched = FALSE;
977 /* Should have gotten reset by the handler function */
978 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
980 /* As well as one in the recent past... */
981 g_source_set_ready_time (source, g_get_monotonic_time () - G_TIME_SPAN_SECOND);
982 while (g_main_context_iteration (NULL, FALSE));
983 g_assert (ready_time_dispatched);
984 ready_time_dispatched = FALSE;
985 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
987 /* Zero is the 'official' way to get a source to fire immediately */
988 g_source_set_ready_time (source, 0);
989 while (g_main_context_iteration (NULL, FALSE));
990 g_assert (ready_time_dispatched);
991 ready_time_dispatched = FALSE;
992 g_assert_cmpint (g_source_get_ready_time (source), ==, -1);
994 /* Now do some tests of cross-thread wakeups.
996 * Make sure it wakes up right away from the start.
998 g_source_set_ready_time (source, 0);
999 loop = g_main_loop_new (NULL, FALSE);
1000 thread = g_thread_new ("context thread", run_context, loop);
1001 while (!g_atomic_int_get (&ready_time_dispatched));
1003 /* Now let's see if it can wake up from sleeping. */
1004 g_usleep (G_TIME_SPAN_SECOND / 2);
1005 g_atomic_int_set (&ready_time_dispatched, FALSE);
1006 g_source_set_ready_time (source, 0);
1007 while (!g_atomic_int_get (&ready_time_dispatched));
1009 /* kill the thread */
1010 g_main_loop_quit (loop);
1011 g_thread_join (thread);
1012 g_main_loop_unref (loop);
1014 g_source_destroy (source);
1023 ctx = g_main_context_new ();
1025 /* run a random large enough number of times because
1026 * main contexts tend to wake up a few times after creation.
1028 for (i = 0; i < 100; i++)
1030 /* This is the invariant we care about:
1031 * g_main_context_wakeup(ctx,) ensures that the next call to
1032 * g_main_context_iteration (ctx, TRUE) returns and doesn't
1034 * This is important in threaded apps where we might not know
1035 * if the thread calls g_main_context_wakeup() before or after
1036 * we enter g_main_context_iteration().
1038 g_main_context_wakeup (ctx);
1039 g_main_context_iteration (ctx, TRUE);
1042 g_main_context_unref (ctx);
1046 test_remove_invalid (void)
1048 g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "Source ID 3000000000 was not found*");
1049 g_source_remove (3000000000u);
1050 g_test_assert_expected_messages ();
1054 trivial_prepare (GSource *source,
1061 static gint n_finalized;
1064 trivial_finalize (GSource *source)
1070 test_unref_while_pending (void)
1072 static GSourceFuncs funcs = { trivial_prepare, NULL, NULL, trivial_finalize };
1073 GMainContext *context;
1076 context = g_main_context_new ();
1078 source = g_source_new (&funcs, sizeof (GSource));
1079 g_source_attach (source, context);
1080 g_source_unref (source);
1082 /* Do incomplete main iteration -- get a pending source but don't dispatch it. */
1083 g_main_context_prepare (context, NULL);
1084 g_main_context_query (context, 0, NULL, NULL, 0);
1085 g_main_context_check (context, 1000, NULL, 0);
1087 /* Destroy the context */
1088 g_main_context_unref (context);
1090 /* Make sure we didn't leak the source */
1091 g_assert_cmpint (n_finalized, ==, 1);
1096 #include <glib-unix.h>
1099 static gchar zeros[1024];
1102 fill_a_pipe (gint fd)
1108 pfd.events = G_IO_OUT;
1109 while (g_poll (&pfd, 1, 0) == 1)
1110 /* we should never see -1 here */
1111 written += write (fd, zeros, sizeof zeros);
1117 write_bytes (gint fd,
1118 GIOCondition condition,
1121 gssize *to_write = user_data;
1127 /* Detect if we run before we should */
1128 g_assert (*to_write >= 0);
1130 limit = MIN (*to_write, sizeof zeros);
1131 *to_write -= write (fd, zeros, limit);
1137 read_bytes (gint fd,
1138 GIOCondition condition,
1141 static gchar buffer[1024];
1142 gssize *to_read = user_data;
1144 *to_read -= read (fd, buffer, sizeof buffer);
1146 /* The loop will exit when there is nothing else to read, then we will
1147 * use g_source_remove() to destroy this source.
1155 gssize to_write = -1;
1166 to_read = fill_a_pipe (fds[1]);
1167 /* write at higher priority to keep the pipe full... */
1168 a = g_unix_fd_add_full (G_PRIORITY_HIGH, fds[1], G_IO_OUT, write_bytes, &to_write, NULL);
1169 source_a = g_source_ref (g_main_context_find_source_by_id (NULL, a));
1170 /* make sure no 'writes' get dispatched yet */
1171 while (g_main_context_iteration (NULL, FALSE));
1173 to_read += 128 * 1024 * 1024;
1174 to_write = 128 * 1024 * 1024;
1175 b = g_unix_fd_add (fds[0], G_IO_IN, read_bytes, &to_read);
1176 source_b = g_source_ref (g_main_context_find_source_by_id (NULL, b));
1178 /* Assuming the kernel isn't internally 'laggy' then there will always
1179 * be either data to read or room in which to write. That will keep
1180 * the loop running until all data has been read and written.
1184 gssize to_write_was = to_write;
1185 gssize to_read_was = to_read;
1187 if (!g_main_context_iteration (NULL, FALSE))
1190 /* Since the sources are at different priority, only one of them
1191 * should possibly have run.
1193 g_assert (to_write == to_write_was || to_read == to_read_was);
1196 g_assert (to_write == 0);
1197 g_assert (to_read == 0);
1199 /* 'a' is already removed by itself */
1200 g_assert (g_source_is_destroyed (source_a));
1201 g_source_unref (source_a);
1202 g_source_remove (b);
1203 g_assert (g_source_is_destroyed (source_b));
1204 g_source_unref (source_b);
1210 assert_main_context_state (gint n_to_poll,
1213 GMainContext *context;
1214 gboolean consumed[10] = { };
1215 GPollFD poll_fds[10];
1223 context = g_main_context_default ();
1225 immediate = g_main_context_prepare (context, &max_priority);
1226 g_assert (!immediate);
1227 n = g_main_context_query (context, max_priority, &timeout, poll_fds, 10);
1228 g_assert_cmpint (n, ==, n_to_poll + 1); /* one will be the gwakeup */
1230 va_start (ap, n_to_poll);
1231 for (i = 0; i < n_to_poll; i++)
1233 gint expected_fd = va_arg (ap, gint);
1234 GIOCondition expected_events = va_arg (ap, GIOCondition);
1235 GIOCondition report_events = va_arg (ap, GIOCondition);
1237 for (j = 0; j < n; j++)
1238 if (!consumed[j] && poll_fds[j].fd == expected_fd && poll_fds[j].events == expected_events)
1240 poll_fds[j].revents = report_events;
1246 g_error ("Unable to find fd %d (index %d) with events 0x%x\n", expected_fd, i, (guint) expected_events);
1250 /* find the gwakeup, flag as non-ready */
1251 for (i = 0; i < n; i++)
1253 poll_fds[i].revents = 0;
1255 if (g_main_context_check (context, max_priority, poll_fds, n))
1256 g_main_context_dispatch (context);
1261 GIOCondition condition,
1264 gboolean *flag = user_data;
1272 test_unix_fd_source (void)
1274 GSource *out_source;
1281 assert_main_context_state (0);
1286 source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1287 g_source_attach (source, NULL);
1289 /* Check that a source with no callback gets successfully detached
1290 * with a warning printed.
1292 g_test_expect_message ("GLib", G_LOG_LEVEL_WARNING, "*GUnixFDSource dispatched without callback*");
1293 while (g_main_context_iteration (NULL, FALSE));
1294 g_test_assert_expected_messages ();
1295 g_assert (g_source_is_destroyed (source));
1296 g_source_unref (source);
1299 out_source = g_unix_fd_source_new (fds[1], G_IO_OUT);
1300 g_source_set_callback (out_source, (GSourceFunc) flag_bool, &out, NULL);
1301 g_source_attach (out_source, NULL);
1302 assert_main_context_state (1,
1303 fds[1], G_IO_OUT, 0);
1304 g_assert (!in && !out);
1306 in_source = g_unix_fd_source_new (fds[0], G_IO_IN);
1307 g_source_set_callback (in_source, (GSourceFunc) flag_bool, &in, NULL);
1308 g_source_set_priority (in_source, G_PRIORITY_DEFAULT_IDLE);
1309 g_source_attach (in_source, NULL);
1310 assert_main_context_state (2,
1311 fds[0], G_IO_IN, G_IO_IN,
1312 fds[1], G_IO_OUT, G_IO_OUT);
1313 /* out is higher priority so only it should fire */
1314 g_assert (!in && out);
1316 /* raise the priority of the in source to higher than out*/
1318 g_source_set_priority (in_source, G_PRIORITY_HIGH);
1319 assert_main_context_state (2,
1320 fds[0], G_IO_IN, G_IO_IN,
1321 fds[1], G_IO_OUT, G_IO_OUT);
1322 g_assert (in && !out);
1324 /* now, let them be equal */
1326 g_source_set_priority (in_source, G_PRIORITY_DEFAULT);
1327 assert_main_context_state (2,
1328 fds[0], G_IO_IN, G_IO_IN,
1329 fds[1], G_IO_OUT, G_IO_OUT);
1330 g_assert (in && out);
1332 g_source_destroy (out_source);
1333 g_source_unref (out_source);
1334 g_source_destroy (in_source);
1335 g_source_unref (in_source);
1347 return_true (GSource *source, GSourceFunc callback, gpointer user_data)
1349 FlagSource *flag_source = (FlagSource *) source;
1351 flag_source->flagged = TRUE;
1356 #define assert_flagged(s) g_assert (((FlagSource *) (s))->flagged);
1357 #define assert_not_flagged(s) g_assert (!((FlagSource *) (s))->flagged);
1358 #define clear_flag(s) ((FlagSource *) (s))->flagged = 0
1361 test_source_unix_fd_api (void)
1363 GSourceFuncs no_funcs = {
1364 NULL, NULL, return_true
1368 gpointer tag1, tag2;
1375 source_a = g_source_new (&no_funcs, sizeof (FlagSource));
1376 source_b = g_source_new (&no_funcs, sizeof (FlagSource));
1378 /* attach a source with more than one fd */
1379 g_source_add_unix_fd (source_a, fds_a[0], G_IO_IN);
1380 g_source_add_unix_fd (source_a, fds_a[1], G_IO_OUT);
1381 g_source_attach (source_a, NULL);
1382 assert_main_context_state (2,
1383 fds_a[0], G_IO_IN, 0,
1384 fds_a[1], G_IO_OUT, 0);
1385 assert_not_flagged (source_a);
1387 /* attach a higher priority source with no fds */
1388 g_source_set_priority (source_b, G_PRIORITY_HIGH);
1389 g_source_attach (source_b, NULL);
1390 assert_main_context_state (2,
1391 fds_a[0], G_IO_IN, G_IO_IN,
1392 fds_a[1], G_IO_OUT, 0);
1393 assert_flagged (source_a);
1394 assert_not_flagged (source_b);
1395 clear_flag (source_a);
1397 /* add some fds to the second source, while attached */
1398 tag1 = g_source_add_unix_fd (source_b, fds_b[0], G_IO_IN);
1399 tag2 = g_source_add_unix_fd (source_b, fds_b[1], G_IO_OUT);
1400 assert_main_context_state (4,
1401 fds_a[0], G_IO_IN, 0,
1402 fds_a[1], G_IO_OUT, G_IO_OUT,
1403 fds_b[0], G_IO_IN, 0,
1404 fds_b[1], G_IO_OUT, G_IO_OUT);
1405 /* only 'b' (higher priority) should have dispatched */
1406 assert_not_flagged (source_a);
1407 assert_flagged (source_b);
1408 clear_flag (source_b);
1410 /* change our events on b to the same as they were before */
1411 g_source_modify_unix_fd (source_b, tag1, G_IO_IN);
1412 g_source_modify_unix_fd (source_b, tag2, G_IO_OUT);
1413 assert_main_context_state (4,
1414 fds_a[0], G_IO_IN, 0,
1415 fds_a[1], G_IO_OUT, G_IO_OUT,
1416 fds_b[0], G_IO_IN, 0,
1417 fds_b[1], G_IO_OUT, G_IO_OUT);
1418 assert_not_flagged (source_a);
1419 assert_flagged (source_b);
1420 clear_flag (source_b);
1422 /* now reverse them */
1423 g_source_modify_unix_fd (source_b, tag1, G_IO_OUT);
1424 g_source_modify_unix_fd (source_b, tag2, G_IO_IN);
1425 assert_main_context_state (4,
1426 fds_a[0], G_IO_IN, 0,
1427 fds_a[1], G_IO_OUT, G_IO_OUT,
1428 fds_b[0], G_IO_OUT, 0,
1429 fds_b[1], G_IO_IN, 0);
1430 /* 'b' had no events, so 'a' can go this time */
1431 assert_flagged (source_a);
1432 assert_not_flagged (source_b);
1433 clear_flag (source_a);
1435 /* remove one of the fds from 'b' */
1436 g_source_remove_unix_fd (source_b, tag1);
1437 assert_main_context_state (3,
1438 fds_a[0], G_IO_IN, 0,
1439 fds_a[1], G_IO_OUT, 0,
1440 fds_b[1], G_IO_IN, 0);
1441 assert_not_flagged (source_a);
1442 assert_not_flagged (source_b);
1444 /* remove the other */
1445 g_source_remove_unix_fd (source_b, tag2);
1446 assert_main_context_state (2,
1447 fds_a[0], G_IO_IN, 0,
1448 fds_a[1], G_IO_OUT, 0);
1449 assert_not_flagged (source_a);
1450 assert_not_flagged (source_b);
1452 /* destroy the sources */
1453 g_source_destroy (source_a);
1454 g_source_destroy (source_b);
1455 assert_main_context_state (0);
1457 g_source_unref (source_a);
1458 g_source_unref (source_b);
1468 timeout_cb (gpointer data)
1470 GMainLoop *loop = data;
1471 GMainContext *context;
1473 context = g_main_loop_get_context (loop);
1474 g_assert (g_main_loop_is_running (loop));
1475 g_assert (g_main_context_is_owner (context));
1477 g_main_loop_quit (loop);
1479 return G_SOURCE_REMOVE;
1483 threadf (gpointer data)
1485 GMainContext *context = data;
1489 loop = g_main_loop_new (context, FALSE);
1490 source = g_timeout_source_new (250);
1491 g_source_set_callback (source, timeout_cb, loop, NULL);
1492 g_source_attach (source, context);
1493 g_source_unref (source);
1495 g_main_loop_run (loop);
1497 g_main_loop_unref (loop);
1503 test_mainloop_wait (void)
1505 GMainContext *context;
1508 context = g_main_context_new ();
1510 t1 = g_thread_new ("t1", threadf, context);
1511 t2 = g_thread_new ("t2", threadf, context);
1516 g_main_context_unref (context);
1520 main (int argc, char *argv[])
1522 g_test_init (&argc, &argv, NULL);
1523 g_test_bug_base ("http://bugzilla.gnome.org/");
1525 g_test_add_func ("/maincontext/basic", test_maincontext_basic);
1526 g_test_add_func ("/mainloop/basic", test_mainloop_basic);
1527 g_test_add_func ("/mainloop/timeouts", test_timeouts);
1528 g_test_add_func ("/mainloop/priorities", test_priorities);
1529 g_test_add_func ("/mainloop/invoke", test_invoke);
1530 g_test_add_func ("/mainloop/child_sources", test_child_sources);
1531 g_test_add_func ("/mainloop/recursive_child_sources", test_recursive_child_sources);
1532 g_test_add_func ("/mainloop/swapping_child_sources", test_swapping_child_sources);
1533 g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources);
1534 g_test_add_func ("/mainloop/source_time", test_source_time);
1535 g_test_add_func ("/mainloop/overflow", test_mainloop_overflow);
1536 g_test_add_func ("/mainloop/ready-time", test_ready_time);
1537 g_test_add_func ("/mainloop/wakeup", test_wakeup);
1538 g_test_add_func ("/mainloop/remove-invalid", test_remove_invalid);
1539 g_test_add_func ("/mainloop/unref-while-pending", test_unref_while_pending);
1541 g_test_add_func ("/mainloop/unix-fd", test_unix_fd);
1542 g_test_add_func ("/mainloop/unix-fd-source", test_unix_fd_source);
1543 g_test_add_func ("/mainloop/source-unix-fd-api", test_source_unix_fd_api);
1544 g_test_add_func ("/mainloop/wait", test_mainloop_wait);
1547 return g_test_run ();