1
#include "qemu/osdep.h"
2
#include "qemu-common.h"
4
#include "qemu/sockets.h"
6
/* create a randomly-sized iovec with random vectors */
7
static void iov_random(struct iovec **iovp, unsigned *iov_cntp)
9
unsigned niov = g_test_rand_int_range(3,8);
10
struct iovec *iov = g_malloc(niov * sizeof(*iov));
12
for (i = 0; i < niov; ++i) {
13
iov[i].iov_len = g_test_rand_int_range(5,20);
14
iov[i].iov_base = g_malloc(iov[i].iov_len);
20
static void iov_free(struct iovec *iov, unsigned niov)
23
for (i = 0; i < niov; ++i) {
24
g_free(iov[i].iov_base);
29
static void test_iov_bytes(struct iovec *iov, unsigned niov,
30
size_t offset, size_t bytes)
37
/* we walk over all elements, */
38
for (i = 0; i < niov; ++i) {
40
/* over each char of each element, */
41
for (j = 0; j < iov[i].iov_len; ++j) {
42
/* counting each of them and
43
* verifying that the ones within [offset,offset+bytes)
44
* range are equal to the position number (o) */
45
if (o >= offset && o < offset + bytes) {
46
g_assert(b[j] == (o & 255));
48
g_assert(b[j] == 0xff);
55
static void test_to_from_buf_1(void)
60
unsigned char *ibuf, *obuf;
63
iov_random(&iov, &niov);
65
sz = iov_size(iov, niov);
67
ibuf = g_malloc(sz + 8) + 4;
68
memcpy(ibuf-4, "aaaa", 4); memcpy(ibuf + sz, "bbbb", 4);
69
obuf = g_malloc(sz + 8) + 4;
70
memcpy(obuf-4, "xxxx", 4); memcpy(obuf + sz, "yyyy", 4);
72
/* fill in ibuf with 0123456... */
73
for (i = 0; i < sz; ++i) {
77
for (i = 0; i <= sz; ++i) {
79
/* Test from/to buf for offset(i) in [0..sz] up to the end of buffer.
80
* For last iteration with offset == sz, the procedure should
81
* skip whole vector and process exactly 0 bytes */
83
/* first set bytes [i..sz) to some "random" value */
84
n = iov_memset(iov, niov, 0, 0xff, -1);
87
/* next copy bytes [i..sz) from ibuf to iovec */
88
n = iov_from_buf(iov, niov, i, ibuf + i, -1);
89
g_assert(n == sz - i);
91
/* clear part of obuf */
92
memset(obuf + i, 0, sz - i);
93
/* and set this part of obuf to values from iovec */
94
n = iov_to_buf(iov, niov, i, obuf + i, -1);
95
g_assert(n == sz - i);
97
/* now compare resulting buffers */
98
g_assert(memcmp(ibuf, obuf, sz) == 0);
100
/* test just one char */
101
n = iov_to_buf(iov, niov, i, obuf + i, 1);
102
g_assert(n == (i < sz));
104
g_assert(obuf[i] == (i & 255));
107
for (j = i; j <= sz; ++j) {
108
/* now test num of bytes cap up to byte no. j,
109
* with j in [i..sz]. */
112
n = iov_memset(iov, niov, 0, 0xff, -1);
115
/* copy bytes [i..j) from ibuf to iovec */
116
n = iov_from_buf(iov, niov, i, ibuf + i, j - i);
117
g_assert(n == j - i);
119
/* clear part of obuf */
120
memset(obuf + i, 0, j - i);
122
/* copy bytes [i..j) from iovec to obuf */
123
n = iov_to_buf(iov, niov, i, obuf + i, j - i);
124
g_assert(n == j - i);
127
g_assert(memcmp(ibuf, obuf, sz) == 0);
129
/* now actually check if the iovec contains the right data */
130
test_iov_bytes(iov, niov, i, j - i);
133
g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4));
135
g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
140
static void test_to_from_buf(void)
143
for (x = 0; x < 4; ++x) {
144
test_to_from_buf_1();
148
static void test_io(void)
151
/* socketpair(PF_UNIX) which does not exist on windows */
155
unsigned i, j, k, s, t;
158
struct iovec *iov, *siov;
162
iov_random(&iov, &niov);
163
sz = iov_size(iov, niov);
165
for (i = 0; i < sz; ++i) {
168
iov_from_buf(iov, niov, 0, buf, sz);
170
siov = g_malloc(sizeof(*iov) * niov);
171
memcpy(siov, iov, sizeof(*iov) * niov);
173
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
174
perror("socketpair");
186
fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK);
187
r = g_test_rand_int_range(sz / 2, sz);
188
setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
190
for (i = 0; i <= sz; ++i) {
191
for (j = i; j <= sz; ++j) {
194
s = g_test_rand_int_range(0, j - k + 1);
195
r = iov_send(sv[1], iov, niov, k, s);
196
g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
200
usleep(g_test_rand_int_range(0, 30));
201
} else if (errno == EAGAIN) {
202
select(sv[1]+1, NULL, &fds, NULL, NULL);
217
/* reader & verifier */
221
fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK);
222
r = g_test_rand_int_range(sz / 2, sz);
223
setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
226
for (i = 0; i <= sz; ++i) {
227
for (j = i; j <= sz; ++j) {
229
iov_memset(iov, niov, 0, 0xff, -1);
231
s = g_test_rand_int_range(0, j - k + 1);
232
r = iov_recv(sv[0], iov, niov, k, s);
233
g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
241
} else if (errno == EAGAIN) {
242
select(sv[0]+1, &fds, NULL, NULL, NULL);
249
test_iov_bytes(iov, niov, i, j - i);
260
static void test_discard_front(void)
263
struct iovec *iov_tmp;
264
unsigned int iov_cnt;
265
unsigned int iov_cnt_tmp;
270
/* Discard zero bytes */
271
iov_random(&iov, &iov_cnt);
273
iov_cnt_tmp = iov_cnt;
274
ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
276
g_assert(iov_tmp == iov);
277
g_assert(iov_cnt_tmp == iov_cnt);
278
iov_free(iov, iov_cnt);
280
/* Discard more bytes than vector size */
281
iov_random(&iov, &iov_cnt);
283
iov_cnt_tmp = iov_cnt;
284
size = iov_size(iov, iov_cnt);
285
ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
286
g_assert(ret == size);
287
g_assert(iov_cnt_tmp == 0);
288
iov_free(iov, iov_cnt);
290
/* Discard entire vector */
291
iov_random(&iov, &iov_cnt);
293
iov_cnt_tmp = iov_cnt;
294
size = iov_size(iov, iov_cnt);
295
ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
296
g_assert(ret == size);
297
g_assert(iov_cnt_tmp == 0);
298
iov_free(iov, iov_cnt);
300
/* Discard within first element */
301
iov_random(&iov, &iov_cnt);
303
iov_cnt_tmp = iov_cnt;
304
old_base = iov->iov_base;
305
size = g_test_rand_int_range(1, iov->iov_len);
306
ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
307
g_assert(ret == size);
308
g_assert(iov_tmp == iov);
309
g_assert(iov_cnt_tmp == iov_cnt);
310
g_assert(iov_tmp->iov_base == old_base + size);
311
iov_tmp->iov_base = old_base; /* undo before g_free() */
312
iov_free(iov, iov_cnt);
314
/* Discard entire first element */
315
iov_random(&iov, &iov_cnt);
317
iov_cnt_tmp = iov_cnt;
318
ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
319
g_assert(ret == iov->iov_len);
320
g_assert(iov_tmp == iov + 1);
321
g_assert(iov_cnt_tmp == iov_cnt - 1);
322
iov_free(iov, iov_cnt);
324
/* Discard within second element */
325
iov_random(&iov, &iov_cnt);
327
iov_cnt_tmp = iov_cnt;
328
old_base = iov[1].iov_base;
329
size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
330
ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
331
g_assert(ret == size);
332
g_assert(iov_tmp == iov + 1);
333
g_assert(iov_cnt_tmp == iov_cnt - 1);
334
g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
335
iov_tmp->iov_base = old_base; /* undo before g_free() */
336
iov_free(iov, iov_cnt);
339
static void test_discard_back(void)
342
unsigned int iov_cnt;
343
unsigned int iov_cnt_tmp;
348
/* Discard zero bytes */
349
iov_random(&iov, &iov_cnt);
350
iov_cnt_tmp = iov_cnt;
351
ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
353
g_assert(iov_cnt_tmp == iov_cnt);
354
iov_free(iov, iov_cnt);
356
/* Discard more bytes than vector size */
357
iov_random(&iov, &iov_cnt);
358
iov_cnt_tmp = iov_cnt;
359
size = iov_size(iov, iov_cnt);
360
ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
361
g_assert(ret == size);
362
g_assert(iov_cnt_tmp == 0);
363
iov_free(iov, iov_cnt);
365
/* Discard entire vector */
366
iov_random(&iov, &iov_cnt);
367
iov_cnt_tmp = iov_cnt;
368
size = iov_size(iov, iov_cnt);
369
ret = iov_discard_back(iov, &iov_cnt_tmp, size);
370
g_assert(ret == size);
371
g_assert(iov_cnt_tmp == 0);
372
iov_free(iov, iov_cnt);
374
/* Discard within last element */
375
iov_random(&iov, &iov_cnt);
376
iov_cnt_tmp = iov_cnt;
377
old_base = iov[iov_cnt - 1].iov_base;
378
size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
379
ret = iov_discard_back(iov, &iov_cnt_tmp, size);
380
g_assert(ret == size);
381
g_assert(iov_cnt_tmp == iov_cnt);
382
g_assert(iov[iov_cnt - 1].iov_base == old_base);
383
iov_free(iov, iov_cnt);
385
/* Discard entire last element */
386
iov_random(&iov, &iov_cnt);
387
iov_cnt_tmp = iov_cnt;
388
old_base = iov[iov_cnt - 1].iov_base;
389
size = iov[iov_cnt - 1].iov_len;
390
ret = iov_discard_back(iov, &iov_cnt_tmp, size);
391
g_assert(ret == size);
392
g_assert(iov_cnt_tmp == iov_cnt - 1);
393
iov_free(iov, iov_cnt);
395
/* Discard within second-to-last element */
396
iov_random(&iov, &iov_cnt);
397
iov_cnt_tmp = iov_cnt;
398
old_base = iov[iov_cnt - 2].iov_base;
399
size = iov[iov_cnt - 1].iov_len +
400
g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
401
ret = iov_discard_back(iov, &iov_cnt_tmp, size);
402
g_assert(ret == size);
403
g_assert(iov_cnt_tmp == iov_cnt - 1);
404
g_assert(iov[iov_cnt - 2].iov_base == old_base);
405
iov_free(iov, iov_cnt);
408
int main(int argc, char **argv)
410
g_test_init(&argc, &argv, NULL);
412
g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
413
g_test_add_func("/basic/iov/io", test_io);
414
g_test_add_func("/basic/iov/discard-front", test_discard_front);
415
g_test_add_func("/basic/iov/discard-back", test_discard_back);