freading has an undefined value after repositioning a read-write stream.
[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   /* freading (fp) is undefined here, because on some implementations (e.g.
101      glibc) fseek causes a buffer to be read.
102      fwriting (fp) is undefined as well.  */
103   if (fclose (fp))
104     goto skip;
105
106   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
107      fsetpos, rewind) or fflush when transitioning from write to read,
108      fwriting is only deterministic after input or output, but this
109      test case should be portable even on open, after reposition, and
110      after fflush.  */
111   /* Here a scenario that includes fflush.  */
112   fp = fopen (TESTFILE, "r+");
113   if (fp == NULL)
114     goto skip;
115   ASSERT (!fwriting (fp));
116   if (fgetc (fp) != 'f')
117     goto skip;
118   ASSERT (!fwriting (fp));
119   if (fseek (fp, 2, SEEK_CUR))
120     goto skip;
121   ASSERT (!fwriting (fp));
122   if (fgetc (fp) != 'b')
123     goto skip;
124   ASSERT (!fwriting (fp));
125   fflush (fp);
126   ASSERT (!fwriting (fp));
127   if (fgetc (fp) != 'x')
128     goto skip;
129   ASSERT (!fwriting (fp));
130   /* This fseek call is necessary when switching from reading to writing.
131      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
132   if (fseek (fp, 0, SEEK_CUR) != 0)
133     goto skip;
134   ASSERT (!fwriting (fp));
135   if (fputc ('z', fp) != 'z')
136     goto skip;
137   ASSERT (fwriting (fp));
138   if (fseek (fp, 0, SEEK_END))
139     goto skip;
140   /* freading (fp) is undefined here, because on some implementations (e.g.
141      glibc) fseek causes a buffer to be read.
142      fwriting (fp) is undefined as well.  */
143   if (fclose (fp))
144     goto skip;
145
146   /* Open it in append mode.  */
147   fp = fopen (TESTFILE, "a");
148   if (fp == NULL)
149     goto skip;
150   ASSERT (fwriting (fp));
151   if (fwrite ("bla", 1, 3, fp) < 3)
152     goto skip;
153   ASSERT (fwriting (fp));
154   if (fclose (fp))
155     goto skip;
156
157   return 0;
158
159  skip:
160   fprintf (stderr, "Skipping test: file operations failed.\n");
161   return 77;
162 }