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

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. test_fopen_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_fopen_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     FILE *fp =
  34       fopen_supersede (filename, "wb",
  35                        supersede_if_exists, supersede_if_does_not_exist,
  36                        &action);
  37     ASSERT (fp != NULL);
  38     ASSERT (fwrite ("Hello world\n", 1, 12, fp) == 12 && fflush (fp) == 0);
  39     if (supersede_if_does_not_exist)
  40       ASSERT (stat (filename, &statbuf) < 0);
  41     else
  42       ASSERT (stat (filename, &statbuf) == 0);
  43     ASSERT (fclose_supersede (fp, &action) == 0);
  44 
  45     ASSERT (stat (filename, &statbuf) == 0);
  46 
  47     size_t file_size;
  48     char *file_contents = read_file (filename, RF_BINARY, &file_size);
  49     ASSERT (file_size == 12);
  50     ASSERT (memcmp (file_contents, "Hello world\n", 12) == 0);
  51   }
  52 
  53   /* Test the case that the file exists and is a regular file.  */
  54   {
  55     ASSERT (stat (filename, &statbuf) == 0);
  56     dev_t orig_dev = statbuf.st_dev;
  57     ino_t orig_ino = statbuf.st_ino;
  58 
  59     struct supersede_final_action action;
  60     FILE *fp =
  61       fopen_supersede (filename, "wb",
  62                        supersede_if_exists, supersede_if_does_not_exist,
  63                        &action);
  64     ASSERT (fp != NULL);
  65     ASSERT (fwrite ("Foobar\n", 1, 7, fp) == 7 && fflush (fp) == 0);
  66     ASSERT (stat (filename, &statbuf) == 0);
  67     {
  68       size_t file_size;
  69       char *file_contents = read_file (filename, RF_BINARY, &file_size);
  70       if (supersede_if_exists)
  71         {
  72           ASSERT (file_size == 12);
  73           ASSERT (memcmp (file_contents, "Hello world\n", 12) == 0);
  74         }
  75       else
  76         {
  77           ASSERT (file_size == 7);
  78           ASSERT (memcmp (file_contents, "Foobar\n", 7) == 0);
  79         }
  80     }
  81     ASSERT (fclose_supersede (fp, &action) == 0);
  82 
  83     ASSERT (stat (filename, &statbuf) == 0);
  84 
  85     size_t file_size;
  86     char *file_contents = read_file (filename, RF_BINARY, &file_size);
  87     ASSERT (file_size == 7);
  88     ASSERT (memcmp (file_contents, "Foobar\n", 7) == 0);
  89 
  90     if (supersede_if_exists)
  91       {
  92         /* Verify that the file now has a different inode number, on the same
  93            device.  */
  94 #if !(defined _WIN32 && !defined __CYGWIN__)
  95         /* Note: On Linux/mips, statbuf.st_dev is smaller than a dev_t!  */
  96         dev_t new_dev = statbuf.st_dev;
  97         ASSERT (memcmp (&orig_dev, &new_dev, sizeof (dev_t)) == 0);
  98         ASSERT (memcmp (&orig_ino, &statbuf.st_ino, sizeof (ino_t)) != 0);
  99 #endif
 100       }
 101   }
 102 
 103   /* Test the case that the file exists and is a character device.  */
 104   {
 105     ASSERT (stat (DEV_NULL, &statbuf) == 0);
 106 
 107     struct supersede_final_action action;
 108     FILE *fp =
 109       fopen_supersede (DEV_NULL, "wb",
 110                        supersede_if_exists, supersede_if_does_not_exist,
 111                        &action);
 112     ASSERT (fp != NULL);
 113     ASSERT (fwrite ("Foobar\n", 1, 7, fp) == 7 && fflush (fp) == 0);
 114     ASSERT (stat (DEV_NULL, &statbuf) == 0);
 115     ASSERT (fclose_supersede (fp, &action) == 0);
 116 
 117     ASSERT (stat (DEV_NULL, &statbuf) == 0);
 118   }
 119 
 120   /* Test the case that the file is a symbolic link to an existing regular
 121      file.  */
 122   {
 123     const char *linkname = "link1";
 124     unlink (linkname);
 125     if (symlink (filename, linkname) >= 0)
 126       {
 127         ASSERT (stat (linkname, &statbuf) == 0);
 128         dev_t orig_dev = statbuf.st_dev;
 129         ino_t orig_ino = statbuf.st_ino;
 130 
 131         struct supersede_final_action action;
 132         FILE *fp =
 133           fopen_supersede (linkname, "wb",
 134                            supersede_if_exists, supersede_if_does_not_exist,
 135                            &action);
 136         ASSERT (fp != NULL);
 137         ASSERT (fwrite ("New\n", 1, 4, fp) == 4 && fflush (fp) == 0);
 138         ASSERT (stat (linkname, &statbuf) == 0);
 139         {
 140           size_t file_size;
 141           char *file_contents = read_file (linkname, RF_BINARY, &file_size);
 142           if (supersede_if_exists)
 143             {
 144               ASSERT (file_size == 7);
 145               ASSERT (memcmp (file_contents, "Foobar\n", 7) == 0);
 146             }
 147           else
 148             {
 149               ASSERT (file_size == 4);
 150               ASSERT (memcmp (file_contents, "New\n", 4) == 0);
 151             }
 152         }
 153         ASSERT (fclose_supersede (fp, &action) == 0);
 154 
 155         ASSERT (stat (linkname, &statbuf) == 0);
 156 
 157         size_t file_size;
 158         char *file_contents = read_file (linkname, RF_BINARY, &file_size);
 159         ASSERT (file_size == 4);
 160         ASSERT (memcmp (file_contents, "New\n", 4) == 0);
 161 
 162         if (supersede_if_exists)
 163           {
 164             /* Verify that the file now has a different inode number, on the
 165                same device.  */
 166 #if !(defined _WIN32 && !defined __CYGWIN__)
 167             /* Note: On Linux/mips, statbuf.st_dev is smaller than a dev_t!  */
 168             dev_t new_dev = statbuf.st_dev;
 169             ASSERT (memcmp (&orig_dev, &new_dev, sizeof (dev_t)) == 0);
 170             ASSERT (memcmp (&orig_ino, &statbuf.st_ino, sizeof (ino_t)) != 0);
 171 #endif
 172           }
 173 
 174         /* Clean up.  */
 175         unlink (linkname);
 176       }
 177   }
 178 
 179   /* Test the case that the file is a symbolic link to an existing character
 180      device.  */
 181   {
 182     const char *linkname = "link2";
 183     unlink (linkname);
 184     if (symlink (DEV_NULL, linkname) >= 0)
 185       {
 186         ASSERT (stat (linkname, &statbuf) == 0);
 187 
 188         struct supersede_final_action action;
 189         FILE *fp =
 190           fopen_supersede (linkname, "wb",
 191                            supersede_if_exists, supersede_if_does_not_exist,
 192                            &action);
 193         ASSERT (fp != NULL);
 194         ASSERT (fwrite ("New\n", 1, 4, fp) == 4 && fflush (fp) == 0);
 195         ASSERT (stat (linkname, &statbuf) == 0);
 196         ASSERT (fclose_supersede (fp, &action) == 0);
 197 
 198         ASSERT (stat (linkname, &statbuf) == 0);
 199 
 200         /* Clean up.  */
 201         unlink (linkname);
 202       }
 203   }
 204 
 205   /* Clean up.  */
 206   unlink (filename);
 207 
 208   /* Test the case that the file is a symbolic link to a nonexistent file in an
 209      existing directory.  */
 210   {
 211     const char *linkname = "link3";
 212     unlink (linkname);
 213     if (symlink (filename, linkname) >= 0)
 214       {
 215         ASSERT (stat (linkname, &statbuf) < 0);
 216 
 217         struct supersede_final_action action;
 218         FILE *fp =
 219           fopen_supersede (linkname, "wb",
 220                            supersede_if_exists, supersede_if_does_not_exist,
 221                            &action);
 222         ASSERT (fp != NULL);
 223         ASSERT (fwrite ("Hello world\n", 1, 12, fp) == 12 && fflush (fp) == 0);
 224         if (supersede_if_does_not_exist)
 225           ASSERT (stat (linkname, &statbuf) < 0);
 226         else
 227           ASSERT (stat (linkname, &statbuf) == 0);
 228         ASSERT (fclose_supersede (fp, &action) == 0);
 229 
 230         ASSERT (stat (linkname, &statbuf) == 0);
 231 
 232         size_t file_size;
 233         char *file_contents = read_file (linkname, RF_BINARY, &file_size);
 234         ASSERT (file_size == 12);
 235         ASSERT (memcmp (file_contents, "Hello world\n", 12) == 0);
 236 
 237         /* Clean up.  */
 238         unlink (linkname);
 239       }
 240   }
 241 
 242   /* Test the case that the file is a symbolic link to a nonexistent file in a
 243      nonexistent directory.  */
 244   {
 245     const char *linkname = "link4";
 246     unlink (linkname);
 247     if (symlink ("/nonexistent/gnulibtest8237/24715863701440", linkname) >= 0)
 248       {
 249         ASSERT (stat (linkname, &statbuf) < 0);
 250 
 251         struct supersede_final_action action;
 252         FILE *fp =
 253           fopen_supersede (linkname, "wb",
 254                            supersede_if_exists, supersede_if_does_not_exist,
 255                            &action);
 256         ASSERT (fp == NULL);
 257         ASSERT (errno == ENOENT);
 258 
 259         ASSERT (stat (linkname, &statbuf) < 0);
 260 
 261         /* Clean up.  */
 262         unlink (linkname);
 263       }
 264   }
 265 
 266   /* Clean up.  */
 267   unlink (filename);
 268   rmdir (dir);
 269 }

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