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"
28 static gboolean
cb (gpointer data
)
33 static gboolean
prepare (GSource
*source
, gint
*time
)
37 static gboolean
check (GSource
*source
)
41 static gboolean
dispatch (GSource
*source
, GSourceFunc cb
, gpointer date
)
46 GSourceFuncs funcs
= {
54 test_maincontext_basic (void)
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
));
129 test_mainloop_basic (void)
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
);
155 count_calls (gpointer data
)
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
);
214 test_priorities (void)
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
);
259 quit_loop (gpointer data
)
261 GMainLoop
*loop
= data
;
263 g_main_loop_quit (loop
);
265 return G_SOURCE_REMOVE
;
274 g_assert (data
== g_thread_self ());
282 call_func (gpointer data
)
284 func (g_thread_self ());
286 return G_SOURCE_REMOVE
;
291 static gboolean thread_ready
;
294 thread_func (gpointer data
)
296 GMainContext
*ctx
= data
;
300 g_main_context_push_thread_default (ctx
);
301 loop
= g_main_loop_new (ctx
, FALSE
);
303 g_mutex_lock (&mutex
);
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
);
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
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.
364 static gint64 last_counter_update
;
373 counter_source_prepare (GSource
*source
,
376 CounterSource
*csource
= (CounterSource
*)source
;
379 now
= g_source_get_time (source
);
380 if (now
!= last_counter_update
)
382 last_counter_update
= now
;
387 return counter
>= csource
->timeout
;
391 counter_source_dispatch (GSource
*source
,
392 GSourceFunc callback
,
395 CounterSource
*csource
= (CounterSource
*) source
;
398 again
= callback (user_data
);
401 csource
->timeout
= counter
+ csource
->interval
;
406 static GSourceFuncs counter_source_funcs
= {
407 counter_source_prepare
,
409 counter_source_dispatch
,
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
;
427 run_inner_loop (gpointer user_data
)
429 GMainContext
*ctx
= user_data
;
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
;
448 test_child_sources (void)
452 GSource
*parent
, *child_b
, *child_c
, *end
;
454 ctx
= g_main_context_new ();
455 loop
= g_main_loop_new (ctx
, FALSE
);
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
);
526 test_recursive_child_sources (void)
530 GSource
*parent
, *child_b
, *child_c
, *end
;
532 ctx
= g_main_context_new ();
533 loop
= g_main_loop_new (ctx
, FALSE
);
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
);
583 GSource
*parent
, *old_child
, *new_child
;
588 swap_sources (gpointer user_data
)
590 SwappingTestData
*data
= user_data
;
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
;
609 assert_not_reached_callback (gpointer user_data
)
611 g_assert_not_reached ();
613 return G_SOURCE_REMOVE
;
617 test_swapping_child_sources (void)
621 SwappingTestData data
;
623 ctx
= g_main_context_new ();
624 loop
= g_main_loop_new (ctx
, FALSE
);
626 data
.parent
= counter_source_new (50);
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
);
647 add_source_callback (gpointer user_data
)
649 GMainLoop
*loop
= user_data
;
650 GSource
*self
= g_main_current_source (), *child
;
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
);
668 test_blocked_child_sources (void)
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
);
696 GSource
*timeout1
, *timeout2
;
702 timeout1_callback (gpointer user_data
)
704 TimeTestData
*data
= user_data
;
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 */
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
);
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()
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
);
760 timeout2_callback (gpointer user_data
)
762 TimeTestData
*data
= user_data
;
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
);
788 test_source_time (void)
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
);
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
);
819 guint outstanding_ops
;
824 on_source_fired_cb (gpointer user_data
)
826 TestOverflowData
*data
= user_data
;
827 GSource
*current_source
;
828 GMainContext
*current_context
;
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
);
846 add_idle_source (GMainContext
*ctx
,
847 TestOverflowData
*data
)
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
++;
861 test_mainloop_overflow (void)
866 TestOverflowData data
;
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;
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
;
905 ready_time_dispatch (GSource
*source
,
906 GSourceFunc callback
,
909 g_atomic_int_set (&ready_time_dispatched
, TRUE
);
911 g_source_set_ready_time (source
, -1);
917 run_context (gpointer user_data
)
919 g_main_loop_run (user_data
);
925 test_ready_time (void)
929 GSourceFuncs source_funcs
= {
930 NULL
, NULL
, ready_time_dispatch
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
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
);
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
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
);
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 ();
1055 trivial_prepare (GSource
*source
,
1062 static gint n_finalized
;
1065 trivial_finalize (GSource
*source
)
1071 test_unref_while_pending (void)
1073 static GSourceFuncs funcs
= { trivial_prepare
, NULL
, NULL
, trivial_finalize
};
1074 GMainContext
*context
;
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);
1097 #include <glib-unix.h>
1100 static gchar zeros
[1024];
1103 fill_a_pipe (gint 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
);
1118 write_bytes (gint fd
,
1119 GIOCondition condition
,
1122 gssize
*to_write
= user_data
;
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
);
1138 read_bytes (gint fd
,
1139 GIOCondition condition
,
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.
1157 gssize to_write
= -1;
1168 to_read
= fill_a_pipe (fds
[1]);
1169 /* write at higher priority to keep the pipe full... */
1170 a
= g_unix_fd_add_full (G_PRIORITY_HIGH
, fds
[1], G_IO_OUT
, write_bytes
, &to_write
, NULL
);
1171 source_a
= g_source_ref (g_main_context_find_source_by_id (NULL
, a
));
1172 /* make sure no 'writes' get dispatched yet */
1173 while (g_main_context_iteration (NULL
, FALSE
));
1175 to_read
+= 128 * 1024 * 1024;
1176 to_write
= 128 * 1024 * 1024;
1177 b
= g_unix_fd_add (fds
[0], G_IO_IN
, read_bytes
, &to_read
);
1178 source_b
= g_source_ref (g_main_context_find_source_by_id (NULL
, b
));
1180 /* Assuming the kernel isn't internally 'laggy' then there will always
1181 * be either data to read or room in which to write. That will keep
1182 * the loop running until all data has been read and written.
1186 gssize to_write_was
= to_write
;
1187 gssize to_read_was
= to_read
;
1189 if (!g_main_context_iteration (NULL
, FALSE
))
1192 /* Since the sources are at different priority, only one of them
1193 * should possibly have run.
1195 g_assert (to_write
== to_write_was
|| to_read
== to_read_was
);
1198 g_assert (to_write
== 0);
1199 g_assert (to_read
== 0);
1201 /* 'a' is already removed by itself */
1202 g_assert (g_source_is_destroyed (source_a
));
1203 g_source_unref (source_a
);
1204 g_source_remove (b
);
1205 g_assert (g_source_is_destroyed (source_b
));
1206 g_source_unref (source_b
);
1213 assert_main_context_state (gint n_to_poll
,
1216 GMainContext
*context
;
1217 gboolean consumed
[10] = { };
1218 GPollFD poll_fds
[10];
1227 context
= g_main_context_default ();
1229 acquired
= g_main_context_acquire (context
);
1230 g_assert (acquired
);
1232 immediate
= g_main_context_prepare (context
, &max_priority
);
1233 g_assert (!immediate
);
1234 n
= g_main_context_query (context
, max_priority
, &timeout
, poll_fds
, 10);
1235 g_assert_cmpint (n
, ==, n_to_poll
+ 1); /* one will be the gwakeup */
1237 va_start (ap
, n_to_poll
);
1238 for (i
= 0; i
< n_to_poll
; i
++)
1240 gint expected_fd
= va_arg (ap
, gint
);
1241 GIOCondition expected_events
= va_arg (ap
, GIOCondition
);
1242 GIOCondition report_events
= va_arg (ap
, GIOCondition
);
1244 for (j
= 0; j
< n
; j
++)
1245 if (!consumed
[j
] && poll_fds
[j
].fd
== expected_fd
&& poll_fds
[j
].events
== expected_events
)
1247 poll_fds
[j
].revents
= report_events
;
1253 g_error ("Unable to find fd %d (index %d) with events 0x%x", expected_fd
, i
, (guint
) expected_events
);
1257 /* find the gwakeup, flag as non-ready */
1258 for (i
= 0; i
< n
; i
++)
1260 poll_fds
[i
].revents
= 0;
1262 if (g_main_context_check (context
, max_priority
, poll_fds
, n
))
1263 g_main_context_dispatch (context
);
1265 g_main_context_release (context
);
1270 GIOCondition condition
,
1273 gboolean
*flag
= user_data
;
1281 test_unix_fd_source (void)
1283 GSource
*out_source
;
1290 assert_main_context_state (0);
1295 source
= g_unix_fd_source_new (fds
[1], G_IO_OUT
);
1296 g_source_attach (source
, NULL
);
1298 /* Check that a source with no callback gets successfully detached
1299 * with a warning printed.
1301 g_test_expect_message ("GLib", G_LOG_LEVEL_WARNING
, "*GUnixFDSource dispatched without callback*");
1302 while (g_main_context_iteration (NULL
, FALSE
));
1303 g_test_assert_expected_messages ();
1304 g_assert (g_source_is_destroyed (source
));
1305 g_source_unref (source
);
1308 out_source
= g_unix_fd_source_new (fds
[1], G_IO_OUT
);
1309 /* -Wcast-function-type complains about casting 'flag_bool' to GSourceFunc.
1310 * GCC has no way of knowing that it will be cast back to GUnixFDSourceFunc
1311 * before being called. Although GLib itself is not compiled with
1312 * -Wcast-function-type, applications that use GLib may well be (since
1313 * -Wextra includes it), so we provide a G_SOURCE_FUNC() macro to suppress
1314 * the warning. We check that it works here.
1316 #if G_GNUC_CHECK_VERSION(8, 0)
1317 #pragma GCC diagnostic push
1318 #pragma GCC diagnostic error "-Wcast-function-type"
1320 g_source_set_callback (out_source
, G_SOURCE_FUNC (flag_bool
), &out
, NULL
);
1321 #if G_GNUC_CHECK_VERSION(8, 0)
1322 #pragma GCC diagnostic pop
1324 g_source_attach (out_source
, NULL
);
1325 assert_main_context_state (1,
1326 fds
[1], G_IO_OUT
, 0);
1327 g_assert (!in
&& !out
);
1329 in_source
= g_unix_fd_source_new (fds
[0], G_IO_IN
);
1330 g_source_set_callback (in_source
, (GSourceFunc
) flag_bool
, &in
, NULL
);
1331 g_source_set_priority (in_source
, G_PRIORITY_DEFAULT_IDLE
);
1332 g_source_attach (in_source
, NULL
);
1333 assert_main_context_state (2,
1334 fds
[0], G_IO_IN
, G_IO_IN
,
1335 fds
[1], G_IO_OUT
, G_IO_OUT
);
1336 /* out is higher priority so only it should fire */
1337 g_assert (!in
&& out
);
1339 /* raise the priority of the in source to higher than out*/
1341 g_source_set_priority (in_source
, G_PRIORITY_HIGH
);
1342 assert_main_context_state (2,
1343 fds
[0], G_IO_IN
, G_IO_IN
,
1344 fds
[1], G_IO_OUT
, G_IO_OUT
);
1345 g_assert (in
&& !out
);
1347 /* now, let them be equal */
1349 g_source_set_priority (in_source
, G_PRIORITY_DEFAULT
);
1350 assert_main_context_state (2,
1351 fds
[0], G_IO_IN
, G_IO_IN
,
1352 fds
[1], G_IO_OUT
, G_IO_OUT
);
1353 g_assert (in
&& out
);
1355 g_source_destroy (out_source
);
1356 g_source_unref (out_source
);
1357 g_source_destroy (in_source
);
1358 g_source_unref (in_source
);
1370 return_true (GSource
*source
, GSourceFunc callback
, gpointer user_data
)
1372 FlagSource
*flag_source
= (FlagSource
*) source
;
1374 flag_source
->flagged
= TRUE
;
1379 #define assert_flagged(s) g_assert (((FlagSource *) (s))->flagged);
1380 #define assert_not_flagged(s) g_assert (!((FlagSource *) (s))->flagged);
1381 #define clear_flag(s) ((FlagSource *) (s))->flagged = 0
1384 test_source_unix_fd_api (void)
1386 GSourceFuncs no_funcs
= {
1387 NULL
, NULL
, return_true
1391 gpointer tag1
, tag2
;
1398 source_a
= g_source_new (&no_funcs
, sizeof (FlagSource
));
1399 source_b
= g_source_new (&no_funcs
, sizeof (FlagSource
));
1401 /* attach a source with more than one fd */
1402 g_source_add_unix_fd (source_a
, fds_a
[0], G_IO_IN
);
1403 g_source_add_unix_fd (source_a
, fds_a
[1], G_IO_OUT
);
1404 g_source_attach (source_a
, NULL
);
1405 assert_main_context_state (2,
1406 fds_a
[0], G_IO_IN
, 0,
1407 fds_a
[1], G_IO_OUT
, 0);
1408 assert_not_flagged (source_a
);
1410 /* attach a higher priority source with no fds */
1411 g_source_set_priority (source_b
, G_PRIORITY_HIGH
);
1412 g_source_attach (source_b
, NULL
);
1413 assert_main_context_state (2,
1414 fds_a
[0], G_IO_IN
, G_IO_IN
,
1415 fds_a
[1], G_IO_OUT
, 0);
1416 assert_flagged (source_a
);
1417 assert_not_flagged (source_b
);
1418 clear_flag (source_a
);
1420 /* add some fds to the second source, while attached */
1421 tag1
= g_source_add_unix_fd (source_b
, fds_b
[0], G_IO_IN
);
1422 tag2
= g_source_add_unix_fd (source_b
, fds_b
[1], G_IO_OUT
);
1423 assert_main_context_state (4,
1424 fds_a
[0], G_IO_IN
, 0,
1425 fds_a
[1], G_IO_OUT
, G_IO_OUT
,
1426 fds_b
[0], G_IO_IN
, 0,
1427 fds_b
[1], G_IO_OUT
, G_IO_OUT
);
1428 /* only 'b' (higher priority) should have dispatched */
1429 assert_not_flagged (source_a
);
1430 assert_flagged (source_b
);
1431 clear_flag (source_b
);
1433 /* change our events on b to the same as they were before */
1434 g_source_modify_unix_fd (source_b
, tag1
, G_IO_IN
);
1435 g_source_modify_unix_fd (source_b
, tag2
, G_IO_OUT
);
1436 assert_main_context_state (4,
1437 fds_a
[0], G_IO_IN
, 0,
1438 fds_a
[1], G_IO_OUT
, G_IO_OUT
,
1439 fds_b
[0], G_IO_IN
, 0,
1440 fds_b
[1], G_IO_OUT
, G_IO_OUT
);
1441 assert_not_flagged (source_a
);
1442 assert_flagged (source_b
);
1443 clear_flag (source_b
);
1445 /* now reverse them */
1446 g_source_modify_unix_fd (source_b
, tag1
, G_IO_OUT
);
1447 g_source_modify_unix_fd (source_b
, tag2
, G_IO_IN
);
1448 assert_main_context_state (4,
1449 fds_a
[0], G_IO_IN
, 0,
1450 fds_a
[1], G_IO_OUT
, G_IO_OUT
,
1451 fds_b
[0], G_IO_OUT
, 0,
1452 fds_b
[1], G_IO_IN
, 0);
1453 /* 'b' had no events, so 'a' can go this time */
1454 assert_flagged (source_a
);
1455 assert_not_flagged (source_b
);
1456 clear_flag (source_a
);
1458 /* remove one of the fds from 'b' */
1459 g_source_remove_unix_fd (source_b
, tag1
);
1460 assert_main_context_state (3,
1461 fds_a
[0], G_IO_IN
, 0,
1462 fds_a
[1], G_IO_OUT
, 0,
1463 fds_b
[1], G_IO_IN
, 0);
1464 assert_not_flagged (source_a
);
1465 assert_not_flagged (source_b
);
1467 /* remove the other */
1468 g_source_remove_unix_fd (source_b
, tag2
);
1469 assert_main_context_state (2,
1470 fds_a
[0], G_IO_IN
, 0,
1471 fds_a
[1], G_IO_OUT
, 0);
1472 assert_not_flagged (source_a
);
1473 assert_not_flagged (source_b
);
1475 /* destroy the sources */
1476 g_source_destroy (source_a
);
1477 g_source_destroy (source_b
);
1478 assert_main_context_state (0);
1480 g_source_unref (source_a
);
1481 g_source_unref (source_b
);
1489 unixfd_quit_loop (gint fd
,
1490 GIOCondition condition
,
1493 GMainLoop
*loop
= user_data
;
1495 g_main_loop_quit (loop
);
1501 test_unix_file_poll (void)
1507 fd
= open ("/dev/null", O_RDONLY
);
1510 loop
= g_main_loop_new (NULL
, FALSE
);
1512 source
= g_unix_fd_source_new (fd
, G_IO_IN
);
1513 g_source_set_callback (source
, (GSourceFunc
) unixfd_quit_loop
, loop
, NULL
);
1514 g_source_attach (source
, NULL
);
1516 /* Should not block */
1517 g_main_loop_run (loop
);
1519 g_source_destroy (source
);
1521 assert_main_context_state (0);
1523 g_source_unref (source
);
1525 g_main_loop_unref (loop
);
1534 timeout_cb (gpointer data
)
1536 GMainLoop
*loop
= data
;
1537 GMainContext
*context
;
1539 context
= g_main_loop_get_context (loop
);
1540 g_assert (g_main_loop_is_running (loop
));
1541 g_assert (g_main_context_is_owner (context
));
1543 g_main_loop_quit (loop
);
1545 return G_SOURCE_REMOVE
;
1549 threadf (gpointer data
)
1551 GMainContext
*context
= data
;
1555 loop
= g_main_loop_new (context
, FALSE
);
1556 source
= g_timeout_source_new (250);
1557 g_source_set_callback (source
, timeout_cb
, loop
, NULL
);
1558 g_source_attach (source
, context
);
1559 g_source_unref (source
);
1561 g_main_loop_run (loop
);
1563 g_main_loop_unref (loop
);
1569 test_mainloop_wait (void)
1571 GMainContext
*context
;
1574 context
= g_main_context_new ();
1576 t1
= g_thread_new ("t1", threadf
, context
);
1577 t2
= g_thread_new ("t2", threadf
, context
);
1582 g_main_context_unref (context
);
1587 nfds_in_cb (GIOChannel
*io
,
1588 GIOCondition condition
,
1591 gboolean
*in_cb_ran
= user_data
;
1594 g_assert_cmpint (condition
, ==, G_IO_IN
);
1599 nfds_out_cb (GIOChannel
*io
,
1600 GIOCondition condition
,
1603 gboolean
*out_cb_ran
= user_data
;
1606 g_assert_cmpint (condition
, ==, G_IO_OUT
);
1611 nfds_out_low_cb (GIOChannel
*io
,
1612 GIOCondition condition
,
1615 g_assert_not_reached ();
1626 GSource
*source1
, *source2
, *source3
;
1627 gboolean source1_ran
= FALSE
, source3_ran
= FALSE
;
1629 GError
*error
= NULL
;
1631 ctx
= g_main_context_new ();
1632 nfds
= g_main_context_query (ctx
, G_MAXINT
, NULL
,
1633 out_fds
, G_N_ELEMENTS (out_fds
));
1634 /* An "empty" GMainContext will have a single GPollFD, for its
1637 g_assert_cmpint (nfds
, ==, 1);
1639 fd
= g_file_open_tmp (NULL
, &tmpfile
, &error
);
1640 g_assert_no_error (error
);
1642 io
= g_io_channel_unix_new (fd
);
1644 /* The fd in the pollfds won't be the same fd we passed in */
1645 g_io_channel_win32_make_pollfd (io
, G_IO_IN
, out_fds
);
1649 /* Add our first pollfd */
1650 source1
= g_io_create_watch (io
, G_IO_IN
);
1651 g_source_set_priority (source1
, G_PRIORITY_DEFAULT
);
1652 g_source_set_callback (source1
, (GSourceFunc
) nfds_in_cb
,
1653 &source1_ran
, NULL
);
1654 g_source_attach (source1
, ctx
);
1656 nfds
= g_main_context_query (ctx
, G_MAXINT
, NULL
,
1657 out_fds
, G_N_ELEMENTS (out_fds
));
1658 g_assert_cmpint (nfds
, ==, 2);
1659 if (out_fds
[0].fd
== fd
)
1660 g_assert_cmpint (out_fds
[0].events
, ==, G_IO_IN
);
1661 else if (out_fds
[1].fd
== fd
)
1662 g_assert_cmpint (out_fds
[1].events
, ==, G_IO_IN
);
1664 g_assert_not_reached ();
1666 /* Add a second pollfd with the same fd but different event, and
1669 source2
= g_io_create_watch (io
, G_IO_OUT
);
1670 g_source_set_priority (source2
, G_PRIORITY_LOW
);
1671 g_source_set_callback (source2
, (GSourceFunc
) nfds_out_low_cb
,
1673 g_source_attach (source2
, ctx
);
1675 /* g_main_context_query() should still return only 2 pollfds,
1676 * one of which has our fd, and a combined events field.
1678 nfds
= g_main_context_query (ctx
, G_MAXINT
, NULL
,
1679 out_fds
, G_N_ELEMENTS (out_fds
));
1680 g_assert_cmpint (nfds
, ==, 2);
1681 if (out_fds
[0].fd
== fd
)
1682 g_assert_cmpint (out_fds
[0].events
, ==, G_IO_IN
| G_IO_OUT
);
1683 else if (out_fds
[1].fd
== fd
)
1684 g_assert_cmpint (out_fds
[1].events
, ==, G_IO_IN
| G_IO_OUT
);
1686 g_assert_not_reached ();
1688 /* But if we query with a max priority, we won't see the
1689 * lower-priority one.
1691 nfds
= g_main_context_query (ctx
, G_PRIORITY_DEFAULT
, NULL
,
1692 out_fds
, G_N_ELEMENTS (out_fds
));
1693 g_assert_cmpint (nfds
, ==, 2);
1694 if (out_fds
[0].fd
== fd
)
1695 g_assert_cmpint (out_fds
[0].events
, ==, G_IO_IN
);
1696 else if (out_fds
[1].fd
== fd
)
1697 g_assert_cmpint (out_fds
[1].events
, ==, G_IO_IN
);
1699 g_assert_not_reached ();
1702 source3
= g_io_create_watch (io
, G_IO_OUT
);
1703 g_source_set_priority (source3
, G_PRIORITY_DEFAULT
);
1704 g_source_set_callback (source3
, (GSourceFunc
) nfds_out_cb
,
1705 &source3_ran
, NULL
);
1706 g_source_attach (source3
, ctx
);
1708 nfds
= g_main_context_query (ctx
, G_MAXINT
, NULL
,
1709 out_fds
, G_N_ELEMENTS (out_fds
));
1710 g_assert_cmpint (nfds
, ==, 2);
1711 if (out_fds
[0].fd
== fd
)
1712 g_assert_cmpint (out_fds
[0].events
, ==, G_IO_IN
| G_IO_OUT
);
1713 else if (out_fds
[1].fd
== fd
)
1714 g_assert_cmpint (out_fds
[1].events
, ==, G_IO_IN
| G_IO_OUT
);
1716 g_assert_not_reached ();
1718 /* Now actually iterate the loop; the fd should be readable and
1719 * writable, so source1 and source3 should be triggered, but *not*
1720 * source2, since it's lower priority than them. (Though on
1721 * G_OS_WIN32, source3 doesn't get triggered, probably because of
1722 * giowin32 weirdness...)
1724 g_main_context_iteration (ctx
, FALSE
);
1726 g_assert (source1_ran
);
1728 g_assert (source3_ran
);
1731 g_source_destroy (source1
);
1732 g_source_unref (source1
);
1733 g_source_destroy (source2
);
1734 g_source_unref (source2
);
1735 g_source_destroy (source3
);
1736 g_source_unref (source3
);
1738 g_io_channel_unref (io
);
1742 g_main_context_unref (ctx
);
1746 main (int argc
, char *argv
[])
1748 g_test_init (&argc
, &argv
, NULL
);
1749 g_test_bug_base ("http://bugzilla.gnome.org/");
1751 g_test_add_func ("/maincontext/basic", test_maincontext_basic
);
1752 g_test_add_func ("/mainloop/basic", test_mainloop_basic
);
1753 g_test_add_func ("/mainloop/timeouts", test_timeouts
);
1754 g_test_add_func ("/mainloop/priorities", test_priorities
);
1755 g_test_add_func ("/mainloop/invoke", test_invoke
);
1756 g_test_add_func ("/mainloop/child_sources", test_child_sources
);
1757 g_test_add_func ("/mainloop/recursive_child_sources", test_recursive_child_sources
);
1758 g_test_add_func ("/mainloop/swapping_child_sources", test_swapping_child_sources
);
1759 g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources
);
1760 g_test_add_func ("/mainloop/source_time", test_source_time
);
1761 g_test_add_func ("/mainloop/overflow", test_mainloop_overflow
);
1762 g_test_add_func ("/mainloop/ready-time", test_ready_time
);
1763 g_test_add_func ("/mainloop/wakeup", test_wakeup
);
1764 g_test_add_func ("/mainloop/remove-invalid", test_remove_invalid
);
1765 g_test_add_func ("/mainloop/unref-while-pending", test_unref_while_pending
);
1767 g_test_add_func ("/mainloop/unix-fd", test_unix_fd
);
1768 g_test_add_func ("/mainloop/unix-fd-source", test_unix_fd_source
);
1769 g_test_add_func ("/mainloop/source-unix-fd-api", test_source_unix_fd_api
);
1770 g_test_add_func ("/mainloop/wait", test_mainloop_wait
);
1771 g_test_add_func ("/mainloop/unix-file-poll", test_unix_file_poll
);
1773 g_test_add_func ("/mainloop/nfds", test_nfds
);
1775 return g_test_run ();