bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen#include "test-lib.h"
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen#include "istream.h"
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen#include "ostream.h"
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen#include "iostream-temp.h"
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen#include <unistd.h>
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen#include <fcntl.h>
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainenstatic void test_iostream_temp_create_sized_memory(void)
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen{
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen struct ostream *output;
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_begin("iostream_temp_create_sized() memory");
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/", 0, "test", 4);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_send(output, "123", 3) == 3);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 3);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_send(output, "4", 1) == 1);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 4);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_get_fd(output) == -1);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen /* now we'll try to switch to writing to a file, but it'll fail */
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_expect_error_string("safe_mkstemp");
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_send(output, "5", 1) == 1);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_expect_no_more_errors();
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_get_fd(output) == -1);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen o_stream_destroy(&output);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_end();
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen}
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainenstatic void test_iostream_temp_create_sized_disk(void)
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen{
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen struct ostream *output;
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_begin("iostream_temp_create_sized() disk");
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen output = iostream_temp_create_sized(".", 0, "test", 4);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_send(output, "123", 3) == 3);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 3);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_send(output, "4", 1) == 1);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 4);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_get_fd(output) == -1);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_send(output, "5", 1) == 1);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 5);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_assert(o_stream_get_fd(output) != -1);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen o_stream_destroy(&output);
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_end();
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen}
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen
d97f081a3de44852197ced772e21560c108895a6Timo Sirainenstatic void test_iostream_temp_create_write_error(void)
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen{
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen struct ostream *output;
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_begin("iostream_temp_create_sized() write error");
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen output = iostream_temp_create_sized(".", 0, "test", 1);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(o_stream_send(output, "123", 3) == 3);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(o_stream_get_fd(output) != -1);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(output->offset == 3);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(o_stream_temp_move_to_memory(output) == 0);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(o_stream_get_fd(output) == -1);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(o_stream_send(output, "45", 2) == 2);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(output->offset == 5);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen const unsigned char *data;
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen size_t size;
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen struct istream *input = iostream_temp_finish(&output, 128);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_assert(i_stream_read_bytes(input, &data, &size, 5) == 1 &&
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen memcmp(data, "12345", 5) == 0);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen i_stream_destroy(&input);
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_end();
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen}
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainenstatic void test_iostream_temp_istream(void)
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen{
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen struct istream *input, *input2, *temp_input;
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen struct ostream *output;
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen int fd;
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_begin("iostream_temp istream");
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen fd = open(".temp.istream", O_RDWR | O_CREAT | O_TRUNC, 0600);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen if (fd == -1)
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen i_fatal("create(.temp.istream) failed: %m");
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_assert(write(fd, "foobar", 6) == 6);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_assert(lseek(fd, 0, SEEK_SET) == 0);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi input = i_stream_create_fd_autoclose(&fd, 1024);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen /* a working fd-dup */
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen output = iostream_temp_create_sized(".nonexistent/",
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 1);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 6);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen temp_input = iostream_temp_finish(&output, 128);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_assert(i_stream_read(temp_input) == 6);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen i_stream_destroy(&temp_input);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen /* non-working fd-dup: write data before sending istream */
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen i_stream_seek(input, 0);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/",
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_assert(o_stream_send(output, "1234", 4) == 4);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 4);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_expect_error_string("safe_mkstemp");
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 10);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_expect_no_more_errors();
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen o_stream_destroy(&output);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen /* non-working fd-dup: write data after sending istream */
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen i_stream_seek(input, 0);
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/",
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 6);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_expect_error_string("safe_mkstemp");
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen test_assert(o_stream_send(output, "1", 1) == 1);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 7);
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen test_expect_no_more_errors();
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen o_stream_destroy(&output);
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen /* non-working fd-dup: send two istreams */
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen i_stream_seek(input, 0);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen input2 = i_stream_create_limit(input, (uoff_t)-1);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen output = iostream_temp_create_sized(".intentional-nonexistent-error/",
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen test_assert(o_stream_send_istream(output, input) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 6);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_expect_error_string("safe_mkstemp");
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen test_assert(o_stream_send_istream(output, input2) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
431c0aba57fba2fd6eb398acd6ef4e73b5dc1b86Timo Sirainen test_assert(output->offset == 12);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_expect_no_more_errors();
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen o_stream_destroy(&output);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen i_stream_unref(&input2);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen i_stream_destroy(&input);
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen i_unlink(".temp.istream");
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_end();
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen}
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainenvoid test_iostream_temp(void)
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen{
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_iostream_temp_create_sized_memory();
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen test_iostream_temp_create_sized_disk();
d97f081a3de44852197ced772e21560c108895a6Timo Sirainen test_iostream_temp_create_write_error();
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen test_iostream_temp_istream();
2686ef87921233609d1d8ec8dee2883facc2c5ebTimo Sirainen}