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 void test_iov_bytes(struct iovec
*iov
, unsigned niov
,
30 size_t offset
, size_t bytes
)
37 /* we walk over all elements, */
38 for (i
= 0; i
< niov
; ++i
) {
40 /* over each char of each element, */
41 for (j
= 0; j
< iov
[i
].iov_len
; ++j
) {
42 /* counting each of them and
43 * verifying that the ones within [offset,offset+bytes)
44 * range are equal to the position number (o) */
45 if (o
>= offset
&& o
< offset
+ bytes
) {
46 g_assert(b
[j
] == (o
& 255));
48 g_assert(b
[j
] == 0xff);
55 static void test_to_from_buf_1(void)
60 unsigned char *ibuf
, *obuf
;
63 iov_random(&iov
, &niov
);
65 sz
= iov_size(iov
, niov
);
67 ibuf
= g_malloc(sz
+ 8) + 4;
68 memcpy(ibuf
-4, "aaaa", 4); memcpy(ibuf
+ sz
, "bbbb", 4);
69 obuf
= g_malloc(sz
+ 8) + 4;
70 memcpy(obuf
-4, "xxxx", 4); memcpy(obuf
+ sz
, "yyyy", 4);
72 /* fill in ibuf with 0123456... */
73 for (i
= 0; i
< sz
; ++i
) {
77 for (i
= 0; i
<= sz
; ++i
) {
79 /* Test from/to buf for offset(i) in [0..sz] up to the end of buffer.
80 * For last iteration with offset == sz, the procedure should
81 * skip whole vector and process exactly 0 bytes */
83 /* first set bytes [i..sz) to some "random" value */
84 n
= iov_memset(iov
, niov
, 0, 0xff, -1);
87 /* next copy bytes [i..sz) from ibuf to iovec */
88 n
= iov_from_buf(iov
, niov
, i
, ibuf
+ i
, -1);
89 g_assert(n
== sz
- i
);
91 /* clear part of obuf */
92 memset(obuf
+ i
, 0, sz
- i
);
93 /* and set this part of obuf to values from iovec */
94 n
= iov_to_buf(iov
, niov
, i
, obuf
+ i
, -1);
95 g_assert(n
== sz
- i
);
97 /* now compare resulting buffers */
98 g_assert(memcmp(ibuf
, obuf
, sz
) == 0);
100 /* test just one char */
101 n
= iov_to_buf(iov
, niov
, i
, obuf
+ i
, 1);
102 g_assert(n
== (i
< sz
));
104 g_assert(obuf
[i
] == (i
& 255));
107 for (j
= i
; j
<= sz
; ++j
) {
108 /* now test num of bytes cap up to byte no. j,
109 * with j in [i..sz]. */
112 n
= iov_memset(iov
, niov
, 0, 0xff, -1);
115 /* copy bytes [i..j) from ibuf to iovec */
116 n
= iov_from_buf(iov
, niov
, i
, ibuf
+ i
, j
- i
);
117 g_assert(n
== j
- i
);
119 /* clear part of obuf */
120 memset(obuf
+ i
, 0, j
- i
);
122 /* copy bytes [i..j) from iovec to obuf */
123 n
= iov_to_buf(iov
, niov
, i
, obuf
+ i
, j
- i
);
124 g_assert(n
== j
- i
);
127 g_assert(memcmp(ibuf
, obuf
, sz
) == 0);
129 /* now actually check if the iovec contains the right data */
130 test_iov_bytes(iov
, niov
, i
, j
- i
);
133 g_assert(!memcmp(ibuf
-4, "aaaa", 4) && !memcmp(ibuf
+sz
, "bbbb", 4));
135 g_assert(!memcmp(obuf
-4, "xxxx", 4) && !memcmp(obuf
+sz
, "yyyy", 4));
140 static void test_to_from_buf(void)
143 for (x
= 0; x
< 4; ++x
) {
144 test_to_from_buf_1();
148 static void test_io(void)
151 /* socketpair(PF_UNIX) which does not exist on windows */
155 unsigned i
, j
, k
, s
, t
;
158 struct iovec
*iov
, *siov
;
162 iov_random(&iov
, &niov
);
163 sz
= iov_size(iov
, niov
);
165 for (i
= 0; i
< sz
; ++i
) {
168 iov_from_buf(iov
, niov
, 0, buf
, sz
);
170 siov
= g_malloc(sizeof(*iov
) * niov
);
171 memcpy(siov
, iov
, sizeof(*iov
) * niov
);
173 if (socketpair(PF_UNIX
, SOCK_STREAM
, 0, sv
) < 0) {
174 perror("socketpair");
186 fcntl(sv
[1], F_SETFL
, O_RDWR
|O_NONBLOCK
);
187 r
= g_test_rand_int_range(sz
/ 2, sz
);
188 setsockopt(sv
[1], SOL_SOCKET
, SO_SNDBUF
, &r
, sizeof(r
));
190 for (i
= 0; i
<= sz
; ++i
) {
191 for (j
= i
; j
<= sz
; ++j
) {
194 s
= g_test_rand_int_range(0, j
- k
+ 1);
195 r
= iov_send(sv
[1], iov
, niov
, k
, s
);
196 g_assert(memcmp(iov
, siov
, sizeof(*iov
)*niov
) == 0);
200 usleep(g_test_rand_int_range(0, 30));
201 } else if (errno
== EAGAIN
) {
202 select(sv
[1]+1, NULL
, &fds
, NULL
, NULL
);
217 /* reader & verifier */
221 fcntl(sv
[0], F_SETFL
, O_RDWR
|O_NONBLOCK
);
222 r
= g_test_rand_int_range(sz
/ 2, sz
);
223 setsockopt(sv
[0], SOL_SOCKET
, SO_RCVBUF
, &r
, sizeof(r
));
226 for (i
= 0; i
<= sz
; ++i
) {
227 for (j
= i
; j
<= sz
; ++j
) {
229 iov_memset(iov
, niov
, 0, 0xff, -1);
231 s
= g_test_rand_int_range(0, j
- k
+ 1);
232 r
= iov_recv(sv
[0], iov
, niov
, k
, s
);
233 g_assert(memcmp(iov
, siov
, sizeof(*iov
)*niov
) == 0);
241 } else if (errno
== EAGAIN
) {
242 select(sv
[0]+1, &fds
, NULL
, NULL
, NULL
);
249 test_iov_bytes(iov
, niov
, i
, j
- i
);
260 static void test_discard_front(void)
263 struct iovec
*iov_tmp
;
264 unsigned int iov_cnt
;
265 unsigned int iov_cnt_tmp
;
270 /* Discard zero bytes */
271 iov_random(&iov
, &iov_cnt
);
273 iov_cnt_tmp
= iov_cnt
;
274 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, 0);
276 g_assert(iov_tmp
== iov
);
277 g_assert(iov_cnt_tmp
== iov_cnt
);
278 iov_free(iov
, iov_cnt
);
280 /* Discard more bytes than vector size */
281 iov_random(&iov
, &iov_cnt
);
283 iov_cnt_tmp
= iov_cnt
;
284 size
= iov_size(iov
, iov_cnt
);
285 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
+ 1);
286 g_assert(ret
== size
);
287 g_assert(iov_cnt_tmp
== 0);
288 iov_free(iov
, iov_cnt
);
290 /* Discard entire vector */
291 iov_random(&iov
, &iov_cnt
);
293 iov_cnt_tmp
= iov_cnt
;
294 size
= iov_size(iov
, iov_cnt
);
295 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
296 g_assert(ret
== size
);
297 g_assert(iov_cnt_tmp
== 0);
298 iov_free(iov
, iov_cnt
);
300 /* Discard within first element */
301 iov_random(&iov
, &iov_cnt
);
303 iov_cnt_tmp
= iov_cnt
;
304 old_base
= iov
->iov_base
;
305 size
= g_test_rand_int_range(1, iov
->iov_len
);
306 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
307 g_assert(ret
== size
);
308 g_assert(iov_tmp
== iov
);
309 g_assert(iov_cnt_tmp
== iov_cnt
);
310 g_assert(iov_tmp
->iov_base
== old_base
+ size
);
311 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
312 iov_free(iov
, iov_cnt
);
314 /* Discard entire first element */
315 iov_random(&iov
, &iov_cnt
);
317 iov_cnt_tmp
= iov_cnt
;
318 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, iov
->iov_len
);
319 g_assert(ret
== iov
->iov_len
);
320 g_assert(iov_tmp
== iov
+ 1);
321 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
322 iov_free(iov
, iov_cnt
);
324 /* Discard within second element */
325 iov_random(&iov
, &iov_cnt
);
327 iov_cnt_tmp
= iov_cnt
;
328 old_base
= iov
[1].iov_base
;
329 size
= iov
->iov_len
+ g_test_rand_int_range(1, iov
[1].iov_len
);
330 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
331 g_assert(ret
== size
);
332 g_assert(iov_tmp
== iov
+ 1);
333 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
334 g_assert(iov_tmp
->iov_base
== old_base
+ (size
- iov
->iov_len
));
335 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
336 iov_free(iov
, iov_cnt
);
339 static void test_discard_back(void)
342 unsigned int iov_cnt
;
343 unsigned int iov_cnt_tmp
;
348 /* Discard zero bytes */
349 iov_random(&iov
, &iov_cnt
);
350 iov_cnt_tmp
= iov_cnt
;
351 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, 0);
353 g_assert(iov_cnt_tmp
== iov_cnt
);
354 iov_free(iov
, iov_cnt
);
356 /* Discard more bytes than vector size */
357 iov_random(&iov
, &iov_cnt
);
358 iov_cnt_tmp
= iov_cnt
;
359 size
= iov_size(iov
, iov_cnt
);
360 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
+ 1);
361 g_assert(ret
== size
);
362 g_assert(iov_cnt_tmp
== 0);
363 iov_free(iov
, iov_cnt
);
365 /* Discard entire vector */
366 iov_random(&iov
, &iov_cnt
);
367 iov_cnt_tmp
= iov_cnt
;
368 size
= iov_size(iov
, iov_cnt
);
369 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
370 g_assert(ret
== size
);
371 g_assert(iov_cnt_tmp
== 0);
372 iov_free(iov
, iov_cnt
);
374 /* Discard within last element */
375 iov_random(&iov
, &iov_cnt
);
376 iov_cnt_tmp
= iov_cnt
;
377 old_base
= iov
[iov_cnt
- 1].iov_base
;
378 size
= g_test_rand_int_range(1, iov
[iov_cnt
- 1].iov_len
);
379 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
380 g_assert(ret
== size
);
381 g_assert(iov_cnt_tmp
== iov_cnt
);
382 g_assert(iov
[iov_cnt
- 1].iov_base
== old_base
);
383 iov_free(iov
, iov_cnt
);
385 /* Discard entire last element */
386 iov_random(&iov
, &iov_cnt
);
387 iov_cnt_tmp
= iov_cnt
;
388 old_base
= iov
[iov_cnt
- 1].iov_base
;
389 size
= iov
[iov_cnt
- 1].iov_len
;
390 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
391 g_assert(ret
== size
);
392 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
393 iov_free(iov
, iov_cnt
);
395 /* Discard within second-to-last element */
396 iov_random(&iov
, &iov_cnt
);
397 iov_cnt_tmp
= iov_cnt
;
398 old_base
= iov
[iov_cnt
- 2].iov_base
;
399 size
= iov
[iov_cnt
- 1].iov_len
+
400 g_test_rand_int_range(1, iov
[iov_cnt
- 2].iov_len
);
401 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
402 g_assert(ret
== size
);
403 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
404 g_assert(iov
[iov_cnt
- 2].iov_base
== old_base
);
405 iov_free(iov
, iov_cnt
);
408 int main(int argc
, char **argv
)
410 g_test_init(&argc
, &argv
, NULL
);
412 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf
);
413 g_test_add_func("/basic/iov/io", test_io
);
414 g_test_add_func("/basic/iov/discard-front", test_discard_front
);
415 g_test_add_func("/basic/iov/discard-back", test_discard_back
);