1 | #include <glib-object.h> |
2 | |
3 | #ifdef G_OS_UNIX |
4 | #include <glib-unix.h> |
5 | |
6 | #include <fcntl.h> |
7 | #include <signal.h> |
8 | #include <unistd.h> |
9 | #endif |
10 | |
11 | static void |
12 | test_source (GSource *one, GCallback quit_callback) |
13 | { |
14 | GClosure *closure; |
15 | GMainLoop *loop; |
16 | |
17 | /* Callback with GMainLoop user_data */ |
18 | loop = g_main_loop_new (NULL, FALSE); |
19 | |
20 | closure = g_cclosure_new (callback_func: quit_callback, user_data: loop, NULL); |
21 | g_source_set_closure (source: one, closure); |
22 | |
23 | g_source_attach (source: one, NULL); |
24 | g_main_loop_run (loop); |
25 | |
26 | g_source_destroy (source: one); |
27 | g_main_loop_unref (loop); |
28 | } |
29 | |
30 | static gboolean |
31 | simple_quit_callback (gpointer user_data) |
32 | { |
33 | GMainLoop *loop = user_data; |
34 | |
35 | g_main_loop_quit (loop); |
36 | |
37 | return TRUE; |
38 | } |
39 | |
40 | static void |
41 | test_closure_idle (void) |
42 | { |
43 | GSource *source; |
44 | |
45 | source = g_idle_source_new (); |
46 | test_source (one: source, G_CALLBACK (simple_quit_callback)); |
47 | g_source_unref (source); |
48 | } |
49 | |
50 | static void |
51 | test_closure_timeout (void) |
52 | { |
53 | GSource *source; |
54 | |
55 | source = g_timeout_source_new (interval: 10); |
56 | test_source (one: source, G_CALLBACK (simple_quit_callback)); |
57 | g_source_unref (source); |
58 | } |
59 | |
60 | static gboolean |
61 | iochannel_quit_callback (GIOChannel *channel, |
62 | GIOCondition cond, |
63 | gpointer user_data) |
64 | { |
65 | GMainLoop *loop = user_data; |
66 | |
67 | g_main_loop_quit (loop); |
68 | |
69 | return TRUE; |
70 | } |
71 | |
72 | static void |
73 | test_closure_iochannel (void) |
74 | { |
75 | GIOChannel *chan; |
76 | GSource *source; |
77 | char *path; |
78 | GError *error = NULL; |
79 | |
80 | if (g_path_is_absolute (file_name: g_get_prgname ())) |
81 | path = g_strdup (str: g_get_prgname ()); |
82 | else |
83 | { |
84 | path = g_test_build_filename (file_type: G_TEST_BUILT, |
85 | first_path: g_get_prgname (), |
86 | NULL); |
87 | } |
88 | chan = g_io_channel_new_file (filename: path, mode: "r" , error: &error); |
89 | g_assert_no_error (error); |
90 | g_free (mem: path); |
91 | |
92 | source = g_io_create_watch (channel: chan, condition: G_IO_IN); |
93 | test_source (one: source, G_CALLBACK (iochannel_quit_callback)); |
94 | g_source_unref (source); |
95 | |
96 | g_io_channel_unref (channel: chan); |
97 | } |
98 | |
99 | static void |
100 | test_closure_child (void) |
101 | { |
102 | GSource *source; |
103 | GPid pid; |
104 | GError *error = NULL; |
105 | gchar *argv[3]; |
106 | |
107 | g_assert (g_getenv ("DO_NOT_ACCIDENTALLY_RECURSE" ) == NULL); |
108 | g_setenv (variable: "DO_NOT_ACCIDENTALLY_RECURSE" , value: "1" , TRUE); |
109 | |
110 | if (g_path_is_absolute (file_name: g_get_prgname ())) |
111 | argv[0] = g_strdup (str: g_get_prgname ()); |
112 | else |
113 | { |
114 | argv[0] = g_test_build_filename (file_type: G_TEST_BUILT, |
115 | first_path: g_get_prgname (), |
116 | NULL); |
117 | } |
118 | argv[1] = "-l" ; |
119 | argv[2] = NULL; |
120 | |
121 | g_spawn_async (NULL, argv, NULL, |
122 | flags: G_SPAWN_STDOUT_TO_DEV_NULL | |
123 | G_SPAWN_STDERR_TO_DEV_NULL | |
124 | G_SPAWN_DO_NOT_REAP_CHILD, |
125 | NULL, NULL, |
126 | child_pid: &pid, error: &error); |
127 | g_assert_no_error (error); |
128 | |
129 | g_free (mem: argv[0]); |
130 | |
131 | source = g_child_watch_source_new (pid); |
132 | test_source (one: source, G_CALLBACK (iochannel_quit_callback)); |
133 | g_source_unref (source); |
134 | } |
135 | |
136 | #ifdef G_OS_UNIX |
137 | static gboolean |
138 | fd_quit_callback (gint fd, |
139 | GIOCondition condition, |
140 | gpointer user_data) |
141 | { |
142 | GMainLoop *loop = user_data; |
143 | |
144 | g_main_loop_quit (loop); |
145 | |
146 | return TRUE; |
147 | } |
148 | |
149 | static void |
150 | test_closure_fd (void) |
151 | { |
152 | gint fd; |
153 | GSource *source; |
154 | |
155 | fd = open (file: "/dev/null" , O_RDONLY); |
156 | g_assert (fd != -1); |
157 | |
158 | source = g_unix_fd_source_new (fd, condition: G_IO_IN); |
159 | test_source (one: source, G_CALLBACK (fd_quit_callback)); |
160 | g_source_unref (source); |
161 | |
162 | close (fd: fd); |
163 | } |
164 | |
165 | static gboolean |
166 | send_usr1 (gpointer user_data) |
167 | { |
168 | kill (pid: getpid (), SIGUSR1); |
169 | return FALSE; |
170 | } |
171 | |
172 | static gboolean |
173 | closure_quit_callback (gpointer user_data) |
174 | { |
175 | GMainLoop *loop = user_data; |
176 | |
177 | g_main_loop_quit (loop); |
178 | |
179 | return TRUE; |
180 | } |
181 | |
182 | static void |
183 | test_closure_signal (void) |
184 | { |
185 | GSource *source; |
186 | |
187 | g_idle_add_full (G_PRIORITY_LOW, function: send_usr1, NULL, NULL); |
188 | |
189 | source = g_unix_signal_source_new (SIGUSR1); |
190 | test_source (one: source, G_CALLBACK (closure_quit_callback)); |
191 | g_source_unref (source); |
192 | } |
193 | #endif |
194 | |
195 | int |
196 | main (int argc, |
197 | char *argv[]) |
198 | { |
199 | #ifndef G_OS_WIN32 |
200 | sigset_t sig_mask, old_mask; |
201 | |
202 | sigemptyset (set: &sig_mask); |
203 | sigaddset (set: &sig_mask, SIGUSR1); |
204 | if (sigprocmask (SIG_UNBLOCK, set: &sig_mask, oset: &old_mask) == 0) |
205 | { |
206 | if (sigismember (set: &old_mask, SIGUSR1)) |
207 | g_message ("SIGUSR1 was blocked, unblocking it" ); |
208 | } |
209 | #endif |
210 | |
211 | g_test_init (argc: &argc, argv: &argv, NULL); |
212 | |
213 | g_test_add_func (testpath: "/closure/idle" , test_func: test_closure_idle); |
214 | g_test_add_func (testpath: "/closure/timeout" , test_func: test_closure_timeout); |
215 | g_test_add_func (testpath: "/closure/iochannel" , test_func: test_closure_iochannel); |
216 | g_test_add_func (testpath: "/closure/child" , test_func: test_closure_child); |
217 | #ifdef G_OS_UNIX |
218 | g_test_add_func (testpath: "/closure/fd" , test_func: test_closure_fd); |
219 | g_test_add_func (testpath: "/closure/signal" , test_func: test_closure_signal); |
220 | #endif |
221 | |
222 | return g_test_run (); |
223 | } |
224 | |