Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
[qemu/ar7.git] / tests / test-iov.c
blob458ca250994d800ec3ac34eba6cb932b188cbd3f
1 #include "qemu/osdep.h"
2 #include "qemu-common.h"
3 #include "qemu/iov.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));
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);
16 *iovp = iov;
17 *iov_cntp = niov;
20 static void iov_free(struct iovec *iov, unsigned niov)
22 unsigned i;
23 for (i = 0; i < niov; ++i) {
24 g_free(iov[i].iov_base);
26 g_free(iov);
29 static void test_iov_bytes(struct iovec *iov, unsigned niov,
30 size_t offset, size_t bytes)
32 unsigned i;
33 size_t j, o;
34 unsigned char *b;
35 o = 0;
37 /* we walk over all elements, */
38 for (i = 0; i < niov; ++i) {
39 b = iov[i].iov_base;
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));
47 } else {
48 g_assert(b[j] == 0xff);
50 ++o;
55 static void test_to_from_buf_1(void)
57 unsigned niov;
58 struct iovec *iov;
59 size_t sz;
60 unsigned char *ibuf, *obuf;
61 unsigned i, j, n;
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) {
74 ibuf[i] = i & 255;
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, sz);
85 g_assert(n == sz);
87 /* next copy bytes [i..sz) from ibuf to iovec */
88 n = iov_from_buf(iov, niov, i, ibuf + i, sz - i);
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, sz - i);
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));
103 if (n) {
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]. */
111 /* clear iovec */
112 n = iov_memset(iov, niov, 0, 0xff, sz);
113 g_assert(n == sz);
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);
126 /* verify result */
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));
134 g_free(ibuf-4);
135 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
136 g_free(obuf-4);
137 iov_free(iov, niov);
140 static void test_to_from_buf(void)
142 int x;
143 for (x = 0; x < 4; ++x) {
144 test_to_from_buf_1();
148 static void test_io(void)
150 #ifndef _WIN32
151 /* socketpair(PF_UNIX) which does not exist on windows */
153 int sv[2];
154 int r;
155 unsigned i, j, k, s, t;
156 fd_set fds;
157 unsigned niov;
158 struct iovec *iov, *siov;
159 unsigned char *buf;
160 size_t sz;
162 iov_random(&iov, &niov);
163 sz = iov_size(iov, niov);
164 buf = g_malloc(sz);
165 for (i = 0; i < sz; ++i) {
166 buf[i] = i & 255;
168 iov_from_buf(iov, niov, 0, buf, sz);
170 siov = g_memdup(iov, sizeof(*iov) * niov);
172 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
173 perror("socketpair");
174 exit(1);
177 FD_ZERO(&fds);
179 t = 0;
180 if (fork() == 0) {
181 /* writer */
183 close(sv[0]);
184 FD_SET(sv[1], &fds);
185 fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK);
186 r = g_test_rand_int_range(sz / 2, sz);
187 setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
189 for (i = 0; i <= sz; ++i) {
190 for (j = i; j <= sz; ++j) {
191 k = i;
192 do {
193 s = g_test_rand_int_range(0, j - k + 1);
194 r = iov_send(sv[1], iov, niov, k, s);
195 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
196 if (r >= 0) {
197 k += r;
198 t += r;
199 usleep(g_test_rand_int_range(0, 30));
200 } else if (errno == EAGAIN) {
201 select(sv[1]+1, NULL, &fds, NULL, NULL);
202 continue;
203 } else {
204 perror("send");
205 exit(1);
207 } while(k < j);
210 iov_free(iov, niov);
211 g_free(buf);
212 g_free(siov);
213 exit(0);
215 } else {
216 /* reader & verifier */
218 close(sv[1]);
219 FD_SET(sv[0], &fds);
220 fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK);
221 r = g_test_rand_int_range(sz / 2, sz);
222 setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
223 usleep(500000);
225 for (i = 0; i <= sz; ++i) {
226 for (j = i; j <= sz; ++j) {
227 k = i;
228 iov_memset(iov, niov, 0, 0xff, sz);
229 do {
230 s = g_test_rand_int_range(0, j - k + 1);
231 r = iov_recv(sv[0], iov, niov, k, s);
232 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
233 if (r > 0) {
234 k += r;
235 t += r;
236 } else if (!r) {
237 if (s) {
238 break;
240 } else if (errno == EAGAIN) {
241 select(sv[0]+1, &fds, NULL, NULL, NULL);
242 continue;
243 } else {
244 perror("recv");
245 exit(1);
247 } while(k < j);
248 test_iov_bytes(iov, niov, i, j - i);
252 iov_free(iov, niov);
253 g_free(buf);
254 g_free(siov);
256 #endif
259 static void test_discard_front(void)
261 struct iovec *iov;
262 struct iovec *iov_tmp;
263 unsigned int iov_cnt;
264 unsigned int iov_cnt_tmp;
265 void *old_base;
266 size_t size;
267 size_t ret;
269 /* Discard zero bytes */
270 iov_random(&iov, &iov_cnt);
271 iov_tmp = iov;
272 iov_cnt_tmp = iov_cnt;
273 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
274 g_assert(ret == 0);
275 g_assert(iov_tmp == iov);
276 g_assert(iov_cnt_tmp == iov_cnt);
277 iov_free(iov, iov_cnt);
279 /* Discard more bytes than vector size */
280 iov_random(&iov, &iov_cnt);
281 iov_tmp = iov;
282 iov_cnt_tmp = iov_cnt;
283 size = iov_size(iov, iov_cnt);
284 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
285 g_assert(ret == size);
286 g_assert(iov_cnt_tmp == 0);
287 iov_free(iov, iov_cnt);
289 /* Discard entire vector */
290 iov_random(&iov, &iov_cnt);
291 iov_tmp = iov;
292 iov_cnt_tmp = iov_cnt;
293 size = iov_size(iov, iov_cnt);
294 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
295 g_assert(ret == size);
296 g_assert(iov_cnt_tmp == 0);
297 iov_free(iov, iov_cnt);
299 /* Discard within first element */
300 iov_random(&iov, &iov_cnt);
301 iov_tmp = iov;
302 iov_cnt_tmp = iov_cnt;
303 old_base = iov->iov_base;
304 size = g_test_rand_int_range(1, iov->iov_len);
305 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
306 g_assert(ret == size);
307 g_assert(iov_tmp == iov);
308 g_assert(iov_cnt_tmp == iov_cnt);
309 g_assert(iov_tmp->iov_base == old_base + size);
310 iov_tmp->iov_base = old_base; /* undo before g_free() */
311 iov_free(iov, iov_cnt);
313 /* Discard entire first element */
314 iov_random(&iov, &iov_cnt);
315 iov_tmp = iov;
316 iov_cnt_tmp = iov_cnt;
317 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
318 g_assert(ret == iov->iov_len);
319 g_assert(iov_tmp == iov + 1);
320 g_assert(iov_cnt_tmp == iov_cnt - 1);
321 iov_free(iov, iov_cnt);
323 /* Discard within second element */
324 iov_random(&iov, &iov_cnt);
325 iov_tmp = iov;
326 iov_cnt_tmp = iov_cnt;
327 old_base = iov[1].iov_base;
328 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
329 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
330 g_assert(ret == size);
331 g_assert(iov_tmp == iov + 1);
332 g_assert(iov_cnt_tmp == iov_cnt - 1);
333 g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
334 iov_tmp->iov_base = old_base; /* undo before g_free() */
335 iov_free(iov, iov_cnt);
338 static void test_discard_back(void)
340 struct iovec *iov;
341 unsigned int iov_cnt;
342 unsigned int iov_cnt_tmp;
343 void *old_base;
344 size_t size;
345 size_t ret;
347 /* Discard zero bytes */
348 iov_random(&iov, &iov_cnt);
349 iov_cnt_tmp = iov_cnt;
350 ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
351 g_assert(ret == 0);
352 g_assert(iov_cnt_tmp == iov_cnt);
353 iov_free(iov, iov_cnt);
355 /* Discard more bytes than vector size */
356 iov_random(&iov, &iov_cnt);
357 iov_cnt_tmp = iov_cnt;
358 size = iov_size(iov, iov_cnt);
359 ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
360 g_assert(ret == size);
361 g_assert(iov_cnt_tmp == 0);
362 iov_free(iov, iov_cnt);
364 /* Discard entire vector */
365 iov_random(&iov, &iov_cnt);
366 iov_cnt_tmp = iov_cnt;
367 size = iov_size(iov, iov_cnt);
368 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
369 g_assert(ret == size);
370 g_assert(iov_cnt_tmp == 0);
371 iov_free(iov, iov_cnt);
373 /* Discard within last element */
374 iov_random(&iov, &iov_cnt);
375 iov_cnt_tmp = iov_cnt;
376 old_base = iov[iov_cnt - 1].iov_base;
377 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
378 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
379 g_assert(ret == size);
380 g_assert(iov_cnt_tmp == iov_cnt);
381 g_assert(iov[iov_cnt - 1].iov_base == old_base);
382 iov_free(iov, iov_cnt);
384 /* Discard entire last element */
385 iov_random(&iov, &iov_cnt);
386 iov_cnt_tmp = iov_cnt;
387 old_base = iov[iov_cnt - 1].iov_base;
388 size = iov[iov_cnt - 1].iov_len;
389 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
390 g_assert(ret == size);
391 g_assert(iov_cnt_tmp == iov_cnt - 1);
392 iov_free(iov, iov_cnt);
394 /* Discard within second-to-last element */
395 iov_random(&iov, &iov_cnt);
396 iov_cnt_tmp = iov_cnt;
397 old_base = iov[iov_cnt - 2].iov_base;
398 size = iov[iov_cnt - 1].iov_len +
399 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
400 ret = iov_discard_back(iov, &iov_cnt_tmp, size);
401 g_assert(ret == size);
402 g_assert(iov_cnt_tmp == iov_cnt - 1);
403 g_assert(iov[iov_cnt - 2].iov_base == old_base);
404 iov_free(iov, iov_cnt);
407 int main(int argc, char **argv)
409 g_test_init(&argc, &argv, NULL);
410 g_test_rand_int();
411 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
412 g_test_add_func("/basic/iov/io", test_io);
413 g_test_add_func("/basic/iov/discard-front", test_discard_front);
414 g_test_add_func("/basic/iov/discard-back", test_discard_back);
415 return g_test_run();