qemu/tests/unit/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.1 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    size_t len;
  29    size_t niov;
  30    char *input;
  31    struct iovec *inputv;
  32    char *output;
  33    struct iovec *outputv;
  34    Error *writeerr;
  35    Error *readerr;
  36};
  37
  38
  39/* This thread sends all data using iovecs */
  40static gpointer test_io_thread_writer(gpointer opaque)
  41{
  42    QIOChannelTest *data = opaque;
  43
  44    qio_channel_writev_all(data->src,
  45                           data->inputv,
  46                           data->niov,
  47                           &data->writeerr);
  48
  49    return NULL;
  50}
  51
  52
  53/* This thread receives all data using iovecs */
  54static gpointer test_io_thread_reader(gpointer opaque)
  55{
  56    QIOChannelTest *data = opaque;
  57
  58    qio_channel_readv_all(data->dst,
  59                          data->outputv,
  60                          data->niov,
  61                          &data->readerr);
  62
  63    return NULL;
  64}
  65
  66
  67QIOChannelTest *qio_channel_test_new(void)
  68{
  69    QIOChannelTest *data = g_new0(QIOChannelTest, 1);
  70    size_t i;
  71    size_t offset;
  72
  73
  74    /* We'll send 1 MB of data */
  75#define CHUNK_COUNT 250
  76#define CHUNK_LEN 4194
  77
  78    data->len = CHUNK_COUNT * CHUNK_LEN;
  79    data->input = g_new0(char, data->len);
  80    data->output = g_new0(gchar, data->len);
  81
  82    /* Fill input with a pattern */
  83    for (i = 0; i < data->len; i += CHUNK_LEN) {
  84        memset(data->input + i, (i / CHUNK_LEN), CHUNK_LEN);
  85    }
  86
  87    /* We'll split the data across a bunch of IO vecs */
  88    data->niov = CHUNK_COUNT;
  89    data->inputv = g_new0(struct iovec, data->niov);
  90    data->outputv = g_new0(struct iovec, data->niov);
  91
  92    for (i = 0, offset = 0; i < data->niov; i++, offset += CHUNK_LEN) {
  93        data->inputv[i].iov_base = data->input + offset;
  94        data->outputv[i].iov_base = data->output + offset;
  95        data->inputv[i].iov_len = CHUNK_LEN;
  96        data->outputv[i].iov_len = CHUNK_LEN;
  97    }
  98
  99    return data;
 100}
 101
 102void qio_channel_test_run_threads(QIOChannelTest *test,
 103                                  bool blocking,
 104                                  QIOChannel *src,
 105                                  QIOChannel *dst)
 106{
 107    GThread *reader, *writer;
 108
 109    test->src = src;
 110    test->dst = dst;
 111
 112    qio_channel_set_blocking(test->dst, blocking, NULL);
 113    qio_channel_set_blocking(test->src, blocking, NULL);
 114
 115    reader = g_thread_new("reader",
 116                          test_io_thread_reader,
 117                          test);
 118    writer = g_thread_new("writer",
 119                          test_io_thread_writer,
 120                          test);
 121
 122    g_thread_join(reader);
 123    g_thread_join(writer);
 124
 125    test->dst = test->src = NULL;
 126}
 127
 128
 129void qio_channel_test_run_writer(QIOChannelTest *test,
 130                                 QIOChannel *src)
 131{
 132    test->src = src;
 133    test_io_thread_writer(test);
 134    test->src = NULL;
 135}
 136
 137
 138void qio_channel_test_run_reader(QIOChannelTest *test,
 139                                 QIOChannel *dst)
 140{
 141    test->dst = dst;
 142    test_io_thread_reader(test);
 143    test->dst = NULL;
 144}
 145
 146
 147void qio_channel_test_validate(QIOChannelTest *test)
 148{
 149    g_assert(test->readerr == NULL);
 150    g_assert(test->writeerr == NULL);
 151    g_assert_cmpint(memcmp(test->input,
 152                           test->output,
 153                           test->len), ==, 0);
 154
 155    g_free(test->inputv);
 156    g_free(test->outputv);
 157    g_free(test->input);
 158    g_free(test->output);
 159    g_free(test);
 160}
 161