master
c 580 lines 17.3 KB
Raw
1 #include "qemu/osdep.h"
2 #include "qapi/error.h"
3 #include "qemu/iov.h"
4 #include "qemu/sockets.h"
5
6 /* create a randomly-sized iovec with random vectors */
7 static 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
20 static 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
29 static 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
35 static 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 /* we walk over all elements, */
44 for (i = 0; i < niov; ++i) {
45 b = iov[i].iov_base;
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));
53 } else {
54 g_assert(b[j] == 0xff);
55 }
56 ++o;
57 }
58 }
59 }
60
61 static 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 /* fill in ibuf with 0123456... */
79 for (i = 0; i < sz; ++i) {
80 ibuf[i] = i & 255;
81 }
82
83 for (i = 0; i <= sz; ++i) {
84
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 */
88
89 /* first set bytes [i..sz) to some "random" value */
90 n = iov_memset(iov, niov, 0, 0xff, sz);
91 g_assert(n == sz);
92
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);
96
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);
102
103 /* now compare resulting buffers */
104 g_assert(memcmp(ibuf, obuf, sz) == 0);
105
106 /* test just one char */
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 /* now test num of bytes cap up to byte no. j,
115 * with j in [i..sz]. */
116
117 /* clear iovec */
118 n = iov_memset(iov, niov, 0, 0xff, sz);
119 g_assert(n == sz);
120
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);
124
125 /* clear part of obuf */
126 memset(obuf + i, 0, j - i);
127
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);
131
132 /* verify result */
133 g_assert(memcmp(ibuf, obuf, sz) == 0);
134
135 /* now actually check if the iovec contains the right data */
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
146 static 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
154 static void test_io(void)
155 {
156 #ifndef _WIN32
157 /* socketpair(PF_UNIX) which does not exist on windows */
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_memdup2(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 /* writer */
187
188 close(sv[0]);
189 FD_SET(sv[1], &fds);
190 qemu_set_blocking(sv[1], false, &error_abort);
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 if (errno == EAGAIN) {
203 r = 0;
204 } else {
205 perror("send");
206 exit(1);
207 }
208 }
209 k += r;
210 if (k < j) {
211 select(sv[1] + 1, NULL, &fds, NULL, NULL);
212 }
213 } while(k < j);
214 }
215 }
216 iov_free(iov, niov);
217 g_free(buf);
218 g_free(siov);
219 exit(0);
220
221 } else {
222 /* reader & verifier */
223
224 close(sv[1]);
225 FD_SET(sv[0], &fds);
226 qemu_set_blocking(sv[0], false, &error_abort);
227 r = g_test_rand_int_range(sz / 2, sz);
228 setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
229 usleep(500000);
230
231 for (i = 0; i <= sz; ++i) {
232 for (j = i; j <= sz; ++j) {
233 k = i;
234 iov_memset(iov, niov, 0, 0xff, sz);
235 do {
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);
239 if (r > 0) {
240 k += r;
241 } else if (!r) {
242 if (s) {
243 break;
244 }
245 } else if (errno == EAGAIN) {
246 select(sv[0]+1, &fds, NULL, NULL, NULL);
247 continue;
248 } else {
249 perror("recv");
250 exit(1);
251 }
252 } while(k < j);
253 test_iov_bytes(iov, niov, i, j - i);
254 }
255 }
256
257 iov_free(iov, niov);
258 g_free(buf);
259 g_free(siov);
260 }
261 #endif
262 }
263
264 static void test_discard_front(void)
265 {
266 struct iovec *iov;
267 struct iovec *iov_tmp;
268 unsigned int iov_cnt;
269 unsigned int iov_cnt_tmp;
270 void *old_base;
271 size_t size;
272 size_t ret;
273
274 /* Discard zero bytes */
275 iov_random(&iov, &iov_cnt);
276 iov_tmp = iov;
277 iov_cnt_tmp = iov_cnt;
278 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
279 g_assert(ret == 0);
280 g_assert(iov_tmp == iov);
281 g_assert(iov_cnt_tmp == iov_cnt);
282 iov_free(iov, iov_cnt);
283
284 /* Discard more bytes than vector size */
285 iov_random(&iov, &iov_cnt);
286 iov_tmp = iov;
287 iov_cnt_tmp = iov_cnt;
288 size = iov_size(iov, iov_cnt);
289 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
290 g_assert(ret == size);
291 g_assert(iov_cnt_tmp == 0);
292 iov_free(iov, iov_cnt);
293
294 /* Discard entire vector */
295 iov_random(&iov, &iov_cnt);
296 iov_tmp = iov;
297 iov_cnt_tmp = iov_cnt;
298 size = iov_size(iov, iov_cnt);
299 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
300 g_assert(ret == size);
301 g_assert(iov_cnt_tmp == 0);
302 iov_free(iov, iov_cnt);
303
304 /* Discard within first element */
305 iov_random(&iov, &iov_cnt);
306 iov_tmp = iov;
307 iov_cnt_tmp = iov_cnt;
308 old_base = iov->iov_base;
309 size = g_test_rand_int_range(1, iov->iov_len);
310 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
311 g_assert(ret == size);
312 g_assert(iov_tmp == iov);
313 g_assert(iov_cnt_tmp == iov_cnt);
314 g_assert(iov_tmp->iov_base == old_base + size);
315 iov_tmp->iov_base = old_base; /* undo before g_free() */
316 iov_free(iov, iov_cnt);
317
318 /* Discard entire first element */
319 iov_random(&iov, &iov_cnt);
320 iov_tmp = iov;
321 iov_cnt_tmp = iov_cnt;
322 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
323 g_assert(ret == iov->iov_len);
324 g_assert(iov_tmp == iov + 1);
325 g_assert(iov_cnt_tmp == iov_cnt - 1);
326 iov_free(iov, iov_cnt);
327
328 /* Discard within second element */
329 iov_random(&iov, &iov_cnt);
330 iov_tmp = iov;
331 iov_cnt_tmp = iov_cnt;
332 old_base = iov[1].iov_base;
333 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
334 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
335 g_assert(ret == size);
336 g_assert(iov_tmp == iov + 1);
337 g_assert(iov_cnt_tmp == iov_cnt - 1);
338 g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
339 iov_tmp->iov_base = old_base; /* undo before g_free() */
340 iov_free(iov, iov_cnt);
341 }
342
343 static void test_discard_front_undo(void)
344 {
345 IOVDiscardUndo undo;
346 struct iovec *iov;
347 struct iovec *iov_tmp;
348 struct iovec *iov_orig;
349 unsigned int iov_cnt;
350 unsigned int iov_cnt_tmp;
351 size_t size;
352
353 /* Discard zero bytes */
354 iov_random(&iov, &iov_cnt);
355 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
356 iov_tmp = iov;
357 iov_cnt_tmp = iov_cnt;
358 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo);
359 iov_discard_undo(&undo);
360 assert(iov_equals(iov, iov_orig, iov_cnt));
361 g_free(iov_orig);
362 iov_free(iov, iov_cnt);
363
364 /* Discard more bytes than vector size */
365 iov_random(&iov, &iov_cnt);
366 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
367 iov_tmp = iov;
368 iov_cnt_tmp = iov_cnt;
369 size = iov_size(iov, iov_cnt);
370 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo);
371 iov_discard_undo(&undo);
372 assert(iov_equals(iov, iov_orig, iov_cnt));
373 g_free(iov_orig);
374 iov_free(iov, iov_cnt);
375
376 /* Discard entire vector */
377 iov_random(&iov, &iov_cnt);
378 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
379 iov_tmp = iov;
380 iov_cnt_tmp = iov_cnt;
381 size = iov_size(iov, iov_cnt);
382 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
383 iov_discard_undo(&undo);
384 assert(iov_equals(iov, iov_orig, iov_cnt));
385 g_free(iov_orig);
386 iov_free(iov, iov_cnt);
387
388 /* Discard within first element */
389 iov_random(&iov, &iov_cnt);
390 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
391 iov_tmp = iov;
392 iov_cnt_tmp = iov_cnt;
393 size = g_test_rand_int_range(1, iov->iov_len);
394 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
395 iov_discard_undo(&undo);
396 assert(iov_equals(iov, iov_orig, iov_cnt));
397 g_free(iov_orig);
398 iov_free(iov, iov_cnt);
399
400 /* Discard entire first element */
401 iov_random(&iov, &iov_cnt);
402 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
403 iov_tmp = iov;
404 iov_cnt_tmp = iov_cnt;
405 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo);
406 iov_discard_undo(&undo);
407 assert(iov_equals(iov, iov_orig, iov_cnt));
408 g_free(iov_orig);
409 iov_free(iov, iov_cnt);
410
411 /* Discard within second element */
412 iov_random(&iov, &iov_cnt);
413 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
414 iov_tmp = iov;
415 iov_cnt_tmp = iov_cnt;
416 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
417 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
418 iov_discard_undo(&undo);
419 assert(iov_equals(iov, iov_orig, iov_cnt));
420 g_free(iov_orig);
421 iov_free(iov, iov_cnt);
422 }
423
424 static void test_discard_back(void)
425 {
426 struct iovec *iov;
427 unsigned int iov_cnt;
428 unsigned int iov_cnt_tmp;
429 void *old_base;
430 size_t size;
431 size_t ret;
432
433 /* Discard zero bytes */
434 iov_random(&iov, &iov_cnt);
435 iov_cnt_tmp = iov_cnt;
436 ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
437 g_assert(ret == 0);
438 g_assert(iov_cnt_tmp == iov_cnt);
439 iov_free(iov, iov_cnt);
440
441 /* Discard more bytes than vector size */
442 iov_random(&iov, &iov_cnt);
443 iov_cnt_tmp = iov_cnt;
444 size = iov_size(iov, iov_cnt);
445 ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
446 g_assert(ret == size);
447 g_assert(iov_cnt_tmp == 0);
448 iov_free(iov, iov_cnt);
449
450 /* Discard entire vector */
451 iov_random(&iov, &iov_cnt);
452 iov_cnt_tmp = iov_cnt;
453 size = iov_size(iov, iov_cnt);
454 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
455 g_assert(ret == size);
456 g_assert(iov_cnt_tmp == 0);
457 iov_free(iov, iov_cnt);
458
459 /* Discard within last element */
460 iov_random(&iov, &iov_cnt);
461 iov_cnt_tmp = iov_cnt;
462 old_base = iov[iov_cnt - 1].iov_base;
463 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
464 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
465 g_assert(ret == size);
466 g_assert(iov_cnt_tmp == iov_cnt);
467 g_assert(iov[iov_cnt - 1].iov_base == old_base);
468 iov_free(iov, iov_cnt);
469
470 /* Discard entire last element */
471 iov_random(&iov, &iov_cnt);
472 iov_cnt_tmp = iov_cnt;
473 old_base = iov[iov_cnt - 1].iov_base;
474 size = iov[iov_cnt - 1].iov_len;
475 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
476 g_assert(ret == size);
477 g_assert(iov_cnt_tmp == iov_cnt - 1);
478 iov_free(iov, iov_cnt);
479
480 /* Discard within second-to-last element */
481 iov_random(&iov, &iov_cnt);
482 iov_cnt_tmp = iov_cnt;
483 old_base = iov[iov_cnt - 2].iov_base;
484 size = iov[iov_cnt - 1].iov_len +
485 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
486 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
487 g_assert(ret == size);
488 g_assert(iov_cnt_tmp == iov_cnt - 1);
489 g_assert(iov[iov_cnt - 2].iov_base == old_base);
490 iov_free(iov, iov_cnt);
491 }
492
493 static void test_discard_back_undo(void)
494 {
495 IOVDiscardUndo undo;
496 struct iovec *iov;
497 struct iovec *iov_orig;
498 unsigned int iov_cnt;
499 unsigned int iov_cnt_tmp;
500 size_t size;
501
502 /* Discard zero bytes */
503 iov_random(&iov, &iov_cnt);
504 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
505 iov_cnt_tmp = iov_cnt;
506 iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo);
507 iov_discard_undo(&undo);
508 assert(iov_equals(iov, iov_orig, iov_cnt));
509 g_free(iov_orig);
510 iov_free(iov, iov_cnt);
511
512 /* Discard more bytes than vector size */
513 iov_random(&iov, &iov_cnt);
514 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
515 iov_cnt_tmp = iov_cnt;
516 size = iov_size(iov, iov_cnt);
517 iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo);
518 iov_discard_undo(&undo);
519 assert(iov_equals(iov, iov_orig, iov_cnt));
520 g_free(iov_orig);
521 iov_free(iov, iov_cnt);
522
523 /* Discard entire vector */
524 iov_random(&iov, &iov_cnt);
525 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
526 iov_cnt_tmp = iov_cnt;
527 size = iov_size(iov, iov_cnt);
528 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
529 iov_discard_undo(&undo);
530 assert(iov_equals(iov, iov_orig, iov_cnt));
531 g_free(iov_orig);
532 iov_free(iov, iov_cnt);
533
534 /* Discard within last element */
535 iov_random(&iov, &iov_cnt);
536 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
537 iov_cnt_tmp = iov_cnt;
538 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
539 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
540 iov_discard_undo(&undo);
541 assert(iov_equals(iov, iov_orig, iov_cnt));
542 g_free(iov_orig);
543 iov_free(iov, iov_cnt);
544
545 /* Discard entire last element */
546 iov_random(&iov, &iov_cnt);
547 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
548 iov_cnt_tmp = iov_cnt;
549 size = iov[iov_cnt - 1].iov_len;
550 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
551 iov_discard_undo(&undo);
552 assert(iov_equals(iov, iov_orig, iov_cnt));
553 g_free(iov_orig);
554 iov_free(iov, iov_cnt);
555
556 /* Discard within second-to-last element */
557 iov_random(&iov, &iov_cnt);
558 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt);
559 iov_cnt_tmp = iov_cnt;
560 size = iov[iov_cnt - 1].iov_len +
561 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
562 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
563 iov_discard_undo(&undo);
564 assert(iov_equals(iov, iov_orig, iov_cnt));
565 g_free(iov_orig);
566 iov_free(iov, iov_cnt);
567 }
568
569 int main(int argc, char **argv)
570 {
571 g_test_init(&argc, &argv, NULL);
572 g_test_rand_int();
573 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
574 g_test_add_func("/basic/iov/io", test_io);
575 g_test_add_func("/basic/iov/discard-front", test_discard_front);
576 g_test_add_func("/basic/iov/discard-back", test_discard_back);
577 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo);
578 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo);
579 return g_test_run();
580 }