Merge branch 'test-ip_mreq_source-android-only' into 'master'
[glib.git] / tests / mapping-test.c
blob3eb90fa483335778a51def875f54a606ef35d587
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 2005 Matthias Clasen
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <signal.h>
22 #include "glib.h"
23 #include "gstdio.h"
25 #ifdef G_OS_UNIX
26 #include <unistd.h>
27 #endif
29 static gchar *dir, *filename, *displayname, *childname;
31 static gboolean stop = FALSE;
33 static gint parent_pid;
35 #ifndef G_OS_WIN32
37 static void
38 handle_usr1 (int signum)
40 stop = TRUE;
43 #endif
45 static gboolean
46 check_stop (gpointer data)
48 GMainLoop *loop = data;
50 #ifdef G_OS_WIN32
51 stop = g_file_test ("STOP", G_FILE_TEST_EXISTS);
52 #endif
54 if (stop)
55 g_main_loop_quit (loop);
57 return TRUE;
60 static void
61 write_or_die (const gchar *filename,
62 const gchar *contents,
63 gssize length)
65 GError *error = NULL;
66 gchar *displayname;
68 if (!g_file_set_contents (filename, contents, length, &error))
70 displayname = g_filename_display_name (childname);
71 g_print ("failed to write '%s': %s\n",
72 displayname, error->message);
73 exit (1);
77 static GMappedFile *
78 map_or_die (const gchar *filename,
79 gboolean writable)
81 GError *error = NULL;
82 GMappedFile *map;
83 gchar *displayname;
85 map = g_mapped_file_new (filename, writable, &error);
86 if (!map)
88 displayname = g_filename_display_name (childname);
89 g_print ("failed to map '%s' non-writable, shared: %s\n",
90 displayname, error->message);
91 exit (1);
94 return map;
97 static gboolean
98 signal_parent (gpointer data)
100 #ifndef G_OS_WIN32
101 kill (parent_pid, SIGUSR1);
102 #endif
103 return G_SOURCE_REMOVE;
106 static int
107 child_main (int argc, char *argv[])
109 GMappedFile *map;
110 GMainLoop *loop;
112 parent_pid = atoi (argv[2]);
113 map = map_or_die (filename, FALSE);
115 #ifndef G_OS_WIN32
116 signal (SIGUSR1, handle_usr1);
117 #endif
118 loop = g_main_loop_new (NULL, FALSE);
119 g_idle_add (check_stop, loop);
120 g_idle_add (signal_parent, NULL);
121 g_main_loop_run (loop);
123 g_message ("test_child_private: received parent signal");
125 write_or_die (childname,
126 g_mapped_file_get_contents (map),
127 g_mapped_file_get_length (map));
129 signal_parent (NULL);
131 return 0;
134 static void
135 test_mapping (void)
137 GMappedFile *map;
139 write_or_die (filename, "ABC", -1);
141 map = map_or_die (filename, FALSE);
142 g_assert (g_mapped_file_get_length (map) == 3);
143 g_mapped_file_free (map);
145 map = map_or_die (filename, TRUE);
146 g_assert (g_mapped_file_get_length (map) == 3);
147 g_mapped_file_free (map);
148 g_message ("test_mapping: ok");
151 static void
152 test_private (void)
154 GError *error = NULL;
155 GMappedFile *map;
156 gchar *buffer;
157 gsize len;
159 write_or_die (filename, "ABC", -1);
160 map = map_or_die (filename, TRUE);
162 buffer = (gchar *)g_mapped_file_get_contents (map);
163 buffer[0] = '1';
164 buffer[1] = '2';
165 buffer[2] = '3';
166 g_mapped_file_free (map);
168 if (!g_file_get_contents (filename, &buffer, &len, &error))
170 g_print ("failed to read '%s': %s\n",
171 displayname, error->message);
172 exit (1);
175 g_assert (len == 3);
176 g_assert (strcmp (buffer, "ABC") == 0);
177 g_free (buffer);
179 g_message ("test_private: ok");
182 static void
183 test_child_private (gchar *argv0)
185 GError *error = NULL;
186 GMappedFile *map;
187 gchar *buffer;
188 gsize len;
189 gchar *child_argv[4];
190 GPid child_pid;
191 GMainLoop *loop;
192 gchar pid[100];
194 #ifdef G_OS_WIN32
195 g_remove ("STOP");
196 g_assert (!g_file_test ("STOP", G_FILE_TEST_EXISTS));
197 #endif
199 write_or_die (filename, "ABC", -1);
200 map = map_or_die (filename, TRUE);
202 #ifndef G_OS_WIN32
203 signal (SIGUSR1, handle_usr1);
204 #endif
206 g_snprintf (pid, sizeof(pid), "%d", getpid ());
207 child_argv[0] = argv0;
208 child_argv[1] = "mapchild";
209 child_argv[2] = pid;
210 child_argv[3] = NULL;
211 if (!g_spawn_async (dir, child_argv, NULL,
212 0, NULL, NULL, &child_pid, &error))
214 g_print ("failed to spawn child: %s\n",
215 error->message);
216 exit (1);
218 g_message ("test_child_private: child spawned");
220 #ifndef G_OS_WIN32
221 loop = g_main_loop_new (NULL, FALSE);
222 g_idle_add (check_stop, loop);
223 g_main_loop_run (loop);
224 stop = FALSE;
225 #else
226 g_usleep (2000000);
227 #endif
229 g_message ("test_child_private: received first child signal");
231 buffer = (gchar *)g_mapped_file_get_contents (map);
232 buffer[0] = '1';
233 buffer[1] = '2';
234 buffer[2] = '3';
235 g_mapped_file_free (map);
237 #ifndef G_OS_WIN32
238 kill (child_pid, SIGUSR1);
239 #else
240 g_file_set_contents ("STOP", "Hey there\n", -1, NULL);
241 #endif
243 #ifndef G_OS_WIN32
244 g_idle_add (check_stop, loop);
245 g_main_loop_run (loop);
246 #else
247 g_usleep (2000000);
248 #endif
250 g_message ("test_child_private: received second child signal");
252 if (!g_file_get_contents (childname, &buffer, &len, &error))
254 gchar *name;
256 name = g_filename_display_name (childname);
257 g_print ("failed to read '%s': %s\n", name, error->message);
258 exit (1);
260 g_assert (len == 3);
261 g_assert (strcmp (buffer, "ABC") == 0);
262 g_free (buffer);
264 g_message ("test_child_private: ok");
267 static int
268 parent_main (int argc,
269 char *argv[])
271 /* test mapping with various flag combinations */
272 test_mapping ();
274 /* test private modification */
275 test_private ();
277 /* test multiple clients, non-shared */
278 test_child_private (argv[0]);
280 return 0;
284 main (int argc,
285 char *argv[])
287 int ret;
288 #ifndef G_OS_WIN32
289 sigset_t sig_mask, old_mask;
291 sigemptyset (&sig_mask);
292 sigaddset (&sig_mask, SIGUSR1);
293 if (sigprocmask (SIG_UNBLOCK, &sig_mask, &old_mask) == 0)
295 if (sigismember (&old_mask, SIGUSR1))
296 g_message ("SIGUSR1 was blocked, unblocking it");
298 #endif
300 dir = g_get_current_dir ();
301 filename = g_build_filename (dir, "maptest", NULL);
302 displayname = g_filename_display_name (filename);
303 childname = g_build_filename (dir, "mapchild", NULL);
305 if (argc > 1)
306 ret = child_main (argc, argv);
307 else
308 ret = parent_main (argc, argv);
310 g_free (childname);
311 g_free (filename);
312 g_free (displayname);
313 g_free (dir);
315 return ret;