io-channel-helpers.c 4.2 KB

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