c21b21f13754b961d4d6674019658e5a3fb8ab6d
[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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <signal.h>
23
24 #include "glib.h"
25 #include "gstdio.h"
26
27 #ifdef G_OS_UNIX
28 #include <unistd.h>
29 #endif
30
31 static gchar *dir, *filename, *displayname, *childname;
32
33 static gboolean stop = FALSE;
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 int
98 child_main (int argc, char *argv[])
99 {
100   GMappedFile *map;
101   GMainLoop *loop;
102
103   map = map_or_die (filename, FALSE);
104   
105   loop = g_main_loop_new (NULL, FALSE);
106
107 #ifndef G_OS_WIN32
108   signal (SIGUSR1, handle_usr1);
109 #endif
110   g_idle_add (check_stop, loop);
111   g_main_loop_run (loop);
112
113   write_or_die (childname, 
114                 g_mapped_file_get_contents (map),
115                 g_mapped_file_get_length (map));
116
117   return 0;
118 }
119
120 static void
121 test_mapping (void)
122 {
123   GMappedFile *map;
124
125   write_or_die (filename, "ABC", -1);
126
127   map = map_or_die (filename, FALSE);
128   g_assert (g_mapped_file_get_length (map) == 3);
129   g_mapped_file_free (map);
130
131   map = map_or_die (filename, TRUE);
132   g_assert (g_mapped_file_get_length (map) == 3);
133   g_mapped_file_free (map);
134 }
135
136 static void 
137 test_private (void)
138 {
139   GError *error = NULL;
140   GMappedFile *map;
141   gchar *buffer;
142   gsize len;
143
144   write_or_die (filename, "ABC", -1);
145   map = map_or_die (filename, TRUE);
146
147   buffer = (gchar *)g_mapped_file_get_contents (map);
148   buffer[0] = '1';
149   buffer[1] = '2';
150   buffer[2] = '3';
151   g_mapped_file_free (map);
152
153   if (!g_file_get_contents (filename, &buffer, &len, &error))
154     {
155       g_print ("failed to read '%s': %s\n", 
156                displayname, error->message);
157       exit (1);
158       
159     }
160   g_assert (len == 3);
161   g_assert (strcmp (buffer, "ABC") == 0);
162   g_free (buffer);
163
164 }
165
166 static void
167 test_child_private (gchar *argv0)
168 {
169   GError *error = NULL;
170   GMappedFile *map;
171   gchar *buffer;
172   gsize len;
173   gchar *child_argv[3];
174   GPid  child_pid;
175   
176 #ifdef G_OS_WIN32
177   g_remove ("STOP");
178   g_assert (!g_file_test ("STOP", G_FILE_TEST_EXISTS));
179 #endif
180
181   write_or_die (filename, "ABC", -1);
182   map = map_or_die (filename, TRUE);
183
184   child_argv[0] = argv0;
185   child_argv[1] = "mapchild";
186   child_argv[2] = NULL;
187   if (!g_spawn_async (dir, child_argv, NULL,
188                       0, NULL, NULL, &child_pid, &error))
189     {
190       g_print ("failed to spawn child: %s\n", 
191                error->message);
192       exit (1);            
193     }
194
195   /* give the child some time to set up its mapping */
196   g_usleep (2000000);
197
198   buffer = (gchar *)g_mapped_file_get_contents (map);
199   buffer[0] = '1';
200   buffer[1] = '2';
201   buffer[2] = '3';
202   g_mapped_file_free (map);
203
204 #ifndef G_OS_WIN32
205   kill (child_pid, SIGUSR1);
206 #else
207   g_file_set_contents ("STOP", "Hey there\n", -1, NULL);
208 #endif
209
210   /* give the child some time to write the file */
211   g_usleep (2000000);
212
213   if (!g_file_get_contents (childname, &buffer, &len, &error))
214     {
215       gchar *name;
216
217       name = g_filename_display_name (childname);
218       g_print ("failed to read '%s': %s\n", name, error->message);
219       exit (1);      
220     }
221   g_assert (len == 3);
222   g_assert (strcmp (buffer, "ABC") == 0);
223   g_free (buffer);
224 }
225
226 static int 
227 parent_main (int   argc,
228              char *argv[])
229 {
230   /* test mapping with various flag combinations */
231   test_mapping ();
232
233   /* test private modification */
234   test_private ();
235
236   /* test multiple clients, non-shared */
237   test_child_private (argv[0]);
238
239   return 0;
240 }
241
242 int
243 main (int argc, 
244       char *argv[])
245 {
246   int ret;
247
248   dir = g_get_current_dir ();
249   filename = g_build_filename (dir, "maptest", NULL);
250   displayname = g_filename_display_name (filename);
251   childname = g_build_filename (dir, "mapchild", NULL);
252
253   if (argc > 1)
254     ret = child_main (argc, argv);
255   else 
256     ret = parent_main (argc, argv);
257
258   g_free (childname);
259   g_free (filename);
260   g_free (displayname);
261   g_free (dir);
262
263   return ret;
264 }