test-istream-concat.c revision 16b5dc27e7db42849510403d37e3629aba14de21
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "test-lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "istream-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "istream-concat.h"
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include <fcntl.h>
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen#include <unistd.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define TEST_MAX_ISTREAM_COUNT 10
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen#define TEST_MAX_ISTREAM_SIZE 1024
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define TEST_MAX_BUFFER_SIZE 128
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainenstatic void test_istream_concat_one(unsigned int buffer_size)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen static const char *input_string = "xyz";
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen#define STREAM_COUNT 5
5a6343181a5183b1ae1c39d40fc5a1deb3b840d9Timo Sirainen#define STREAM_BYTES 3
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream *streams[STREAM_COUNT+1];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream *input;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const unsigned char *data;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, j;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < STREAM_COUNT; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen streams[i] = test_istream_create(input_string);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_istream_set_allow_eof(streams[i], TRUE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_istream_set_size(streams[i], 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen streams[i] = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input = i_stream_create_concat(streams);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i/STREAM_BYTES < STREAM_COUNT; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_istream_set_size(streams[i/STREAM_BYTES], (i%STREAM_BYTES) + 1);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen test_assert(i_stream_read(input) == 1);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (i < buffer_size) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen data = i_stream_get_data(input, &size);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen test_assert(size == i+1);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen } else {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen i_stream_skip(input, 1);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen data = i_stream_get_data(input, &size);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen test_assert(size == buffer_size);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen }
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen for (j = 0; j < size; j++) {
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen test_assert((char)data[j] == input_string[(input->v_offset + j) % STREAM_BYTES]);
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen test_assert(i_stream_read(input) == -1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_skip(input, i_stream_get_data_size(input));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_unref(&input);
104318260228780a5c6b3181b3401e8e504e2776Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < STREAM_COUNT; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_assert(i_stream_is_eof(streams[i]));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_unref(&streams[i]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainenstatic bool test_istream_concat_random(void)
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream **streams, *concat, **limits = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const unsigned char *data;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned char *w_data;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t size = 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, j, offset, stream_count, data_len, simult;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen stream_count = (rand() % TEST_MAX_ISTREAM_COUNT) + 2;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen streams = t_new(struct istream *, stream_count + 1);
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen for (i = 0, offset = 0; i < stream_count; i++) {
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen data_len = rand() % TEST_MAX_ISTREAM_SIZE + 1;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen w_data = t_malloc_no0(data_len);
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen for (j = 0; j < data_len; j++)
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen w_data[j] = offset++;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen streams[i] = test_istream_create_data(w_data, data_len);
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen test_istream_set_allow_eof(streams[i], TRUE);
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen }
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen streams[i] = NULL;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen i_assert(offset > 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen concat = i_stream_create_concat(streams);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen i_stream_set_max_buffer_size(concat, TEST_MAX_BUFFER_SIZE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen simult = rand() % TEST_MAX_ISTREAM_COUNT;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (simult > 0) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen limits = t_new(struct istream *, simult);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen for (i = 0; i < simult; i++)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen limits[i] = i_stream_create_limit(concat, (uoff_t)-1);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen for (i = 0; i < 1000; i++) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct istream *input = (simult == 0) ? concat : limits[rand() % simult];
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (rand() % 3 == 0) {
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen i_stream_seek(input, rand() % offset);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ssize_t ret = i_stream_read(input);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size = i_stream_get_data_size(input);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret == -2) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_assert(size >= TEST_MAX_BUFFER_SIZE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (input->v_offset + size != offset) {
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainen test_assert(ret > 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_assert(input->v_offset + ret <= offset);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_skip(input, rand() % ret);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen data = i_stream_get_data(input, &size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (j = 0; j < size; j++) {
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen test_assert(data[j] == (input->v_offset + j) % 256);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (test_has_failed())
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < stream_count; i++)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen i_stream_unref(&streams[i]);
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen for (i = 0; i < simult; i++)
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen i_stream_unref(&limits[i]);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen i_stream_unref(&concat);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return !test_has_failed();
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic void test_istream_concat_seek_end(void)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen{
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen test_begin("istream concat seek end");
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen struct istream *streams[] = {
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen test_istream_create("s1"),
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen test_istream_create("s2"),
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen NULL
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen };
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen struct istream *input = i_stream_create_concat(streams);
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen i_stream_seek(input, 4);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen test_assert(i_stream_read(input) == -1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_unref(&input);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_end();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainenstatic void test_istream_concat_early_end(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen struct istream *input, *streams[2];
d6b3cfd855c0eebed68be50d3111de1b5a6afeb0Timo Sirainen
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen test_begin("istream concat early end");
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen streams[0] = test_istream_create("stream");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen test_istream_set_size(streams[0], 3);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_istream_set_allow_eof(streams[0], FALSE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen streams[1] = NULL;
cd2ed64888b42b481cde6bb9548c8520516fa3e9Timo Sirainen
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen input = i_stream_create_concat(streams);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_assert(i_stream_read(input) == 3);
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen test_istream_set_size(streams[0], 5);
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen test_assert(i_stream_read(input) == 2);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_skip(input, 5);
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen i_stream_unref(&input);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen test_assert(streams[0]->v_offset == 5);
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen i_stream_unref(&streams[0]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_end();
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen}
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid test_istream_concat(void)
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen{
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen unsigned int i;
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen test_begin("istream concat");
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen for (i = 1; i < STREAM_BYTES*STREAM_COUNT; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_istream_concat_one(i);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen test_end();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen test_begin("istream concat random");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < 100; i++) T_BEGIN {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if(!test_istream_concat_random())
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen i = 101; /* don't break a T_BEGIN */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen } T_END;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen test_end();
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen test_istream_concat_seek_end();
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen test_istream_concat_early_end();
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen}
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen