root/maint/gnulib/tests/test-supersede-open.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. test_open_supersede

   1 /* Tests for opening a file without destroying an old file with the same name.
   2 
   3    Copyright (C) 2020-2021 Free Software Foundation, Inc.
   4 
   5    This program is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU General Public License as published by
   7    the Free Software Foundation; either version 3 of the License, or
   8    (at your option) any later version.
   9 
  10    This program is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU General Public License for more details.
  14 
  15    You should have received a copy of the GNU General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 /* Written by Bruno Haible, 2020.  */
  19 
  20 static void
  21 test_open_supersede (bool supersede_if_exists, bool supersede_if_does_not_exist)
     /* [previous][next][first][last][top][bottom][index][help] */
  22 {
  23   char xtemplate[] = "gnulibtestXXXXXX";
  24   char *dir = mkdtemp (xtemplate);
  25   char *filename = file_name_concat (dir, "test.mo", NULL);
  26   struct stat statbuf;
  27 
  28   /* Test the case that the file does not yet exist.  */
  29   {
  30     ASSERT (stat (filename, &statbuf) < 0);
  31 
  32     struct supersede_final_action action;
  33     int fd = open_supersede (filename, O_RDWR | O_BINARY | O_TRUNC, 0666,
  34                              supersede_if_exists, supersede_if_does_not_exist,
  35                              &action);
  36     ASSERT (fd >= 0);
  37     ASSERT (write (fd, "Hello world\n", 12) == 12);
  38     if (supersede_if_does_not_exist)
  39       ASSERT (stat (filename, &statbuf) < 0);
  40     else
  41       ASSERT (stat (filename, &statbuf) == 0);
  42     ASSERT (close_supersede (fd, &action) == 0);
  43 
  44     ASSERT (stat (filename, &statbuf) == 0);
  45 
  46     size_t file_size;
  47     char *file_contents = read_file (filename, RF_BINARY, &file_size);
  48     ASSERT (file_size == 12);
  49     ASSERT (memcmp (file_contents, "Hello world\n", 12) == 0);
  50   }
  51 
  52   /* Test the case that the file exists and is a regular file.  */
  53   {
  54     ASSERT (stat (filename, &statbuf) == 0);
  55     dev_t orig_dev = statbuf.st_dev;
  56     ino_t orig_ino = statbuf.st_ino;
  57 
  58     struct supersede_final_action action;
  59     int fd = open_supersede (filename, O_RDWR | O_BINARY | O_TRUNC, 0666,
  60                              supersede_if_exists, supersede_if_does_not_exist,
  61                              &action);
  62     ASSERT (fd >= 0);
  63     ASSERT (write (fd, "Foobar\n", 7) == 7);
  64     ASSERT (stat (filename, &statbuf) == 0);
  65     {
  66       size_t file_size;
  67       char *file_contents = read_file (filename, RF_BINARY, &file_size);
  68       if (supersede_if_exists)
  69         {
  70           ASSERT (file_size == 12);
  71           ASSERT (memcmp (file_contents, "Hello world\n", 12) == 0);
  72         }
  73       else
  74         {
  75           ASSERT (file_size == 7);
  76           ASSERT (memcmp (file_contents, "Foobar\n", 7) == 0);
  77         }
  78     }
  79     ASSERT (close_supersede (fd, &action) == 0);
  80 
  81     ASSERT (stat (filename, &statbuf) == 0);
  82 
  83     size_t file_size;
  84     char *file_contents = read_file (filename, RF_BINARY, &file_size);
  85     ASSERT (file_size == 7);
  86     ASSERT (memcmp (file_contents, "Foobar\n", 7) == 0);
  87 
  88     if (supersede_if_exists)
  89       {
  90         /* Verify that the file now has a different inode number, on the same
  91            device.  */
  92 #if !(defined _WIN32 && !defined __CYGWIN__)
  93         /* Note: On Linux/mips, statbuf.st_dev is smaller than a dev_t!  */
  94         dev_t new_dev = statbuf.st_dev;
  95         ASSERT (memcmp (&orig_dev, &new_dev, sizeof (dev_t)) == 0);
  96         ASSERT (memcmp (&orig_ino, &statbuf.st_ino, sizeof (ino_t)) != 0);
  97 #endif
  98       }
  99   }
 100 
 101   /* Test the case that the file exists and is a character device.  */
 102   {
 103     ASSERT (stat (DEV_NULL, &statbuf) == 0);
 104 
 105     struct supersede_final_action action;
 106     int fd = open_supersede (DEV_NULL, O_RDWR | O_BINARY | O_TRUNC, 0666,
 107                              supersede_if_exists, supersede_if_does_not_exist,
 108                              &action);
 109     ASSERT (fd >= 0);
 110     ASSERT (write (fd, "Foobar\n", 7) == 7);
 111     ASSERT (stat (DEV_NULL, &statbuf) == 0);
 112     ASSERT (close_supersede (fd, &action) == 0);
 113 
 114     ASSERT (stat (DEV_NULL, &statbuf) == 0);
 115   }
 116 
 117   /* Test the case that the file is a symbolic link to an existing regular
 118      file.  */
 119   {
 120     const char *linkname = "link1";
 121     unlink (linkname);
 122     if (symlink (filename, linkname) >= 0)
 123       {
 124         ASSERT (stat (linkname, &statbuf) == 0);
 125         dev_t orig_dev = statbuf.st_dev;
 126         ino_t orig_ino = statbuf.st_ino;
 127 
 128         struct supersede_final_action action;
 129         int fd =
 130           open_supersede (linkname, O_RDWR | O_BINARY | O_TRUNC, 0666,
 131                           supersede_if_exists, supersede_if_does_not_exist,
 132                           &action);
 133         ASSERT (fd >= 0);
 134         ASSERT (write (fd, "New\n", 4) == 4);
 135         ASSERT (stat (linkname, &statbuf) == 0);
 136         {
 137           size_t file_size;
 138           char *file_contents = read_file (linkname, RF_BINARY, &file_size);
 139           if (supersede_if_exists)
 140             {
 141               ASSERT (file_size == 7);
 142               ASSERT (memcmp (file_contents, "Foobar\n", 7) == 0);
 143             }
 144           else
 145             {
 146               ASSERT (file_size == 4);
 147               ASSERT (memcmp (file_contents, "New\n", 4) == 0);
 148             }
 149         }
 150         ASSERT (close_supersede (fd, &action) == 0);
 151 
 152         ASSERT (stat (linkname, &statbuf) == 0);
 153 
 154         size_t file_size;
 155         char *file_contents = read_file (linkname, RF_BINARY, &file_size);
 156         ASSERT (file_size == 4);
 157         ASSERT (memcmp (file_contents, "New\n", 4) == 0);
 158 
 159         if (supersede_if_exists)
 160           {
 161             /* Verify that the file now has a different inode number, on the
 162                same device.  */
 163 #if !(defined _WIN32 && !defined __CYGWIN__)
 164             /* Note: On Linux/mips, statbuf.st_dev is smaller than a dev_t!  */
 165             dev_t new_dev = statbuf.st_dev;
 166             ASSERT (memcmp (&orig_dev, &new_dev, sizeof (dev_t)) == 0);
 167             ASSERT (memcmp (&orig_ino, &statbuf.st_ino, sizeof (ino_t)) != 0);
 168 #endif
 169           }
 170 
 171         /* Clean up.  */
 172         unlink (linkname);
 173       }
 174   }
 175 
 176   /* Test the case that the file is a symbolic link to an existing character
 177      device.  */
 178   {
 179     const char *linkname = "link2";
 180     unlink (linkname);
 181     if (symlink (DEV_NULL, linkname) >= 0)
 182       {
 183         ASSERT (stat (linkname, &statbuf) == 0);
 184 
 185         struct supersede_final_action action;
 186         int fd =
 187           open_supersede (linkname, O_RDWR | O_BINARY | O_TRUNC, 0666,
 188                           supersede_if_exists, supersede_if_does_not_exist,
 189                           &action);
 190         ASSERT (fd >= 0);
 191         ASSERT (write (fd, "New\n", 4) == 4);
 192         ASSERT (stat (linkname, &statbuf) == 0);
 193         ASSERT (close_supersede (fd, &action) == 0);
 194 
 195         ASSERT (stat (linkname, &statbuf) == 0);
 196 
 197         /* Clean up.  */
 198         unlink (linkname);
 199       }
 200   }
 201 
 202   /* Clean up.  */
 203   unlink (filename);
 204 
 205   /* Test the case that the file is a symbolic link to a nonexistent file in an
 206      existing directory.  */
 207   {
 208     const char *linkname = "link3";
 209     unlink (linkname);
 210     if (symlink (filename, linkname) >= 0)
 211       {
 212         ASSERT (stat (linkname, &statbuf) < 0);
 213 
 214         struct supersede_final_action action;
 215         int fd =
 216           open_supersede (linkname, O_RDWR | O_BINARY | O_TRUNC, 0666,
 217                           supersede_if_exists, supersede_if_does_not_exist,
 218                           &action);
 219         ASSERT (fd >= 0);
 220         ASSERT (write (fd, "Hello world\n", 12) == 12);
 221         if (supersede_if_does_not_exist)
 222           ASSERT (stat (linkname, &statbuf) < 0);
 223         else
 224           ASSERT (stat (linkname, &statbuf) == 0);
 225         ASSERT (close_supersede (fd, &action) == 0);
 226 
 227         ASSERT (stat (linkname, &statbuf) == 0);
 228 
 229         size_t file_size;
 230         char *file_contents = read_file (linkname, RF_BINARY, &file_size);
 231         ASSERT (file_size == 12);
 232         ASSERT (memcmp (file_contents, "Hello world\n", 12) == 0);
 233 
 234         /* Clean up.  */
 235         unlink (linkname);
 236       }
 237   }
 238 
 239   /* Test the case that the file is a symbolic link to a nonexistent file in a
 240      nonexistent directory.  */
 241   {
 242     const char *linkname = "link4";
 243     unlink (linkname);
 244     if (symlink ("/nonexistent/gnulibtest8237/24715863701440", linkname) >= 0)
 245       {
 246         ASSERT (stat (linkname, &statbuf) < 0);
 247 
 248         struct supersede_final_action action;
 249         int fd =
 250           open_supersede (linkname, O_RDWR | O_BINARY | O_TRUNC, 0666,
 251                           supersede_if_exists, supersede_if_does_not_exist,
 252                           &action);
 253         ASSERT (fd < 0);
 254         ASSERT (errno == ENOENT);
 255 
 256         ASSERT (stat (linkname, &statbuf) < 0);
 257 
 258         /* Clean up.  */
 259         unlink (linkname);
 260       }
 261   }
 262 
 263   /* Clean up.  */
 264   unlink (filename);
 265   rmdir (dir);
 266 }

/* [previous][next][first][last][top][bottom][index][help] */