bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include "lib.h"
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen#include "buffer.h"
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include "istream.h"
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include "ostream.h"
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include "sha1.h"
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include "randgen.h"
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include "test-common.h"
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include "compression.h"
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include <unistd.h>
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen#include <fcntl.h>
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainenstatic void test_compression_handler(const struct compression_handler *handler)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen{
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen const char *path = "test-compression.tmp";
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen struct istream *file_input, *input;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen struct ostream *file_output, *output;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen unsigned char buf[IO_BLOCK_SIZE];
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen const unsigned char *data;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen size_t size;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen struct sha1_ctxt sha1;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen unsigned char output_sha1[SHA1_RESULTLEN], input_sha1[SHA1_RESULTLEN];
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen unsigned int i;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen int fd;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen ssize_t ret;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_begin(t_strdup_printf("compression handler %s", handler->name));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen /* write compressed data */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen fd = open(path, O_TRUNC | O_CREAT | O_RDWR, 0600);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (fd == -1)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_fatal("creat(%s) failed: %m", path);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen file_output = o_stream_create_fd_file(fd, 0, FALSE);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen output = handler->create_ostream(file_output, 1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_init(&sha1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen /* 1) write lots of easily compressible data */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen memset(buf, 0, sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen for (i = 0; i < 1024*1024*4 / sizeof(buf); i++) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_loop(&sha1, buf, sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_assert(o_stream_send(output, buf, sizeof(buf)) == sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen /* 2) write uncompressible data */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen for (i = 0; i < 1024*128 / sizeof(buf); i++) {
2a628a8c90839439baff5b45116f89f2b3cd9e37Aki Tuomi random_fill(buf, sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_loop(&sha1, buf, sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_assert(o_stream_send(output, buf, sizeof(buf)) == sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen /* 3) write semi-compressible data */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen for (i = 0; i < sizeof(buf); i++) {
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek if (i_rand_limit(3) == 0)
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek buf[i] = i_rand_limit(4);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen else
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen buf[i] = i;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen for (i = 0; i < 1024*128 / sizeof(buf); i++) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_loop(&sha1, buf, sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_assert(o_stream_send(output, buf, sizeof(buf)) == sizeof(buf));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
6fb8641aa5619d0c0dcd7be7570767f9688a953dTimo Sirainen test_assert(o_stream_finish(output) > 0);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen o_stream_destroy(&output);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen o_stream_destroy(&file_output);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_result(&sha1, output_sha1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen /* read and uncompress the data */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_init(&sha1);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi file_input = i_stream_create_fd(fd, IO_BLOCK_SIZE);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen input = handler->create_istream(file_input, FALSE);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_loop(&sha1, data, size);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_skip(input, size);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_assert(ret == -1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_destroy(&input);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_destroy(&file_input);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_result(&sha1, input_sha1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_assert(memcmp(input_sha1, output_sha1, sizeof(input_sha1)) == 0);
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink(path);
5507b0c7e5106e88e038c24f8067ef8d1be4fbaaTimo Sirainen i_close_fd(&fd);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_end();
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen}
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainenstatic void test_compression(void)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen{
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen unsigned int i;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen for (i = 0; compression_handlers[i].name != NULL; i++) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (compression_handlers[i].create_istream != NULL)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_compression_handler(&compression_handlers[i]);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen}
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainenstatic void test_gz(const char *str1, const char *str2)
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen{
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen const struct compression_handler *gz = compression_lookup_handler("gz");
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen struct ostream *buf_output, *output;
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen struct istream *test_input, *input;
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buffer_t *buf = t_buffer_create(512);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen if (gz == NULL || gz->create_ostream == NULL)
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen return; /* not compiled in */
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen /* write concated output */
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen buf_output = o_stream_create_buffer(buf);
8e8b9d01d454fc3dc81dbe3fd1cca772d1d2c381Timo Sirainen o_stream_set_finish_via_child(buf_output, FALSE);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen output = gz->create_ostream(buf_output, 6);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen o_stream_nsend_str(output, str1);
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen test_assert(o_stream_finish(output) > 0);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen o_stream_destroy(&output);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen if (str2[0] != '\0') {
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen output = gz->create_ostream(buf_output, 6);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen o_stream_nsend_str(output, "world");
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen test_assert(o_stream_finish(output) > 0);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen o_stream_destroy(&output);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen }
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen o_stream_destroy(&buf_output);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen /* read concated input */
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen const unsigned char *data;
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen size_t size;
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_input = test_istream_create_data(buf->data, buf->used);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_istream_set_allow_eof(test_input, FALSE);
00bcc83b18793b9ec5e5d264480a88bf78b10b33Timo Sirainen input = gz->create_istream(test_input, TRUE);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen for (size_t i = 0; i <= buf->used; i++) {
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_istream_set_size(test_input, i);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_assert(i_stream_read(input) >= 0);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen }
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_istream_set_allow_eof(test_input, TRUE);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_assert(i_stream_read(input) == -1);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_assert(input->stream_errno == 0);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen data = i_stream_get_data(input, &size);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_assert(size == strlen(str1)+strlen(str2) &&
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen memcmp(data, str1, strlen(str1)) == 0 &&
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen memcmp(data+strlen(str1), str2, strlen(str2)) == 0);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen i_stream_unref(&input);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen i_stream_unref(&test_input);
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen}
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainenstatic void test_gz_concat(void)
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen{
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_begin("gz concat");
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_gz("hello", "world");
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_end();
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen}
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainenstatic void test_gz_no_concat(void)
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen{
b317602a1dd7588710bd004404cd68cf2d699361Timo Sirainen test_begin("gz no concat");
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_gz("hello", "");
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_end();
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen}
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainenstatic void test_gz_large_header(void)
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen{
b317602a1dd7588710bd004404cd68cf2d699361Timo Sirainen const struct compression_handler *gz = compression_lookup_handler("gz");
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen static const unsigned char gz_input[] = {
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen 0x1f, 0x8b, 0x08, 0x08,
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen 'a','a','a','a','a','a','a','a','a','a','a',
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen 0
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen };
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen struct istream *file_input, *input;
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen size_t i;
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen
b317602a1dd7588710bd004404cd68cf2d699361Timo Sirainen if (gz == NULL || gz->create_istream == NULL)
b317602a1dd7588710bd004404cd68cf2d699361Timo Sirainen return; /* not compiled in */
b317602a1dd7588710bd004404cd68cf2d699361Timo Sirainen
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_begin("gz large header");
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen /* max buffer size smaller than gz header */
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen for (i = 1; i < sizeof(gz_input); i++) {
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen file_input = test_istream_create_data(gz_input, sizeof(gz_input));
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_istream_set_size(file_input, i);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_istream_set_max_buffer_size(file_input, i);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen
b317602a1dd7588710bd004404cd68cf2d699361Timo Sirainen input = gz->create_istream(file_input, FALSE);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_assert_idx(i_stream_read(input) == 0, i);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_assert_idx(i_stream_read(input) == -1 &&
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen input->stream_errno == EINVAL, i);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen i_stream_unref(&input);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen i_stream_unref(&file_input);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen }
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen /* max buffer size is exactly the gz header */
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen file_input = test_istream_create_data(gz_input, sizeof(gz_input));
b317602a1dd7588710bd004404cd68cf2d699361Timo Sirainen input = gz->create_istream(file_input, FALSE);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_istream_set_size(input, i);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_istream_set_allow_eof(input, FALSE);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_istream_set_max_buffer_size(input, i);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_assert(i_stream_read(input) == 0);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen i_stream_unref(&input);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen i_stream_unref(&file_input);
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_end();
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen}
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainenstatic void test_uncompress_file(const char *path)
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen{
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen const struct compression_handler *handler;
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen struct istream *input, *file_input;
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen const unsigned char *data;
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen size_t size;
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen handler = compression_lookup_handler_from_ext(path);
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen if (handler == NULL)
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen i_fatal("Can't detect compression algorithm from path %s", path);
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen if (handler->create_istream == NULL)
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen i_fatal("Support not compiled in for %s", handler->name);
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen file_input = i_stream_create_file(path, IO_BLOCK_SIZE);
00bcc83b18793b9ec5e5d264480a88bf78b10b33Timo Sirainen input = handler->create_istream(file_input, TRUE);
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen while (i_stream_read_more(input, &data, &size) > 0) {
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen if (write(STDOUT_FILENO, data, size) < 0)
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen break;
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen i_stream_skip(input, size);
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen }
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen i_stream_destroy(&input);
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen}
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainenstatic void test_compress_file(const char *in_path, const char *out_path)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen{
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen const struct compression_handler *handler;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen struct istream *input, *file_input;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen struct ostream *output, *file_output;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen int fd_in, fd_out;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen struct sha1_ctxt sha1;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen unsigned char output_sha1[SHA1_RESULTLEN], input_sha1[SHA1_RESULTLEN];
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen const unsigned char *data;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen size_t size;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen ssize_t ret;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen handler = compression_lookup_handler_from_ext(out_path);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (handler == NULL)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_fatal("Can't detect compression algorithm from path %s", out_path);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (handler->create_ostream == NULL)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_fatal("Support not compiled in for %s", handler->name);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen /* write the compressed output file */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen fd_in = open(in_path, O_RDONLY);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (fd_in == -1)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_fatal("open(%s) failed: %m", in_path);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen fd_out = open(out_path, O_TRUNC | O_CREAT | O_RDWR, 0600);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (fd_out == -1)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_fatal("creat(%s) failed: %m", out_path);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_init(&sha1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen file_output = o_stream_create_fd_file(fd_out, 0, FALSE);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen output = handler->create_ostream(file_output, 1);
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen input = i_stream_create_fd_autoclose(&fd_in, IO_BLOCK_SIZE);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while (i_stream_read_more(input, &data, &size) > 0) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_loop(&sha1, data, size);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen o_stream_nsend(output, data, size);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_skip(input, size);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen if (o_stream_finish(output) < 0) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_fatal("write(%s) failed: %s",
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen out_path, o_stream_get_error(output));
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_destroy(&input);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen o_stream_destroy(&output);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen o_stream_destroy(&file_output);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_result(&sha1, output_sha1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen /* verify that we can read the compressed file */
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_init(&sha1);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi file_input = i_stream_create_fd(fd_out, IO_BLOCK_SIZE);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen input = handler->create_istream(file_input, FALSE);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_loop(&sha1, data, size);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_skip(input, size);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_destroy(&input);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_stream_destroy(&file_input);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen sha1_result(&sha1, input_sha1);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (memcmp(input_sha1, output_sha1, sizeof(input_sha1)) != 0)
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_fatal("Decompression couldn't get the original input");
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen i_close_fd(&fd_out);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen}
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainenint main(int argc, char *argv[])
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen{
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainen static void (*const test_functions[])(void) = {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_compression,
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_gz_concat,
e7f31dfdcf5c51983bc4a489d69714f763128c18Timo Sirainen test_gz_no_concat,
d827cffa4b59591ab2a5a710237e34839ed6a952Timo Sirainen test_gz_large_header,
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen NULL
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen };
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen if (argc == 2) {
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen test_uncompress_file(argv[1]);
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen return 0;
697a4fbe2d9cd776b8ceecb0c907a7ad55d3153eTimo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen if (argc == 3) {
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen test_compress_file(argv[1], argv[2]);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen return 0;
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen }
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen return test_run(test_functions);
443fd76b8dfbb708bf2eab8bf5fe7440cc90eb13Timo Sirainen}