File: t-rdcache.c

package info (click to toggle)
mailutils 1%3A3.20-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 38,932 kB
  • sloc: ansic: 187,772; sh: 111,430; yacc: 7,463; cpp: 3,834; makefile: 3,166; lex: 1,972; python: 1,617; exp: 1,563; awk: 152; lisp: 132; sed: 31
file content (135 lines) | stat: -rw-r--r-- 4,098 bytes parent folder | download | duplicates (2)
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
135
/* t-rdcache - test mailutils rdcache streams

  SYNOPSIS
    t-rdcache

  DESCRIPTION
    This program test basic functionality of mailutils rdcache streams by
    reading from the stream until the EOF, rewinding it and reading again.
    The obtained content is verified on both passes (the first pass reads
    from the transport stream and fills in the cache, the second pass reads
    cached data).

    Until mailutils version 3.15, read cache stream incorrectly updated
    its size when it should not.  This happened when the stream had cached
    some data, then had been rewound and a read operation performed on it.
    To check if the bug is fixed, the stream size is obtained at the end
    of second pass and compared with the actual size of the transport
    stream.

    Exit code is 0 if all checks passed and 1 otherwise.

  SEE ALSO
    libmailutils/stream/rdcache_stream.c - implementation of the read
    cache stream.

  LICENSE
    This file is part of GNU mailutils.
    Copyright (C) 2020-2025 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, 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 <http://www.gnu.org/licenses/>.
*/

#include <config.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <mailutils/mailutils.h>

static char pattern[] = "0123456789";
static size_t pattern_len = sizeof(pattern) - 1;

void
check_pattern (char *buf, size_t len, void *closure)
{
  mu_off_t pos = *(mu_off_t*)closure;
  while (len--)
    {
      if (*buf != pattern[pos % pattern_len])
	{
	  mu_error ("%zu: pattern mismatch", pos);
	  exit (1);
	}
      buf++;
      pos++;
    }
  *(mu_off_t*)closure = pos;
}

int
main (int argc, char **argv)
{
  mu_stream_t nullstr, cachestr, sink;
  mu_off_t n = 16384, s, p;
  struct mu_nullstream_pattern pat;
  mu_stream_stat_buffer stat;

  /* Create transport stream with a fixed size and well-known pattern. */
  MU_ASSERT (mu_nullstream_create (&nullstr, MU_STREAM_READ));
  MU_ASSERT (mu_stream_ioctl (nullstr, MU_IOCTL_NULLSTREAM, MU_IOCTL_NULLSTREAM_SETSIZE, &n));

  pat.pattern = pattern;
  pat.size = strlen(pattern);
  MU_ASSERT (mu_stream_ioctl (nullstr, MU_IOCTL_NULLSTREAM, MU_IOCTL_NULLSTREAM_SET_PATTERN, &pat));

  /* Create rdcache stream. */
  MU_ASSERT (mu_rdcache_stream_create (&cachestr, nullstr, MU_STREAM_READ));

  /* Create sink. */
  MU_ASSERT (mu_nullstream_create (&sink, MU_STREAM_WRITE));

  /*
   * Copy stream to sink and check if its content matches the pattern.
   * This will read from nullstr and fill in the cache.
   */
  p = 0;
  MU_ASSERT (mu_stream_copy_wcb (sink, cachestr, 0, NULL, check_pattern, &p));
  if (p != n)
    {
      mu_error ("Bad read size on first pass");
      return 1;
    }

  /* Rewind the stream */
  MU_ASSERT (mu_stream_seek (cachestr, 0, MU_SEEK_SET, NULL));

  /*
   * Copy and check the pattern again.  This time data will be served
   * from the cached copy and nullstr should not be accessed at all.
   * To make sure it is so, monitor the number of bytes read from it.
   */
  mu_stream_set_stat (nullstr, MU_STREAM_STAT_MASK (MU_STREAM_STAT_IN), stat);

  p = 0;
  MU_ASSERT (mu_stream_copy_wcb (sink, cachestr, 0, NULL, check_pattern, &p));
  if (p != n)
    {
      mu_error ("Bad read size on second pass");
      return 1;
    }

  if (stat[MU_STREAM_STAT_IN])
    {
      mu_error ("Transport stream accessed when it should not");
      return 1;
    }

  MU_ASSERT (mu_stream_size (cachestr, &s));
  if (s != n)
    {
      mu_error ("wrong stream size reported");
      return 1;
    }
  return 0;
}