test-iostream-temp.c revision d97f081a3de44852197ced772e21560c108895a6
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "test-lib.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "istream.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "ostream.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "iostream-temp.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include <unistd.h>
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include <fcntl.h>
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void test_iostream_temp_create_sized_memory(void)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct ostream *output;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_begin("iostream_temp_create_sized() memory");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/", 0, "test", 4);
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainen test_assert(o_stream_send(output, "123", 3) == 3);
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainen test_assert(output->offset == 3);
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainen test_assert(o_stream_send(output, "4", 1) == 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 4);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_get_fd(output) == -1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* now we'll try to switch to writing to a file, but it'll fail */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_error_string("safe_mkstemp");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send(output, "5", 1) == 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_no_more_errors();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_get_fd(output) == -1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen o_stream_destroy(&output);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_end();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void test_iostream_temp_create_sized_disk(void)
46e917c9fa05cbe7bddf805d3a9838b61e3960e1Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct ostream *output;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_begin("iostream_temp_create_sized() disk");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen output = iostream_temp_create_sized(".", 0, "test", 4);
46e917c9fa05cbe7bddf805d3a9838b61e3960e1Timo Sirainen test_assert(o_stream_send(output, "123", 3) == 3);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 3);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send(output, "4", 1) == 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 4);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_get_fd(output) == -1);
b49aa341d28c0eec1229e30baa2f89d5bae52ff8Phil Carmody test_assert(o_stream_send(output, "5", 1) == 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 5);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_get_fd(output) != -1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen o_stream_destroy(&output);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_end();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void test_iostream_temp_create_write_error(void)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen struct ostream *output;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_begin("iostream_temp_create_sized() write error");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen output = iostream_temp_create_sized(".", 0, "test", 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send(output, "123", 3) == 3);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_get_fd(output) != -1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 3);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_temp_move_to_memory(output) == 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_get_fd(output) == -1);
0ca3b9cb0f2a322a25ce7f229dc3d3a0b46be17bTimo Sirainen test_assert(o_stream_send(output, "45", 2) == 2);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 5);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen const unsigned char *data;
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen size_t size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct istream *input = iostream_temp_finish(&output, 128);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(i_stream_read_bytes(input, &data, &size, 5) == 1 &&
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen memcmp(data, "12345", 5) == 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_destroy(&input);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen test_end();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void test_iostream_temp_istream(void)
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen{
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen struct istream *input, *input2, *temp_input;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct ostream *output;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen int fd;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_begin("iostream_temp istream");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen fd = open(".temp.istream", O_RDWR | O_CREAT | O_TRUNC, 0600);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (fd == -1)
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen i_fatal("create(.temp.istream) failed: %m");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(write(fd, "foobar", 6) == 6);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(lseek(fd, 0, SEEK_SET) == 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen input = i_stream_create_fd_autoclose(&fd, 1024);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* a working fd-dup */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen output = iostream_temp_create_sized(".nonexistent/",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
56aa97d74071f3a2987140c2ff1cfd5a59cb35aaTimo Sirainen test_assert(output->offset == 6);
56aa97d74071f3a2987140c2ff1cfd5a59cb35aaTimo Sirainen temp_input = iostream_temp_finish(&output, 128);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(i_stream_read(temp_input) == 6);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_destroy(&temp_input);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* non-working fd-dup: write data before sending istream */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_seek(input, 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send(output, "1234", 4) == 4);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 4);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_error_string("safe_mkstemp");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 10);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_no_more_errors();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen o_stream_destroy(&output);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* non-working fd-dup: write data after sending istream */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_seek(input, 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 6);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_error_string("safe_mkstemp");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send(output, "1", 1) == 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 7);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_no_more_errors();
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen o_stream_destroy(&output);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* non-working fd-dup: send two istreams */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_seek(input, 0);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen input2 = i_stream_create_limit(input, (uoff_t)-1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 6);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_error_string("safe_mkstemp");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(o_stream_send_istream(output, input2) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_assert(output->offset == 12);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_expect_no_more_errors();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen o_stream_destroy(&output);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_unref(&input2);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_destroy(&input);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_unlink(".temp.istream");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_end();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid test_iostream_temp(void)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_iostream_temp_create_sized_memory();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_iostream_temp_create_sized_disk();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_iostream_temp_create_write_error();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen test_iostream_temp_istream();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen