diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c index fc6f29179..067d9fc4d 100644 --- a/glib/tests/mainloop.c +++ b/glib/tests/mainloop.c @@ -43,6 +43,7 @@ test_maincontext_basic (void) source = g_source_new (&funcs, sizeof (GSource)); g_assert (g_source_get_priority (source) == G_PRIORITY_DEFAULT); + g_assert (!g_source_is_destroyed (source)); g_assert (!g_source_get_can_recurse (source)); g_assert (g_source_get_name (source) == NULL); @@ -72,6 +73,7 @@ test_maincontext_basic (void) id = g_source_attach (source, ctx); g_source_set_name_by_id (id, "e"); g_assert_cmpstr (g_source_get_name (source), ==, "e"); + g_assert (g_source_get_context (source) == ctx); g_assert (g_source_remove_by_funcs_user_data (&funcs, data)); } @@ -95,6 +97,179 @@ test_mainloop_basic (void) g_assert (g_main_depth () == 0); } +static gint a; +static gint b; +static gint c; + +static gboolean +count_calls (gpointer data) +{ + gint *i = data; + + (*i)++; + + return TRUE; +} + +static void +test_timeouts (void) +{ + GMainContext *ctx; + GMainLoop *loop; + GSource *source; + + a = b = c = 0; + + ctx = g_main_context_new (); + loop = g_main_loop_new (ctx, FALSE); + + source = g_timeout_source_new (100); + g_source_set_callback (source, count_calls, &a, NULL); + g_source_attach (source, ctx); + g_source_unref (source); + + source = g_timeout_source_new (250); + g_source_set_callback (source, count_calls, &b, NULL); + g_source_attach (source, ctx); + g_source_unref (source); + + source = g_timeout_source_new (330); + g_source_set_callback (source, count_calls, &c, NULL); + g_source_attach (source, ctx); + g_source_unref (source); + + source = g_timeout_source_new (1050); + g_source_set_callback (source, (GSourceFunc)g_main_loop_quit, loop, NULL); + g_source_attach (source, ctx); + g_source_unref (source); + + g_main_loop_run (loop); + + g_assert (a == 10); + g_assert (b == 4); + g_assert (c == 3); + + g_main_loop_unref (loop); + g_main_context_unref (ctx); +} + +static void +test_priorities (void) +{ + GMainContext *ctx; + GSource *sourcea; + GSource *sourceb; + + a = b = c = 0; + + ctx = g_main_context_new (); + + sourcea = g_idle_source_new (); + g_source_set_callback (sourcea, count_calls, &a, NULL); + g_source_set_priority (sourcea, 1); + g_source_attach (sourcea, ctx); + g_source_unref (sourcea); + + sourceb = g_idle_source_new (); + g_source_set_callback (sourceb, count_calls, &b, NULL); + g_source_set_priority (sourceb, 0); + g_source_attach (sourceb, ctx); + g_source_unref (sourceb); + + g_assert (g_main_context_pending (ctx)); + g_assert (g_main_context_iteration (ctx, FALSE)); + g_assert (a == 0); + g_assert (b == 1); + + g_assert (g_main_context_iteration (ctx, FALSE)); + g_assert (a == 0); + g_assert (b == 2); + + g_source_destroy (sourceb); + + g_assert (g_main_context_iteration (ctx, FALSE)); + g_assert (a == 1); + g_assert (b == 2); + + g_assert (g_main_context_pending (ctx)); + g_source_destroy (sourcea); + g_assert (!g_main_context_pending (ctx)); + + g_main_context_unref (ctx); +} + +static gint count; + +static gboolean +func (gpointer data) +{ + if (data != NULL) + g_assert (data == g_thread_self ()); + + count++; + + return FALSE; +} + +static gboolean +call_func (gpointer data) +{ + func (g_thread_self ()); + + return FALSE; +} + +static gpointer +thread_func (gpointer data) +{ + GMainContext *ctx = data; + GSource *source; + + g_main_context_push_thread_default (ctx); + + source = g_timeout_source_new (500); + g_source_set_callback (source, (GSourceFunc)g_thread_exit, NULL, NULL); + g_source_attach (source, ctx); + g_source_unref (source); + + while (TRUE) + g_main_context_iteration (ctx, TRUE); + + return NULL; +} + +static void +test_invoke (void) +{ + GMainContext *ctx; + GThread *thread; + + count = 0; + + /* this one gets invoked directly */ + g_main_context_invoke (NULL, func, g_thread_self ()); + g_assert (count == 1); + + /* invoking out of an idle works too */ + g_idle_add (call_func, NULL); + g_main_context_iteration (g_main_context_default (), FALSE); + g_assert (count == 2); + + /* test thread-default forcing the invocation to go + * to another thread + */ + ctx = g_main_context_new (); + thread = g_thread_new ("worker", thread_func, ctx); + + g_usleep (1000); /* give some time to push the thread-default */ + + g_main_context_invoke (ctx, func, thread); + g_assert (count == 2); + + g_thread_join (thread); + g_assert (count == 3); +} + int main (int argc, char *argv[]) { @@ -102,6 +277,9 @@ main (int argc, char *argv[]) g_test_add_func ("/maincontext/basic", test_maincontext_basic); g_test_add_func ("/mainloop/basic", test_mainloop_basic); + g_test_add_func ("/mainloop/timeouts", test_timeouts); + g_test_add_func ("/mainloop/priorities", test_priorities); + g_test_add_func ("/mainloop/invoke", test_invoke); return g_test_run (); }