1 #include "qemu/osdep.h"
3 #include "qemu-common.h"
5 #include "qemu/sockets.h"
7 /* create a randomly-sized iovec with random vectors */
8 static void iov_random(struct iovec
**iovp
, unsigned *iov_cntp
)
10 unsigned niov
= g_test_rand_int_range(3,8);
11 struct iovec
*iov
= g_malloc(niov
* sizeof(*iov
));
13 for (i
= 0; i
< niov
; ++i
) {
14 iov
[i
].iov_len
= g_test_rand_int_range(5,20);
15 iov
[i
].iov_base
= g_malloc(iov
[i
].iov_len
);
21 static void iov_free(struct iovec
*iov
, unsigned niov
)
24 for (i
= 0; i
< niov
; ++i
) {
25 g_free(iov
[i
].iov_base
);
30 static void test_iov_bytes(struct iovec
*iov
, unsigned niov
,
31 size_t offset
, size_t bytes
)
38 /* we walk over all elements, */
39 for (i
= 0; i
< niov
; ++i
) {
41 /* over each char of each element, */
42 for (j
= 0; j
< iov
[i
].iov_len
; ++j
) {
43 /* counting each of them and
44 * verifying that the ones within [offset,offset+bytes)
45 * range are equal to the position number (o) */
46 if (o
>= offset
&& o
< offset
+ bytes
) {
47 g_assert(b
[j
] == (o
& 255));
49 g_assert(b
[j
] == 0xff);
56 static void test_to_from_buf_1(void)
61 unsigned char *ibuf
, *obuf
;
64 iov_random(&iov
, &niov
);
66 sz
= iov_size(iov
, niov
);
68 ibuf
= g_malloc(sz
+ 8) + 4;
69 memcpy(ibuf
-4, "aaaa", 4); memcpy(ibuf
+ sz
, "bbbb", 4);
70 obuf
= g_malloc(sz
+ 8) + 4;
71 memcpy(obuf
-4, "xxxx", 4); memcpy(obuf
+ sz
, "yyyy", 4);
73 /* fill in ibuf with 0123456... */
74 for (i
= 0; i
< sz
; ++i
) {
78 for (i
= 0; i
<= sz
; ++i
) {
80 /* Test from/to buf for offset(i) in [0..sz] up to the end of buffer.
81 * For last iteration with offset == sz, the procedure should
82 * skip whole vector and process exactly 0 bytes */
84 /* first set bytes [i..sz) to some "random" value */
85 n
= iov_memset(iov
, niov
, 0, 0xff, -1);
88 /* next copy bytes [i..sz) from ibuf to iovec */
89 n
= iov_from_buf(iov
, niov
, i
, ibuf
+ i
, -1);
90 g_assert(n
== sz
- i
);
92 /* clear part of obuf */
93 memset(obuf
+ i
, 0, sz
- i
);
94 /* and set this part of obuf to values from iovec */
95 n
= iov_to_buf(iov
, niov
, i
, obuf
+ i
, -1);
96 g_assert(n
== sz
- i
);
98 /* now compare resulting buffers */
99 g_assert(memcmp(ibuf
, obuf
, sz
) == 0);
101 /* test just one char */
102 n
= iov_to_buf(iov
, niov
, i
, obuf
+ i
, 1);
103 g_assert(n
== (i
< sz
));
105 g_assert(obuf
[i
] == (i
& 255));
108 for (j
= i
; j
<= sz
; ++j
) {
109 /* now test num of bytes cap up to byte no. j,
110 * with j in [i..sz]. */
113 n
= iov_memset(iov
, niov
, 0, 0xff, -1);
116 /* copy bytes [i..j) from ibuf to iovec */
117 n
= iov_from_buf(iov
, niov
, i
, ibuf
+ i
, j
- i
);
118 g_assert(n
== j
- i
);
120 /* clear part of obuf */
121 memset(obuf
+ i
, 0, j
- i
);
123 /* copy bytes [i..j) from iovec to obuf */
124 n
= iov_to_buf(iov
, niov
, i
, obuf
+ i
, j
- i
);
125 g_assert(n
== j
- i
);
128 g_assert(memcmp(ibuf
, obuf
, sz
) == 0);
130 /* now actually check if the iovec contains the right data */
131 test_iov_bytes(iov
, niov
, i
, j
- i
);
134 g_assert(!memcmp(ibuf
-4, "aaaa", 4) && !memcmp(ibuf
+sz
, "bbbb", 4));
136 g_assert(!memcmp(obuf
-4, "xxxx", 4) && !memcmp(obuf
+sz
, "yyyy", 4));
141 static void test_to_from_buf(void)
144 for (x
= 0; x
< 4; ++x
) {
145 test_to_from_buf_1();
149 static void test_io(void)
152 /* socketpair(PF_UNIX) which does not exist on windows */
156 unsigned i
, j
, k
, s
, t
;
159 struct iovec
*iov
, *siov
;
163 iov_random(&iov
, &niov
);
164 sz
= iov_size(iov
, niov
);
166 for (i
= 0; i
< sz
; ++i
) {
169 iov_from_buf(iov
, niov
, 0, buf
, sz
);
171 siov
= g_malloc(sizeof(*iov
) * niov
);
172 memcpy(siov
, iov
, sizeof(*iov
) * niov
);
174 if (socketpair(PF_UNIX
, SOCK_STREAM
, 0, sv
) < 0) {
175 perror("socketpair");
187 fcntl(sv
[1], F_SETFL
, O_RDWR
|O_NONBLOCK
);
188 r
= g_test_rand_int_range(sz
/ 2, sz
);
189 setsockopt(sv
[1], SOL_SOCKET
, SO_SNDBUF
, &r
, sizeof(r
));
191 for (i
= 0; i
<= sz
; ++i
) {
192 for (j
= i
; j
<= sz
; ++j
) {
195 s
= g_test_rand_int_range(0, j
- k
+ 1);
196 r
= iov_send(sv
[1], iov
, niov
, k
, s
);
197 g_assert(memcmp(iov
, siov
, sizeof(*iov
)*niov
) == 0);
201 usleep(g_test_rand_int_range(0, 30));
202 } else if (errno
== EAGAIN
) {
203 select(sv
[1]+1, NULL
, &fds
, NULL
, NULL
);
215 /* reader & verifier */
219 fcntl(sv
[0], F_SETFL
, O_RDWR
|O_NONBLOCK
);
220 r
= g_test_rand_int_range(sz
/ 2, sz
);
221 setsockopt(sv
[0], SOL_SOCKET
, SO_RCVBUF
, &r
, sizeof(r
));
224 for (i
= 0; i
<= sz
; ++i
) {
225 for (j
= i
; j
<= sz
; ++j
) {
227 iov_memset(iov
, niov
, 0, 0xff, -1);
229 s
= g_test_rand_int_range(0, j
- k
+ 1);
230 r
= iov_recv(sv
[0], iov
, niov
, k
, s
);
231 g_assert(memcmp(iov
, siov
, sizeof(*iov
)*niov
) == 0);
239 } else if (errno
== EAGAIN
) {
240 select(sv
[0]+1, &fds
, NULL
, NULL
, NULL
);
247 test_iov_bytes(iov
, niov
, i
, j
- i
);
254 static void test_discard_front(void)
257 struct iovec
*iov_tmp
;
258 unsigned int iov_cnt
;
259 unsigned int iov_cnt_tmp
;
264 /* Discard zero bytes */
265 iov_random(&iov
, &iov_cnt
);
267 iov_cnt_tmp
= iov_cnt
;
268 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, 0);
270 g_assert(iov_tmp
== iov
);
271 g_assert(iov_cnt_tmp
== iov_cnt
);
272 iov_free(iov
, iov_cnt
);
274 /* Discard more bytes than vector size */
275 iov_random(&iov
, &iov_cnt
);
277 iov_cnt_tmp
= iov_cnt
;
278 size
= iov_size(iov
, iov_cnt
);
279 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
+ 1);
280 g_assert(ret
== size
);
281 g_assert(iov_cnt_tmp
== 0);
282 iov_free(iov
, iov_cnt
);
284 /* Discard entire vector */
285 iov_random(&iov
, &iov_cnt
);
287 iov_cnt_tmp
= iov_cnt
;
288 size
= iov_size(iov
, iov_cnt
);
289 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
290 g_assert(ret
== size
);
291 g_assert(iov_cnt_tmp
== 0);
292 iov_free(iov
, iov_cnt
);
294 /* Discard within first element */
295 iov_random(&iov
, &iov_cnt
);
297 iov_cnt_tmp
= iov_cnt
;
298 old_base
= iov
->iov_base
;
299 size
= g_test_rand_int_range(1, iov
->iov_len
);
300 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
301 g_assert(ret
== size
);
302 g_assert(iov_tmp
== iov
);
303 g_assert(iov_cnt_tmp
== iov_cnt
);
304 g_assert(iov_tmp
->iov_base
== old_base
+ size
);
305 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
306 iov_free(iov
, iov_cnt
);
308 /* Discard entire first element */
309 iov_random(&iov
, &iov_cnt
);
311 iov_cnt_tmp
= iov_cnt
;
312 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, iov
->iov_len
);
313 g_assert(ret
== iov
->iov_len
);
314 g_assert(iov_tmp
== iov
+ 1);
315 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
316 iov_free(iov
, iov_cnt
);
318 /* Discard within second element */
319 iov_random(&iov
, &iov_cnt
);
321 iov_cnt_tmp
= iov_cnt
;
322 old_base
= iov
[1].iov_base
;
323 size
= iov
->iov_len
+ g_test_rand_int_range(1, iov
[1].iov_len
);
324 ret
= iov_discard_front(&iov_tmp
, &iov_cnt_tmp
, size
);
325 g_assert(ret
== size
);
326 g_assert(iov_tmp
== iov
+ 1);
327 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
328 g_assert(iov_tmp
->iov_base
== old_base
+ (size
- iov
->iov_len
));
329 iov_tmp
->iov_base
= old_base
; /* undo before g_free() */
330 iov_free(iov
, iov_cnt
);
333 static void test_discard_back(void)
336 unsigned int iov_cnt
;
337 unsigned int iov_cnt_tmp
;
342 /* Discard zero bytes */
343 iov_random(&iov
, &iov_cnt
);
344 iov_cnt_tmp
= iov_cnt
;
345 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, 0);
347 g_assert(iov_cnt_tmp
== iov_cnt
);
348 iov_free(iov
, iov_cnt
);
350 /* Discard more bytes than vector size */
351 iov_random(&iov
, &iov_cnt
);
352 iov_cnt_tmp
= iov_cnt
;
353 size
= iov_size(iov
, iov_cnt
);
354 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
+ 1);
355 g_assert(ret
== size
);
356 g_assert(iov_cnt_tmp
== 0);
357 iov_free(iov
, iov_cnt
);
359 /* Discard entire vector */
360 iov_random(&iov
, &iov_cnt
);
361 iov_cnt_tmp
= iov_cnt
;
362 size
= iov_size(iov
, iov_cnt
);
363 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
364 g_assert(ret
== size
);
365 g_assert(iov_cnt_tmp
== 0);
366 iov_free(iov
, iov_cnt
);
368 /* Discard within last element */
369 iov_random(&iov
, &iov_cnt
);
370 iov_cnt_tmp
= iov_cnt
;
371 old_base
= iov
[iov_cnt
- 1].iov_base
;
372 size
= g_test_rand_int_range(1, iov
[iov_cnt
- 1].iov_len
);
373 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
374 g_assert(ret
== size
);
375 g_assert(iov_cnt_tmp
== iov_cnt
);
376 g_assert(iov
[iov_cnt
- 1].iov_base
== old_base
);
377 iov_free(iov
, iov_cnt
);
379 /* Discard entire last element */
380 iov_random(&iov
, &iov_cnt
);
381 iov_cnt_tmp
= iov_cnt
;
382 old_base
= iov
[iov_cnt
- 1].iov_base
;
383 size
= iov
[iov_cnt
- 1].iov_len
;
384 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
385 g_assert(ret
== size
);
386 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
387 iov_free(iov
, iov_cnt
);
389 /* Discard within second-to-last element */
390 iov_random(&iov
, &iov_cnt
);
391 iov_cnt_tmp
= iov_cnt
;
392 old_base
= iov
[iov_cnt
- 2].iov_base
;
393 size
= iov
[iov_cnt
- 1].iov_len
+
394 g_test_rand_int_range(1, iov
[iov_cnt
- 2].iov_len
);
395 ret
= iov_discard_back(iov
, &iov_cnt_tmp
, size
);
396 g_assert(ret
== size
);
397 g_assert(iov_cnt_tmp
== iov_cnt
- 1);
398 g_assert(iov
[iov_cnt
- 2].iov_base
== old_base
);
399 iov_free(iov
, iov_cnt
);
402 int main(int argc
, char **argv
)
404 g_test_init(&argc
, &argv
, NULL
);
406 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf
);
407 g_test_add_func("/basic/iov/io", test_io
);
408 g_test_add_func("/basic/iov/discard-front", test_discard_front
);
409 g_test_add_func("/basic/iov/discard-back", test_discard_back
);