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