1#include "qemu/osdep.h"
2#include "qemu-common.h"
3#include "qemu/iov.h"
4#include "qemu/sockets.h"
5
6
7static void iov_random(struct iovec **iovp, unsigned *iov_cntp)
8{
9 unsigned niov = g_test_rand_int_range(3,8);
10 struct iovec *iov = g_malloc(niov * sizeof(*iov));
11 unsigned i;
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);
15 }
16 *iovp = iov;
17 *iov_cntp = niov;
18}
19
20static void iov_free(struct iovec *iov, unsigned niov)
21{
22 unsigned i;
23 for (i = 0; i < niov; ++i) {
24 g_free(iov[i].iov_base);
25 }
26 g_free(iov);
27}
28
29static bool iov_equals(const struct iovec *a, const struct iovec *b,
30 unsigned niov)
31{
32 return memcmp(a, b, sizeof(a[0]) * niov) == 0;
33}
34
35static void test_iov_bytes(struct iovec *iov, unsigned niov,
36 size_t offset, size_t bytes)
37{
38 unsigned i;
39 size_t j, o;
40 unsigned char *b;
41 o = 0;
42
43
44 for (i = 0; i < niov; ++i) {
45 b = iov[i].iov_base;
46
47 for (j = 0; j < iov[i].iov_len; ++j) {
48
49
50
51 if (o >= offset && o < offset + bytes) {
52 g_assert(b[j] == (o & 255));
53 } else {
54 g_assert(b[j] == 0xff);
55 }
56 ++o;
57 }
58 }
59}
60
61static void test_to_from_buf_1(void)
62{
63 unsigned niov;
64 struct iovec *iov;
65 size_t sz;
66 unsigned char *ibuf, *obuf;
67 unsigned i, j, n;
68
69 iov_random(&iov, &niov);
70
71 sz = iov_size(iov, niov);
72
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);
77
78
79 for (i = 0; i < sz; ++i) {
80 ibuf[i] = i & 255;
81 }
82
83 for (i = 0; i <= sz; ++i) {
84
85
86
87
88
89
90 n = iov_memset(iov, niov, 0, 0xff, sz);
91 g_assert(n == sz);
92
93
94 n = iov_from_buf(iov, niov, i, ibuf + i, sz - i);
95 g_assert(n == sz - i);
96
97
98 memset(obuf + i, 0, sz - i);
99
100 n = iov_to_buf(iov, niov, i, obuf + i, sz - i);
101 g_assert(n == sz - i);
102
103
104 g_assert(memcmp(ibuf, obuf, sz) == 0);
105
106
107 n = iov_to_buf(iov, niov, i, obuf + i, 1);
108 g_assert(n == (i < sz));
109 if (n) {
110 g_assert(obuf[i] == (i & 255));
111 }
112
113 for (j = i; j <= sz; ++j) {
114
115
116
117
118 n = iov_memset(iov, niov, 0, 0xff, sz);
119 g_assert(n == sz);
120
121
122 n = iov_from_buf(iov, niov, i, ibuf + i, j - i);
123 g_assert(n == j - i);
124
125
126 memset(obuf + i, 0, j - i);
127
128
129 n = iov_to_buf(iov, niov, i, obuf + i, j - i);
130 g_assert(n == j - i);
131
132
133 g_assert(memcmp(ibuf, obuf, sz) == 0);
134
135
136 test_iov_bytes(iov, niov, i, j - i);
137 }
138 }
139 g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4));
140 g_free(ibuf-4);
141 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
142 g_free(obuf-4);
143 iov_free(iov, niov);
144}
145
146static void test_to_from_buf(void)
147{
148 int x;
149 for (x = 0; x < 4; ++x) {
150 test_to_from_buf_1();
151 }
152}
153
154static void test_io(void)
155{
156#ifndef _WIN32
157
158
159 int sv[2];
160 int r;
161 unsigned i, j, k, s;
162 fd_set fds;
163 unsigned niov;
164 struct iovec *iov, *siov;
165 unsigned char *buf;
166 size_t sz;
167
168 iov_random(&iov, &niov);
169 sz = iov_size(iov, niov);
170 buf = g_malloc(sz);
171 for (i = 0; i < sz; ++i) {
172 buf[i] = i & 255;
173 }
174 iov_from_buf(iov, niov, 0, buf, sz);
175
176 siov = g_memdup(iov, sizeof(*iov) * niov);
177
178 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
179 perror("socketpair");
180 exit(1);
181 }
182
183 FD_ZERO(&fds);
184
185 if (fork() == 0) {
186
187
188 close(sv[0]);
189 FD_SET(sv[1], &fds);
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));
193
194 for (i = 0; i <= sz; ++i) {
195 for (j = i; j <= sz; ++j) {
196 k = i;
197 do {
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);
201 if (r >= 0) {
202 k += r;
203 usleep(g_test_rand_int_range(0, 30));
204 } else if (errno == EAGAIN) {
205 select(sv[1]+1, NULL, &fds, NULL, NULL);
206 continue;
207 } else {
208 perror("send");
209 exit(1);
210 }
211 } while(k < j);
212 }
213 }
214 iov_free(iov, niov);
215 g_free(buf);
216 g_free(siov);
217 exit(0);
218
219 } else {
220
221
222 close(sv[1]);
223 FD_SET(sv[0], &fds);
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));
227 usleep(500000);
228
229 for (i = 0; i <= sz; ++i) {
230 for (j = i; j <= sz; ++j) {
231 k = i;
232 iov_memset(iov, niov, 0, 0xff, sz);
233 do {
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);
237 if (r > 0) {
238 k += r;
239 } else if (!r) {
240 if (s) {
241 break;
242 }
243 } else if (errno == EAGAIN) {
244 select(sv[0]+1, &fds, NULL, NULL, NULL);
245 continue;
246 } else {
247 perror("recv");
248 exit(1);
249 }
250 } while(k < j);
251 test_iov_bytes(iov, niov, i, j - i);
252 }
253 }
254
255 iov_free(iov, niov);
256 g_free(buf);
257 g_free(siov);
258 }
259#endif
260}
261
262static void test_discard_front(void)
263{
264 struct iovec *iov;
265 struct iovec *iov_tmp;
266 unsigned int iov_cnt;
267 unsigned int iov_cnt_tmp;
268 void *old_base;
269 size_t size;
270 size_t ret;
271
272
273 iov_random(&iov, &iov_cnt);
274 iov_tmp = iov;
275 iov_cnt_tmp = iov_cnt;
276 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
277 g_assert(ret == 0);
278 g_assert(iov_tmp == iov);
279 g_assert(iov_cnt_tmp == iov_cnt);
280 iov_free(iov, iov_cnt);
281
282
283 iov_random(&iov, &iov_cnt);
284 iov_tmp = iov;
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);
291
292
293 iov_random(&iov, &iov_cnt);
294 iov_tmp = iov;
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);
301
302
303 iov_random(&iov, &iov_cnt);
304 iov_tmp = iov;
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;
314 iov_free(iov, iov_cnt);
315
316
317 iov_random(&iov, &iov_cnt);
318 iov_tmp = iov;
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);
325
326
327 iov_random(&iov, &iov_cnt);
328 iov_tmp = iov;
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;
338 iov_free(iov, iov_cnt);
339}
340
341static void test_discard_front_undo(void)
342{
343 IOVDiscardUndo undo;
344 struct iovec *iov;
345 struct iovec *iov_tmp;
346 struct iovec *iov_orig;
347 unsigned int iov_cnt;
348 unsigned int iov_cnt_tmp;
349 size_t size;
350
351
352 iov_random(&iov, &iov_cnt);
353 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
354 iov_tmp = iov;
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));
359 g_free(iov_orig);
360 iov_free(iov, iov_cnt);
361
362
363 iov_random(&iov, &iov_cnt);
364 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
365 iov_tmp = iov;
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));
371 g_free(iov_orig);
372 iov_free(iov, iov_cnt);
373
374
375 iov_random(&iov, &iov_cnt);
376 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
377 iov_tmp = iov;
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));
383 g_free(iov_orig);
384 iov_free(iov, iov_cnt);
385
386
387 iov_random(&iov, &iov_cnt);
388 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
389 iov_tmp = iov;
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));
395 g_free(iov_orig);
396 iov_free(iov, iov_cnt);
397
398
399 iov_random(&iov, &iov_cnt);
400 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
401 iov_tmp = iov;
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));
406 g_free(iov_orig);
407 iov_free(iov, iov_cnt);
408
409
410 iov_random(&iov, &iov_cnt);
411 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
412 iov_tmp = iov;
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));
418 g_free(iov_orig);
419 iov_free(iov, iov_cnt);
420}
421
422static void test_discard_back(void)
423{
424 struct iovec *iov;
425 unsigned int iov_cnt;
426 unsigned int iov_cnt_tmp;
427 void *old_base;
428 size_t size;
429 size_t ret;
430
431
432 iov_random(&iov, &iov_cnt);
433 iov_cnt_tmp = iov_cnt;
434 ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
435 g_assert(ret == 0);
436 g_assert(iov_cnt_tmp == iov_cnt);
437 iov_free(iov, iov_cnt);
438
439
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);
447
448
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);
456
457
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);
467
468
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);
477
478
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);
489}
490
491static void test_discard_back_undo(void)
492{
493 IOVDiscardUndo undo;
494 struct iovec *iov;
495 struct iovec *iov_orig;
496 unsigned int iov_cnt;
497 unsigned int iov_cnt_tmp;
498 size_t size;
499
500
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));
507 g_free(iov_orig);
508 iov_free(iov, iov_cnt);
509
510
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));
518 g_free(iov_orig);
519 iov_free(iov, iov_cnt);
520
521
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));
529 g_free(iov_orig);
530 iov_free(iov, iov_cnt);
531
532
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));
540 g_free(iov_orig);
541 iov_free(iov, iov_cnt);
542
543
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));
551 g_free(iov_orig);
552 iov_free(iov, iov_cnt);
553
554
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));
563 g_free(iov_orig);
564 iov_free(iov, iov_cnt);
565}
566
567int main(int argc, char **argv)
568{
569 g_test_init(&argc, &argv, NULL);
570 g_test_rand_int();
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);
577 return g_test_run();
578}
579