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