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;
}
|