Replace fcntl(O_NONBLOCK) with g_unix_set_fd_nonblocking()
[qemu/ar7.git] / tests / unit / test-iov.c
blob93bda00f0e10dd053eeaf3c8a436308ddb05f567
1 #include "qemu/osdep.h"
2 #include "qemu/iov.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));
10 unsigned i;
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);
15 *iovp = iov;
16 *iov_cntp = niov;
19 static void iov_free(struct iovec *iov, unsigned niov)
21 unsigned i;
22 for (i = 0; i < niov; ++i) {
23 g_free(iov[i].iov_base);
25 g_free(iov);
28 static bool iov_equals(const struct iovec *a, const struct iovec *b,
29 unsigned niov)
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)
37 unsigned i;
38 size_t j, o;
39 unsigned char *b;
40 o = 0;
42 /* we walk over all elements, */
43 for (i = 0; i < niov; ++i) {
44 b = iov[i].iov_base;
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));
52 } else {
53 g_assert(b[j] == 0xff);
55 ++o;
60 static void test_to_from_buf_1(void)
62 unsigned niov;
63 struct iovec *iov;
64 size_t sz;
65 unsigned char *ibuf, *obuf;
66 unsigned i, j, n;
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) {
79 ibuf[i] = i & 255;
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);
90 g_assert(n == 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));
108 if (n) {
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]. */
116 /* clear iovec */
117 n = iov_memset(iov, niov, 0, 0xff, sz);
118 g_assert(n == 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);
131 /* verify result */
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));
139 g_free(ibuf-4);
140 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
141 g_free(obuf-4);
142 iov_free(iov, niov);
145 static void test_to_from_buf(void)
147 int x;
148 for (x = 0; x < 4; ++x) {
149 test_to_from_buf_1();
153 static void test_io(void)
155 #ifndef _WIN32
156 /* socketpair(PF_UNIX) which does not exist on windows */
158 int sv[2];
159 int r;
160 unsigned i, j, k, s;
161 fd_set fds;
162 unsigned niov;
163 struct iovec *iov, *siov;
164 unsigned char *buf;
165 size_t sz;
167 iov_random(&iov, &niov);
168 sz = iov_size(iov, niov);
169 buf = g_malloc(sz);
170 for (i = 0; i < sz; ++i) {
171 buf[i] = i & 255;
173 iov_from_buf(iov, niov, 0, buf, sz);
175 siov = g_memdup(iov, sizeof(*iov) * niov);
177 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
178 perror("socketpair");
179 exit(1);
182 FD_ZERO(&fds);
184 if (fork() == 0) {
185 /* writer */
187 close(sv[0]);
188 FD_SET(sv[1], &fds);
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) {
195 k = i;
196 do {
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);
200 if (r >= 0) {
201 k += r;
202 usleep(g_test_rand_int_range(0, 30));
203 } else if (errno == EAGAIN) {
204 select(sv[1]+1, NULL, &fds, NULL, NULL);
205 continue;
206 } else {
207 perror("send");
208 exit(1);
210 } while(k < j);
213 iov_free(iov, niov);
214 g_free(buf);
215 g_free(siov);
216 exit(0);
218 } else {
219 /* reader & verifier */
221 close(sv[1]);
222 FD_SET(sv[0], &fds);
223 g_unix_set_fd_nonblocking(sv[0], true, NULL);
224 r = g_test_rand_int_range(sz / 2, sz);
225 setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
226 usleep(500000);
228 for (i = 0; i <= sz; ++i) {
229 for (j = i; j <= sz; ++j) {
230 k = i;
231 iov_memset(iov, niov, 0, 0xff, sz);
232 do {
233 s = g_test_rand_int_range(0, j - k + 1);
234 r = iov_recv(sv[0], iov, niov, k, s);
235 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
236 if (r > 0) {
237 k += r;
238 } else if (!r) {
239 if (s) {
240 break;
242 } else if (errno == EAGAIN) {
243 select(sv[0]+1, &fds, NULL, NULL, NULL);
244 continue;
245 } else {
246 perror("recv");
247 exit(1);
249 } while(k < j);
250 test_iov_bytes(iov, niov, i, j - i);
254 iov_free(iov, niov);
255 g_free(buf);
256 g_free(siov);
258 #endif
261 static void test_discard_front(void)
263 struct iovec *iov;
264 struct iovec *iov_tmp;
265 unsigned int iov_cnt;
266 unsigned int iov_cnt_tmp;
267 void *old_base;
268 size_t size;
269 size_t ret;
271 /* Discard zero bytes */
272 iov_random(&iov, &iov_cnt);
273 iov_tmp = iov;
274 iov_cnt_tmp = iov_cnt;
275 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
276 g_assert(ret == 0);
277 g_assert(iov_tmp == iov);
278 g_assert(iov_cnt_tmp == iov_cnt);
279 iov_free(iov, iov_cnt);
281 /* Discard more bytes than vector size */
282 iov_random(&iov, &iov_cnt);
283 iov_tmp = iov;
284 iov_cnt_tmp = iov_cnt;
285 size = iov_size(iov, iov_cnt);
286 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
287 g_assert(ret == size);
288 g_assert(iov_cnt_tmp == 0);
289 iov_free(iov, iov_cnt);
291 /* Discard entire vector */
292 iov_random(&iov, &iov_cnt);
293 iov_tmp = iov;
294 iov_cnt_tmp = iov_cnt;
295 size = iov_size(iov, iov_cnt);
296 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
297 g_assert(ret == size);
298 g_assert(iov_cnt_tmp == 0);
299 iov_free(iov, iov_cnt);
301 /* Discard within first element */
302 iov_random(&iov, &iov_cnt);
303 iov_tmp = iov;
304 iov_cnt_tmp = iov_cnt;
305 old_base = iov->iov_base;
306 size = g_test_rand_int_range(1, iov->iov_len);
307 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
308 g_assert(ret == size);
309 g_assert(iov_tmp == iov);
310 g_assert(iov_cnt_tmp == iov_cnt);
311 g_assert(iov_tmp->iov_base == old_base + size);
312 iov_tmp->iov_base = old_base; /* undo before g_free() */
313 iov_free(iov, iov_cnt);
315 /* Discard entire first element */
316 iov_random(&iov, &iov_cnt);
317 iov_tmp = iov;
318 iov_cnt_tmp = iov_cnt;
319 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
320 g_assert(ret == iov->iov_len);
321 g_assert(iov_tmp == iov + 1);
322 g_assert(iov_cnt_tmp == iov_cnt - 1);
323 iov_free(iov, iov_cnt);
325 /* Discard within second element */
326 iov_random(&iov, &iov_cnt);
327 iov_tmp = iov;
328 iov_cnt_tmp = iov_cnt;
329 old_base = iov[1].iov_base;
330 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
331 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
332 g_assert(ret == size);
333 g_assert(iov_tmp == iov + 1);
334 g_assert(iov_cnt_tmp == iov_cnt - 1);
335 g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
336 iov_tmp->iov_base = old_base; /* undo before g_free() */
337 iov_free(iov, iov_cnt);
340 static void test_discard_front_undo(void)
342 IOVDiscardUndo undo;
343 struct iovec *iov;
344 struct iovec *iov_tmp;
345 struct iovec *iov_orig;
346 unsigned int iov_cnt;
347 unsigned int iov_cnt_tmp;
348 size_t size;
350 /* Discard zero bytes */
351 iov_random(&iov, &iov_cnt);
352 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
353 iov_tmp = iov;
354 iov_cnt_tmp = iov_cnt;
355 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo);
356 iov_discard_undo(&undo);
357 assert(iov_equals(iov, iov_orig, iov_cnt));
358 g_free(iov_orig);
359 iov_free(iov, iov_cnt);
361 /* Discard more bytes than vector size */
362 iov_random(&iov, &iov_cnt);
363 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
364 iov_tmp = iov;
365 iov_cnt_tmp = iov_cnt;
366 size = iov_size(iov, iov_cnt);
367 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo);
368 iov_discard_undo(&undo);
369 assert(iov_equals(iov, iov_orig, iov_cnt));
370 g_free(iov_orig);
371 iov_free(iov, iov_cnt);
373 /* Discard entire vector */
374 iov_random(&iov, &iov_cnt);
375 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
376 iov_tmp = iov;
377 iov_cnt_tmp = iov_cnt;
378 size = iov_size(iov, iov_cnt);
379 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
380 iov_discard_undo(&undo);
381 assert(iov_equals(iov, iov_orig, iov_cnt));
382 g_free(iov_orig);
383 iov_free(iov, iov_cnt);
385 /* Discard within first element */
386 iov_random(&iov, &iov_cnt);
387 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
388 iov_tmp = iov;
389 iov_cnt_tmp = iov_cnt;
390 size = g_test_rand_int_range(1, iov->iov_len);
391 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
392 iov_discard_undo(&undo);
393 assert(iov_equals(iov, iov_orig, iov_cnt));
394 g_free(iov_orig);
395 iov_free(iov, iov_cnt);
397 /* Discard entire first element */
398 iov_random(&iov, &iov_cnt);
399 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
400 iov_tmp = iov;
401 iov_cnt_tmp = iov_cnt;
402 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo);
403 iov_discard_undo(&undo);
404 assert(iov_equals(iov, iov_orig, iov_cnt));
405 g_free(iov_orig);
406 iov_free(iov, iov_cnt);
408 /* Discard within second element */
409 iov_random(&iov, &iov_cnt);
410 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
411 iov_tmp = iov;
412 iov_cnt_tmp = iov_cnt;
413 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
414 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
415 iov_discard_undo(&undo);
416 assert(iov_equals(iov, iov_orig, iov_cnt));
417 g_free(iov_orig);
418 iov_free(iov, iov_cnt);
421 static void test_discard_back(void)
423 struct iovec *iov;
424 unsigned int iov_cnt;
425 unsigned int iov_cnt_tmp;
426 void *old_base;
427 size_t size;
428 size_t ret;
430 /* Discard zero bytes */
431 iov_random(&iov, &iov_cnt);
432 iov_cnt_tmp = iov_cnt;
433 ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
434 g_assert(ret == 0);
435 g_assert(iov_cnt_tmp == iov_cnt);
436 iov_free(iov, iov_cnt);
438 /* Discard more bytes than vector size */
439 iov_random(&iov, &iov_cnt);
440 iov_cnt_tmp = iov_cnt;
441 size = iov_size(iov, iov_cnt);
442 ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
443 g_assert(ret == size);
444 g_assert(iov_cnt_tmp == 0);
445 iov_free(iov, iov_cnt);
447 /* Discard entire vector */
448 iov_random(&iov, &iov_cnt);
449 iov_cnt_tmp = iov_cnt;
450 size = iov_size(iov, iov_cnt);
451 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
452 g_assert(ret == size);
453 g_assert(iov_cnt_tmp == 0);
454 iov_free(iov, iov_cnt);
456 /* Discard within last element */
457 iov_random(&iov, &iov_cnt);
458 iov_cnt_tmp = iov_cnt;
459 old_base = iov[iov_cnt - 1].iov_base;
460 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
461 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
462 g_assert(ret == size);
463 g_assert(iov_cnt_tmp == iov_cnt);
464 g_assert(iov[iov_cnt - 1].iov_base == old_base);
465 iov_free(iov, iov_cnt);
467 /* Discard entire last element */
468 iov_random(&iov, &iov_cnt);
469 iov_cnt_tmp = iov_cnt;
470 old_base = iov[iov_cnt - 1].iov_base;
471 size = iov[iov_cnt - 1].iov_len;
472 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
473 g_assert(ret == size);
474 g_assert(iov_cnt_tmp == iov_cnt - 1);
475 iov_free(iov, iov_cnt);
477 /* Discard within second-to-last element */
478 iov_random(&iov, &iov_cnt);
479 iov_cnt_tmp = iov_cnt;
480 old_base = iov[iov_cnt - 2].iov_base;
481 size = iov[iov_cnt - 1].iov_len +
482 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
483 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
484 g_assert(ret == size);
485 g_assert(iov_cnt_tmp == iov_cnt - 1);
486 g_assert(iov[iov_cnt - 2].iov_base == old_base);
487 iov_free(iov, iov_cnt);
490 static void test_discard_back_undo(void)
492 IOVDiscardUndo undo;
493 struct iovec *iov;
494 struct iovec *iov_orig;
495 unsigned int iov_cnt;
496 unsigned int iov_cnt_tmp;
497 size_t size;
499 /* Discard zero bytes */
500 iov_random(&iov, &iov_cnt);
501 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
502 iov_cnt_tmp = iov_cnt;
503 iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo);
504 iov_discard_undo(&undo);
505 assert(iov_equals(iov, iov_orig, iov_cnt));
506 g_free(iov_orig);
507 iov_free(iov, iov_cnt);
509 /* Discard more bytes than vector size */
510 iov_random(&iov, &iov_cnt);
511 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
512 iov_cnt_tmp = iov_cnt;
513 size = iov_size(iov, iov_cnt);
514 iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo);
515 iov_discard_undo(&undo);
516 assert(iov_equals(iov, iov_orig, iov_cnt));
517 g_free(iov_orig);
518 iov_free(iov, iov_cnt);
520 /* Discard entire vector */
521 iov_random(&iov, &iov_cnt);
522 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
523 iov_cnt_tmp = iov_cnt;
524 size = iov_size(iov, iov_cnt);
525 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
526 iov_discard_undo(&undo);
527 assert(iov_equals(iov, iov_orig, iov_cnt));
528 g_free(iov_orig);
529 iov_free(iov, iov_cnt);
531 /* Discard within last element */
532 iov_random(&iov, &iov_cnt);
533 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
534 iov_cnt_tmp = iov_cnt;
535 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
536 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
537 iov_discard_undo(&undo);
538 assert(iov_equals(iov, iov_orig, iov_cnt));
539 g_free(iov_orig);
540 iov_free(iov, iov_cnt);
542 /* Discard entire last element */
543 iov_random(&iov, &iov_cnt);
544 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
545 iov_cnt_tmp = iov_cnt;
546 size = iov[iov_cnt - 1].iov_len;
547 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
548 iov_discard_undo(&undo);
549 assert(iov_equals(iov, iov_orig, iov_cnt));
550 g_free(iov_orig);
551 iov_free(iov, iov_cnt);
553 /* Discard within second-to-last element */
554 iov_random(&iov, &iov_cnt);
555 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
556 iov_cnt_tmp = iov_cnt;
557 size = iov[iov_cnt - 1].iov_len +
558 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
559 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
560 iov_discard_undo(&undo);
561 assert(iov_equals(iov, iov_orig, iov_cnt));
562 g_free(iov_orig);
563 iov_free(iov, iov_cnt);
566 int main(int argc, char **argv)
568 g_test_init(&argc, &argv, NULL);
569 g_test_rand_int();
570 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
571 g_test_add_func("/basic/iov/io", test_io);
572 g_test_add_func("/basic/iov/discard-front", test_discard_front);
573 g_test_add_func("/basic/iov/discard-back", test_discard_back);
574 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo);
575 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo);
576 return g_test_run();