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