(root)/
glib-2.79.0/
glib/
tests/
mapping.c
       1  /* GLIB - Library of useful routines for C programming
       2   * Copyright (C) 2005 Matthias Clasen
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public
      17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   */
      19  
      20  #include <glib.h>
      21  #include <glib/gstdio.h>
      22  
      23  #ifdef G_OS_UNIX
      24  #include <unistd.h>
      25  #endif
      26  #ifdef G_OS_WIN32
      27  #include <process.h>
      28  #endif
      29  
      30  static gboolean stop = FALSE;
      31  static gint parent_pid;
      32  
      33  /* Passing argc and argv through global variables */
      34  static char **local_argv;
      35  
      36  #ifndef G_OS_WIN32
      37  
      38  static void
      39  handle_usr1 (int signum)
      40  {
      41    stop = TRUE;
      42  }
      43  
      44  #endif
      45  
      46  static gboolean
      47  check_stop (gpointer data)
      48  {
      49    GMainLoop *loop = data;
      50  
      51  #ifdef G_OS_WIN32
      52    stop = g_file_test ("STOP", G_FILE_TEST_EXISTS);
      53  #endif
      54  
      55    if (stop)
      56      g_main_loop_quit (loop);
      57  
      58    return TRUE;
      59  }
      60  
      61  static void
      62  write_or_die (const gchar *filename,
      63  	      const gchar *contents,
      64  	      gssize       length)
      65  {
      66    GError *error = NULL;
      67    gboolean result;
      68  
      69    result = g_file_set_contents (filename, contents, length, &error);
      70    g_assert_no_error (error);
      71    g_assert_true (result);
      72  }
      73  
      74  static GMappedFile *
      75  map_or_die (const gchar *filename,
      76  	    gboolean     writable)
      77  {
      78    GError *error = NULL;
      79    GMappedFile *map;
      80  
      81    map = g_mapped_file_new (filename, writable, &error);
      82    g_assert_no_error (error);
      83    g_assert_nonnull (map);
      84  
      85    return map;
      86  }
      87  
      88  static void
      89  signal_parent (gpointer data)
      90  {
      91  #ifndef G_OS_WIN32
      92    kill (parent_pid, SIGUSR1);
      93  #endif
      94  }
      95  
      96  static void
      97  child_main (void)
      98  {
      99    GMappedFile *map;
     100    GMainLoop *loop;
     101    gchar *dir, *global_filename, *childname;
     102  
     103    dir = g_get_current_dir ();
     104    global_filename = g_build_filename (dir, "maptest", NULL);
     105    childname = g_build_filename (dir, "mapchild", NULL);
     106  
     107    parent_pid = atoi (local_argv[2]);
     108    map = map_or_die (global_filename, FALSE);
     109  
     110  #ifndef G_OS_WIN32
     111    signal (SIGUSR1, handle_usr1);
     112  #endif
     113    loop = g_main_loop_new (NULL, FALSE);
     114    g_idle_add (check_stop, loop);
     115    g_idle_add_once (signal_parent, NULL);
     116    g_main_loop_run (loop);
     117  
     118    g_test_message ("test_child_private: received parent signal");
     119  
     120    write_or_die (childname,
     121                  g_mapped_file_get_contents (map),
     122                  g_mapped_file_get_length (map));
     123  
     124    g_free (childname);
     125    g_free (global_filename);
     126    g_free (dir);
     127  
     128    signal_parent (NULL);
     129  }
     130  
     131  static void
     132  test_mapping_flags (void)
     133  {
     134    GMappedFile *map;
     135    gchar *dir, *global_filename;
     136  
     137   dir = g_get_current_dir ();
     138    global_filename = g_build_filename (dir, "maptest", NULL);
     139  
     140    write_or_die (global_filename, "ABC", -1);
     141  
     142    map = map_or_die (global_filename, FALSE);
     143    g_assert_cmpint (g_mapped_file_get_length (map), ==, 3);
     144    g_mapped_file_unref (map);
     145  
     146    map = map_or_die (global_filename, TRUE);
     147    g_assert_cmpint (g_mapped_file_get_length (map), ==, 3);
     148    g_mapped_file_unref (map);
     149    g_test_message ("test_mapping: ok");
     150  
     151    /* Cleaning left over files */
     152    g_remove ("maptest");
     153  
     154    g_free (global_filename);
     155    g_free (dir);
     156  }
     157  
     158  static void
     159  test_private (void)
     160  {
     161    GError *error = NULL;
     162    GMappedFile *map;
     163    gboolean result;
     164    gchar *buffer;
     165    gsize len;
     166    gchar *dir, *global_filename;
     167  
     168    dir = g_get_current_dir ();
     169    global_filename = g_build_filename (dir, "maptest", NULL);
     170  
     171    write_or_die (global_filename, "ABC", -1);
     172    map = map_or_die (global_filename, TRUE);
     173  
     174    buffer = (gchar *)g_mapped_file_get_contents (map);
     175    buffer[0] = '1';
     176    buffer[1] = '2';
     177    buffer[2] = '3';
     178    g_mapped_file_unref (map);
     179  
     180    result = g_file_get_contents (global_filename, &buffer, &len, &error);
     181    g_assert_no_error (error);
     182    g_assert_true (result);
     183    g_assert_cmpint (len, ==, 3);
     184    g_assert_cmpstr (buffer, ==, "ABC");
     185    g_free (buffer);
     186  
     187    g_free (global_filename);
     188    g_free (dir);
     189  
     190    /* Cleaning left over files */
     191    g_remove ("maptest");
     192  
     193    g_test_message ("test_private: ok");
     194  }
     195  
     196  static void
     197  test_child_private (void)
     198  {
     199    GError *error = NULL;
     200    GMappedFile *map;
     201    gboolean result;
     202    gchar *buffer;
     203    gsize len;
     204    gchar *child_argv[4];
     205    GPid  child_pid;
     206  #ifndef G_OS_WIN32
     207    GMainLoop *loop;
     208  #endif
     209    gchar pid[100];
     210    gchar *dir, *global_filename, *childname;
     211  
     212  #ifdef G_OS_WIN32
     213    g_remove ("STOP");
     214    g_assert_false (g_file_test ("STOP", G_FILE_TEST_EXISTS));
     215  #endif
     216  
     217    dir = g_get_current_dir ();
     218    global_filename = g_build_filename (dir, "maptest", NULL);
     219    childname = g_build_filename (dir, "mapchild", NULL);
     220  
     221    write_or_die (global_filename, "ABC", -1);
     222    map = map_or_die (global_filename, TRUE);
     223  
     224  #ifndef G_OS_WIN32
     225    signal (SIGUSR1, handle_usr1);
     226  #endif
     227  
     228    g_snprintf (pid, sizeof(pid), "%d", getpid ());
     229    child_argv[0] = local_argv[0];
     230    child_argv[1] = "mapchild";
     231    child_argv[2] = pid;
     232    child_argv[3] = NULL;
     233  
     234    result = g_spawn_async (dir, child_argv, NULL,
     235                            0, NULL, NULL, &child_pid, &error);
     236    g_assert_no_error (error);
     237    g_assert_true (result);
     238    g_test_message ("test_child_private: child spawned");
     239  
     240  #ifndef G_OS_WIN32
     241    loop = g_main_loop_new (NULL, FALSE);
     242    g_idle_add (check_stop, loop);
     243    g_main_loop_run (loop);
     244    stop = FALSE;
     245  #else
     246    g_usleep (2000000);
     247  #endif
     248  
     249    g_test_message ("test_child_private: received first child signal");
     250  
     251    buffer = (gchar *)g_mapped_file_get_contents (map);
     252    buffer[0] = '1';
     253    buffer[1] = '2';
     254    buffer[2] = '3';
     255    g_mapped_file_unref (map);
     256  
     257  #ifndef G_OS_WIN32
     258    kill (child_pid, SIGUSR1);
     259  #else
     260    g_file_set_contents ("STOP", "Hey there\n", -1, NULL);
     261  #endif
     262  
     263  #ifndef G_OS_WIN32
     264    g_idle_add (check_stop, loop);
     265    g_main_loop_run (loop);
     266  #else
     267    g_usleep (2000000);
     268  #endif
     269  
     270    g_test_message ("test_child_private: received second child signal");
     271  
     272    result = g_file_get_contents (childname, &buffer, &len, &error);
     273    g_assert_no_error (error);
     274    g_assert_true (result);
     275    g_assert_cmpint (len, ==, 3);
     276    g_assert_cmpstr (buffer, ==, "ABC");
     277    g_free (buffer);
     278  
     279    g_free (childname);
     280    g_free (global_filename);
     281    g_free (dir);
     282  
     283    /* Cleaning left over files */
     284    g_remove ("mapchild");
     285    g_remove ("maptest");
     286  
     287    g_test_message ("test_child_private: ok");
     288  }
     289  
     290  int
     291  main (int argc,
     292        char *argv[])
     293  {
     294  #ifndef G_OS_WIN32
     295    sigset_t sig_mask, old_mask;
     296  
     297    sigemptyset (&sig_mask);
     298    sigaddset (&sig_mask, SIGUSR1);
     299    if (sigprocmask (SIG_UNBLOCK, &sig_mask, &old_mask) == 0)
     300      {
     301        if (sigismember (&old_mask, SIGUSR1))
     302          g_test_message ("SIGUSR1 was blocked, unblocking it");
     303      }
     304  #endif
     305  
     306    local_argv = argv;
     307  
     308    if (argc > 1)
     309      {
     310        child_main ();
     311        return EXIT_SUCCESS;
     312      }
     313  
     314    g_test_init (&argc, &argv, NULL);
     315  
     316    g_test_add_func ("/mapping/flags", test_mapping_flags);
     317    g_test_add_func ("/mapping/private", test_private);
     318    g_test_add_func ("/mapping/private-child", test_child_private);
     319  
     320    return g_test_run ();
     321  }