test-ostream-multiplex.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "test-lib.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "ioloop.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "str.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "istream.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "ostream-private.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "ostream-multiplex.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "ostream.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include <unistd.h>
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "hex-binary.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void test_ostream_multiplex_simple(void)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_begin("ostream multiplex (simple)");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const unsigned char expected[] = {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen '\x00','\x00','\x00','\x00','\x05','\x68','\x65',
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen '\x6c','\x6c','\x6f','\x01','\x00','\x00','\x00',
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen '\x05','\x77','\x6f','\x72','\x6c','\x64'
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen };
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen buffer_t *result = t_str_new(64);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct ostream *os = test_ostream_create(result);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream *os2 = o_stream_create_multiplex(os, (size_t)-1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct ostream *os3 = o_stream_multiplex_add_channel(os2, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert(o_stream_send_str(os2, "hello") == 5);
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen test_assert(o_stream_send_str(os3, "world") == 5);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen o_stream_unref(&os3);
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen o_stream_unref(&os2);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_unref(&os);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen test_assert(sizeof(expected) == result->used);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen test_assert(memcmp(result->data, expected, I_MIN(sizeof(expected),
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen result->used)) == 0);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen test_end();
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen}
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic unsigned int channel_counter[2] = {0, 0};
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainenstatic struct ostream *chan0, *chan1;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainenstatic const char *msgs[] = {
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen "",
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen "a",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen "bb",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "ccc",
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen "dddd",
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen "eeeee",
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen "ffffff"
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen};
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainenstatic void test_ostream_multiplex_stream_read(struct istream *is)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uint8_t cid;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const unsigned char *data;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t siz,dlen=0,pos=0;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (i_stream_read_more(is, &data, &siz)>0) {
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen /* parse stream */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen for(;pos<siz;) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (dlen > 0) {
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen if (dlen < N_ELEMENTS(msgs)) {
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen test_assert_idx(memcmp(&data[pos],
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen msgs[dlen], dlen)==0,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen channel_counter[data[0] % 2]);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen channel_counter[data[0] % 2]++;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen pos += dlen;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen dlen = 0;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen } else if (dlen == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen cid = data[pos] % 2;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert_idx(data[pos] < 2, channel_counter[cid]);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen pos++;
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen dlen = be32_to_cpu_unaligned(&data[pos]);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pos += 4;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert(dlen > 0 && dlen < N_ELEMENTS(msgs));
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen i_stream_skip(is, siz);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (channel_counter[0] > 100 && channel_counter[1] > 100)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen io_loop_stop(current_ioloop);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainenstatic void test_ostream_multiplex_stream_write(struct ostream *channel ATTR_UNUSED)
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen{
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen size_t rounds = 1 + i_rand() % 10;
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen for(size_t i = 0; i < rounds; i++) {
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen if ((i_rand() % 2) != 0)
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen o_stream_nsend_str(chan1, msgs[i_rand() % N_ELEMENTS(msgs)]);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen else
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen o_stream_nsend_str(chan0, msgs[i_rand() % N_ELEMENTS(msgs)]);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen}
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic void test_ostream_multiplex_stream(void)
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen{
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen test_begin("ostream multiplex (stream)");
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen struct ioloop *ioloop = io_loop_create();
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen io_loop_set_current(ioloop);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen int fds[2];
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen test_assert(pipe(fds) == 0);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen fd_set_nonblock(fds[0], TRUE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fd_set_nonblock(fds[1], TRUE);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen struct ostream *os = o_stream_create_fd(fds[1], (size_t)-1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct istream *is = i_stream_create_fd(fds[0], (size_t)-1);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen chan0 = o_stream_create_multiplex(os, (size_t)-1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen chan1 = o_stream_multiplex_add_channel(chan0, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen struct io *io0 =
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen io_add_istream(is, test_ostream_multiplex_stream_read, is);
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen struct io *io1 =
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen io_add(fds[1], IO_WRITE, test_ostream_multiplex_stream_write, os);
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen io_loop_run(current_ioloop);
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen io_remove(&io0);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen io_remove(&io1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen test_assert(o_stream_finish(chan1) > 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen o_stream_unref(&chan1);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen test_assert(o_stream_finish(chan0) > 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen o_stream_unref(&chan0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen i_stream_unref(&is);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen o_stream_unref(&os);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen io_loop_destroy(&ioloop);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen i_close_fd(&fds[0]);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen i_close_fd(&fds[1]);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen test_end();
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen}
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainenvoid test_ostream_multiplex(void)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_ostream_multiplex_simple();
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen test_ostream_multiplex_stream();
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen