1da668aa1SThomas Huth /*
2da668aa1SThomas Huth * QEMU I/O channel test helpers
3da668aa1SThomas Huth *
4da668aa1SThomas Huth * Copyright (c) 2015 Red Hat, Inc.
5da668aa1SThomas Huth *
6da668aa1SThomas Huth * This library is free software; you can redistribute it and/or
7da668aa1SThomas Huth * modify it under the terms of the GNU Lesser General Public
8da668aa1SThomas Huth * License as published by the Free Software Foundation; either
9da668aa1SThomas Huth * version 2.1 of the License, or (at your option) any later version.
10da668aa1SThomas Huth *
11da668aa1SThomas Huth * This library is distributed in the hope that it will be useful,
12da668aa1SThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13da668aa1SThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14da668aa1SThomas Huth * Lesser General Public License for more details.
15da668aa1SThomas Huth *
16da668aa1SThomas Huth * You should have received a copy of the GNU Lesser General Public
17da668aa1SThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18da668aa1SThomas Huth *
19da668aa1SThomas Huth */
20da668aa1SThomas Huth
21da668aa1SThomas Huth #include "qemu/osdep.h"
22da668aa1SThomas Huth #include "io-channel-helpers.h"
23da668aa1SThomas Huth #include "qemu/iov.h"
24da668aa1SThomas Huth
25da668aa1SThomas Huth struct QIOChannelTest {
26da668aa1SThomas Huth QIOChannel *src;
27da668aa1SThomas Huth QIOChannel *dst;
28da668aa1SThomas Huth size_t len;
29da668aa1SThomas Huth size_t niov;
30da668aa1SThomas Huth char *input;
31da668aa1SThomas Huth struct iovec *inputv;
32da668aa1SThomas Huth char *output;
33da668aa1SThomas Huth struct iovec *outputv;
34da668aa1SThomas Huth Error *writeerr;
35da668aa1SThomas Huth Error *readerr;
36da668aa1SThomas Huth };
37da668aa1SThomas Huth
38da668aa1SThomas Huth
39da668aa1SThomas Huth /* This thread sends all data using iovecs */
test_io_thread_writer(gpointer opaque)40da668aa1SThomas Huth static gpointer test_io_thread_writer(gpointer opaque)
41da668aa1SThomas Huth {
42da668aa1SThomas Huth QIOChannelTest *data = opaque;
43da668aa1SThomas Huth
44da668aa1SThomas Huth qio_channel_writev_all(data->src,
45da668aa1SThomas Huth data->inputv,
46da668aa1SThomas Huth data->niov,
47da668aa1SThomas Huth &data->writeerr);
48da668aa1SThomas Huth
49da668aa1SThomas Huth return NULL;
50da668aa1SThomas Huth }
51da668aa1SThomas Huth
52da668aa1SThomas Huth
53da668aa1SThomas Huth /* This thread receives all data using iovecs */
test_io_thread_reader(gpointer opaque)54da668aa1SThomas Huth static gpointer test_io_thread_reader(gpointer opaque)
55da668aa1SThomas Huth {
56da668aa1SThomas Huth QIOChannelTest *data = opaque;
57da668aa1SThomas Huth
58da668aa1SThomas Huth qio_channel_readv_all(data->dst,
59da668aa1SThomas Huth data->outputv,
60da668aa1SThomas Huth data->niov,
61da668aa1SThomas Huth &data->readerr);
62da668aa1SThomas Huth
63da668aa1SThomas Huth return NULL;
64da668aa1SThomas Huth }
65da668aa1SThomas Huth
66da668aa1SThomas Huth
qio_channel_test_new(void)67da668aa1SThomas Huth QIOChannelTest *qio_channel_test_new(void)
68da668aa1SThomas Huth {
69da668aa1SThomas Huth QIOChannelTest *data = g_new0(QIOChannelTest, 1);
70da668aa1SThomas Huth size_t i;
71da668aa1SThomas Huth size_t offset;
72da668aa1SThomas Huth
73da668aa1SThomas Huth
74da668aa1SThomas Huth /* We'll send 1 MB of data */
75da668aa1SThomas Huth #define CHUNK_COUNT 250
76da668aa1SThomas Huth #define CHUNK_LEN 4194
77da668aa1SThomas Huth
78da668aa1SThomas Huth data->len = CHUNK_COUNT * CHUNK_LEN;
79da668aa1SThomas Huth data->input = g_new0(char, data->len);
80da668aa1SThomas Huth data->output = g_new0(gchar, data->len);
81da668aa1SThomas Huth
82da668aa1SThomas Huth /* Fill input with a pattern */
83da668aa1SThomas Huth for (i = 0; i < data->len; i += CHUNK_LEN) {
84da668aa1SThomas Huth memset(data->input + i, (i / CHUNK_LEN), CHUNK_LEN);
85da668aa1SThomas Huth }
86da668aa1SThomas Huth
87da668aa1SThomas Huth /* We'll split the data across a bunch of IO vecs */
88da668aa1SThomas Huth data->niov = CHUNK_COUNT;
89da668aa1SThomas Huth data->inputv = g_new0(struct iovec, data->niov);
90da668aa1SThomas Huth data->outputv = g_new0(struct iovec, data->niov);
91da668aa1SThomas Huth
92da668aa1SThomas Huth for (i = 0, offset = 0; i < data->niov; i++, offset += CHUNK_LEN) {
93da668aa1SThomas Huth data->inputv[i].iov_base = data->input + offset;
94da668aa1SThomas Huth data->outputv[i].iov_base = data->output + offset;
95da668aa1SThomas Huth data->inputv[i].iov_len = CHUNK_LEN;
96da668aa1SThomas Huth data->outputv[i].iov_len = CHUNK_LEN;
97da668aa1SThomas Huth }
98da668aa1SThomas Huth
99da668aa1SThomas Huth return data;
100da668aa1SThomas Huth }
101da668aa1SThomas Huth
qio_channel_test_run_threads(QIOChannelTest * test,bool blocking,QIOChannel * src,QIOChannel * dst)102da668aa1SThomas Huth void qio_channel_test_run_threads(QIOChannelTest *test,
103da668aa1SThomas Huth bool blocking,
104da668aa1SThomas Huth QIOChannel *src,
105da668aa1SThomas Huth QIOChannel *dst)
106da668aa1SThomas Huth {
107da668aa1SThomas Huth GThread *reader, *writer;
108da668aa1SThomas Huth
109da668aa1SThomas Huth test->src = src;
110da668aa1SThomas Huth test->dst = dst;
111*bb06b014SMarc-André Lureau
112*bb06b014SMarc-André Lureau qio_channel_set_blocking(test->dst, blocking, NULL);
113*bb06b014SMarc-André Lureau qio_channel_set_blocking(test->src, blocking, NULL);
114da668aa1SThomas Huth
115da668aa1SThomas Huth reader = g_thread_new("reader",
116da668aa1SThomas Huth test_io_thread_reader,
117da668aa1SThomas Huth test);
118da668aa1SThomas Huth writer = g_thread_new("writer",
119da668aa1SThomas Huth test_io_thread_writer,
120da668aa1SThomas Huth test);
121da668aa1SThomas Huth
122da668aa1SThomas Huth g_thread_join(reader);
123da668aa1SThomas Huth g_thread_join(writer);
124da668aa1SThomas Huth
125da668aa1SThomas Huth test->dst = test->src = NULL;
126da668aa1SThomas Huth }
127da668aa1SThomas Huth
128da668aa1SThomas Huth
qio_channel_test_run_writer(QIOChannelTest * test,QIOChannel * src)129da668aa1SThomas Huth void qio_channel_test_run_writer(QIOChannelTest *test,
130da668aa1SThomas Huth QIOChannel *src)
131da668aa1SThomas Huth {
132da668aa1SThomas Huth test->src = src;
133da668aa1SThomas Huth test_io_thread_writer(test);
134da668aa1SThomas Huth test->src = NULL;
135da668aa1SThomas Huth }
136da668aa1SThomas Huth
137da668aa1SThomas Huth
qio_channel_test_run_reader(QIOChannelTest * test,QIOChannel * dst)138da668aa1SThomas Huth void qio_channel_test_run_reader(QIOChannelTest *test,
139da668aa1SThomas Huth QIOChannel *dst)
140da668aa1SThomas Huth {
141da668aa1SThomas Huth test->dst = dst;
142da668aa1SThomas Huth test_io_thread_reader(test);
143da668aa1SThomas Huth test->dst = NULL;
144da668aa1SThomas Huth }
145da668aa1SThomas Huth
146da668aa1SThomas Huth
qio_channel_test_validate(QIOChannelTest * test)147da668aa1SThomas Huth void qio_channel_test_validate(QIOChannelTest *test)
148da668aa1SThomas Huth {
149da668aa1SThomas Huth g_assert(test->readerr == NULL);
150da668aa1SThomas Huth g_assert(test->writeerr == NULL);
151da668aa1SThomas Huth g_assert_cmpint(memcmp(test->input,
152da668aa1SThomas Huth test->output,
153da668aa1SThomas Huth test->len), ==, 0);
154da668aa1SThomas Huth
155da668aa1SThomas Huth g_free(test->inputv);
156da668aa1SThomas Huth g_free(test->outputv);
157da668aa1SThomas Huth g_free(test->input);
158da668aa1SThomas Huth g_free(test->output);
159da668aa1SThomas Huth g_free(test);
160da668aa1SThomas Huth }
161