summaryrefslogtreecommitdiff
path: root/tests/test-fpurge.c
blob: 386bbe9fa2ed27919bb7dd48be182a54eed524e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Test of fpurge() function.
   Copyright (C) 2007-2023 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <bruno@clisp.org>, 2007.  */

#include <config.h>

/* None of the files accessed by this test are large, so disable the
   fseek link warning if we are not using the gnulib fseek module.  */
#define _GL_NO_LARGE_FILES
#include <stdio.h>

#include <string.h>

#include "macros.h"

#define TESTFILE "t-fpurge.tmp"

int
main (void)
{
  int check_filepos;

  for (check_filepos = 0; check_filepos <= 1; check_filepos++)
    {
      FILE *fp;

      /* Create a file with some contents.  */
      fp = fopen (TESTFILE, "w");
      if (fp == NULL)
        goto skip;
      if (fwrite ("foobarsh", 1, 8, fp) < 8)
        goto skip;
      if (fclose (fp))
        goto skip;

      /* The file's contents is now "foobarsh".  */

      /* Open it in read-write mode.  */
      fp = fopen (TESTFILE, "r+");
      if (fp == NULL)
        goto skip;
      if (fseek (fp, 3, SEEK_CUR))
        goto skip;
      if (fwrite ("g", 1, 1, fp) < 1)
        goto skip;
      if (fflush (fp))
        goto skip;
      if (fwrite ("bz", 1, 2, fp) < 2)
        goto skip;
      /* Discard pending write.  */
      ASSERT (fpurge (fp) == 0);
      /* Verify that when discarding pending output, the file position is set
         back to where it was before the write calls.  */
      if (check_filepos)
        ASSERT (ftell (fp) == 4);
      ASSERT (fclose (fp) == 0);

      /* Open it in read-only mode.  */
      fp = fopen (TESTFILE, "r");
      if (fp == NULL)
        goto skip;
      /* Verify that the pending writes before the fpurge were really
         discarded.  */
      {
        char buf[8];
        if (fread (buf, 1, 7, fp) < 7)
          goto skip;
        ASSERT (memcmp (buf, "foogars", 7) == 0);
      }
      /* Discard the buffered 'h'.  */
      if (check_filepos)
        ASSERT (ftell (fp) == 7);
      ASSERT (fpurge (fp) == 0);
      /* Verify that when discarding pending input, the file position is
         advanced to match the end of the previously read input.  */
      if (check_filepos)
        ASSERT (ftell (fp) == 8);
      ASSERT (getc (fp) == EOF);
      ASSERT (fclose (fp) == 0);

      /* The file's contents is now "foogarsh".  */

      /* Ensure that purging a read does not corrupt subsequent writes.  */
      fp = fopen (TESTFILE, "r+");
      if (fp == NULL)
        goto skip;
      if (fseek (fp, -1, SEEK_END))
        goto skip;
      ASSERT (getc (fp) == 'h');
      ASSERT (getc (fp) == EOF);
      if (check_filepos)
        ASSERT (ftell (fp) == 8);
      ASSERT (fpurge (fp) == 0);
      if (check_filepos)
        ASSERT (ftell (fp) == 8);
      ASSERT (putc ('!', fp) == '!');
      if (check_filepos)
        ASSERT (ftell (fp) == 9);
      ASSERT (fclose (fp) == 0);
      fp = fopen (TESTFILE, "r");
      if (fp == NULL)
        goto skip;
      {
        char buf[10];
        ASSERT (fread (buf, 1, 10, fp) == 9);
        ASSERT (memcmp (buf, "foogarsh!", 9) == 0);
      }
      ASSERT (fclose (fp) == 0);

      /* The file's contents is now "foogarsh!".  */
    }

  remove (TESTFILE);
  return 0;

 skip:
  fprintf (stderr, "Skipping test: prerequisite file operations failed.\n");
  remove (TESTFILE);
  return 77;
}