bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 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-concat.h"
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#include <fcntl.h>
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen#include <unistd.h>
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen#define TEST_MAX_ISTREAM_COUNT 10
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen#define TEST_MAX_ISTREAM_SIZE 1024
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen#define TEST_MAX_BUFFER_SIZE 128
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainenstatic void test_istream_concat_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 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_concat(streams);
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 test_assert(i_stream_read(input) == 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen if (i < buffer_size) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen data = i_stream_get_data(input, &size);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(size == i+1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen } else {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_skip(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 }
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_assert(i_stream_read(input) == -1);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen i_stream_skip(input, i_stream_get_data_size(input));
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_unref(&input);
0abffe9703523839120b199257ecc995c353cc3cPhil Carmody
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen for (i = 0; i < STREAM_COUNT; i++) {
a05250bd599fca0cb8b761c4fd69f91bc1c3667eTimo Sirainen test_assert(streams[i]->eof && streams[i]->stream_errno == 0);
0abffe9703523839120b199257ecc995c353cc3cPhil Carmody i_stream_unref(&streams[i]);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen}
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
95be1d89911c56664b05ab1c16bbc5cbc1331df3Phil Carmodystatic bool test_istream_concat_random(void)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen{
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody struct istream **streams, *concat, **limits = NULL;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen const unsigned char *data;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen unsigned char *w_data;
c345aae9f46e6ecad7bd562089696e449f8b0099Timo Sirainen size_t size = 0;
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody unsigned int i, j, offset, stream_count, data_len, simult;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek stream_count = i_rand_minmax(2, TEST_MAX_ISTREAM_COUNT + 2 - 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams = t_new(struct istream *, stream_count + 1);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0, offset = 0; i < stream_count; i++) {
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek data_len = i_rand_minmax(1, TEST_MAX_ISTREAM_SIZE);
0175d37a5ae5a4d146ca41b684bd38d9b03683cbMartti Rannanjärvi w_data = t_malloc_no0(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 test_istream_set_allow_eof(streams[i], TRUE);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen streams[i] = NULL;
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen i_assert(offset > 0);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody concat = i_stream_create_concat(streams);
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody i_stream_set_max_buffer_size(concat, TEST_MAX_BUFFER_SIZE);
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek simult = i_rand_limit(TEST_MAX_ISTREAM_COUNT);
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody if (simult > 0) {
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody limits = t_new(struct istream *, simult);
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody for (i = 0; i < simult; i++)
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody limits[i] = i_stream_create_limit(concat, (uoff_t)-1);
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody }
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen for (i = 0; i < 1000; i++) {
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek struct istream *input = (simult == 0) ? concat : limits[i_rand_limit(simult)];
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek if (i_rand_limit(3) == 0) {
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek i_stream_seek(input, i_rand_limit(offset));
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen } else {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen ssize_t ret = i_stream_read(input);
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen size = i_stream_get_data_size(input);
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen if (ret == -2) {
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen test_assert(size >= TEST_MAX_BUFFER_SIZE);
32142dc3b19a1dff23ef351596703f1a43ea51a0Timo Sirainen } else if (input->v_offset + size != offset) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(ret > 0);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_assert(input->v_offset + ret <= offset);
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek i_stream_skip(input, i_rand_limit(ret));
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 }
95be1d89911c56664b05ab1c16bbc5cbc1331df3Phil Carmody if (test_has_failed())
95be1d89911c56664b05ab1c16bbc5cbc1331df3Phil Carmody break;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i < stream_count; i++)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen i_stream_unref(&streams[i]);
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody for (i = 0; i < simult; i++)
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody i_stream_unref(&limits[i]);
1d020f1c116ce86af2ebd108a453f7bb31240adaPhil Carmody i_stream_unref(&concat);
95be1d89911c56664b05ab1c16bbc5cbc1331df3Phil Carmody return !test_has_failed();
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen}
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainenstatic void test_istream_concat_seek_end(void)
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen{
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen test_begin("istream concat seek end");
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen struct istream *streams[] = {
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen test_istream_create("s1"),
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen test_istream_create("s2"),
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen NULL
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen };
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen struct istream *input = i_stream_create_concat(streams);
cb4d75e1b821feb577cfe6236d692a992203014eTimo Sirainen i_stream_unref(&streams[0]);
cb4d75e1b821feb577cfe6236d692a992203014eTimo Sirainen i_stream_unref(&streams[1]);
cb4d75e1b821feb577cfe6236d692a992203014eTimo Sirainen
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen i_stream_seek(input, 4);
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen test_assert(i_stream_read(input) == -1);
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen i_stream_unref(&input);
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen test_end();
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen}
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainenstatic void test_istream_concat_early_end(void)
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen{
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen struct istream *input, *streams[2];
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_begin("istream concat early end");
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen streams[0] = test_istream_create("stream");
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_istream_set_size(streams[0], 3);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_istream_set_allow_eof(streams[0], FALSE);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen streams[1] = NULL;
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen input = i_stream_create_concat(streams);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_assert(i_stream_read(input) == 3);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_istream_set_size(streams[0], 5);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_assert(i_stream_read(input) == 2);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen i_stream_skip(input, 5);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen i_stream_unref(&input);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_assert(streams[0]->v_offset == 5);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen i_stream_unref(&streams[0]);
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_end();
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen}
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainenvoid test_istream_concat(void)
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen{
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen unsigned int i;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_begin("istream concat");
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 1; i < STREAM_BYTES*STREAM_COUNT; i++) {
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_istream_concat_one(i);
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen }
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_end();
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_begin("istream concat random");
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen for (i = 0; i < 100; i++) T_BEGIN {
95be1d89911c56664b05ab1c16bbc5cbc1331df3Phil Carmody if(!test_istream_concat_random())
95be1d89911c56664b05ab1c16bbc5cbc1331df3Phil Carmody i = 101; /* don't break a T_BEGIN */
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen } T_END;
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen test_end();
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen
16b5dc27e7db42849510403d37e3629aba14de21Timo Sirainen test_istream_concat_seek_end();
5c92436a61569c0b56a9374e60e779fa4455edefTimo Sirainen test_istream_concat_early_end();
7d548d4984752d74bfea8dc4bf1781a8996f43e7Timo Sirainen}