Use spaces for indentation, not tabs.
[gnulib.git] / tests / test-fwriting.c
1 /* Test of fwriting() function.
2    Copyright (C) 2007-2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program 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
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
18
19 #include <config.h>
20
21 #include "fwriting.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 /* None of the files accessed by this test are large, so disable the
27    fseek link warning if we are not using the gnulib fseek module.  */
28 #if !GNULIB_FSEEK
29 # undef fseek
30 #endif
31
32 #define ASSERT(expr) \
33   do                                                                         \
34     {                                                                        \
35       if (!(expr))                                                           \
36         {                                                                    \
37           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
38           fflush (stderr);                                                   \
39           abort ();                                                          \
40         }                                                                    \
41     }                                                                        \
42   while (0)
43
44 #define TESTFILE "t-fwriting.tmp"
45
46 int
47 main ()
48 {
49   FILE *fp;
50
51   /* Create a file with some contents.  Write-only file is always writing.  */
52   fp = fopen (TESTFILE, "w");
53   if (fp == NULL)
54     goto skip;
55   ASSERT (fwriting (fp));
56   if (fwrite ("foobarsh", 1, 8, fp) < 8)
57     goto skip;
58   ASSERT (fwriting (fp));
59   if (fclose (fp))
60     goto skip;
61
62   /* Open it in read-only mode.  Read-only file is never writing.  */
63   fp = fopen (TESTFILE, "r");
64   if (fp == NULL)
65     goto skip;
66   ASSERT (!fwriting (fp));
67   if (fgetc (fp) != 'f')
68     goto skip;
69   ASSERT (!fwriting (fp));
70   if (fseek (fp, 2, SEEK_CUR))
71     goto skip;
72   ASSERT (!fwriting (fp));
73   if (fgetc (fp) != 'b')
74     goto skip;
75   ASSERT (!fwriting (fp));
76   fflush (fp);
77   ASSERT (!fwriting (fp));
78   if (fgetc (fp) != 'a')
79     goto skip;
80   ASSERT (!fwriting (fp));
81   if (fseek (fp, 0, SEEK_END))
82     goto skip;
83   ASSERT (!fwriting (fp));
84   if (fclose (fp))
85     goto skip;
86
87   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
88      fsetpos, rewind) or fflush when transitioning from write to read,
89      fwriting is only deterministic after input or output, but this
90      test case should be portable even on open, after reposition, and
91      after fflush.  */
92   /* First a scenario with only fgetc, fseek, fputc.  */
93   fp = fopen (TESTFILE, "r+");
94   if (fp == NULL)
95     goto skip;
96   ASSERT (!fwriting (fp));
97   if (fgetc (fp) != 'f')
98     goto skip;
99   ASSERT (!fwriting (fp));
100   if (fseek (fp, 2, SEEK_CUR))
101     goto skip;
102   ASSERT (!fwriting (fp));
103   if (fgetc (fp) != 'b')
104     goto skip;
105   ASSERT (!fwriting (fp));
106   /* This fseek call is necessary when switching from reading to writing.
107      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
108   if (fseek (fp, 0, SEEK_CUR) != 0)
109     goto skip;
110   ASSERT (!fwriting (fp));
111   if (fputc ('x', fp) != 'x')
112     goto skip;
113   ASSERT (fwriting (fp));
114   if (fseek (fp, 0, SEEK_END))
115     goto skip;
116   /* freading (fp) is undefined here, because on some implementations (e.g.
117      glibc) fseek causes a buffer to be read.
118      fwriting (fp) is undefined as well.  */
119   if (fclose (fp))
120     goto skip;
121
122   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
123      fsetpos, rewind) or fflush when transitioning from write to read,
124      fwriting is only deterministic after input or output, but this
125      test case should be portable even on open, after reposition, and
126      after fflush.  */
127   /* Here a scenario that includes fflush.  */
128   fp = fopen (TESTFILE, "r+");
129   if (fp == NULL)
130     goto skip;
131   ASSERT (!fwriting (fp));
132   if (fgetc (fp) != 'f')
133     goto skip;
134   ASSERT (!fwriting (fp));
135   if (fseek (fp, 2, SEEK_CUR))
136     goto skip;
137   ASSERT (!fwriting (fp));
138   if (fgetc (fp) != 'b')
139     goto skip;
140   ASSERT (!fwriting (fp));
141   fflush (fp);
142   ASSERT (!fwriting (fp));
143   if (fgetc (fp) != 'x')
144     goto skip;
145   ASSERT (!fwriting (fp));
146   /* This fseek call is necessary when switching from reading to writing.
147      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
148   if (fseek (fp, 0, SEEK_CUR) != 0)
149     goto skip;
150   ASSERT (!fwriting (fp));
151   if (fputc ('z', fp) != 'z')
152     goto skip;
153   ASSERT (fwriting (fp));
154   if (fseek (fp, 0, SEEK_END))
155     goto skip;
156   /* freading (fp) is undefined here, because on some implementations (e.g.
157      glibc) fseek causes a buffer to be read.
158      fwriting (fp) is undefined as well.  */
159   if (fclose (fp))
160     goto skip;
161
162   /* Open it in append mode.  */
163   fp = fopen (TESTFILE, "a");
164   if (fp == NULL)
165     goto skip;
166   ASSERT (fwriting (fp));
167   if (fwrite ("bla", 1, 3, fp) < 3)
168     goto skip;
169   ASSERT (fwriting (fp));
170   if (fclose (fp))
171     goto skip;
172
173   return 0;
174
175  skip:
176   fprintf (stderr, "Skipping test: file operations failed.\n");
177   return 77;
178 }