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