Refactor common macros used in tests.
[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
25 #include "macros.h"
26
27 /* None of the files accessed by this test are large, so disable the
28    fseek link warning if we are not using the gnulib fseek module.  */
29 #if !GNULIB_FSEEK
30 # undef fseek
31 #endif
32
33 #define TESTFILE "t-fwriting.tmp"
34
35 int
36 main ()
37 {
38   FILE *fp;
39
40   /* Create a file with some contents.  Write-only file is always writing.  */
41   fp = fopen (TESTFILE, "w");
42   if (fp == NULL)
43     goto skip;
44   ASSERT (fwriting (fp));
45   if (fwrite ("foobarsh", 1, 8, fp) < 8)
46     goto skip;
47   ASSERT (fwriting (fp));
48   if (fclose (fp))
49     goto skip;
50
51   /* Open it in read-only mode.  Read-only file is never writing.  */
52   fp = fopen (TESTFILE, "r");
53   if (fp == NULL)
54     goto skip;
55   ASSERT (!fwriting (fp));
56   if (fgetc (fp) != 'f')
57     goto skip;
58   ASSERT (!fwriting (fp));
59   if (fseek (fp, 2, SEEK_CUR))
60     goto skip;
61   ASSERT (!fwriting (fp));
62   if (fgetc (fp) != 'b')
63     goto skip;
64   ASSERT (!fwriting (fp));
65   fflush (fp);
66   ASSERT (!fwriting (fp));
67   if (fgetc (fp) != 'a')
68     goto skip;
69   ASSERT (!fwriting (fp));
70   if (fseek (fp, 0, SEEK_END))
71     goto skip;
72   ASSERT (!fwriting (fp));
73   if (fclose (fp))
74     goto skip;
75
76   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
77      fsetpos, rewind) or fflush when transitioning from write to read,
78      fwriting is only deterministic after input or output, but this
79      test case should be portable even on open, after reposition, and
80      after fflush.  */
81   /* First a scenario with only fgetc, fseek, fputc.  */
82   fp = fopen (TESTFILE, "r+");
83   if (fp == NULL)
84     goto skip;
85   ASSERT (!fwriting (fp));
86   if (fgetc (fp) != 'f')
87     goto skip;
88   ASSERT (!fwriting (fp));
89   if (fseek (fp, 2, SEEK_CUR))
90     goto skip;
91   ASSERT (!fwriting (fp));
92   if (fgetc (fp) != 'b')
93     goto skip;
94   ASSERT (!fwriting (fp));
95   /* This fseek call is necessary when switching from reading to writing.
96      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
97   if (fseek (fp, 0, SEEK_CUR) != 0)
98     goto skip;
99   ASSERT (!fwriting (fp));
100   if (fputc ('x', fp) != 'x')
101     goto skip;
102   ASSERT (fwriting (fp));
103   if (fseek (fp, 0, SEEK_END))
104     goto skip;
105   /* freading (fp) is undefined here, because on some implementations (e.g.
106      glibc) fseek causes a buffer to be read.
107      fwriting (fp) is undefined as well.  */
108   if (fclose (fp))
109     goto skip;
110
111   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
112      fsetpos, rewind) or fflush when transitioning from write to read,
113      fwriting is only deterministic after input or output, but this
114      test case should be portable even on open, after reposition, and
115      after fflush.  */
116   /* Here a scenario that includes fflush.  */
117   fp = fopen (TESTFILE, "r+");
118   if (fp == NULL)
119     goto skip;
120   ASSERT (!fwriting (fp));
121   if (fgetc (fp) != 'f')
122     goto skip;
123   ASSERT (!fwriting (fp));
124   if (fseek (fp, 2, SEEK_CUR))
125     goto skip;
126   ASSERT (!fwriting (fp));
127   if (fgetc (fp) != 'b')
128     goto skip;
129   ASSERT (!fwriting (fp));
130   fflush (fp);
131   ASSERT (!fwriting (fp));
132   if (fgetc (fp) != 'x')
133     goto skip;
134   ASSERT (!fwriting (fp));
135   /* This fseek call is necessary when switching from reading to writing.
136      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
137   if (fseek (fp, 0, SEEK_CUR) != 0)
138     goto skip;
139   ASSERT (!fwriting (fp));
140   if (fputc ('z', fp) != 'z')
141     goto skip;
142   ASSERT (fwriting (fp));
143   if (fseek (fp, 0, SEEK_END))
144     goto skip;
145   /* freading (fp) is undefined here, because on some implementations (e.g.
146      glibc) fseek causes a buffer to be read.
147      fwriting (fp) is undefined as well.  */
148   if (fclose (fp))
149     goto skip;
150
151   /* Open it in append mode.  */
152   fp = fopen (TESTFILE, "a");
153   if (fp == NULL)
154     goto skip;
155   ASSERT (fwriting (fp));
156   if (fwrite ("bla", 1, 3, fp) < 3)
157     goto skip;
158   ASSERT (fwriting (fp));
159   if (fclose (fp))
160     goto skip;
161
162   return 0;
163
164  skip:
165   fprintf (stderr, "Skipping test: file operations failed.\n");
166   return 77;
167 }