linux-user: Support for restarting system calls for OpenRISC targets
[qemu.git] / tests / test-iov.c
1 #include "qemu/osdep.h"
2 #include <glib.h>
3 #include "qemu-common.h"
4 #include "qemu/iov.h"
5 #include "qemu/sockets.h"
6
7 /* create a randomly-sized iovec with random vectors */
8 static void iov_random(struct iovec **iovp, unsigned *iov_cntp)
9 {
10 unsigned niov = g_test_rand_int_range(3,8);
11 struct iovec *iov = g_malloc(niov * sizeof(*iov));
12 unsigned i;
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);
16 }
17 *iovp = iov;
18 *iov_cntp = niov;
19 }
20
21 static void iov_free(struct iovec *iov, unsigned niov)
22 {
23 unsigned i;
24 for (i = 0; i < niov; ++i) {
25 g_free(iov[i].iov_base);
26 }
27 g_free(iov);
28 }
29
30 static void test_iov_bytes(struct iovec *iov, unsigned niov,
31 size_t offset, size_t bytes)
32 {
33 unsigned i;
34 size_t j, o;
35 unsigned char *b;
36 o = 0;
37
38 /* we walk over all elements, */
39 for (i = 0; i < niov; ++i) {
40 b = iov[i].iov_base;
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));
48 } else {
49 g_assert(b[j] == 0xff);
50 }
51 ++o;
52 }
53 }
54 }
55
56 static void test_to_from_buf_1(void)
57 {
58 unsigned niov;
59 struct iovec *iov;
60 size_t sz;
61 unsigned char *ibuf, *obuf;
62 unsigned i, j, n;
63
64 iov_random(&iov, &niov);
65
66 sz = iov_size(iov, niov);
67
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);
72
73 /* fill in ibuf with 0123456... */
74 for (i = 0; i < sz; ++i) {
75 ibuf[i] = i & 255;
76 }
77
78 for (i = 0; i <= sz; ++i) {
79
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 */
83
84 /* first set bytes [i..sz) to some "random" value */
85 n = iov_memset(iov, niov, 0, 0xff, -1);
86 g_assert(n == sz);
87
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);
91
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);
97
98 /* now compare resulting buffers */
99 g_assert(memcmp(ibuf, obuf, sz) == 0);
100
101 /* test just one char */
102 n = iov_to_buf(iov, niov, i, obuf + i, 1);
103 g_assert(n == (i < sz));
104 if (n) {
105 g_assert(obuf[i] == (i & 255));
106 }
107
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]. */
111
112 /* clear iovec */
113 n = iov_memset(iov, niov, 0, 0xff, -1);
114 g_assert(n == sz);
115
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);
119
120 /* clear part of obuf */
121 memset(obuf + i, 0, j - i);
122
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);
126
127 /* verify result */
128 g_assert(memcmp(ibuf, obuf, sz) == 0);
129
130 /* now actually check if the iovec contains the right data */
131 test_iov_bytes(iov, niov, i, j - i);
132 }
133 }
134 g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4));
135 g_free(ibuf-4);
136 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
137 g_free(obuf-4);
138 iov_free(iov, niov);
139 }
140
141 static void test_to_from_buf(void)
142 {
143 int x;
144 for (x = 0; x < 4; ++x) {
145 test_to_from_buf_1();
146 }
147 }
148
149 static void test_io(void)
150 {
151 #ifndef _WIN32
152 /* socketpair(PF_UNIX) which does not exist on windows */
153
154 int sv[2];
155 int r;
156 unsigned i, j, k, s, t;
157 fd_set fds;
158 unsigned niov;
159 struct iovec *iov, *siov;
160 unsigned char *buf;
161 size_t sz;
162
163 iov_random(&iov, &niov);
164 sz = iov_size(iov, niov);
165 buf = g_malloc(sz);
166 for (i = 0; i < sz; ++i) {
167 buf[i] = i & 255;
168 }
169 iov_from_buf(iov, niov, 0, buf, sz);
170
171 siov = g_malloc(sizeof(*iov) * niov);
172 memcpy(siov, iov, sizeof(*iov) * niov);
173
174 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
175 perror("socketpair");
176 exit(1);
177 }
178
179 FD_ZERO(&fds);
180
181 t = 0;
182 if (fork() == 0) {
183 /* writer */
184
185 close(sv[0]);
186 FD_SET(sv[1], &fds);
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));
190
191 for (i = 0; i <= sz; ++i) {
192 for (j = i; j <= sz; ++j) {
193 k = i;
194 do {
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);
198 if (r >= 0) {
199 k += r;
200 t += r;
201 usleep(g_test_rand_int_range(0, 30));
202 } else if (errno == EAGAIN) {
203 select(sv[1]+1, NULL, &fds, NULL, NULL);
204 continue;
205 } else {
206 perror("send");
207 exit(1);
208 }
209 } while(k < j);
210 }
211 }
212 exit(0);
213
214 } else {
215 /* reader & verifier */
216
217 close(sv[1]);
218 FD_SET(sv[0], &fds);
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));
222 usleep(500000);
223
224 for (i = 0; i <= sz; ++i) {
225 for (j = i; j <= sz; ++j) {
226 k = i;
227 iov_memset(iov, niov, 0, 0xff, -1);
228 do {
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);
232 if (r > 0) {
233 k += r;
234 t += r;
235 } else if (!r) {
236 if (s) {
237 break;
238 }
239 } else if (errno == EAGAIN) {
240 select(sv[0]+1, &fds, NULL, NULL, NULL);
241 continue;
242 } else {
243 perror("recv");
244 exit(1);
245 }
246 } while(k < j);
247 test_iov_bytes(iov, niov, i, j - i);
248 }
249 }
250 }
251 #endif
252 }
253
254 static void test_discard_front(void)
255 {
256 struct iovec *iov;
257 struct iovec *iov_tmp;
258 unsigned int iov_cnt;
259 unsigned int iov_cnt_tmp;
260 void *old_base;
261 size_t size;
262 size_t ret;
263
264 /* Discard zero bytes */
265 iov_random(&iov, &iov_cnt);
266 iov_tmp = iov;
267 iov_cnt_tmp = iov_cnt;
268 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
269 g_assert(ret == 0);
270 g_assert(iov_tmp == iov);
271 g_assert(iov_cnt_tmp == iov_cnt);
272 iov_free(iov, iov_cnt);
273
274 /* Discard more bytes than vector size */
275 iov_random(&iov, &iov_cnt);
276 iov_tmp = iov;
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);
283
284 /* Discard entire vector */
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);
290 g_assert(ret == size);
291 g_assert(iov_cnt_tmp == 0);
292 iov_free(iov, iov_cnt);
293
294 /* Discard within first element */
295 iov_random(&iov, &iov_cnt);
296 iov_tmp = iov;
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);
307
308 /* Discard entire first element */
309 iov_random(&iov, &iov_cnt);
310 iov_tmp = iov;
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);
317
318 /* Discard within second element */
319 iov_random(&iov, &iov_cnt);
320 iov_tmp = iov;
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);
331 }
332
333 static void test_discard_back(void)
334 {
335 struct iovec *iov;
336 unsigned int iov_cnt;
337 unsigned int iov_cnt_tmp;
338 void *old_base;
339 size_t size;
340 size_t ret;
341
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);
346 g_assert(ret == 0);
347 g_assert(iov_cnt_tmp == iov_cnt);
348 iov_free(iov, iov_cnt);
349
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);
358
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);
367
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);
378
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);
388
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);
400 }
401
402 int main(int argc, char **argv)
403 {
404 g_test_init(&argc, &argv, NULL);
405 g_test_rand_int();
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);
410 return g_test_run();
411 }