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 9*8cbff3c1SGan Qixin * version 2.1 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" 23d4622e55SDaniel P. Berrange #include "qemu/iov.h" 24559607eaSDaniel P. Berrange 25559607eaSDaniel P. Berrange struct QIOChannelTest { 26559607eaSDaniel P. Berrange QIOChannel *src; 27559607eaSDaniel P. Berrange QIOChannel *dst; 28559607eaSDaniel P. Berrange bool blocking; 29559607eaSDaniel P. Berrange size_t len; 30559607eaSDaniel P. Berrange size_t niov; 31559607eaSDaniel P. Berrange char *input; 32559607eaSDaniel P. Berrange struct iovec *inputv; 33559607eaSDaniel P. Berrange char *output; 34559607eaSDaniel P. Berrange struct iovec *outputv; 35559607eaSDaniel P. Berrange Error *writeerr; 36559607eaSDaniel P. Berrange Error *readerr; 37559607eaSDaniel P. Berrange }; 38559607eaSDaniel P. Berrange 39559607eaSDaniel P. Berrange 40559607eaSDaniel P. Berrange /* This thread sends all data using iovecs */ 41559607eaSDaniel P. Berrange static gpointer test_io_thread_writer(gpointer opaque) 42559607eaSDaniel P. Berrange { 43559607eaSDaniel P. Berrange QIOChannelTest *data = opaque; 44559607eaSDaniel P. Berrange 45559607eaSDaniel P. Berrange qio_channel_set_blocking(data->src, data->blocking, NULL); 46559607eaSDaniel P. Berrange 47d4622e55SDaniel P. Berrange qio_channel_writev_all(data->src, 48d4622e55SDaniel P. Berrange data->inputv, 49d4622e55SDaniel P. Berrange data->niov, 50559607eaSDaniel P. Berrange &data->writeerr); 51559607eaSDaniel P. Berrange 52559607eaSDaniel P. Berrange return NULL; 53559607eaSDaniel P. Berrange } 54559607eaSDaniel P. Berrange 55559607eaSDaniel P. Berrange 56559607eaSDaniel P. Berrange /* This thread receives all data using iovecs */ 57559607eaSDaniel P. Berrange static gpointer test_io_thread_reader(gpointer opaque) 58559607eaSDaniel P. Berrange { 59559607eaSDaniel P. Berrange QIOChannelTest *data = opaque; 60559607eaSDaniel P. Berrange 61559607eaSDaniel P. Berrange qio_channel_set_blocking(data->dst, data->blocking, NULL); 62559607eaSDaniel P. Berrange 63d4622e55SDaniel P. Berrange qio_channel_readv_all(data->dst, 64d4622e55SDaniel P. Berrange data->outputv, 65d4622e55SDaniel P. Berrange data->niov, 66559607eaSDaniel P. Berrange &data->readerr); 67559607eaSDaniel P. Berrange 68559607eaSDaniel P. Berrange return NULL; 69559607eaSDaniel P. Berrange } 70559607eaSDaniel P. Berrange 71559607eaSDaniel P. Berrange 72559607eaSDaniel P. Berrange QIOChannelTest *qio_channel_test_new(void) 73559607eaSDaniel P. Berrange { 74559607eaSDaniel P. Berrange QIOChannelTest *data = g_new0(QIOChannelTest, 1); 75559607eaSDaniel P. Berrange size_t i; 76559607eaSDaniel P. Berrange size_t offset; 77559607eaSDaniel P. Berrange 78559607eaSDaniel P. Berrange 79559607eaSDaniel P. Berrange /* We'll send 1 MB of data */ 80559607eaSDaniel P. Berrange #define CHUNK_COUNT 250 81559607eaSDaniel P. Berrange #define CHUNK_LEN 4194 82559607eaSDaniel P. Berrange 83559607eaSDaniel P. Berrange data->len = CHUNK_COUNT * CHUNK_LEN; 84559607eaSDaniel P. Berrange data->input = g_new0(char, data->len); 85559607eaSDaniel P. Berrange data->output = g_new0(gchar, data->len); 86559607eaSDaniel P. Berrange 87559607eaSDaniel P. Berrange /* Fill input with a pattern */ 88559607eaSDaniel P. Berrange for (i = 0; i < data->len; i += CHUNK_LEN) { 89559607eaSDaniel P. Berrange memset(data->input + i, (i / CHUNK_LEN), CHUNK_LEN); 90559607eaSDaniel P. Berrange } 91559607eaSDaniel P. Berrange 92559607eaSDaniel P. Berrange /* We'll split the data across a bunch of IO vecs */ 93559607eaSDaniel P. Berrange data->niov = CHUNK_COUNT; 94559607eaSDaniel P. Berrange data->inputv = g_new0(struct iovec, data->niov); 95559607eaSDaniel P. Berrange data->outputv = g_new0(struct iovec, data->niov); 96559607eaSDaniel P. Berrange 97559607eaSDaniel P. Berrange for (i = 0, offset = 0; i < data->niov; i++, offset += CHUNK_LEN) { 98559607eaSDaniel P. Berrange data->inputv[i].iov_base = data->input + offset; 99559607eaSDaniel P. Berrange data->outputv[i].iov_base = data->output + offset; 100559607eaSDaniel P. Berrange data->inputv[i].iov_len = CHUNK_LEN; 101559607eaSDaniel P. Berrange data->outputv[i].iov_len = CHUNK_LEN; 102559607eaSDaniel P. Berrange } 103559607eaSDaniel P. Berrange 104559607eaSDaniel P. Berrange return data; 105559607eaSDaniel P. Berrange } 106559607eaSDaniel P. Berrange 107559607eaSDaniel P. Berrange void qio_channel_test_run_threads(QIOChannelTest *test, 108559607eaSDaniel P. Berrange bool blocking, 109559607eaSDaniel P. Berrange QIOChannel *src, 110559607eaSDaniel P. Berrange QIOChannel *dst) 111559607eaSDaniel P. Berrange { 112559607eaSDaniel P. Berrange GThread *reader, *writer; 113559607eaSDaniel P. Berrange 114559607eaSDaniel P. Berrange test->src = src; 115559607eaSDaniel P. Berrange test->dst = dst; 116559607eaSDaniel P. Berrange test->blocking = blocking; 117559607eaSDaniel P. Berrange 118559607eaSDaniel P. Berrange reader = g_thread_new("reader", 119559607eaSDaniel P. Berrange test_io_thread_reader, 120559607eaSDaniel P. Berrange test); 121559607eaSDaniel P. Berrange writer = g_thread_new("writer", 122559607eaSDaniel P. Berrange test_io_thread_writer, 123559607eaSDaniel P. Berrange test); 124559607eaSDaniel P. Berrange 125559607eaSDaniel P. Berrange g_thread_join(reader); 126559607eaSDaniel P. Berrange g_thread_join(writer); 127559607eaSDaniel P. Berrange 128559607eaSDaniel P. Berrange test->dst = test->src = NULL; 129559607eaSDaniel P. Berrange } 130559607eaSDaniel P. Berrange 131559607eaSDaniel P. Berrange 132559607eaSDaniel P. Berrange void qio_channel_test_run_writer(QIOChannelTest *test, 133559607eaSDaniel P. Berrange QIOChannel *src) 134559607eaSDaniel P. Berrange { 135559607eaSDaniel P. Berrange test->src = src; 136559607eaSDaniel P. Berrange test_io_thread_writer(test); 137559607eaSDaniel P. Berrange test->src = NULL; 138559607eaSDaniel P. Berrange } 139559607eaSDaniel P. Berrange 140559607eaSDaniel P. Berrange 141559607eaSDaniel P. Berrange void qio_channel_test_run_reader(QIOChannelTest *test, 142559607eaSDaniel P. Berrange QIOChannel *dst) 143559607eaSDaniel P. Berrange { 144559607eaSDaniel P. Berrange test->dst = dst; 145559607eaSDaniel P. Berrange test_io_thread_reader(test); 146559607eaSDaniel P. Berrange test->dst = NULL; 147559607eaSDaniel P. Berrange } 148559607eaSDaniel P. Berrange 149559607eaSDaniel P. Berrange 150559607eaSDaniel P. Berrange void qio_channel_test_validate(QIOChannelTest *test) 151559607eaSDaniel P. Berrange { 152294bbbb4SDaniel P. Berrange g_assert(test->readerr == NULL); 153294bbbb4SDaniel P. Berrange g_assert(test->writeerr == NULL); 154559607eaSDaniel P. Berrange g_assert_cmpint(memcmp(test->input, 155559607eaSDaniel P. Berrange test->output, 156559607eaSDaniel P. Berrange test->len), ==, 0); 157559607eaSDaniel P. Berrange 158559607eaSDaniel P. Berrange g_free(test->inputv); 159559607eaSDaniel P. Berrange g_free(test->outputv); 160559607eaSDaniel P. Berrange g_free(test->input); 161559607eaSDaniel P. Berrange g_free(test->output); 162559607eaSDaniel P. Berrange g_free(test); 163559607eaSDaniel P. Berrange } 164