xref: /openbmc/qemu/tests/unit/io-channel-helpers.c (revision 644eb9ceb4582ee2ccb84b6b7f7cb6d3b2d0c692)
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