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 bool iov_equals(const struct iovec *a, const struct iovec *b,
32 return memcmp(a, b, sizeof(a[0]) * niov) == 0;
35 static void test_iov_bytes(struct iovec *iov, unsigned niov,
36 size_t offset, size_t bytes)
43 /* we walk over all elements, */
44 for (i = 0; i < niov; ++i) {
46 /* over each char of each element, */
47 for (j = 0; j < iov[i].iov_len; ++j) {
48 /* counting each of them and
49 * verifying that the ones within [offset,offset+bytes)
50 * range are equal to the position number (o) */
51 if (o >= offset && o < offset + bytes) {
52 g_assert(b[j] == (o & 255));
54 g_assert(b[j] == 0xff);
61 static void test_to_from_buf_1(void)
66 unsigned char *ibuf, *obuf;
69 iov_random(&iov, &niov);
71 sz = iov_size(iov, niov);
73 ibuf = g_malloc(sz + 8) + 4;
74 memcpy(ibuf-4, "aaaa", 4); memcpy(ibuf + sz, "bbbb", 4);
75 obuf = g_malloc(sz + 8) + 4;
76 memcpy(obuf-4, "xxxx", 4); memcpy(obuf + sz, "yyyy", 4);
78 /* fill in ibuf with 0123456... */
79 for (i = 0; i < sz; ++i) {
83 for (i = 0; i <= sz; ++i) {
85 /* Test from/to buf for offset(i) in [0..sz] up to the end of buffer.
86 * For last iteration with offset == sz, the procedure should
87 * skip whole vector and process exactly 0 bytes */
89 /* first set bytes [i..sz) to some "random" value */
90 n = iov_memset(iov, niov, 0, 0xff, sz);
93 /* next copy bytes [i..sz) from ibuf to iovec */
94 n = iov_from_buf(iov, niov, i, ibuf + i, sz - i);
95 g_assert(n == sz - i);
97 /* clear part of obuf */
98 memset(obuf + i, 0, sz - i);
99 /* and set this part of obuf to values from iovec */
100 n = iov_to_buf(iov, niov, i, obuf + i, sz - i);
101 g_assert(n == sz - i);
103 /* now compare resulting buffers */
104 g_assert(memcmp(ibuf, obuf, sz) == 0);
106 /* test just one char */
107 n = iov_to_buf(iov, niov, i, obuf + i, 1);
108 g_assert(n == (i < sz));
110 g_assert(obuf[i] == (i & 255));
113 for (j = i; j <= sz; ++j) {
114 /* now test num of bytes cap up to byte no. j,
115 * with j in [i..sz]. */
118 n = iov_memset(iov, niov, 0, 0xff, sz);
121 /* copy bytes [i..j) from ibuf to iovec */
122 n = iov_from_buf(iov, niov, i, ibuf + i, j - i);
123 g_assert(n == j - i);
125 /* clear part of obuf */
126 memset(obuf + i, 0, j - i);
128 /* copy bytes [i..j) from iovec to obuf */
129 n = iov_to_buf(iov, niov, i, obuf + i, j - i);
130 g_assert(n == j - i);
133 g_assert(memcmp(ibuf, obuf, sz) == 0);
135 /* now actually check if the iovec contains the right data */
136 test_iov_bytes(iov, niov, i, j - i);
139 g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4));
141 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
146 static void test_to_from_buf(void)
149 for (x = 0; x < 4; ++x) {
150 test_to_from_buf_1();
154 static void test_io(void)
157 /* socketpair(PF_UNIX) which does not exist on windows */
161 unsigned i, j, k, s, t;
164 struct iovec *iov, *siov;
168 iov_random(&iov, &niov);
169 sz = iov_size(iov, niov);
171 for (i = 0; i < sz; ++i) {
174 iov_from_buf(iov, niov, 0, buf, sz);
176 siov = g_memdup(iov, sizeof(*iov) * niov);
178 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
179 perror("socketpair");
191 fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK);
192 r = g_test_rand_int_range(sz / 2, sz);
193 setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
195 for (i = 0; i <= sz; ++i) {
196 for (j = i; j <= sz; ++j) {
199 s = g_test_rand_int_range(0, j - k + 1);
200 r = iov_send(sv[1], iov, niov, k, s);
201 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
205 usleep(g_test_rand_int_range(0, 30));
206 } else if (errno == EAGAIN) {
207 select(sv[1]+1, NULL, &fds, NULL, NULL);
222 /* reader & verifier */
226 fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK);
227 r = g_test_rand_int_range(sz / 2, sz);
228 setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
231 for (i = 0; i <= sz; ++i) {
232 for (j = i; j <= sz; ++j) {
234 iov_memset(iov, niov, 0, 0xff, sz);
236 s = g_test_rand_int_range(0, j - k + 1);
237 r = iov_recv(sv[0], iov, niov, k, s);
238 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
246 } else if (errno == EAGAIN) {
247 select(sv[0]+1, &fds, NULL, NULL, NULL);
254 test_iov_bytes(iov, niov, i, j - i);
265 static void test_discard_front(void)
268 struct iovec *iov_tmp;
269 unsigned int iov_cnt;
270 unsigned int iov_cnt_tmp;
275 /* Discard zero bytes */
276 iov_random(&iov, &iov_cnt);
278 iov_cnt_tmp = iov_cnt;
279 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
281 g_assert(iov_tmp == iov);
282 g_assert(iov_cnt_tmp == iov_cnt);
283 iov_free(iov, iov_cnt);
285 /* Discard more bytes than vector size */
286 iov_random(&iov, &iov_cnt);
288 iov_cnt_tmp = iov_cnt;
289 size = iov_size(iov, iov_cnt);
290 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
291 g_assert(ret == size);
292 g_assert(iov_cnt_tmp == 0);
293 iov_free(iov, iov_cnt);
295 /* Discard entire vector */
296 iov_random(&iov, &iov_cnt);
298 iov_cnt_tmp = iov_cnt;
299 size = iov_size(iov, iov_cnt);
300 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
301 g_assert(ret == size);
302 g_assert(iov_cnt_tmp == 0);
303 iov_free(iov, iov_cnt);
305 /* Discard within first element */
306 iov_random(&iov, &iov_cnt);
308 iov_cnt_tmp = iov_cnt;
309 old_base = iov->iov_base;
310 size = g_test_rand_int_range(1, iov->iov_len);
311 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
312 g_assert(ret == size);
313 g_assert(iov_tmp == iov);
314 g_assert(iov_cnt_tmp == iov_cnt);
315 g_assert(iov_tmp->iov_base == old_base + size);
316 iov_tmp->iov_base = old_base; /* undo before g_free() */
317 iov_free(iov, iov_cnt);
319 /* Discard entire first element */
320 iov_random(&iov, &iov_cnt);
322 iov_cnt_tmp = iov_cnt;
323 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
324 g_assert(ret == iov->iov_len);
325 g_assert(iov_tmp == iov + 1);
326 g_assert(iov_cnt_tmp == iov_cnt - 1);
327 iov_free(iov, iov_cnt);
329 /* Discard within second element */
330 iov_random(&iov, &iov_cnt);
332 iov_cnt_tmp = iov_cnt;
333 old_base = iov[1].iov_base;
334 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
335 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
336 g_assert(ret == size);
337 g_assert(iov_tmp == iov + 1);
338 g_assert(iov_cnt_tmp == iov_cnt - 1);
339 g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
340 iov_tmp->iov_base = old_base; /* undo before g_free() */
341 iov_free(iov, iov_cnt);
344 static void test_discard_front_undo(void)
348 struct iovec *iov_tmp;
349 struct iovec *iov_orig;
350 unsigned int iov_cnt;
351 unsigned int iov_cnt_tmp;
354 /* Discard zero bytes */
355 iov_random(&iov, &iov_cnt);
356 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
358 iov_cnt_tmp = iov_cnt;
359 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo);
360 iov_discard_undo(&undo);
361 assert(iov_equals(iov, iov_orig, iov_cnt));
363 iov_free(iov, iov_cnt);
365 /* Discard more bytes than vector size */
366 iov_random(&iov, &iov_cnt);
367 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
369 iov_cnt_tmp = iov_cnt;
370 size = iov_size(iov, iov_cnt);
371 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo);
372 iov_discard_undo(&undo);
373 assert(iov_equals(iov, iov_orig, iov_cnt));
375 iov_free(iov, iov_cnt);
377 /* Discard entire vector */
378 iov_random(&iov, &iov_cnt);
379 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
381 iov_cnt_tmp = iov_cnt;
382 size = iov_size(iov, iov_cnt);
383 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
384 iov_discard_undo(&undo);
385 assert(iov_equals(iov, iov_orig, iov_cnt));
387 iov_free(iov, iov_cnt);
389 /* Discard within first element */
390 iov_random(&iov, &iov_cnt);
391 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
393 iov_cnt_tmp = iov_cnt;
394 size = g_test_rand_int_range(1, iov->iov_len);
395 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
396 iov_discard_undo(&undo);
397 assert(iov_equals(iov, iov_orig, iov_cnt));
399 iov_free(iov, iov_cnt);
401 /* Discard entire first element */
402 iov_random(&iov, &iov_cnt);
403 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
405 iov_cnt_tmp = iov_cnt;
406 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo);
407 iov_discard_undo(&undo);
408 assert(iov_equals(iov, iov_orig, iov_cnt));
410 iov_free(iov, iov_cnt);
412 /* Discard within second element */
413 iov_random(&iov, &iov_cnt);
414 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
416 iov_cnt_tmp = iov_cnt;
417 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
418 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
419 iov_discard_undo(&undo);
420 assert(iov_equals(iov, iov_orig, iov_cnt));
422 iov_free(iov, iov_cnt);
425 static void test_discard_back(void)
428 unsigned int iov_cnt;
429 unsigned int iov_cnt_tmp;
434 /* Discard zero bytes */
435 iov_random(&iov, &iov_cnt);
436 iov_cnt_tmp = iov_cnt;
437 ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
439 g_assert(iov_cnt_tmp == iov_cnt);
440 iov_free(iov, iov_cnt);
442 /* Discard more bytes than vector size */
443 iov_random(&iov, &iov_cnt);
444 iov_cnt_tmp = iov_cnt;
445 size = iov_size(iov, iov_cnt);
446 ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
447 g_assert(ret == size);
448 g_assert(iov_cnt_tmp == 0);
449 iov_free(iov, iov_cnt);
451 /* Discard entire vector */
452 iov_random(&iov, &iov_cnt);
453 iov_cnt_tmp = iov_cnt;
454 size = iov_size(iov, iov_cnt);
455 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
456 g_assert(ret == size);
457 g_assert(iov_cnt_tmp == 0);
458 iov_free(iov, iov_cnt);
460 /* Discard within last element */
461 iov_random(&iov, &iov_cnt);
462 iov_cnt_tmp = iov_cnt;
463 old_base = iov[iov_cnt - 1].iov_base;
464 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
465 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
466 g_assert(ret == size);
467 g_assert(iov_cnt_tmp == iov_cnt);
468 g_assert(iov[iov_cnt - 1].iov_base == old_base);
469 iov_free(iov, iov_cnt);
471 /* Discard entire last element */
472 iov_random(&iov, &iov_cnt);
473 iov_cnt_tmp = iov_cnt;
474 old_base = iov[iov_cnt - 1].iov_base;
475 size = iov[iov_cnt - 1].iov_len;
476 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
477 g_assert(ret == size);
478 g_assert(iov_cnt_tmp == iov_cnt - 1);
479 iov_free(iov, iov_cnt);
481 /* Discard within second-to-last element */
482 iov_random(&iov, &iov_cnt);
483 iov_cnt_tmp = iov_cnt;
484 old_base = iov[iov_cnt - 2].iov_base;
485 size = iov[iov_cnt - 1].iov_len +
486 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
487 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
488 g_assert(ret == size);
489 g_assert(iov_cnt_tmp == iov_cnt - 1);
490 g_assert(iov[iov_cnt - 2].iov_base == old_base);
491 iov_free(iov, iov_cnt);
494 static void test_discard_back_undo(void)
498 struct iovec *iov_orig;
499 unsigned int iov_cnt;
500 unsigned int iov_cnt_tmp;
503 /* Discard zero bytes */
504 iov_random(&iov, &iov_cnt);
505 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
506 iov_cnt_tmp = iov_cnt;
507 iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo);
508 iov_discard_undo(&undo);
509 assert(iov_equals(iov, iov_orig, iov_cnt));
511 iov_free(iov, iov_cnt);
513 /* Discard more bytes than vector size */
514 iov_random(&iov, &iov_cnt);
515 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
516 iov_cnt_tmp = iov_cnt;
517 size = iov_size(iov, iov_cnt);
518 iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo);
519 iov_discard_undo(&undo);
520 assert(iov_equals(iov, iov_orig, iov_cnt));
522 iov_free(iov, iov_cnt);
524 /* Discard entire vector */
525 iov_random(&iov, &iov_cnt);
526 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
527 iov_cnt_tmp = iov_cnt;
528 size = iov_size(iov, iov_cnt);
529 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
530 iov_discard_undo(&undo);
531 assert(iov_equals(iov, iov_orig, iov_cnt));
533 iov_free(iov, iov_cnt);
535 /* Discard within last element */
536 iov_random(&iov, &iov_cnt);
537 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
538 iov_cnt_tmp = iov_cnt;
539 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
540 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
541 iov_discard_undo(&undo);
542 assert(iov_equals(iov, iov_orig, iov_cnt));
544 iov_free(iov, iov_cnt);
546 /* Discard entire last element */
547 iov_random(&iov, &iov_cnt);
548 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
549 iov_cnt_tmp = iov_cnt;
550 size = iov[iov_cnt - 1].iov_len;
551 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
552 iov_discard_undo(&undo);
553 assert(iov_equals(iov, iov_orig, iov_cnt));
555 iov_free(iov, iov_cnt);
557 /* Discard within second-to-last element */
558 iov_random(&iov, &iov_cnt);
559 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
560 iov_cnt_tmp = iov_cnt;
561 size = iov[iov_cnt - 1].iov_len +
562 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
563 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
564 iov_discard_undo(&undo);
565 assert(iov_equals(iov, iov_orig, iov_cnt));
567 iov_free(iov, iov_cnt);
570 int main(int argc, char **argv)
572 g_test_init(&argc, &argv, NULL);
574 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
575 g_test_add_func("/basic/iov/io", test_io);
576 g_test_add_func("/basic/iov/discard-front", test_discard_front);
577 g_test_add_func("/basic/iov/discard-back", test_discard_back);
578 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo);
579 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo);