test-istream-seekable.c revision 5f5870385cff47efd2f58e7892f251cf13761528
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2009-2012 Dovecot authors, see the included COPYING file */
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#include "test-lib.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "istream-private.h"
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#include "istream-seekable.h"
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#include <stdlib.h>
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#include <fcntl.h>
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#include <unistd.h>
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainenstatic int fd_callback(const char **path_r, void *context ATTR_UNUSED)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen{
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen int fd;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen *path_r = "test-lib.tmp";
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen fd = open(*path_r, O_RDWR | O_CREAT | O_TRUNC, 0600);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen if (fd == -1)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_error("creat(%s) failed: %m", *path_r);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen else
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen unlink(*path_r);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen return fd;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen}
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainenstatic void test_istream_seekable_one(unsigned int buffer_size)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen{
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen static const char *input_string = "xyz";
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#define STREAM_COUNT 5
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#define STREAM_BYTES 3
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen struct istream *streams[STREAM_COUNT+1];
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen struct istream *input;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen const unsigned char *data;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen size_t size;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen unsigned int i, j;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i < STREAM_COUNT; i++) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams[i] = test_istream_create(input_string);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams[i]->seekable = FALSE;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_istream_set_allow_eof(streams[i], TRUE);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_istream_set_size(streams[i], 0);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams[i] = NULL;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen input = i_stream_create_seekable(streams, buffer_size, fd_callback, NULL);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i/STREAM_BYTES < STREAM_COUNT; i++) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_istream_set_size(streams[i/STREAM_BYTES], (i%STREAM_BYTES) + 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen if (i < buffer_size) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(i_stream_read(input) == 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen data = i_stream_get_data(input, &size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(size == i+1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen } else {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(i_stream_read(input) == -2);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_skip(input, 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(i_stream_read(input) == 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen data = i_stream_get_data(input, &size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(size == buffer_size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (j = 0; j < size; j++) {
4efba37e4f27b93832f6147c3a353d6d22c855c7Timo Sirainen test_assert((char)data[j] == input_string[(input->v_offset + j) % STREAM_BYTES]);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i < STREAM_COUNT; i++)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_unref(&streams[i]);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_unref(&input);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen}
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainenstatic void test_istream_seekable_random(void)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen{
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen struct istream **streams, *input;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen const unsigned char *data;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen unsigned char *w_data;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen size_t size;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen unsigned int i, j, offset, stream_count, data_len, buffer_size;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen stream_count = (rand() % 10) + 2;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams = t_new(struct istream *, stream_count + 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0, offset = 0; i < stream_count; i++) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen data_len = rand() % 100 + 1;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen w_data = t_malloc(data_len);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (j = 0; j < data_len; j++)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen w_data[j] = offset++;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams[i] = test_istream_create_data(w_data, data_len);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams[i]->seekable = FALSE;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_istream_set_allow_eof(streams[i], TRUE);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams[i] = NULL;
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen i_assert(offset > 0);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen buffer_size = (rand() % 100) + 1; size = 0;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen input = i_stream_create_seekable(streams, buffer_size, fd_callback, NULL);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen /* first read it through */
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen while (i_stream_read(input) > 0) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen (void)i_stream_get_data(input, &size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_skip(input, size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_seek(input, 0);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i < 100; i++) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen if (rand() % 3 == 0) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_seek(input, rand() % offset);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen } else {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen ssize_t ret = i_stream_read(input);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen if (input->v_offset + size == offset)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(ret < 0);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen else if (ret == -2) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(size == buffer_size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen } else {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(ret > 0);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(input->v_offset + ret <= offset);
32f39001908869449523f53d2d08b2653d2d9772Timo Sirainen i_stream_skip(input, rand() % (ret+1));
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen data = i_stream_get_data(input, &size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (j = 0; j < size; j++) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(data[j] == (input->v_offset + j) % 256);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen (void)i_stream_get_data(input, &size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i < stream_count; i++)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_unref(&streams[i]);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_unref(&input);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen}
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainenstatic void test_istream_seekable_eof(void)
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen{
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen static const char *in_str = "foo";
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen unsigned int in_str_len = strlen(in_str);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen struct istream *streams[2], *input;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen const unsigned char *data;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen size_t size;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_begin("istream seekable eof");
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen streams[0] = i_stream_create_from_data(in_str, in_str_len);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen streams[0]->seekable = FALSE;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen streams[1] = NULL;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen input = i_stream_create_seekable(streams, in_str_len, fd_callback, NULL);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_stream_unref(&streams[0]);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_assert(i_stream_read(input) == (ssize_t)in_str_len);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen data = i_stream_get_data(input, &size);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_assert(size == in_str_len);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_assert(memcmp(data, in_str, in_str_len) == 0);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_assert(i_stream_read(input) == -1);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen data = i_stream_get_data(input, &size);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_assert(size == in_str_len);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_assert(memcmp(data, in_str, in_str_len) == 0);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_stream_unref(&input);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_end();
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen}
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainenvoid test_istream_seekable(void)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen{
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen unsigned int i;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_begin("istream seekable");
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 1; i <= STREAM_BYTES*STREAM_COUNT; i++)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_istream_seekable_one(i);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_end();
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_begin("istream seekable random");
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i < 100; i++) T_BEGIN {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_istream_seekable_random();
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen } T_END;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_end();
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen test_istream_seekable_eof();
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen}