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
);