Try to fix mapping-test
[platform/upstream/glib.git] / tests / mapping-test.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 2005 Matthias Clasen
3  *
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 of the License, or (at your option) any later version.
8  *
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.
13  *
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/>.
16  */
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <signal.h>
21
22 #include "glib.h"
23 #include "gstdio.h"
24
25 #ifdef G_OS_UNIX
26 #include <unistd.h>
27 #endif
28
29 static gchar *dir, *filename, *displayname, *childname;
30
31 static gboolean stop = FALSE;
32
33 static gint parent_pid;
34
35 #ifndef G_OS_WIN32
36
37 static void
38 handle_usr1 (int signum)
39 {
40   stop = TRUE;
41 }
42
43 #endif
44
45 static gboolean
46 check_stop (gpointer data)
47 {
48   GMainLoop *loop = data;
49
50 #ifdef G_OS_WIN32
51   stop = g_file_test ("STOP", G_FILE_TEST_EXISTS);
52 #endif
53
54   if (stop)
55     g_main_loop_quit (loop);
56
57   return TRUE;
58 }
59
60 static void
61 write_or_die (const gchar *filename,
62               const gchar *contents,
63               gssize       length)
64 {
65   GError *error = NULL;
66   gchar *displayname;    
67
68   if (!g_file_set_contents (filename, contents, length, &error)) 
69     {
70       displayname = g_filename_display_name (childname);
71       g_print ("failed to write '%s': %s\n", 
72                displayname, error->message);
73       exit (1);
74     }
75 }
76
77 static GMappedFile *
78 map_or_die (const gchar *filename,
79             gboolean     writable)
80 {
81   GError *error = NULL;
82   GMappedFile *map;
83   gchar *displayname;
84
85   map = g_mapped_file_new (filename, writable, &error);
86   if (!map)
87     {
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);
92     }
93
94   return map;
95 }
96     
97 static gboolean
98 signal_parent (gpointer data)
99 {
100 #ifndef G_OS_WIN32
101   kill (parent_pid, SIGUSR1);
102 #endif
103   return G_SOURCE_REMOVE;
104 }
105
106 static int
107 child_main (int argc, char *argv[])
108 {
109   GMappedFile *map;
110   GMainLoop *loop;
111
112   parent_pid = atoi (argv[2]);
113   map = map_or_die (filename, FALSE);
114
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);
122
123   write_or_die (childname, 
124                 g_mapped_file_get_contents (map),
125                 g_mapped_file_get_length (map));
126
127   signal_parent (NULL);
128
129   return 0;
130 }
131
132 static void
133 test_mapping (void)
134 {
135   GMappedFile *map;
136
137   write_or_die (filename, "ABC", -1);
138
139   map = map_or_die (filename, FALSE);
140   g_assert (g_mapped_file_get_length (map) == 3);
141   g_mapped_file_free (map);
142
143   map = map_or_die (filename, TRUE);
144   g_assert (g_mapped_file_get_length (map) == 3);
145   g_mapped_file_free (map);
146 }
147
148 static void 
149 test_private (void)
150 {
151   GError *error = NULL;
152   GMappedFile *map;
153   gchar *buffer;
154   gsize len;
155
156   write_or_die (filename, "ABC", -1);
157   map = map_or_die (filename, TRUE);
158
159   buffer = (gchar *)g_mapped_file_get_contents (map);
160   buffer[0] = '1';
161   buffer[1] = '2';
162   buffer[2] = '3';
163   g_mapped_file_free (map);
164
165   if (!g_file_get_contents (filename, &buffer, &len, &error))
166     {
167       g_print ("failed to read '%s': %s\n", 
168                displayname, error->message);
169       exit (1);
170       
171     }
172   g_assert (len == 3);
173   g_assert (strcmp (buffer, "ABC") == 0);
174   g_free (buffer);
175
176 }
177
178 static void
179 test_child_private (gchar *argv0)
180 {
181   GError *error = NULL;
182   GMappedFile *map;
183   gchar *buffer;
184   gsize len;
185   gchar *child_argv[4];
186   GPid  child_pid;
187   GMainLoop *loop;
188   gchar pid[100];
189   
190 #ifdef G_OS_WIN32
191   g_remove ("STOP");
192   g_assert (!g_file_test ("STOP", G_FILE_TEST_EXISTS));
193 #endif
194
195   write_or_die (filename, "ABC", -1);
196   map = map_or_die (filename, TRUE);
197
198 #ifndef G_OS_WIN32
199   signal (SIGUSR1, handle_usr1);
200 #endif
201
202   g_snprintf (pid, sizeof(pid), "%d", getpid ());
203   child_argv[0] = argv0;
204   child_argv[1] = "mapchild";
205   child_argv[2] = pid;
206   child_argv[3] = NULL;
207   if (!g_spawn_async (dir, child_argv, NULL,
208                       0, NULL, NULL, &child_pid, &error))
209     {
210       g_print ("failed to spawn child: %s\n", 
211                error->message);
212       exit (1);            
213     }
214
215 #ifndef G_OS_WIN32
216   loop = g_main_loop_new (NULL, FALSE);
217   g_idle_add (check_stop, loop);
218   g_main_loop_run (loop);
219   stop = FALSE;
220 #else
221   g_usleep (2000000);
222 #endif
223
224   buffer = (gchar *)g_mapped_file_get_contents (map);
225   buffer[0] = '1';
226   buffer[1] = '2';
227   buffer[2] = '3';
228   g_mapped_file_free (map);
229
230 #ifndef G_OS_WIN32
231   kill (child_pid, SIGUSR1);
232 #else
233   g_file_set_contents ("STOP", "Hey there\n", -1, NULL);
234 #endif
235
236 #ifndef G_OS_WIN32
237   g_idle_add (check_stop, loop);
238   g_main_loop_run (loop);
239 #else
240   g_usleep (2000000);
241 #endif
242
243   if (!g_file_get_contents (childname, &buffer, &len, &error))
244     {
245       gchar *name;
246
247       name = g_filename_display_name (childname);
248       g_print ("failed to read '%s': %s\n", name, error->message);
249       exit (1);      
250     }
251   g_assert (len == 3);
252   g_assert (strcmp (buffer, "ABC") == 0);
253   g_free (buffer);
254 }
255
256 static int 
257 parent_main (int   argc,
258              char *argv[])
259 {
260   /* test mapping with various flag combinations */
261   test_mapping ();
262
263   /* test private modification */
264   test_private ();
265
266   /* test multiple clients, non-shared */
267   test_child_private (argv[0]);
268
269   return 0;
270 }
271
272 int
273 main (int argc, 
274       char *argv[])
275 {
276   int ret;
277
278   dir = g_get_current_dir ();
279   filename = g_build_filename (dir, "maptest", NULL);
280   displayname = g_filename_display_name (filename);
281   childname = g_build_filename (dir, "mapchild", NULL);
282
283   if (argc > 1)
284     ret = child_main (argc, argv);
285   else 
286     ret = parent_main (argc, argv);
287
288   g_free (childname);
289   g_free (filename);
290   g_free (displayname);
291   g_free (dir);
292
293   return ret;
294 }