Make the tests sharper: also test the interaction with fflush().
[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   fp = fopen (TESTFILE, "r+");
77   if (fp == NULL)
78     goto skip;
79   ASSERT (!fwriting (fp));
80   if (fgetc (fp) != 'f')
81     goto skip;
82   ASSERT (!fwriting (fp));
83   if (fseek (fp, 2, SEEK_CUR))
84     goto skip;
85   ASSERT (!fwriting (fp));
86   if (fgetc (fp) != 'b')
87     goto skip;
88   ASSERT (!fwriting (fp));
89   /* This fseek call is necessary when switching from reading to writing.
90      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
91   if (fseek (fp, 0, SEEK_CUR) != 0)
92     goto skip;
93   ASSERT (!fwriting (fp));
94   if (fputc ('z', fp) != 'z')
95     goto skip;
96   ASSERT (fwriting (fp));
97   if (fseek (fp, 0, SEEK_END))
98     goto skip;
99   /* fwriting (fp) is undefined here, but freading (fp) is false.  */
100   if (fclose (fp))
101     goto skip;
102
103   /* Open it in read-write mode.  POSIX requires a reposition (fseek,
104      fsetpos, rewind) or fflush when transitioning from write to read,
105      fwriting is only deterministic after input or output, but this
106      test case should be portable even on open, after reposition, and
107      after fflush.  */
108   fp = fopen (TESTFILE, "r+");
109   if (fp == NULL)
110     goto skip;
111   ASSERT (!fwriting (fp));
112   if (fgetc (fp) != 'f')
113     goto skip;
114   ASSERT (!fwriting (fp));
115   if (fseek (fp, 2, SEEK_CUR))
116     goto skip;
117   ASSERT (!fwriting (fp));
118   if (fgetc (fp) != 'b')
119     goto skip;
120   ASSERT (!fwriting (fp));
121   fflush (fp);
122   ASSERT (!fwriting (fp));
123   if (fgetc (fp) != 'a')
124     goto skip;
125   ASSERT (!fwriting (fp));
126   /* This fseek call is necessary when switching from reading to writing.
127      See the description of fopen(), ISO C 99 7.19.5.3.(6).  */
128   if (fseek (fp, 0, SEEK_CUR) != 0)
129     goto skip;
130   ASSERT (!fwriting (fp));
131   if (fputc ('z', fp) != 'z')
132     goto skip;
133   ASSERT (fwriting (fp));
134   if (fseek (fp, 0, SEEK_END))
135     goto skip;
136   /* fwriting (fp) is undefined here, but freading (fp) is false.  */
137   if (fclose (fp))
138     goto skip;
139
140   /* Open it in append mode.  */
141   fp = fopen (TESTFILE, "a");
142   if (fp == NULL)
143     goto skip;
144   ASSERT (fwriting (fp));
145   if (fwrite ("bla", 1, 3, fp) < 3)
146     goto skip;
147   ASSERT (fwriting (fp));
148   if (fclose (fp))
149     goto skip;
150
151   return 0;
152
153  skip:
154   fprintf (stderr, "Skipping test: file operations failed.\n");
155   return 77;
156 }