mapping-test.c revision 748c2302056a6f447aa2aac4a181d42281624bdd
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
28static gchar *dir, *filename, *displayname, *childname;
29
30static gboolean stop = FALSE;
31
32static void
33handle_usr1 (int signum)
34{
35  stop = TRUE;
36}
37
38static gboolean
39check_stop (gpointer data)
40{
41  GMainLoop *loop = data;
42
43  if (stop)
44    g_main_loop_quit (loop);
45
46  return TRUE;
47}
48
49static void
50write_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
66static GMappedFile *
67map_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
86static int
87child_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
107static void
108test_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
123static void
124test_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
153static void
154test_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
204static int
205parent_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
220int
221main (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}
234