| #include <glib-object.h> | |
| #ifdef G_OS_UNIX | |
| #include <glib-unix.h> | |
| #include <fcntl.h> | |
| #include <signal.h> | |
| #include <unistd.h> | |
| #endif | |
| static void | |
| test_source (GSource *one, GCallback quit_callback) | |
| { | |
| GClosure *closure; | |
| GMainLoop *loop; | |
| /* Callback with GMainLoop user_data */ | |
| loop = g_main_loop_new (NULL, FALSE); | |
| closure = g_cclosure_new (quit_callback, loop, NULL); | |
| g_source_set_closure (one, closure); | |
| g_source_attach (one, NULL); | |
| g_main_loop_run (loop); | |
| g_source_destroy (one); | |
| g_main_loop_unref (loop); | |
| } | |
| static gboolean | |
| simple_quit_callback (gpointer user_data) | |
| { | |
| GMainLoop *loop = user_data; | |
| g_main_loop_quit (loop); | |
| return TRUE; | |
| } | |
| static void | |
| test_closure_idle (void) | |
| { | |
| GSource *source; | |
| source = g_idle_source_new (); | |
| test_source (source, G_CALLBACK (simple_quit_callback)); | |
| g_source_unref (source); | |
| } | |
| static void | |
| test_closure_timeout (void) | |
| { | |
| GSource *source; | |
| source = g_timeout_source_new (10); | |
| test_source (source, G_CALLBACK (simple_quit_callback)); | |
| g_source_unref (source); | |
| } | |
| static gboolean | |
| iochannel_quit_callback (GIOChannel *channel, | |
| GIOCondition cond, | |
| gpointer user_data) | |
| { | |
| GMainLoop *loop = user_data; | |
| g_main_loop_quit (loop); | |
| return TRUE; | |
| } | |
| static void | |
| test_closure_iochannel (void) | |
| { | |
| GIOChannel *chan; | |
| GSource *source; | |
| char *path; | |
| GError *error = NULL; | |
| if (g_path_is_absolute (g_get_prgname ())) | |
| path = g_strdup (g_get_prgname ()); | |
| else | |
| { | |
| path = g_test_build_filename (G_TEST_BUILT, | |
| g_get_prgname (), | |
| NULL); | |
| } | |
| chan = g_io_channel_new_file (path, "r", &error); | |
| g_assert_no_error (error); | |
| g_free (path); | |
| source = g_io_create_watch (chan, G_IO_IN); | |
| test_source (source, G_CALLBACK (iochannel_quit_callback)); | |
| g_source_unref (source); | |
| g_io_channel_unref (chan); | |
| } | |
| static void | |
| test_closure_child (void) | |
| { | |
| GSource *source; | |
| GPid pid; | |
| GError *error = NULL; | |
| gchar *argv[3]; | |
| g_assert (g_getenv ("DO_NOT_ACCIDENTALLY_RECURSE") == NULL); | |
| g_setenv ("DO_NOT_ACCIDENTALLY_RECURSE", "1", TRUE); | |
| if (g_path_is_absolute (g_get_prgname ())) | |
| argv[0] = g_strdup (g_get_prgname ()); | |
| else | |
| { | |
| argv[0] = g_test_build_filename (G_TEST_BUILT, | |
| g_get_prgname (), | |
| NULL); | |
| } | |
| argv[1] = "-l"; | |
| argv[2] = NULL; | |
| g_spawn_async (NULL, argv, NULL, | |
| G_SPAWN_STDOUT_TO_DEV_NULL | | |
| G_SPAWN_STDERR_TO_DEV_NULL | | |
| G_SPAWN_DO_NOT_REAP_CHILD, | |
| NULL, NULL, | |
| &pid, &error); | |
| g_assert_no_error (error); | |
| g_free (argv[0]); | |
| source = g_child_watch_source_new (pid); | |
| test_source (source, G_CALLBACK (iochannel_quit_callback)); | |
| g_source_unref (source); | |
| } | |
| #ifdef G_OS_UNIX | |
| static gboolean | |
| fd_quit_callback (gint fd, | |
| GIOCondition condition, | |
| gpointer user_data) | |
| { | |
| GMainLoop *loop = user_data; | |
| g_main_loop_quit (loop); | |
| return TRUE; | |
| } | |
| static void | |
| test_closure_fd (void) | |
| { | |
| gint fd; | |
| GSource *source; | |
| fd = open ("/dev/null", O_RDONLY); | |
| g_assert (fd != -1); | |
| source = g_unix_fd_source_new (fd, G_IO_IN); | |
| test_source (source, G_CALLBACK (fd_quit_callback)); | |
| g_source_unref (source); | |
| close (fd); | |
| } | |
| static gboolean | |
| send_usr1 (gpointer user_data) | |
| { | |
| kill (getpid (), SIGUSR1); | |
| return FALSE; | |
| } | |
| static gboolean | |
| closure_quit_callback (gpointer user_data) | |
| { | |
| GMainLoop *loop = user_data; | |
| g_main_loop_quit (loop); | |
| return TRUE; | |
| } | |
| static void | |
| test_closure_signal (void) | |
| { | |
| GSource *source; | |
| g_idle_add_full (G_PRIORITY_LOW, send_usr1, NULL, NULL); | |
| source = g_unix_signal_source_new (SIGUSR1); | |
| test_source (source, G_CALLBACK (closure_quit_callback)); | |
| g_source_unref (source); | |
| } | |
| #endif | |
| int | |
| main (int argc, | |
| char *argv[]) | |
| { | |
| #ifndef G_OS_WIN32 | |
| sigset_t sig_mask, old_mask; | |
| sigemptyset (&sig_mask); | |
| sigaddset (&sig_mask, SIGUSR1); | |
| if (sigprocmask (SIG_UNBLOCK, &sig_mask, &old_mask) == 0) | |
| { | |
| if (sigismember (&old_mask, SIGUSR1)) | |
| g_message ("SIGUSR1 was blocked, unblocking it"); | |
| } | |
| #endif | |
| g_test_init (&argc, &argv, NULL); | |
| g_test_add_func ("/closure/idle", test_closure_idle); | |
| g_test_add_func ("/closure/timeout", test_closure_timeout); | |
| g_test_add_func ("/closure/iochannel", test_closure_iochannel); | |
| g_test_add_func ("/closure/child", test_closure_child); | |
| #ifdef G_OS_UNIX | |
| g_test_add_func ("/closure/fd", test_closure_fd); | |
| g_test_add_func ("/closure/signal", test_closure_signal); | |
| #endif | |
| return g_test_run (); | |
| } |