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 */
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");
190 fcntl(sv
[1], F_SETFL
, O_RDWR
|O_NONBLOCK
);
191 r
= g_test_rand_int_range(sz
/ 2, sz
);
192 setsockopt(sv
[1], SOL_SOCKET
, SO_SNDBUF
, &r
, sizeof(r
));
194 for (i
= 0; i
<= sz
; ++i
) {
195 for (j
= i
; j
<= sz
; ++j
) {
198 s
= g_test_rand_int_range(0, j
- k
+ 1);
199 r
= iov_send(sv
[1], iov
, niov
, k
, s
);
200 g_assert(memcmp(iov
, siov
, sizeof(*iov
)*niov
) == 0);
203 usleep(g_test_rand_int_range(0, 30));
204 } else if (errno
== EAGAIN
) {
205 select(sv
[1]+1, NULL
, &fds
, NULL
, NULL
);
220 /* reader & verifier */
224 fcntl(sv
[0], F_SETFL
, O_RDWR
|O_NONBLOCK
);
225 r
= g_test_rand_int_range(sz
/ 2, sz
);
226 setsockopt(sv
[0], SOL_SOCKET
, SO_RCVBUF
, &r
, sizeof(r
));
229 for (i
= 0; i
<= sz
; ++i
) {
230 for (j
= i
; j
<= sz
; ++j
) {
232 iov_memset(iov
, niov
, 0, 0xff, sz
);
234 s
= g_test_rand_int_range(0, j
- k
+ 1);
235 r
= iov_recv(sv
[0], iov
, niov
, k
, s
);
236 g_assert(memcmp(iov
, siov
, sizeof(*iov
)*niov
) == 0);
243 } else if (errno
== EAGAIN
) {
244 select(sv
[0]+1, &fds
, NULL
, NULL
, NULL
);
251 test_iov_bytes(iov
, niov
, i
, j
- i
);
262 static void test_discard_front(void)
265 struct iovec
*iov_tmp
;
266 unsigned int iov_cnt
;
267 unsigned int iov_cnt_tmp
;
272 /* Discard zero bytes */
273 iov_random(&iov
, &iov_cnt
);
275 iov_cnt_tmp
= iov_cnt
;
276 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, 0);
278 g_assert(iov_tmp
== iov
);
279 g_assert(iov_cnt_tmp
== iov_cnt
);
280 iov_free(iov
, iov_cnt
);
282 /* Discard more bytes than vector size */
283 iov_random(&iov
, &iov_cnt
);
285 iov_cnt_tmp
= iov_cnt
;
286 size
= iov_size(iov
, iov_cnt
);
287 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
+ 1);
288 g_assert(ret
== size
);
289 g_assert(iov_cnt_tmp
== 0);
290 iov_free(iov
, iov_cnt
);
292 /* Discard entire vector */
293 iov_random(&iov
, &iov_cnt
);
295 iov_cnt_tmp
= iov_cnt
;
296 size
= iov_size(iov
, iov_cnt
);
297 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
298 g_assert(ret
== size
);
299 g_assert(iov_cnt_tmp
== 0);
300 iov_free(iov
, iov_cnt
);
302 /* Discard within first element */
303 iov_random(&iov
, &iov_cnt
);
305 iov_cnt_tmp
= iov_cnt
;
306 old_base
= iov
->iov_base
;
307 size
= g_test_rand_int_range(1, iov
->iov_len
);
308 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
309 g_assert(ret
== size
);
310 g_assert(iov_tmp
== iov
);
311 g_assert(iov_cnt_tmp
== iov_cnt
);
312 g_assert(iov_tmp
->iov_base
== old_base
+ size
);
313 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
314 iov_free(iov
, iov_cnt
);
316 /* Discard entire first element */
317 iov_random(&iov
, &iov_cnt
);
319 iov_cnt_tmp
= iov_cnt
;
320 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, iov
->iov_len
);
321 g_assert(ret
== iov
->iov_len
);
322 g_assert(iov_tmp
== iov
+ 1);
323 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
324 iov_free(iov
, iov_cnt
);
326 /* Discard within second element */
327 iov_random(&iov
, &iov_cnt
);
329 iov_cnt_tmp
= iov_cnt
;
330 old_base
= iov
[1].iov_base
;
331 size
= iov
->iov_len
+ g_test_rand_int_range(1, iov
[1].iov_len
);
332 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
333 g_assert(ret
== size
);
334 g_assert(iov_tmp
== iov
+ 1);
335 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
336 g_assert(iov_tmp
->iov_base
== old_base
+ (size
- iov
->iov_len
));
337 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
338 iov_free(iov
, iov_cnt
);
341 static void test_discard_front_undo(void)
345 struct iovec
*iov_tmp
;
346 struct iovec
*iov_orig
;
347 unsigned int iov_cnt
;
348 unsigned int iov_cnt_tmp
;
351 /* Discard zero bytes */
352 iov_random(&iov
, &iov_cnt
);
353 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
355 iov_cnt_tmp
= iov_cnt
;
356 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, 0, &undo
);
357 iov_discard_undo(&undo
);
358 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
360 iov_free(iov
, iov_cnt
);
362 /* Discard more bytes than vector size */
363 iov_random(&iov
, &iov_cnt
);
364 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
366 iov_cnt_tmp
= iov_cnt
;
367 size
= iov_size(iov
, iov_cnt
);
368 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
+ 1, &undo
);
369 iov_discard_undo(&undo
);
370 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
372 iov_free(iov
, iov_cnt
);
374 /* Discard entire vector */
375 iov_random(&iov
, &iov_cnt
);
376 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
378 iov_cnt_tmp
= iov_cnt
;
379 size
= iov_size(iov
, iov_cnt
);
380 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
, &undo
);
381 iov_discard_undo(&undo
);
382 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
384 iov_free(iov
, iov_cnt
);
386 /* Discard within first element */
387 iov_random(&iov
, &iov_cnt
);
388 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
390 iov_cnt_tmp
= iov_cnt
;
391 size
= g_test_rand_int_range(1, iov
->iov_len
);
392 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
, &undo
);
393 iov_discard_undo(&undo
);
394 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
396 iov_free(iov
, iov_cnt
);
398 /* Discard entire first element */
399 iov_random(&iov
, &iov_cnt
);
400 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
402 iov_cnt_tmp
= iov_cnt
;
403 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, iov
->iov_len
, &undo
);
404 iov_discard_undo(&undo
);
405 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
407 iov_free(iov
, iov_cnt
);
409 /* Discard within second element */
410 iov_random(&iov
, &iov_cnt
);
411 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
413 iov_cnt_tmp
= iov_cnt
;
414 size
= iov
->iov_len
+ g_test_rand_int_range(1, iov
[1].iov_len
);
415 iov_discard_front_undoable(&iov_tmp
, &iov_cnt_tmp
, size
, &undo
);
416 iov_discard_undo(&undo
);
417 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
419 iov_free(iov
, iov_cnt
);
422 static void test_discard_back(void)
425 unsigned int iov_cnt
;
426 unsigned int iov_cnt_tmp
;
431 /* Discard zero bytes */
432 iov_random(&iov
, &iov_cnt
);
433 iov_cnt_tmp
= iov_cnt
;
434 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, 0);
436 g_assert(iov_cnt_tmp
== iov_cnt
);
437 iov_free(iov
, iov_cnt
);
439 /* Discard more bytes than vector size */
440 iov_random(&iov
, &iov_cnt
);
441 iov_cnt_tmp
= iov_cnt
;
442 size
= iov_size(iov
, iov_cnt
);
443 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
+ 1);
444 g_assert(ret
== size
);
445 g_assert(iov_cnt_tmp
== 0);
446 iov_free(iov
, iov_cnt
);
448 /* Discard entire vector */
449 iov_random(&iov
, &iov_cnt
);
450 iov_cnt_tmp
= iov_cnt
;
451 size
= iov_size(iov
, iov_cnt
);
452 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
453 g_assert(ret
== size
);
454 g_assert(iov_cnt_tmp
== 0);
455 iov_free(iov
, iov_cnt
);
457 /* Discard within last element */
458 iov_random(&iov
, &iov_cnt
);
459 iov_cnt_tmp
= iov_cnt
;
460 old_base
= iov
[iov_cnt
- 1].iov_base
;
461 size
= g_test_rand_int_range(1, iov
[iov_cnt
- 1].iov_len
);
462 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
463 g_assert(ret
== size
);
464 g_assert(iov_cnt_tmp
== iov_cnt
);
465 g_assert(iov
[iov_cnt
- 1].iov_base
== old_base
);
466 iov_free(iov
, iov_cnt
);
468 /* Discard entire last element */
469 iov_random(&iov
, &iov_cnt
);
470 iov_cnt_tmp
= iov_cnt
;
471 old_base
= iov
[iov_cnt
- 1].iov_base
;
472 size
= iov
[iov_cnt
- 1].iov_len
;
473 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
474 g_assert(ret
== size
);
475 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
476 iov_free(iov
, iov_cnt
);
478 /* Discard within second-to-last element */
479 iov_random(&iov
, &iov_cnt
);
480 iov_cnt_tmp
= iov_cnt
;
481 old_base
= iov
[iov_cnt
- 2].iov_base
;
482 size
= iov
[iov_cnt
- 1].iov_len
+
483 g_test_rand_int_range(1, iov
[iov_cnt
- 2].iov_len
);
484 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
485 g_assert(ret
== size
);
486 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
487 g_assert(iov
[iov_cnt
- 2].iov_base
== old_base
);
488 iov_free(iov
, iov_cnt
);
491 static void test_discard_back_undo(void)
495 struct iovec
*iov_orig
;
496 unsigned int iov_cnt
;
497 unsigned int iov_cnt_tmp
;
500 /* Discard zero bytes */
501 iov_random(&iov
, &iov_cnt
);
502 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
503 iov_cnt_tmp
= iov_cnt
;
504 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, 0, &undo
);
505 iov_discard_undo(&undo
);
506 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
508 iov_free(iov
, iov_cnt
);
510 /* Discard more bytes than vector size */
511 iov_random(&iov
, &iov_cnt
);
512 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
513 iov_cnt_tmp
= iov_cnt
;
514 size
= iov_size(iov
, iov_cnt
);
515 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
+ 1, &undo
);
516 iov_discard_undo(&undo
);
517 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
519 iov_free(iov
, iov_cnt
);
521 /* Discard entire vector */
522 iov_random(&iov
, &iov_cnt
);
523 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
524 iov_cnt_tmp
= iov_cnt
;
525 size
= iov_size(iov
, iov_cnt
);
526 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
527 iov_discard_undo(&undo
);
528 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
530 iov_free(iov
, iov_cnt
);
532 /* Discard within last element */
533 iov_random(&iov
, &iov_cnt
);
534 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
535 iov_cnt_tmp
= iov_cnt
;
536 size
= g_test_rand_int_range(1, iov
[iov_cnt
- 1].iov_len
);
537 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
538 iov_discard_undo(&undo
);
539 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
541 iov_free(iov
, iov_cnt
);
543 /* Discard entire last element */
544 iov_random(&iov
, &iov_cnt
);
545 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
546 iov_cnt_tmp
= iov_cnt
;
547 size
= iov
[iov_cnt
- 1].iov_len
;
548 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
549 iov_discard_undo(&undo
);
550 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
552 iov_free(iov
, iov_cnt
);
554 /* Discard within second-to-last element */
555 iov_random(&iov
, &iov_cnt
);
556 iov_orig
= g_memdup(iov
, sizeof(iov
[0]) * iov_cnt
);
557 iov_cnt_tmp
= iov_cnt
;
558 size
= iov
[iov_cnt
- 1].iov_len
+
559 g_test_rand_int_range(1, iov
[iov_cnt
- 2].iov_len
);
560 iov_discard_back_undoable(iov
, &iov_cnt_tmp
, size
, &undo
);
561 iov_discard_undo(&undo
);
562 assert(iov_equals(iov
, iov_orig
, iov_cnt
));
564 iov_free(iov
, iov_cnt
);
567 int main(int argc
, char **argv
)
569 g_test_init(&argc
, &argv
, NULL
);
571 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf
);
572 g_test_add_func("/basic/iov/io", test_io
);
573 g_test_add_func("/basic/iov/discard-front", test_discard_front
);
574 g_test_add_func("/basic/iov/discard-back", test_discard_back
);
575 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo
);
576 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo
);