Add an mmap() wrapper called GMappedFile. (#148218, David Schleef, Behdad
[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
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <signal.h>
25
26 #include "glib.h"
27
28 static gchar *dir, *filename, *displayname, *childname;
29
30 static gboolean stop = FALSE;
31
32 static void
33 handle_usr1 (int signum)
34 {
35   stop = TRUE;
36 }
37
38 static gboolean
39 check_stop (gpointer data)
40 {
41   GMainLoop *loop = data;
42
43   if (stop)
44     g_main_loop_quit (loop);
45
46   return TRUE;
47 }
48
49 static void
50 write_or_die (const gchar *filename,
51               const gchar *contents,
52               gssize       length)
53 {
54   GError *error = NULL;
55   gchar *displayname;    
56
57   if (!g_file_set_contents (filename, contents, length, &error)) 
58     {
59       displayname = g_filename_display_name (childname);
60       g_print ("failed to write '%s': %s\n", 
61                displayname, error->message);
62       exit (1);
63     }
64 }
65
66 static GMappedFile *
67 map_or_die (const gchar *filename,
68             gboolean     writable)
69 {
70   GError *error = NULL;
71   GMappedFile *map;
72   gchar *displayname;
73
74   map = g_mapped_file_new (filename, writable, &error);
75   if (!map)
76     {
77       displayname = g_filename_display_name (childname);
78       g_print ("failed to map '%s' non-writable, shared: %s\n", 
79                displayname, error->message);
80       exit (1);
81     }
82
83   return map;
84 }
85             
86 static int
87 child_main (int argc, char *argv[])
88 {
89   GMappedFile *map;
90   GMainLoop *loop;
91
92   map = map_or_die (filename, FALSE);
93   
94   loop = g_main_loop_new (NULL, FALSE);
95
96   signal (SIGUSR1, handle_usr1);
97   g_idle_add (check_stop, loop);
98   g_main_loop_run (loop);
99
100   write_or_die (childname, 
101                 g_mapped_file_get_contents (map),
102                 g_mapped_file_get_length (map));
103
104   return 0;
105 }
106
107 static void
108 test_mapping (void)
109 {
110   GMappedFile *map;
111
112   write_or_die (filename, "ABC", -1);
113
114   map = map_or_die (filename, FALSE);
115   g_assert (g_mapped_file_get_length (map) == 3);
116   g_mapped_file_free (map);
117
118   map = map_or_die (filename, TRUE);
119   g_assert (g_mapped_file_get_length (map) == 3);
120   g_mapped_file_free (map);
121 }
122
123 static void 
124 test_private (void)
125 {
126   GError *error = NULL;
127   GMappedFile *map;
128   gchar *buffer;
129   gsize len;
130
131   write_or_die (filename, "ABC", -1);
132   map = map_or_die (filename, TRUE);
133
134   buffer = (gchar *)g_mapped_file_get_contents (map);
135   buffer[0] = '1';
136   buffer[1] = '2';
137   buffer[2] = '3';
138   g_mapped_file_free (map);
139
140   if (!g_file_get_contents (filename, &buffer, &len, &error))
141     {
142       g_print ("failed to read '%s': %s\n", 
143                displayname, error->message);
144       exit (1);
145       
146     }
147   g_assert (len == 3);
148   g_assert (strcmp (buffer, "ABC") == 0);
149   g_free (buffer);
150
151 }
152
153 static void
154 test_child_private (gchar *argv0)
155 {
156   GError *error = NULL;
157   GMappedFile *map;
158   gchar *buffer;
159   gsize len;
160   gchar *child_argv[3];
161   GPid  child_pid;
162   
163   write_or_die (filename, "ABC", -1);
164   map = map_or_die (filename, TRUE);
165
166   child_argv[0] = argv0;
167   child_argv[1] = "mapchild";
168   child_argv[2] = NULL;
169   if (!g_spawn_async (dir, child_argv, NULL,
170                       0, NULL, NULL, &child_pid, &error))
171     {
172       g_print ("failed to spawn child: %s\n", 
173                error->message);
174       exit (1);            
175     }
176
177   /* give the child some time to set up its mapping */
178   sleep (2);
179
180   buffer = (gchar *)g_mapped_file_get_contents (map);
181   buffer[0] = '1';
182   buffer[1] = '2';
183   buffer[2] = '3';
184   g_mapped_file_free (map);
185
186   kill (child_pid, SIGUSR1);
187
188   /* give the child some time to write the file */
189   sleep (2);
190
191   if (!g_file_get_contents (childname, &buffer, &len, &error))
192     {
193       gchar *name;
194
195       name = g_filename_display_name (childname);
196       g_print ("failed to read '%s': %s\n", name, error->message);
197       exit (1);      
198     }
199   g_assert (len == 3);
200   g_assert (strcmp (buffer, "ABC") == 0);
201   g_free (buffer);
202 }
203
204 static int 
205 parent_main (int   argc,
206              char *argv[])
207 {
208   /* test mapping with various flag combinations */
209   test_mapping ();
210
211   /* test private modification */
212   test_private ();
213
214   /* test multiple clients, non-shared */
215   test_child_private (argv[0]);
216
217   return 0;
218 }
219
220 int
221 main (int argc, 
222       char *argv[])
223 {
224   dir = g_get_current_dir ();
225   filename = g_build_filename (dir, "maptest", NULL);
226   displayname = g_filename_display_name (filename);
227   childname = g_build_filename (dir, "mapchild", NULL);
228
229   if (argc > 1)
230     return child_main (argc, argv);
231   else 
232     return parent_main (argc, argv);
233 }