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);
201 if (errno
== EAGAIN
) {
210 select(sv
[1] + 1, NULL
, &fds
, NULL
, NULL
);
221 /* reader & verifier */
225 g_unix_set_fd_nonblocking(sv
[0], true, NULL
);
226 r
= g_test_rand_int_range(sz
/ 2, sz
);
227 setsockopt(sv
[0], SOL_SOCKET
, SO_RCVBUF
, &r
, sizeof(r
));
230 for (i
= 0; i
<= sz
; ++i
) {
231 for (j
= i
; j
<= sz
; ++j
) {
233 iov_memset(iov
, niov
, 0, 0xff, sz
);
235 s
= g_test_rand_int_range(0, j
- k
+ 1);
236 r
= iov_recv(sv
[0], iov
, niov
, k
, s
);
237 g_assert(memcmp(iov
, siov
, sizeof(*iov
)*niov
) == 0);
244 } else if (errno
== EAGAIN
) {
245 select(sv
[0]+1, &fds
, NULL
, NULL
, NULL
);
252 test_iov_bytes(iov
, niov
, i
, j
- i
);
263 static void test_discard_front(void)
266 struct iovec
*iov_tmp
;
267 unsigned int iov_cnt
;
268 unsigned int iov_cnt_tmp
;
273 /* Discard zero bytes */
274 iov_random(&iov
, &iov_cnt
);
276 iov_cnt_tmp
= iov_cnt
;
277 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, 0);
279 g_assert(iov_tmp
== iov
);
280 g_assert(iov_cnt_tmp
== iov_cnt
);
281 iov_free(iov
, iov_cnt
);
283 /* Discard more bytes than vector size */
284 iov_random(&iov
, &iov_cnt
);
286 iov_cnt_tmp
= iov_cnt
;
287 size
= iov_size(iov
, iov_cnt
);
288 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
+ 1);
289 g_assert(ret
== size
);
290 g_assert(iov_cnt_tmp
== 0);
291 iov_free(iov
, iov_cnt
);
293 /* Discard entire vector */
294 iov_random(&iov
, &iov_cnt
);
296 iov_cnt_tmp
= iov_cnt
;
297 size
= iov_size(iov
, iov_cnt
);
298 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
299 g_assert(ret
== size
);
300 g_assert(iov_cnt_tmp
== 0);
301 iov_free(iov
, iov_cnt
);
303 /* Discard within first element */
304 iov_random(&iov
, &iov_cnt
);
306 iov_cnt_tmp
= iov_cnt
;
307 old_base
= iov
->iov_base
;
308 size
= g_test_rand_int_range(1, iov
->iov_len
);
309 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
310 g_assert(ret
== size
);
311 g_assert(iov_tmp
== iov
);
312 g_assert(iov_cnt_tmp
== iov_cnt
);
313 g_assert(iov_tmp
->iov_base
== old_base
+ size
);
314 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
315 iov_free(iov
, iov_cnt
);
317 /* Discard entire first element */
318 iov_random(&iov
, &iov_cnt
);
320 iov_cnt_tmp
= iov_cnt
;
321 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, iov
->iov_len
);
322 g_assert(ret
== iov
->iov_len
);
323 g_assert(iov_tmp
== iov
+ 1);
324 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
325 iov_free(iov
, iov_cnt
);
327 /* Discard within second element */
328 iov_random(&iov
, &iov_cnt
);
330 iov_cnt_tmp
= iov_cnt
;
331 old_base
= iov
[1].iov_base
;
332 size
= iov
->iov_len
+ g_test_rand_int_range(1, iov
[1].iov_len
);
333 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
334 g_assert(ret
== size
);
335 g_assert(iov_tmp
== iov
+ 1);
336 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
337 g_assert(iov_tmp
->iov_base
== old_base
+ (size
- iov
->iov_len
));
338 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
339 iov_free(iov
, iov_cnt
);
342 static void test_discard_front_undo(void)
346 struct iovec
*iov_tmp
;
347 struct iovec
*iov_orig
;
348 unsigned int iov_cnt
;
349 unsigned int iov_cnt_tmp
;
352 /* Discard zero bytes */
353 iov_random(&iov
, &iov_cnt
);
354 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
356 iov_cnt_tmp
= iov_cnt
;
357 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, 0, &undo
);
358 iov_discard_undo(&undo
);
359 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
361 iov_free(iov
, iov_cnt
);
363 /* Discard more bytes than vector size */
364 iov_random(&iov
, &iov_cnt
);
365 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
367 iov_cnt_tmp
= iov_cnt
;
368 size
= iov_size(iov
, iov_cnt
);
369 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
+ 1, &undo
);
370 iov_discard_undo(&undo
);
371 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
373 iov_free(iov
, iov_cnt
);
375 /* Discard entire vector */
376 iov_random(&iov
, &iov_cnt
);
377 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
379 iov_cnt_tmp
= iov_cnt
;
380 size
= iov_size(iov
, iov_cnt
);
381 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
, &undo
);
382 iov_discard_undo(&undo
);
383 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
385 iov_free(iov
, iov_cnt
);
387 /* Discard within first element */
388 iov_random(&iov
, &iov_cnt
);
389 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
391 iov_cnt_tmp
= iov_cnt
;
392 size
= g_test_rand_int_range(1, iov
->iov_len
);
393 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
, &undo
);
394 iov_discard_undo(&undo
);
395 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
397 iov_free(iov
, iov_cnt
);
399 /* Discard entire first element */
400 iov_random(&iov
, &iov_cnt
);
401 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
403 iov_cnt_tmp
= iov_cnt
;
404 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, iov
->iov_len
, &undo
);
405 iov_discard_undo(&undo
);
406 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
408 iov_free(iov
, iov_cnt
);
410 /* Discard within second element */
411 iov_random(&iov
, &iov_cnt
);
412 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
414 iov_cnt_tmp
= iov_cnt
;
415 size
= iov
->iov_len
+ g_test_rand_int_range(1, iov
[1].iov_len
);
416 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
, &undo
);
417 iov_discard_undo(&undo
);
418 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
420 iov_free(iov
, iov_cnt
);
423 static void test_discard_back(void)
426 unsigned int iov_cnt
;
427 unsigned int iov_cnt_tmp
;
432 /* Discard zero bytes */
433 iov_random(&iov
, &iov_cnt
);
434 iov_cnt_tmp
= iov_cnt
;
435 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, 0);
437 g_assert(iov_cnt_tmp
== iov_cnt
);
438 iov_free(iov
, iov_cnt
);
440 /* Discard more bytes than vector size */
441 iov_random(&iov
, &iov_cnt
);
442 iov_cnt_tmp
= iov_cnt
;
443 size
= iov_size(iov
, iov_cnt
);
444 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
+ 1);
445 g_assert(ret
== size
);
446 g_assert(iov_cnt_tmp
== 0);
447 iov_free(iov
, iov_cnt
);
449 /* Discard entire vector */
450 iov_random(&iov
, &iov_cnt
);
451 iov_cnt_tmp
= iov_cnt
;
452 size
= iov_size(iov
, iov_cnt
);
453 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
454 g_assert(ret
== size
);
455 g_assert(iov_cnt_tmp
== 0);
456 iov_free(iov
, iov_cnt
);
458 /* Discard within last element */
459 iov_random(&iov
, &iov_cnt
);
460 iov_cnt_tmp
= iov_cnt
;
461 old_base
= iov
[iov_cnt
- 1].iov_base
;
462 size
= g_test_rand_int_range(1, iov
[iov_cnt
- 1].iov_len
);
463 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
464 g_assert(ret
== size
);
465 g_assert(iov_cnt_tmp
== iov_cnt
);
466 g_assert(iov
[iov_cnt
- 1].iov_base
== old_base
);
467 iov_free(iov
, iov_cnt
);
469 /* Discard entire last element */
470 iov_random(&iov
, &iov_cnt
);
471 iov_cnt_tmp
= iov_cnt
;
472 old_base
= iov
[iov_cnt
- 1].iov_base
;
473 size
= iov
[iov_cnt
- 1].iov_len
;
474 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
475 g_assert(ret
== size
);
476 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
477 iov_free(iov
, iov_cnt
);
479 /* Discard within second-to-last element */
480 iov_random(&iov
, &iov_cnt
);
481 iov_cnt_tmp
= iov_cnt
;
482 old_base
= iov
[iov_cnt
- 2].iov_base
;
483 size
= iov
[iov_cnt
- 1].iov_len
+
484 g_test_rand_int_range(1, iov
[iov_cnt
- 2].iov_len
);
485 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
486 g_assert(ret
== size
);
487 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
488 g_assert(iov
[iov_cnt
- 2].iov_base
== old_base
);
489 iov_free(iov
, iov_cnt
);
492 static void test_discard_back_undo(void)
496 struct iovec
*iov_orig
;
497 unsigned int iov_cnt
;
498 unsigned int iov_cnt_tmp
;
501 /* Discard zero bytes */
502 iov_random(&iov
, &iov_cnt
);
503 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
504 iov_cnt_tmp
= iov_cnt
;
505 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, 0, &undo
);
506 iov_discard_undo(&undo
);
507 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
509 iov_free(iov
, iov_cnt
);
511 /* Discard more bytes than vector size */
512 iov_random(&iov
, &iov_cnt
);
513 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
514 iov_cnt_tmp
= iov_cnt
;
515 size
= iov_size(iov
, iov_cnt
);
516 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
+ 1, &undo
);
517 iov_discard_undo(&undo
);
518 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
520 iov_free(iov
, iov_cnt
);
522 /* Discard entire vector */
523 iov_random(&iov
, &iov_cnt
);
524 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
525 iov_cnt_tmp
= iov_cnt
;
526 size
= iov_size(iov
, iov_cnt
);
527 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
528 iov_discard_undo(&undo
);
529 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
531 iov_free(iov
, iov_cnt
);
533 /* Discard within last element */
534 iov_random(&iov
, &iov_cnt
);
535 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
536 iov_cnt_tmp
= iov_cnt
;
537 size
= g_test_rand_int_range(1, iov
[iov_cnt
- 1].iov_len
);
538 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
539 iov_discard_undo(&undo
);
540 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
542 iov_free(iov
, iov_cnt
);
544 /* Discard entire last element */
545 iov_random(&iov
, &iov_cnt
);
546 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
547 iov_cnt_tmp
= iov_cnt
;
548 size
= iov
[iov_cnt
- 1].iov_len
;
549 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
550 iov_discard_undo(&undo
);
551 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
553 iov_free(iov
, iov_cnt
);
555 /* Discard within second-to-last element */
556 iov_random(&iov
, &iov_cnt
);
557 iov_orig
= g_memdup2(iov
, sizeof(iov
[0]) * iov_cnt
);
558 iov_cnt_tmp
= iov_cnt
;
559 size
= iov
[iov_cnt
- 1].iov_len
+
560 g_test_rand_int_range(1, iov
[iov_cnt
- 2].iov_len
);
561 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
562 iov_discard_undo(&undo
);
563 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
565 iov_free(iov
, iov_cnt
);
568 int main(int argc
, char **argv
)
570 g_test_init(&argc
, &argv
, NULL
);
572 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf
);
573 g_test_add_func("/basic/iov/io", test_io
);
574 g_test_add_func("/basic/iov/discard-front", test_discard_front
);
575 g_test_add_func("/basic/iov/discard-back", test_discard_back
);
576 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo
);
577 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo
);