diff options
author | Michael Tokarev <mjt@tls.msk.ru> | 2012-03-14 11:18:54 +0400 |
---|---|---|
committer | Michael Tokarev <mjt@tls.msk.ru> | 2012-06-11 23:12:11 +0400 |
commit | 25e5e4c7e9d5ec3e95c9526d1abaca40ada50ab0 (patch) | |
tree | 0c224d409dd20ca4c613d3ee35fab755ca13c1a2 /tests | |
parent | 2fc8ae1dd77fbc55146b602f703add6dc314dea4 (diff) |
rewrite iov_send_recv() and move it to iov.c
Make it much more understandable, add a missing
iov_cnt argument (number of iovs in the iov), and
add comments to it.
The new implementation has been extensively tested
by splitting a large buffer into many small
randomly-sized chunks, sending it over socket to
another, slow process and verifying the receiving
data is the same.
Also add a unit test for iov_send_recv(), sending/
receiving data between two processes over a socketpair
using random vectors and random sizes.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test-iov.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/tests/test-iov.c b/tests/test-iov.c index 5f82296a86..cbe7a8955c 100644 --- a/tests/test-iov.c +++ b/tests/test-iov.c @@ -1,6 +1,7 @@ #include <glib.h> #include "qemu-common.h" #include "iov.h" +#include "qemu_socket.h" /* create a randomly-sized iovec with random vectors */ static void iov_random(struct iovec **iovp, unsigned *iov_cntp) @@ -144,10 +145,116 @@ static void test_to_from_buf(void) } } +static void test_io(void) +{ +#ifndef _WIN32 +/* socketpair(PF_UNIX) which does not exist on windows */ + + int sv[2]; + int r; + unsigned i, j, k, s, t; + fd_set fds; + unsigned niov; + struct iovec *iov, *siov; + unsigned char *buf; + size_t sz; + + iov_random(&iov, &niov); + sz = iov_size(iov, niov); + buf = g_malloc(sz); + for (i = 0; i < sz; ++i) { + buf[i] = i & 255; + } + iov_from_buf(iov, niov, 0, buf, sz); + + siov = g_malloc(sizeof(*iov) * niov); + memcpy(siov, iov, sizeof(*iov) * niov); + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) { + perror("socketpair"); + exit(1); + } + + FD_ZERO(&fds); + + t = 0; + if (fork() == 0) { + /* writer */ + + close(sv[0]); + FD_SET(sv[1], &fds); + fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK); + r = g_test_rand_int_range(sz / 2, sz); + setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r)); + + for (i = 0; i <= sz; ++i) { + for (j = i; j <= sz; ++j) { + k = i; + do { + s = g_test_rand_int_range(0, j - k + 1); + r = iov_send(sv[1], iov, niov, k, s); + g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0); + if (r >= 0) { + k += r; + t += r; + usleep(g_test_rand_int_range(0, 30)); + } else if (errno == EAGAIN) { + select(sv[1]+1, NULL, &fds, NULL, NULL); + continue; + } else { + perror("send"); + exit(1); + } + } while(k < j); + } + } + exit(0); + + } else { + /* reader & verifier */ + + close(sv[1]); + FD_SET(sv[0], &fds); + fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK); + r = g_test_rand_int_range(sz / 2, sz); + setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r)); + usleep(500000); + + for (i = 0; i <= sz; ++i) { + for (j = i; j <= sz; ++j) { + k = i; + iov_memset(iov, niov, 0, 0xff, -1); + do { + s = g_test_rand_int_range(0, j - k + 1); + r = iov_recv(sv[0], iov, niov, k, s); + g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0); + if (r > 0) { + k += r; + t += r; + } else if (!r) { + if (s) { + break; + } + } else if (errno == EAGAIN) { + select(sv[0]+1, &fds, NULL, NULL, NULL); + continue; + } else { + perror("recv"); + exit(1); + } + } while(k < j); + test_iov_bytes(iov, niov, i, j - i); + } + } + } +#endif +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); g_test_rand_int(); g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf); + g_test_add_func("/basic/iov/io", test_io); return g_test_run(); } |