bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "test-lib.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "ioloop.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "str.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "istream.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "ostream-private.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "ostream-multiplex.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "ostream.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include <unistd.h>
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi#include "hex-binary.h"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic void test_ostream_multiplex_simple(void)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi{
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_begin("ostream multiplex (simple)");
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi const unsigned char expected[] = {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi '\x00','\x00','\x00','\x00','\x05','\x68','\x65',
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi '\x6c','\x6c','\x6f','\x01','\x00','\x00','\x00',
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi '\x05','\x77','\x6f','\x72','\x6c','\x64'
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi };
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi buffer_t *result = t_str_new(64);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct ostream *os = test_ostream_create(result);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct ostream *os2 = o_stream_create_multiplex(os, (size_t)-1);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct ostream *os3 = o_stream_multiplex_add_channel(os2, 1);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert(o_stream_send_str(os2, "hello") == 5);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert(o_stream_send_str(os3, "world") == 5);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi o_stream_unref(&os3);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi o_stream_unref(&os2);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi o_stream_unref(&os);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert(sizeof(expected) == result->used);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert(memcmp(result->data, expected, I_MIN(sizeof(expected),
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi result->used)) == 0);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_end();
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi}
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic unsigned int channel_counter[2] = {0, 0};
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic struct ostream *chan0, *chan1;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic const char *msgs[] = {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "a",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "bb",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "ccc",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "dddd",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "eeeee",
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi "ffffff"
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi};
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic void test_ostream_multiplex_stream_read(struct istream *is)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi{
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi uint8_t cid;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi const unsigned char *data;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi size_t siz,dlen=0,pos=0;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (i_stream_read_more(is, &data, &siz)>0) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi /* parse stream */
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi for(;pos<siz;) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (dlen > 0) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (dlen < N_ELEMENTS(msgs)) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert_idx(memcmp(&data[pos],
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi msgs[dlen], dlen)==0,
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi channel_counter[data[0] % 2]);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi }
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi channel_counter[data[0] % 2]++;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi pos += dlen;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi dlen = 0;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi } else if (dlen == 0) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi cid = data[pos] % 2;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert_idx(data[pos] < 2, channel_counter[cid]);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi pos++;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi dlen = be32_to_cpu_unaligned(&data[pos]);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi pos += 4;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert(dlen > 0 && dlen < N_ELEMENTS(msgs));
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi }
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi }
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi i_stream_skip(is, siz);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi }
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if (channel_counter[0] > 100 && channel_counter[1] > 100)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_loop_stop(current_ioloop);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi}
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic void test_ostream_multiplex_stream_write(struct ostream *channel ATTR_UNUSED)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi{
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi size_t rounds = 1 + i_rand() % 10;
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi for(size_t i = 0; i < rounds; i++) {
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi if ((i_rand() % 2) != 0)
bc038dfe3ea41392ab50cd4c1c1fdd620cc3deefAki Tuomi o_stream_nsend_str(chan1, msgs[i_rand() % N_ELEMENTS(msgs)]);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi else
bc038dfe3ea41392ab50cd4c1c1fdd620cc3deefAki Tuomi o_stream_nsend_str(chan0, msgs[i_rand() % N_ELEMENTS(msgs)]);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi }
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi}
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomistatic void test_ostream_multiplex_stream(void)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi{
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_begin("ostream multiplex (stream)");
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct ioloop *ioloop = io_loop_create();
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_loop_set_current(ioloop);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi int fds[2];
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_assert(pipe(fds) == 0);
c704b7fa16ac4fa95c1d84d82d93837ae5cf98e7Timo Sirainen fd_set_nonblock(fds[0], TRUE);
c704b7fa16ac4fa95c1d84d82d93837ae5cf98e7Timo Sirainen fd_set_nonblock(fds[1], TRUE);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct ostream *os = o_stream_create_fd(fds[1], (size_t)-1);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct istream *is = i_stream_create_fd(fds[0], (size_t)-1);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi chan0 = o_stream_create_multiplex(os, (size_t)-1);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi chan1 = o_stream_multiplex_add_channel(chan0, 1);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct io *io0 =
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_add_istream(is, test_ostream_multiplex_stream_read, is);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi struct io *io1 =
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_add(fds[1], IO_WRITE, test_ostream_multiplex_stream_write, os);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_loop_run(current_ioloop);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_remove(&io0);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_remove(&io1);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen test_assert(o_stream_finish(chan1) > 0);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi o_stream_unref(&chan1);
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen test_assert(o_stream_finish(chan0) > 0);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi o_stream_unref(&chan0);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi i_stream_unref(&is);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi o_stream_unref(&os);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi io_loop_destroy(&ioloop);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi i_close_fd(&fds[0]);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi i_close_fd(&fds[1]);
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_end();
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi}
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomivoid test_ostream_multiplex(void)
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi{
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_ostream_multiplex_simple();
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi test_ostream_multiplex_stream();
1de7b73a11afda43323410a4481d866930b1e632Aki Tuomi}