test-ostream-file.c revision cd07d97b7da550b52d60e3020f64821f7e35ceaa
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "test-lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "net.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "str.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "safe-mkstemp.h"
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#include "randgen.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "istream.h"
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#include "ostream.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include <fcntl.h>
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include <unistd.h>
657afb33796f8216c568ad813627da89970760beTimo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen#define MAX_BUFSIZE 256
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainenstatic void test_ostream_file_random_once(void)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct ostream *output;
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen string_t *path = t_str_new(128);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen char buf[MAX_BUFSIZE*4], buf2[MAX_BUFSIZE*4], randbuf[MAX_BUFSIZE];
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen unsigned int i, offset, size;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ssize_t ret;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen int fd;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen memset(buf, 0, sizeof(buf));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (fd == -1)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_fatal("safe_mkstemp(%s) failed: %m", str_c(path));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_unlink(str_c(path));
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen output = o_stream_create_fd(fd, MAX_BUFSIZE, FALSE);
657afb33796f8216c568ad813627da89970760beTimo Sirainen o_stream_cork(output);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen size = (rand() % MAX_BUFSIZE) + 1;
657afb33796f8216c568ad813627da89970760beTimo Sirainen random_fill_weak(randbuf, size);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen memcpy(buf, randbuf, size);
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen test_assert(o_stream_send(output, buf, size) > 0);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen for (i = 0; i < 10; i++) {
657afb33796f8216c568ad813627da89970760beTimo Sirainen offset = rand() % (MAX_BUFSIZE*3);
657afb33796f8216c568ad813627da89970760beTimo Sirainen size = (rand() % MAX_BUFSIZE) + 1;
657afb33796f8216c568ad813627da89970760beTimo Sirainen random_fill_weak(randbuf, size);
657afb33796f8216c568ad813627da89970760beTimo Sirainen memcpy(buf + offset, randbuf, size);
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen test_assert(o_stream_pwrite(output, randbuf, size, offset) == 0);
657afb33796f8216c568ad813627da89970760beTimo Sirainen if (rand() % 10 == 0)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen test_assert(o_stream_flush(output) > 0);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert(o_stream_flush(output) > 0);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen o_stream_uncork(output);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ret = pread(fd, buf2, sizeof(buf2), 0);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (ret < 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_fatal("pread() failed: %m");
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen else {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_assert(ret > 0);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert(memcmp(buf, buf2, ret) == 0);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen o_stream_unref(&output);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_close_fd(&fd);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void test_ostream_file_random(void)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen unsigned int i;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen test_begin("ostream pwrite random");
657afb33796f8216c568ad813627da89970760beTimo Sirainen for (i = 0; i < 100; i++) T_BEGIN {
657afb33796f8216c568ad813627da89970760beTimo Sirainen test_ostream_file_random_once();
657afb33796f8216c568ad813627da89970760beTimo Sirainen } T_END;
657afb33796f8216c568ad813627da89970760beTimo Sirainen test_end();
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainenstatic void test_ostream_file_send_istream_file(void)
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct istream *input, *input2;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen struct ostream *output;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen char buf[10];
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen int fd;
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen test_begin("ostream file send istream file");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen /* temp file istream */
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen fd = open(".temp.istream", O_RDWR | O_CREAT | O_TRUNC, 0600);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen if (fd == -1)
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen i_fatal("creat(.temp.istream) failed: %m");
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen test_assert(write(fd, "1234567890", 10) == 10);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen test_assert(lseek(fd, 0, SEEK_SET) == 0);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen input = i_stream_create_fd(fd, 1024, TRUE);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen /* temp file ostream */
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen fd = open(".temp.ostream", O_RDWR | O_CREAT | O_TRUNC, 0600);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen if (fd == -1)
3ee2da6133bd7773961d1f3f3ac531448a5158b9Timo Sirainen i_fatal("creat(.temp.ostream) failed: %m");
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen output = o_stream_create_fd(fd, 0, TRUE);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen /* test that writing works between two files */
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen i_stream_seek(input, 3);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen input2 = i_stream_create_limit(input, 4);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen test_assert(o_stream_send_istream(output, input2) > 0);
397165dbd694272487e29c8d48d619822da52abcTimo Sirainen test_assert(output->offset == 4);
397165dbd694272487e29c8d48d619822da52abcTimo Sirainen test_assert(pread(fd, buf, sizeof(buf), 0) == 4 &&
397165dbd694272487e29c8d48d619822da52abcTimo Sirainen memcmp(buf, "4567", 4) == 0);
397165dbd694272487e29c8d48d619822da52abcTimo Sirainen i_stream_unref(&input2);
3ee2da6133bd7773961d1f3f3ac531448a5158b9Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen /* test that writing works within the same file */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_stream_destroy(&input);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen input = i_stream_create_fd(fd, 1024, FALSE);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* forwards: 4567 -> 4677 */
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen o_stream_seek(output, 1);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen i_stream_seek(input, 2);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen input2 = i_stream_create_limit(input, 2);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen test_assert(o_stream_send_istream(output, input2) > 0);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen test_assert(output->offset == 3);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen test_assert(pread(fd, buf, sizeof(buf), 0) == 4 &&
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen memcmp(buf, "4677", 4) == 0);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen i_stream_destroy(&input2);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen i_stream_destroy(&input);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen /* backwards: 1234 -> 11234 */
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen memcpy(buf, "1234", 4);
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen test_assert(pwrite(fd, buf, 4, 0) == 4);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen input = i_stream_create_fd(fd, 1024, FALSE);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen o_stream_seek(output, 1);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen test_assert(o_stream_send_istream(output, input) > 0);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen test_assert(output->offset == 5);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen test_assert(pread(fd, buf, sizeof(buf), 0) == 5 &&
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen memcmp(buf, "11234", 5) == 0);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen i_stream_destroy(&input);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen o_stream_destroy(&output);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen i_unlink(".temp.istream");
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen i_unlink(".temp.ostream");
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen test_end();
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen}
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainenstatic void test_ostream_file_send_istream_sendfile(void)
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen{
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen struct istream *input, *input2;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen struct ostream *output;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen char buf[10];
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen int fd, sock_fd[2];
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen test_begin("ostream file send istream sendfile()");
2703c3499e2d422d4f26e62720a4e8a43164fa57Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen /* temp file istream */
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen fd = open(".temp.istream", O_RDWR | O_CREAT | O_TRUNC, 0600);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen if (fd == -1)
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen i_fatal("creat(.temp.istream) failed: %m");
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen test_assert(write(fd, "abcdefghij", 10) == 10);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen test_assert(lseek(fd, 0, SEEK_SET) == 0);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen input = i_stream_create_fd(fd, 1024, TRUE);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* temp socket ostream */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fd) == 0);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen output = o_stream_create_fd(sock_fd[0], 0, TRUE);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* test that sendfile() works */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_stream_seek(input, 3);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen input2 = i_stream_create_limit(input, 4);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert(o_stream_send_istream(output, input2) > 0);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert(output->offset == 4);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert(read(sock_fd[1], buf, sizeof(buf)) == 4 &&
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen memcmp(buf, "defg", 4) == 0);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_stream_unref(&input2);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_stream_unref(&input);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen o_stream_destroy(&output);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_close_fd(&sock_fd[1]);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen i_unlink(".temp.istream");
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen test_end();
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen}
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainenvoid test_ostream_file(void)
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen{
4b8c92b4773677a7b4064816e469eeafc976ba75Timo Sirainen test_ostream_file_random();
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen test_ostream_file_send_istream_file();
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen test_ostream_file_send_istream_sendfile();
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen