1 #include "qemu/osdep.h"
3 #include "qemu/sockets.h"
5 /* create a randomly-sized iovec with random vectors */
6 static void iov_random(struct iovec **iovp, unsigned *iov_cntp)
8 unsigned niov = g_test_rand_int_range(3,8);
9 struct iovec *iov = g_malloc(niov * sizeof(*iov));
11 for (i = 0; i < niov; ++i) {
12 iov[i].iov_len = g_test_rand_int_range(5,20);
13 iov[i].iov_base = g_malloc(iov[i].iov_len);
19 static void iov_free(struct iovec *iov, unsigned niov)
22 for (i = 0; i < niov; ++i) {
23 g_free(iov[i].iov_base);
28 static bool iov_equals(const struct iovec *a, const struct iovec *b,
31 return memcmp(a, b, sizeof(a[0]) * niov) == 0;
34 static void test_iov_bytes(struct iovec *iov, unsigned niov,
35 size_t offset, size_t bytes)
42 /* we walk over all elements, */
43 for (i = 0; i < niov; ++i) {
45 /* over each char of each element, */
46 for (j = 0; j < iov[i].iov_len; ++j) {
47 /* counting each of them and
48 * verifying that the ones within [offset,offset+bytes)
49 * range are equal to the position number (o) */
50 if (o >= offset && o < offset + bytes) {
51 g_assert(b[j] == (o & 255));
53 g_assert(b[j] == 0xff);
60 static void test_to_from_buf_1(void)
65 unsigned char *ibuf, *obuf;
68 iov_random(&iov, &niov);
70 sz = iov_size(iov, niov);
72 ibuf = g_malloc(sz + 8) + 4;
73 memcpy(ibuf-4, "aaaa", 4); memcpy(ibuf + sz, "bbbb", 4);
74 obuf = g_malloc(sz + 8) + 4;
75 memcpy(obuf-4, "xxxx", 4); memcpy(obuf + sz, "yyyy", 4);
77 /* fill in ibuf with 0123456... */
78 for (i = 0; i < sz; ++i) {
82 for (i = 0; i <= sz; ++i) {
84 /* Test from/to buf for offset(i) in [0..sz] up to the end of buffer.
85 * For last iteration with offset == sz, the procedure should
86 * skip whole vector and process exactly 0 bytes */
88 /* first set bytes [i..sz) to some "random" value */
89 n = iov_memset(iov, niov, 0, 0xff, sz);
92 /* next copy bytes [i..sz) from ibuf to iovec */
93 n = iov_from_buf(iov, niov, i, ibuf + i, sz - i);
94 g_assert(n == sz - i);
96 /* clear part of obuf */
97 memset(obuf + i, 0, sz - i);
98 /* and set this part of obuf to values from iovec */
99 n = iov_to_buf(iov, niov, i, obuf + i, sz - i);
100 g_assert(n == sz - i);
102 /* now compare resulting buffers */
103 g_assert(memcmp(ibuf, obuf, sz) == 0);
105 /* test just one char */
106 n = iov_to_buf(iov, niov, i, obuf + i, 1);
107 g_assert(n == (i < sz));
109 g_assert(obuf[i] == (i & 255));
112 for (j = i; j <= sz; ++j) {
113 /* now test num of bytes cap up to byte no. j,
114 * with j in [i..sz]. */
117 n = iov_memset(iov, niov, 0, 0xff, sz);
120 /* copy bytes [i..j) from ibuf to iovec */
121 n = iov_from_buf(iov, niov, i, ibuf + i, j - i);
122 g_assert(n == j - i);
124 /* clear part of obuf */
125 memset(obuf + i, 0, j - i);
127 /* copy bytes [i..j) from iovec to obuf */
128 n = iov_to_buf(iov, niov, i, obuf + i, j - i);
129 g_assert(n == j - i);
132 g_assert(memcmp(ibuf, obuf, sz) == 0);
134 /* now actually check if the iovec contains the right data */
135 test_iov_bytes(iov, niov, i, j - i);
138 g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4));
140 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
145 static void test_to_from_buf(void)
148 for (x = 0; x < 4; ++x) {
149 test_to_from_buf_1();
153 static void test_io(void)
156 /* socketpair(PF_UNIX) which does not exist on windows */
163 struct iovec *iov, *siov;
167 iov_random(&iov, &niov);
168 sz = iov_size(iov, niov);
170 for (i = 0; i < sz; ++i) {
173 iov_from_buf(iov, niov, 0, buf, sz);
175 siov = g_memdup2(iov, sizeof(*iov) * niov);
177 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
178 perror("socketpair");
189 g_unix_set_fd_nonblocking(sv[1], true, NULL);
190 r = g_test_rand_int_range(sz / 2, sz);
191 setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
193 for (i = 0; i <= sz; ++i) {
194 for (j = i; j <= sz; ++j) {
197 s = g_test_rand_int_range(0, j - k + 1);
198 r = iov_send(sv[1], iov, niov, k, s);
199 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
202 usleep(g_test_rand_int_range(0, 30));
203 } else if (errno == EAGAIN) {
204 select(sv[1]+1, NULL, &fds, NULL, NULL);
219 /* reader & verifier */
223 g_unix_set_fd_nonblocking(sv[0], true, NULL);
224 r = g_test_rand_int_range(sz / 2, sz);
225 setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
228 for (i = 0; i <= sz; ++i) {
229 for (j = i; j <= sz; ++j) {
231 iov_memset(iov, niov, 0, 0xff, sz);
233 s = g_test_rand_int_range(0, j - k + 1);
234 r = iov_recv(sv[0], iov, niov, k, s);
235 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
242 } else if (errno == EAGAIN) {
243 select(sv[0]+1, &fds, NULL, NULL, NULL);
250 test_iov_bytes(iov, niov, i, j - i);
261 static void test_discard_front(void)
264 struct iovec *iov_tmp;
265 unsigned int iov_cnt;
266 unsigned int iov_cnt_tmp;
271 /* Discard zero bytes */
272 iov_random(&iov, &iov_cnt);
274 iov_cnt_tmp = iov_cnt;
275 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
277 g_assert(iov_tmp == iov);
278 g_assert(iov_cnt_tmp == iov_cnt);
279 iov_free(iov, iov_cnt);
281 /* Discard more bytes than vector size */
282 iov_random(&iov, &iov_cnt);
284 iov_cnt_tmp = iov_cnt;
285 size = iov_size(iov, iov_cnt);
286 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
287 g_assert(ret == size);
288 g_assert(iov_cnt_tmp == 0);
289 iov_free(iov, iov_cnt);
291 /* Discard entire vector */
292 iov_random(&iov, &iov_cnt);
294 iov_cnt_tmp = iov_cnt;
295 size = iov_size(iov, iov_cnt);
296 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
297 g_assert(ret == size);
298 g_assert(iov_cnt_tmp == 0);
299 iov_free(iov, iov_cnt);
301 /* Discard within first element */
302 iov_random(&iov, &iov_cnt);
304 iov_cnt_tmp = iov_cnt;
305 old_base = iov->iov_base;
306 size = g_test_rand_int_range(1, iov->iov_len);
307 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
308 g_assert(ret == size);
309 g_assert(iov_tmp == iov);
310 g_assert(iov_cnt_tmp == iov_cnt);
311 g_assert(iov_tmp->iov_base == old_base + size);
312 iov_tmp->iov_base = old_base; /* undo before g_free() */
313 iov_free(iov, iov_cnt);
315 /* Discard entire first element */
316 iov_random(&iov, &iov_cnt);
318 iov_cnt_tmp = iov_cnt;
319 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
320 g_assert(ret == iov->iov_len);
321 g_assert(iov_tmp == iov + 1);
322 g_assert(iov_cnt_tmp == iov_cnt - 1);
323 iov_free(iov, iov_cnt);
325 /* Discard within second element */
326 iov_random(&iov, &iov_cnt);
328 iov_cnt_tmp = iov_cnt;
329 old_base = iov[1].iov_base;
330 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
331 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
332 g_assert(ret == size);
333 g_assert(iov_tmp == iov + 1);
334 g_assert(iov_cnt_tmp == iov_cnt - 1);
335 g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
336 iov_tmp->iov_base = old_base; /* undo before g_free() */
337 iov_free(iov, iov_cnt);
340 static void test_discard_front_undo(void)
344 struct iovec *iov_tmp;
345 struct iovec *iov_orig;
346 unsigned int iov_cnt;
347 unsigned int iov_cnt_tmp;
350 /* Discard zero bytes */
351 iov_random(&iov, &iov_cnt);
352 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
354 iov_cnt_tmp = iov_cnt;
355 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo);
356 iov_discard_undo(&undo);
357 assert(iov_equals(iov, iov_orig, iov_cnt));
359 iov_free(iov, iov_cnt);
361 /* Discard more bytes than vector size */
362 iov_random(&iov, &iov_cnt);
363 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
365 iov_cnt_tmp = iov_cnt;
366 size = iov_size(iov, iov_cnt);
367 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo);
368 iov_discard_undo(&undo);
369 assert(iov_equals(iov, iov_orig, iov_cnt));
371 iov_free(iov, iov_cnt);
373 /* Discard entire vector */
374 iov_random(&iov, &iov_cnt);
375 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
377 iov_cnt_tmp = iov_cnt;
378 size = iov_size(iov, iov_cnt);
379 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
380 iov_discard_undo(&undo);
381 assert(iov_equals(iov, iov_orig, iov_cnt));
383 iov_free(iov, iov_cnt);
385 /* Discard within first element */
386 iov_random(&iov, &iov_cnt);
387 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
389 iov_cnt_tmp = iov_cnt;
390 size = g_test_rand_int_range(1, iov->iov_len);
391 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
392 iov_discard_undo(&undo);
393 assert(iov_equals(iov, iov_orig, iov_cnt));
395 iov_free(iov, iov_cnt);
397 /* Discard entire first element */
398 iov_random(&iov, &iov_cnt);
399 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
401 iov_cnt_tmp = iov_cnt;
402 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo);
403 iov_discard_undo(&undo);
404 assert(iov_equals(iov, iov_orig, iov_cnt));
406 iov_free(iov, iov_cnt);
408 /* Discard within second element */
409 iov_random(&iov, &iov_cnt);
410 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
412 iov_cnt_tmp = iov_cnt;
413 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
414 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
415 iov_discard_undo(&undo);
416 assert(iov_equals(iov, iov_orig, iov_cnt));
418 iov_free(iov, iov_cnt);
421 static void test_discard_back(void)
424 unsigned int iov_cnt;
425 unsigned int iov_cnt_tmp;
430 /* Discard zero bytes */
431 iov_random(&iov, &iov_cnt);
432 iov_cnt_tmp = iov_cnt;
433 ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
435 g_assert(iov_cnt_tmp == iov_cnt);
436 iov_free(iov, iov_cnt);
438 /* Discard more bytes than vector size */
439 iov_random(&iov, &iov_cnt);
440 iov_cnt_tmp = iov_cnt;
441 size = iov_size(iov, iov_cnt);
442 ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
443 g_assert(ret == size);
444 g_assert(iov_cnt_tmp == 0);
445 iov_free(iov, iov_cnt);
447 /* Discard entire vector */
448 iov_random(&iov, &iov_cnt);
449 iov_cnt_tmp = iov_cnt;
450 size = iov_size(iov, iov_cnt);
451 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
452 g_assert(ret == size);
453 g_assert(iov_cnt_tmp == 0);
454 iov_free(iov, iov_cnt);
456 /* Discard within last element */
457 iov_random(&iov, &iov_cnt);
458 iov_cnt_tmp = iov_cnt;
459 old_base = iov[iov_cnt - 1].iov_base;
460 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
461 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
462 g_assert(ret == size);
463 g_assert(iov_cnt_tmp == iov_cnt);
464 g_assert(iov[iov_cnt - 1].iov_base == old_base);
465 iov_free(iov, iov_cnt);
467 /* Discard entire last element */
468 iov_random(&iov, &iov_cnt);
469 iov_cnt_tmp = iov_cnt;
470 old_base = iov[iov_cnt - 1].iov_base;
471 size = iov[iov_cnt - 1].iov_len;
472 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
473 g_assert(ret == size);
474 g_assert(iov_cnt_tmp == iov_cnt - 1);
475 iov_free(iov, iov_cnt);
477 /* Discard within second-to-last element */
478 iov_random(&iov, &iov_cnt);
479 iov_cnt_tmp = iov_cnt;
480 old_base = iov[iov_cnt - 2].iov_base;
481 size = iov[iov_cnt - 1].iov_len +
482 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
483 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
484 g_assert(ret == size);
485 g_assert(iov_cnt_tmp == iov_cnt - 1);
486 g_assert(iov[iov_cnt - 2].iov_base == old_base);
487 iov_free(iov, iov_cnt);
490 static void test_discard_back_undo(void)
494 struct iovec *iov_orig;
495 unsigned int iov_cnt;
496 unsigned int iov_cnt_tmp;
499 /* Discard zero bytes */
500 iov_random(&iov, &iov_cnt);
501 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
502 iov_cnt_tmp = iov_cnt;
503 iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo);
504 iov_discard_undo(&undo);
505 assert(iov_equals(iov, iov_orig, iov_cnt));
507 iov_free(iov, iov_cnt);
509 /* Discard more bytes than vector size */
510 iov_random(&iov, &iov_cnt);
511 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
512 iov_cnt_tmp = iov_cnt;
513 size = iov_size(iov, iov_cnt);
514 iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo);
515 iov_discard_undo(&undo);
516 assert(iov_equals(iov, iov_orig, iov_cnt));
518 iov_free(iov, iov_cnt);
520 /* Discard entire vector */
521 iov_random(&iov, &iov_cnt);
522 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
523 iov_cnt_tmp = iov_cnt;
524 size = iov_size(iov, iov_cnt);
525 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
526 iov_discard_undo(&undo);
527 assert(iov_equals(iov, iov_orig, iov_cnt));
529 iov_free(iov, iov_cnt);
531 /* Discard within last element */
532 iov_random(&iov, &iov_cnt);
533 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
534 iov_cnt_tmp = iov_cnt;
535 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
536 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
537 iov_discard_undo(&undo);
538 assert(iov_equals(iov, iov_orig, iov_cnt));
540 iov_free(iov, iov_cnt);
542 /* Discard entire last element */
543 iov_random(&iov, &iov_cnt);
544 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
545 iov_cnt_tmp = iov_cnt;
546 size = iov[iov_cnt - 1].iov_len;
547 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
548 iov_discard_undo(&undo);
549 assert(iov_equals(iov, iov_orig, iov_cnt));
551 iov_free(iov, iov_cnt);
553 /* Discard within second-to-last element */
554 iov_random(&iov, &iov_cnt);
555 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
556 iov_cnt_tmp = iov_cnt;
557 size = iov[iov_cnt - 1].iov_len +
558 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
559 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
560 iov_discard_undo(&undo);
561 assert(iov_equals(iov, iov_orig, iov_cnt));
563 iov_free(iov, iov_cnt);
566 int main(int argc, char **argv)
568 g_test_init(&argc, &argv, NULL);
570 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
571 g_test_add_func("/basic/iov/io", test_io);
572 g_test_add_func("/basic/iov/discard-front", test_discard_front);
573 g_test_add_func("/basic/iov/discard-back", test_discard_back);
574 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo);
575 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo);