Oops, fix details and comments of last patch.
[gnulib.git] / tests / test-fwriting.c
1 /* Test of fwriting() function.
2    Copyright (C) 2007 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 2, or (at your option)
7    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, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
19
20 #include <config.h>
21
22 #include "fwriting.h"
23
24 #include <stdlib.h>
25
26 #define ASSERT(expr) if (!(expr)) abort ();
27
28 #define TESTFILE "t-fwriting.tmp"
29
30 int
31 main ()
32 {
33   FILE *fp;
34
35   /* Create a file with some contents.  Write-only file is always writing.  */
36   fp = fopen (TESTFILE, "w");
37   if (fp == NULL)
38     goto skip;
39   ASSERT (fwriting (fp));
40   if (fwrite ("foobarsh", 1, 8, fp) < 8)
41     goto skip;
42   ASSERT (fwriting (fp));
43   if (fclose (fp))
44     goto skip;
45
46   /* Open it in read-only mode.  Read-only file is never writing.  */
47   fp = fopen (TESTFILE, "r");
48   if (fp == NULL)
49     goto skip;
50   ASSERT (!fwriting (fp));
51   if (fgetc (fp) != 'f')
52     goto skip;
53   ASSERT (!fwriting (fp));
54   if (fseek (fp, 2, SEEK_CUR))
55     goto skip;
56   ASSERT (!fwriting (fp));
57   if (fgetc (fp) != 'b')
58     goto skip;
59   ASSERT (!fwriting (fp));
60   fflush (fp);
61   ASSERT (!fwriting (fp));
62   if (fgetc (fp) != 'a')
63     goto skip;
64   ASSERT (!fwriting (fp));
65   if (fseek (fp, 0, SEEK_END))
66     goto skip;
67   ASSERT (!fwriting (fp));
68   if (fclose (fp))
69     goto skip;
70
71   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
72      fsetpos, rewind) or fflush when transitioning from write to read,
73      fwriting is only deterministic after input or output, but this
74      test case should be portable even on open, after reposition, and
75      after fflush.  */
76   /* First a scenario with only fgetc, fseek, fputc.  */
77   fp = fopen (TESTFILE, "r+");
78   if (fp == NULL)
79     goto skip;
80   ASSERT (!fwriting (fp));
81   if (fgetc (fp) != 'f')
82     goto skip;
83   ASSERT (!fwriting (fp));
84   if (fseek (fp, 2, SEEK_CUR))
85     goto skip;
86   ASSERT (!fwriting (fp));
87   if (fgetc (fp) != 'b')
88     goto skip;
89   ASSERT (!fwriting (fp));
90   /* This fseek call is necessary when switching from reading to writing.
91      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
92   if (fseek (fp, 0, SEEK_CUR) != 0)
93     goto skip;
94   ASSERT (!fwriting (fp));
95   if (fputc ('x', fp) != 'x')
96     goto skip;
97   ASSERT (fwriting (fp));
98   if (fseek (fp, 0, SEEK_END))
99     goto skip;
100   /* fwriting (fp) is undefined here, but freading (fp) is false.  */
101   if (fclose (fp))
102     goto skip;
103
104   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
105      fsetpos, rewind) or fflush when transitioning from write to read,
106      fwriting is only deterministic after input or output, but this
107      test case should be portable even on open, after reposition, and
108      after fflush.  */
109   /* Here a scenario that includes fflush.  */
110   fp = fopen (TESTFILE, "r+");
111   if (fp == NULL)
112     goto skip;
113   ASSERT (!fwriting (fp));
114   if (fgetc (fp) != 'f')
115     goto skip;
116   ASSERT (!fwriting (fp));
117   if (fseek (fp, 2, SEEK_CUR))
118     goto skip;
119   ASSERT (!fwriting (fp));
120   if (fgetc (fp) != 'b')
121     goto skip;
122   ASSERT (!fwriting (fp));
123   fflush (fp);
124   ASSERT (!fwriting (fp));
125   if (fgetc (fp) != 'x')
126     goto skip;
127   ASSERT (!fwriting (fp));
128   /* This fseek call is necessary when switching from reading to writing.
129      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
130   if (fseek (fp, 0, SEEK_CUR) != 0)
131     goto skip;
132   ASSERT (!fwriting (fp));
133   if (fputc ('z', fp) != 'z')
134     goto skip;
135   ASSERT (fwriting (fp));
136   if (fseek (fp, 0, SEEK_END))
137     goto skip;
138   /* fwriting (fp) is undefined here, but freading (fp) is false.  */
139   if (fclose (fp))
140     goto skip;
141
142   /* Open it in append mode.  */
143   fp = fopen (TESTFILE, "a");
144   if (fp == NULL)
145     goto skip;
146   ASSERT (fwriting (fp));
147   if (fwrite ("bla", 1, 3, fp) < 3)
148     goto skip;
149   ASSERT (fwriting (fp));
150   if (fclose (fp))
151     goto skip;
152
153   return 0;
154
155  skip:
156   fprintf (stderr, "Skipping test: file operations failed.\n");
157   return 77;
158 }