Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : * Copyright (C) 2005 Matthias Clasen
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : */
19 : :
20 : : #include <glib.h>
21 : : #include <glib/gstdio.h>
22 : :
23 : : #ifdef G_OS_UNIX
24 : : #include <unistd.h>
25 : : #endif
26 : : #ifdef G_OS_WIN32
27 : : #include <process.h>
28 : : #endif
29 : :
30 : : static gboolean stop = FALSE;
31 : : static gint parent_pid;
32 : :
33 : : /* Passing argc and argv through global variables */
34 : : static char **local_argv;
35 : :
36 : : #ifndef G_OS_WIN32
37 : :
38 : : static void
39 : 3 : handle_usr1 (int signum)
40 : : {
41 : 3 : stop = TRUE;
42 : 3 : }
43 : :
44 : : #endif
45 : :
46 : : static gboolean
47 : 363 : check_stop (gpointer data)
48 : : {
49 : 363 : GMainLoop *loop = data;
50 : :
51 : : #ifdef G_OS_WIN32
52 : : stop = g_file_test ("STOP", G_FILE_TEST_EXISTS);
53 : : #endif
54 : :
55 [ + + ]: 363 : if (stop)
56 : 4 : g_main_loop_quit (loop);
57 : :
58 : 363 : return TRUE;
59 : : }
60 : :
61 : : static void
62 : 4 : write_or_die (const gchar *filename,
63 : : const gchar *contents,
64 : : gssize length)
65 : : {
66 : 4 : GError *error = NULL;
67 : : gboolean result;
68 : :
69 : 4 : result = g_file_set_contents (filename, contents, length, &error);
70 : 4 : g_assert_no_error (error);
71 : 4 : g_assert_true (result);
72 : 4 : }
73 : :
74 : : static GMappedFile *
75 : 5 : map_or_die (const gchar *filename,
76 : : gboolean writable)
77 : : {
78 : 5 : GError *error = NULL;
79 : : GMappedFile *map;
80 : :
81 : 5 : map = g_mapped_file_new (filename, writable, &error);
82 : 5 : g_assert_no_error (error);
83 : 5 : g_assert_nonnull (map);
84 : :
85 : 5 : return map;
86 : : }
87 : :
88 : : static void
89 : 2 : signal_parent (gpointer data)
90 : : {
91 : : #ifndef G_OS_WIN32
92 : 2 : kill (parent_pid, SIGUSR1);
93 : : #endif
94 : 2 : }
95 : :
96 : : static void
97 : 1 : child_main (void)
98 : : {
99 : : GMappedFile *map;
100 : : GMainLoop *loop;
101 : : gchar *dir, *global_filename, *childname;
102 : :
103 : 1 : dir = g_get_current_dir ();
104 : 1 : global_filename = g_build_filename (dir, "maptest", NULL);
105 : 1 : childname = g_build_filename (dir, "mapchild", NULL);
106 : :
107 : 1 : parent_pid = atoi (local_argv[2]);
108 : 1 : map = map_or_die (global_filename, FALSE);
109 : :
110 : : #ifndef G_OS_WIN32
111 : 1 : signal (SIGUSR1, handle_usr1);
112 : : #endif
113 : 1 : loop = g_main_loop_new (NULL, FALSE);
114 : 1 : g_idle_add (check_stop, loop);
115 : 1 : g_idle_add_once (signal_parent, NULL);
116 : 1 : g_main_loop_run (loop);
117 : :
118 : 1 : g_test_message ("test_child_private: received parent signal");
119 : :
120 : 1 : write_or_die (childname,
121 : 1 : g_mapped_file_get_contents (map),
122 : 1 : g_mapped_file_get_length (map));
123 : :
124 : 1 : g_free (childname);
125 : 1 : g_free (global_filename);
126 : 1 : g_free (dir);
127 : :
128 : 1 : signal_parent (NULL);
129 : 1 : }
130 : :
131 : : static void
132 : 1 : test_mapping_flags (void)
133 : : {
134 : : GMappedFile *map;
135 : : gchar *dir, *global_filename;
136 : :
137 : 1 : dir = g_get_current_dir ();
138 : 1 : global_filename = g_build_filename (dir, "maptest", NULL);
139 : :
140 : 1 : write_or_die (global_filename, "ABC", -1);
141 : :
142 : 1 : map = map_or_die (global_filename, FALSE);
143 : 1 : g_assert_cmpint (g_mapped_file_get_length (map), ==, 3);
144 : 1 : g_mapped_file_unref (map);
145 : :
146 : 1 : map = map_or_die (global_filename, TRUE);
147 : 1 : g_assert_cmpint (g_mapped_file_get_length (map), ==, 3);
148 : 1 : g_mapped_file_unref (map);
149 : 1 : g_test_message ("test_mapping: ok");
150 : :
151 : : /* Cleaning left over files */
152 : 1 : g_remove ("maptest");
153 : :
154 : 1 : g_free (global_filename);
155 : 1 : g_free (dir);
156 : 1 : }
157 : :
158 : : static void
159 : 1 : test_private (void)
160 : : {
161 : 1 : GError *error = NULL;
162 : : GMappedFile *map;
163 : : gboolean result;
164 : : gchar *buffer;
165 : : gsize len;
166 : : gchar *dir, *global_filename;
167 : :
168 : 1 : dir = g_get_current_dir ();
169 : 1 : global_filename = g_build_filename (dir, "maptest", NULL);
170 : :
171 : 1 : write_or_die (global_filename, "ABC", -1);
172 : 1 : map = map_or_die (global_filename, TRUE);
173 : :
174 : 1 : buffer = (gchar *)g_mapped_file_get_contents (map);
175 : 1 : buffer[0] = '1';
176 : 1 : buffer[1] = '2';
177 : 1 : buffer[2] = '3';
178 : 1 : g_mapped_file_unref (map);
179 : :
180 : 1 : result = g_file_get_contents (global_filename, &buffer, &len, &error);
181 : 1 : g_assert_no_error (error);
182 : 1 : g_assert_true (result);
183 : 1 : g_assert_cmpint (len, ==, 3);
184 : 1 : g_assert_cmpstr (buffer, ==, "ABC");
185 : 1 : g_free (buffer);
186 : :
187 : 1 : g_free (global_filename);
188 : 1 : g_free (dir);
189 : :
190 : : /* Cleaning left over files */
191 : 1 : g_remove ("maptest");
192 : 1 : }
193 : :
194 : : static void
195 : 1 : test_child_private (void)
196 : : {
197 : 1 : GError *error = NULL;
198 : : GMappedFile *map;
199 : : gboolean result;
200 : : gchar *buffer;
201 : : gsize len;
202 : : gchar *child_argv[4];
203 : : GPid child_pid;
204 : : #ifndef G_OS_WIN32
205 : : GMainLoop *loop;
206 : : #endif
207 : : gchar pid[100];
208 : : gchar *dir, *global_filename, *childname;
209 : :
210 : : #ifdef G_OS_WIN32
211 : : g_remove ("STOP");
212 : : g_assert_false (g_file_test ("STOP", G_FILE_TEST_EXISTS));
213 : : #endif
214 : :
215 : 1 : dir = g_get_current_dir ();
216 : 1 : global_filename = g_build_filename (dir, "maptest", NULL);
217 : 1 : childname = g_build_filename (dir, "mapchild", NULL);
218 : :
219 : 1 : write_or_die (global_filename, "ABC", -1);
220 : 1 : map = map_or_die (global_filename, TRUE);
221 : :
222 : : #ifndef G_OS_WIN32
223 : 1 : signal (SIGUSR1, handle_usr1);
224 : : #endif
225 : :
226 : 1 : g_snprintf (pid, sizeof(pid), "%d", getpid ());
227 : 1 : child_argv[0] = local_argv[0];
228 : 1 : child_argv[1] = "mapchild";
229 : 1 : child_argv[2] = pid;
230 : 1 : child_argv[3] = NULL;
231 : :
232 : 1 : result = g_spawn_async (dir, child_argv, NULL,
233 : : 0, NULL, NULL, &child_pid, &error);
234 : 1 : g_assert_no_error (error);
235 : 1 : g_assert_true (result);
236 : 1 : g_test_message ("test_child_private: child spawned");
237 : :
238 : : #ifndef G_OS_WIN32
239 : 1 : loop = g_main_loop_new (NULL, FALSE);
240 : 1 : g_idle_add (check_stop, loop);
241 : 1 : g_main_loop_run (loop);
242 : 1 : stop = FALSE;
243 : : #else
244 : : g_usleep (2000000);
245 : : #endif
246 : :
247 : 1 : g_test_message ("test_child_private: received first child signal");
248 : :
249 : 1 : buffer = (gchar *)g_mapped_file_get_contents (map);
250 : 1 : buffer[0] = '1';
251 : 1 : buffer[1] = '2';
252 : 1 : buffer[2] = '3';
253 : 1 : g_mapped_file_unref (map);
254 : :
255 : : #ifndef G_OS_WIN32
256 : 1 : kill (child_pid, SIGUSR1);
257 : : #else
258 : : g_file_set_contents ("STOP", "Hey there\n", -1, NULL);
259 : : #endif
260 : :
261 : : #ifndef G_OS_WIN32
262 : 1 : g_idle_add (check_stop, loop);
263 : 1 : g_main_loop_run (loop);
264 : : #else
265 : : g_usleep (2000000);
266 : : #endif
267 : :
268 : 1 : g_test_message ("test_child_private: received second child signal");
269 : :
270 : 1 : result = g_file_get_contents (childname, &buffer, &len, &error);
271 : 1 : g_assert_no_error (error);
272 : 1 : g_assert_true (result);
273 : 1 : g_assert_cmpint (len, ==, 3);
274 : 1 : g_assert_cmpstr (buffer, ==, "ABC");
275 : 1 : g_free (buffer);
276 : :
277 : 1 : g_free (childname);
278 : 1 : g_free (global_filename);
279 : 1 : g_free (dir);
280 : :
281 : : /* Cleaning left over files */
282 : 1 : g_remove ("mapchild");
283 : 1 : g_remove ("maptest");
284 : 1 : }
285 : :
286 : : int
287 : 2 : main (int argc,
288 : : char *argv[])
289 : : {
290 : : #ifndef G_OS_WIN32
291 : : sigset_t sig_mask, old_mask;
292 : :
293 : 2 : sigemptyset (&sig_mask);
294 : 2 : sigaddset (&sig_mask, SIGUSR1);
295 [ + - ]: 2 : if (sigprocmask (SIG_UNBLOCK, &sig_mask, &old_mask) == 0)
296 : : {
297 [ - + ]: 2 : if (sigismember (&old_mask, SIGUSR1))
298 : 0 : g_test_message ("SIGUSR1 was blocked, unblocking it");
299 : : }
300 : : #endif
301 : :
302 : 2 : g_test_init (&argc, &argv, NULL);
303 : 2 : local_argv = argv;
304 : :
305 [ + + ]: 2 : if (argc > 1)
306 : : {
307 : 1 : child_main ();
308 : 1 : return EXIT_SUCCESS;
309 : : }
310 : :
311 : 1 : g_test_add_func ("/mapping/flags", test_mapping_flags);
312 : 1 : g_test_add_func ("/mapping/private", test_private);
313 : 1 : g_test_add_func ("/mapping/private-child", test_child_private);
314 : :
315 : 1 : return g_test_run ();
316 : : }
|