Simplify subprocesses in tests
[platform/upstream/glib.git] / glib / tests / unix.c
1 /* 
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * This work is provided "as is"; redistribution and modification
5  * in whole or in part, in any medium, physical or electronic is
6  * permitted without restriction.
7  *
8  * This work is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * In no event shall the authors or contributors be liable for any
13  * direct, indirect, incidental, special, exemplary, or consequential
14  * damages (including, but not limited to, procurement of substitute
15  * goods or services; loss of use, data, or profits; or business
16  * interruption) however caused and on any theory of liability, whether
17  * in contract, strict liability, or tort (including negligence or
18  * otherwise) arising in any way out of the use of this software, even
19  * if advised of the possibility of such damage.
20  *
21  * Author: Colin Walters <walters@verbum.org> 
22  */
23
24 #include "config.h"
25
26 #include "glib-unix.h"
27 #include <string.h>
28
29 static void
30 test_pipe (void)
31 {
32   GError *error = NULL;
33   int pipefd[2];
34   char buf[1024];
35   ssize_t bytes_read;
36   gboolean res;
37
38   res = g_unix_open_pipe (pipefd, FD_CLOEXEC, &error);
39   g_assert (res);
40   g_assert_no_error (error);
41
42   write (pipefd[1], "hello", sizeof ("hello"));
43   memset (buf, 0, sizeof (buf));
44   bytes_read = read (pipefd[0], buf, sizeof(buf) - 1);
45   g_assert_cmpint (bytes_read, >, 0);
46   buf[bytes_read] = '\0';
47
48   close (pipefd[0]);
49   close (pipefd[1]);
50
51   g_assert (g_str_has_prefix (buf, "hello"));
52 }
53
54 static void
55 test_error (void)
56 {
57   GError *error = NULL;
58   gboolean res;
59
60   res = g_unix_set_fd_nonblocking (123456, TRUE, &error);
61   g_assert_cmpint (errno, ==, EBADF);
62   g_assert (!res);
63   g_assert_error (error, G_UNIX_ERROR, 0);
64   g_clear_error (&error);
65 }
66
67 static gboolean sig_received = FALSE;
68 static gboolean sig_timeout = FALSE;
69 static int sig_counter = 0;
70
71 static gboolean
72 on_sig_received (gpointer user_data)
73 {
74   GMainLoop *loop = user_data;
75   g_main_loop_quit (loop);
76   sig_received = TRUE;
77   sig_counter ++;
78   return G_SOURCE_REMOVE;
79 }
80
81 static gboolean
82 on_sig_timeout (gpointer data)
83 {
84   GMainLoop *loop = data;
85   g_main_loop_quit (loop);
86   sig_timeout = TRUE;
87   return G_SOURCE_REMOVE;
88 }
89
90 static gboolean
91 exit_mainloop (gpointer data)
92 {
93   GMainLoop *loop = data;
94   g_main_loop_quit (loop);
95   return G_SOURCE_REMOVE;
96 }
97
98 static gboolean
99 on_sig_received_2 (gpointer data)
100 {
101   GMainLoop *loop = data;
102
103   sig_counter ++;
104   if (sig_counter == 2)
105     g_main_loop_quit (loop);
106   return G_SOURCE_REMOVE;
107 }
108
109 static void
110 test_signal (int signum)
111 {
112   GMainLoop *mainloop;
113   int id;
114
115   mainloop = g_main_loop_new (NULL, FALSE);
116
117   sig_received = FALSE;
118   sig_counter = 0;
119   g_unix_signal_add (signum, on_sig_received, mainloop);
120   kill (getpid (), signum);
121   g_assert (!sig_received);
122   id = g_timeout_add (5000, on_sig_timeout, mainloop);
123   g_main_loop_run (mainloop);
124   g_assert (sig_received);
125   sig_received = FALSE;
126   g_source_remove (id);
127
128   /* Ensure we don't get double delivery */
129   g_timeout_add (500, exit_mainloop, mainloop);
130   g_main_loop_run (mainloop);
131   g_assert (!sig_received);
132
133   /* Ensure that two sources for the same signal get it */
134   sig_counter = 0;
135   g_unix_signal_add (signum, on_sig_received_2, mainloop);
136   g_unix_signal_add (signum, on_sig_received_2, mainloop);
137   id = g_timeout_add (5000, on_sig_timeout, mainloop);
138
139   kill (getpid (), signum);
140   g_main_loop_run (mainloop);
141   g_assert_cmpint (sig_counter, ==, 2);
142   g_source_remove (id);
143
144   g_main_loop_unref (mainloop);
145 }
146
147 static void
148 test_sighup (void)
149 {
150   test_signal (SIGHUP);
151 }
152
153 static void
154 test_sigterm (void)
155 {
156   test_signal (SIGTERM);
157 }
158
159 static void
160 test_sighup_add_remove (void)
161 {
162   guint id;
163   struct sigaction action;
164
165   sig_received = FALSE;
166   id = g_unix_signal_add (SIGHUP, on_sig_received, NULL);
167   g_source_remove (id);
168
169   sigaction (SIGHUP, NULL, &action);
170   g_assert (action.sa_handler == SIG_DFL);
171 }
172
173 static gboolean
174 nested_idle (gpointer data)
175 {
176   GMainLoop *nested;
177   GMainContext *context;
178   GSource *source;
179
180   context = g_main_context_new ();
181   nested = g_main_loop_new (context, FALSE);
182
183   source = g_unix_signal_source_new (SIGHUP);
184   g_source_set_callback (source, on_sig_received, nested, NULL);
185   g_source_attach (source, context);
186   g_source_unref (source);
187
188   kill (getpid (), SIGHUP);
189   g_main_loop_run (nested);
190   g_assert_cmpint (sig_counter, ==, 1);
191
192   g_main_loop_unref (nested);
193   g_main_context_unref (context);
194
195   return G_SOURCE_REMOVE;
196 }
197
198 static void
199 test_sighup_nested (void)
200 {
201   GMainLoop *mainloop;
202
203   mainloop = g_main_loop_new (NULL, FALSE);
204
205   sig_counter = 0;
206   sig_received = FALSE;
207   g_unix_signal_add (SIGHUP, on_sig_received, mainloop);
208   g_idle_add (nested_idle, mainloop);
209
210   g_main_loop_run (mainloop);
211   g_assert_cmpint (sig_counter, ==, 2);
212
213   g_main_loop_unref (mainloop);
214 }
215
216 int
217 main (int   argc,
218       char *argv[])
219 {
220   g_test_init (&argc, &argv, NULL);
221
222   g_test_add_func ("/glib-unix/pipe", test_pipe);
223   g_test_add_func ("/glib-unix/error", test_error);
224   g_test_add_func ("/glib-unix/sighup", test_sighup);
225   g_test_add_func ("/glib-unix/sigterm", test_sigterm);
226   g_test_add_func ("/glib-unix/sighup_again", test_sighup);
227   g_test_add_func ("/glib-unix/sighup_add_remove", test_sighup_add_remove);
228   g_test_add_func ("/glib-unix/sighup_nested", test_sighup_nested);
229
230   return g_test_run();
231 }