These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / 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 }