1559607eaSDaniel P. Berrange /* 2559607eaSDaniel P. Berrange * QEMU I/O channel test helpers 3559607eaSDaniel P. Berrange * 4559607eaSDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc. 5559607eaSDaniel P. Berrange * 6559607eaSDaniel P. Berrange * This library is free software; you can redistribute it and/or 7559607eaSDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 8559607eaSDaniel P. Berrange * License as published by the Free Software Foundation; either 9559607eaSDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 10559607eaSDaniel P. Berrange * 11559607eaSDaniel P. Berrange * This library is distributed in the hope that it will be useful, 12559607eaSDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 13559607eaSDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14559607eaSDaniel P. Berrange * Lesser General Public License for more details. 15559607eaSDaniel P. Berrange * 16559607eaSDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 17559607eaSDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18559607eaSDaniel P. Berrange * 19559607eaSDaniel P. Berrange */ 20559607eaSDaniel P. Berrange 21681c28a3SPeter Maydell #include "qemu/osdep.h" 22559607eaSDaniel P. Berrange #include "io-channel-helpers.h" 23da34e65cSMarkus Armbruster #include "qapi/error.h" 24*d4622e55SDaniel P. Berrange #include "qemu/iov.h" 25559607eaSDaniel P. Berrange 26559607eaSDaniel P. Berrange struct QIOChannelTest { 27559607eaSDaniel P. Berrange QIOChannel *src; 28559607eaSDaniel P. Berrange QIOChannel *dst; 29559607eaSDaniel P. Berrange bool blocking; 30559607eaSDaniel P. Berrange size_t len; 31559607eaSDaniel P. Berrange size_t niov; 32559607eaSDaniel P. Berrange char *input; 33559607eaSDaniel P. Berrange struct iovec *inputv; 34559607eaSDaniel P. Berrange char *output; 35559607eaSDaniel P. Berrange struct iovec *outputv; 36559607eaSDaniel P. Berrange Error *writeerr; 37559607eaSDaniel P. Berrange Error *readerr; 38559607eaSDaniel P. Berrange }; 39559607eaSDaniel P. Berrange 40559607eaSDaniel P. Berrange 41559607eaSDaniel P. Berrange /* This thread sends all data using iovecs */ 42559607eaSDaniel P. Berrange static gpointer test_io_thread_writer(gpointer opaque) 43559607eaSDaniel P. Berrange { 44559607eaSDaniel P. Berrange QIOChannelTest *data = opaque; 45559607eaSDaniel P. Berrange 46559607eaSDaniel P. Berrange qio_channel_set_blocking(data->src, data->blocking, NULL); 47559607eaSDaniel P. Berrange 48*d4622e55SDaniel P. Berrange qio_channel_writev_all(data->src, 49*d4622e55SDaniel P. Berrange data->inputv, 50*d4622e55SDaniel P. Berrange data->niov, 51559607eaSDaniel P. Berrange &data->writeerr); 52559607eaSDaniel P. Berrange 53559607eaSDaniel P. Berrange return NULL; 54559607eaSDaniel P. Berrange } 55559607eaSDaniel P. Berrange 56559607eaSDaniel P. Berrange 57559607eaSDaniel P. Berrange /* This thread receives all data using iovecs */ 58559607eaSDaniel P. Berrange static gpointer test_io_thread_reader(gpointer opaque) 59559607eaSDaniel P. Berrange { 60559607eaSDaniel P. Berrange QIOChannelTest *data = opaque; 61559607eaSDaniel P. Berrange 62559607eaSDaniel P. Berrange qio_channel_set_blocking(data->dst, data->blocking, NULL); 63559607eaSDaniel P. Berrange 64*d4622e55SDaniel P. Berrange qio_channel_readv_all(data->dst, 65*d4622e55SDaniel P. Berrange data->outputv, 66*d4622e55SDaniel P. Berrange data->niov, 67559607eaSDaniel P. Berrange &data->readerr); 68559607eaSDaniel P. Berrange 69559607eaSDaniel P. Berrange return NULL; 70559607eaSDaniel P. Berrange } 71559607eaSDaniel P. Berrange 72559607eaSDaniel P. Berrange 73559607eaSDaniel P. Berrange QIOChannelTest *qio_channel_test_new(void) 74559607eaSDaniel P. Berrange { 75559607eaSDaniel P. Berrange QIOChannelTest *data = g_new0(QIOChannelTest, 1); 76559607eaSDaniel P. Berrange size_t i; 77559607eaSDaniel P. Berrange size_t offset; 78559607eaSDaniel P. Berrange 79559607eaSDaniel P. Berrange 80559607eaSDaniel P. Berrange /* We'll send 1 MB of data */ 81559607eaSDaniel P. Berrange #define CHUNK_COUNT 250 82559607eaSDaniel P. Berrange #define CHUNK_LEN 4194 83559607eaSDaniel P. Berrange 84559607eaSDaniel P. Berrange data->len = CHUNK_COUNT * CHUNK_LEN; 85559607eaSDaniel P. Berrange data->input = g_new0(char, data->len); 86559607eaSDaniel P. Berrange data->output = g_new0(gchar, data->len); 87559607eaSDaniel P. Berrange 88559607eaSDaniel P. Berrange /* Fill input with a pattern */ 89559607eaSDaniel P. Berrange for (i = 0; i < data->len; i += CHUNK_LEN) { 90559607eaSDaniel P. Berrange memset(data->input + i, (i / CHUNK_LEN), CHUNK_LEN); 91559607eaSDaniel P. Berrange } 92559607eaSDaniel P. Berrange 93559607eaSDaniel P. Berrange /* We'll split the data across a bunch of IO vecs */ 94559607eaSDaniel P. Berrange data->niov = CHUNK_COUNT; 95559607eaSDaniel P. Berrange data->inputv = g_new0(struct iovec, data->niov); 96559607eaSDaniel P. Berrange data->outputv = g_new0(struct iovec, data->niov); 97559607eaSDaniel P. Berrange 98559607eaSDaniel P. Berrange for (i = 0, offset = 0; i < data->niov; i++, offset += CHUNK_LEN) { 99559607eaSDaniel P. Berrange data->inputv[i].iov_base = data->input + offset; 100559607eaSDaniel P. Berrange data->outputv[i].iov_base = data->output + offset; 101559607eaSDaniel P. Berrange data->inputv[i].iov_len = CHUNK_LEN; 102559607eaSDaniel P. Berrange data->outputv[i].iov_len = CHUNK_LEN; 103559607eaSDaniel P. Berrange } 104559607eaSDaniel P. Berrange 105559607eaSDaniel P. Berrange return data; 106559607eaSDaniel P. Berrange } 107559607eaSDaniel P. Berrange 108559607eaSDaniel P. Berrange void qio_channel_test_run_threads(QIOChannelTest *test, 109559607eaSDaniel P. Berrange bool blocking, 110559607eaSDaniel P. Berrange QIOChannel *src, 111559607eaSDaniel P. Berrange QIOChannel *dst) 112559607eaSDaniel P. Berrange { 113559607eaSDaniel P. Berrange GThread *reader, *writer; 114559607eaSDaniel P. Berrange 115559607eaSDaniel P. Berrange test->src = src; 116559607eaSDaniel P. Berrange test->dst = dst; 117559607eaSDaniel P. Berrange test->blocking = blocking; 118559607eaSDaniel P. Berrange 119559607eaSDaniel P. Berrange reader = g_thread_new("reader", 120559607eaSDaniel P. Berrange test_io_thread_reader, 121559607eaSDaniel P. Berrange test); 122559607eaSDaniel P. Berrange writer = g_thread_new("writer", 123559607eaSDaniel P. Berrange test_io_thread_writer, 124559607eaSDaniel P. Berrange test); 125559607eaSDaniel P. Berrange 126559607eaSDaniel P. Berrange g_thread_join(reader); 127559607eaSDaniel P. Berrange g_thread_join(writer); 128559607eaSDaniel P. Berrange 129559607eaSDaniel P. Berrange test->dst = test->src = NULL; 130559607eaSDaniel P. Berrange } 131559607eaSDaniel P. Berrange 132559607eaSDaniel P. Berrange 133559607eaSDaniel P. Berrange void qio_channel_test_run_writer(QIOChannelTest *test, 134559607eaSDaniel P. Berrange QIOChannel *src) 135559607eaSDaniel P. Berrange { 136559607eaSDaniel P. Berrange test->src = src; 137559607eaSDaniel P. Berrange test_io_thread_writer(test); 138559607eaSDaniel P. Berrange test->src = NULL; 139559607eaSDaniel P. Berrange } 140559607eaSDaniel P. Berrange 141559607eaSDaniel P. Berrange 142559607eaSDaniel P. Berrange void qio_channel_test_run_reader(QIOChannelTest *test, 143559607eaSDaniel P. Berrange QIOChannel *dst) 144559607eaSDaniel P. Berrange { 145559607eaSDaniel P. Berrange test->dst = dst; 146559607eaSDaniel P. Berrange test_io_thread_reader(test); 147559607eaSDaniel P. Berrange test->dst = NULL; 148559607eaSDaniel P. Berrange } 149559607eaSDaniel P. Berrange 150559607eaSDaniel P. Berrange 151559607eaSDaniel P. Berrange void qio_channel_test_validate(QIOChannelTest *test) 152559607eaSDaniel P. Berrange { 153294bbbb4SDaniel P. Berrange g_assert(test->readerr == NULL); 154294bbbb4SDaniel P. Berrange g_assert(test->writeerr == NULL); 155559607eaSDaniel P. Berrange g_assert_cmpint(memcmp(test->input, 156559607eaSDaniel P. Berrange test->output, 157559607eaSDaniel P. Berrange test->len), ==, 0); 158559607eaSDaniel P. Berrange 159559607eaSDaniel P. Berrange g_free(test->inputv); 160559607eaSDaniel P. Berrange g_free(test->outputv); 161559607eaSDaniel P. Berrange g_free(test->input); 162559607eaSDaniel P. Berrange g_free(test->output); 163559607eaSDaniel P. Berrange g_free(test); 164559607eaSDaniel P. Berrange } 165