Statistics
| Branch: | Revision:

root / tests / test-iov.c @ 8962e44f

History | View | Annotate | Download (11.8 kB)

1
#include <glib.h>
2
#include "qemu-common.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 void test_iov_bytes(struct iovec *iov, unsigned niov,
30
                           size_t offset, size_t bytes)
31
{
32
    unsigned i;
33
    size_t j, o;
34
    unsigned char *b;
35
    o = 0;
36

    
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);
49
            }
50
            ++o;
51
        }
52
    }
53
}
54

    
55
static void test_to_from_buf_1(void)
56
{
57
     unsigned niov;
58
     struct iovec *iov;
59
     size_t sz;
60
     unsigned char *ibuf, *obuf;
61
     unsigned i, j, n;
62

    
63
     iov_random(&iov, &niov);
64

    
65
     sz = iov_size(iov, niov);
66

    
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);
71

    
72
     /* fill in ibuf with 0123456... */
73
     for (i = 0; i < sz; ++i) {
74
         ibuf[i] = i & 255;
75
     }
76

    
77
     for (i = 0; i <= sz; ++i) {
78

    
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 */
82

    
83
         /* first set bytes [i..sz) to some "random" value */
84
         n = iov_memset(iov, niov, 0, 0xff, -1);
85
         g_assert(n == sz);
86

    
87
         /* next copy bytes [i..sz) from ibuf to iovec */
88
         n = iov_from_buf(iov, niov, i, ibuf + i, -1);
89
         g_assert(n == sz - i);
90

    
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, -1);
95
         g_assert(n == sz - i);
96

    
97
         /* now compare resulting buffers */
98
         g_assert(memcmp(ibuf, obuf, sz) == 0);
99

    
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));
105
         }
106

    
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]. */
110

    
111
             /* clear iovec */
112
             n = iov_memset(iov, niov, 0, 0xff, -1);
113
             g_assert(n == sz);
114

    
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);
118

    
119
             /* clear part of obuf */
120
             memset(obuf + i, 0, j - i);
121

    
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);
125

    
126
             /* verify result */
127
             g_assert(memcmp(ibuf, obuf, sz) == 0);
128

    
129
             /* now actually check if the iovec contains the right data */
130
             test_iov_bytes(iov, niov, i, j - i);
131
         }
132
    }
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);
138
}
139

    
140
static void test_to_from_buf(void)
141
{
142
    int x;
143
    for (x = 0; x < 4; ++x) {
144
        test_to_from_buf_1();
145
    }
146
}
147

    
148
static void test_io(void)
149
{
150
#ifndef _WIN32
151
/* socketpair(PF_UNIX) which does not exist on windows */
152

    
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;
161

    
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;
167
    }
168
    iov_from_buf(iov, niov, 0, buf, sz);
169

    
170
    siov = g_malloc(sizeof(*iov) * niov);
171
    memcpy(siov, iov, sizeof(*iov) * niov);
172

    
173
    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
174
       perror("socketpair");
175
       exit(1);
176
    }
177

    
178
    FD_ZERO(&fds);
179

    
180
    t = 0;
181
    if (fork() == 0) {
182
       /* writer */
183

    
184
       close(sv[0]);
185
       FD_SET(sv[1], &fds);
186
       fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK);
187
       r = g_test_rand_int_range(sz / 2, sz);
188
       setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
189

    
190
       for (i = 0; i <= sz; ++i) {
191
           for (j = i; j <= sz; ++j) {
192
               k = i;
193
               do {
194
                   s = g_test_rand_int_range(0, j - k + 1);
195
                   r = iov_send(sv[1], iov, niov, k, s);
196
                   g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
197
                   if (r >= 0) {
198
                       k += r;
199
                       t += r;
200
                       usleep(g_test_rand_int_range(0, 30));
201
                   } else if (errno == EAGAIN) {
202
                       select(sv[1]+1, NULL, &fds, NULL, NULL);
203
                       continue;
204
                   } else {
205
                       perror("send");
206
                       exit(1);
207
                   }
208
               } while(k < j);
209
           }
210
       }
211
       exit(0);
212

    
213
    } else {
214
       /* reader & verifier */
215

    
216
       close(sv[1]);
217
       FD_SET(sv[0], &fds);
218
       fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK);
219
       r = g_test_rand_int_range(sz / 2, sz);
220
       setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
221
       usleep(500000);
222

    
223
       for (i = 0; i <= sz; ++i) {
224
           for (j = i; j <= sz; ++j) {
225
               k = i;
226
               iov_memset(iov, niov, 0, 0xff, -1);
227
               do {
228
                   s = g_test_rand_int_range(0, j - k + 1);
229
                   r = iov_recv(sv[0], iov, niov, k, s);
230
                   g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
231
                   if (r > 0) {
232
                       k += r;
233
                       t += r;
234
                   } else if (!r) {
235
                       if (s) {
236
                           break;
237
                       }
238
                   } else if (errno == EAGAIN) {
239
                       select(sv[0]+1, &fds, NULL, NULL, NULL);
240
                       continue;
241
                   } else {
242
                       perror("recv");
243
                       exit(1);
244
                   }
245
               } while(k < j);
246
               test_iov_bytes(iov, niov, i, j - i);
247
           }
248
        }
249
     }
250
#endif
251
}
252

    
253
static void test_discard_front(void)
254
{
255
    struct iovec *iov;
256
    struct iovec *iov_tmp;
257
    unsigned int iov_cnt;
258
    unsigned int iov_cnt_tmp;
259
    void *old_base;
260
    size_t size;
261
    size_t ret;
262

    
263
    /* Discard zero bytes */
264
    iov_random(&iov, &iov_cnt);
265
    iov_tmp = iov;
266
    iov_cnt_tmp = iov_cnt;
267
    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
268
    g_assert(ret == 0);
269
    g_assert(iov_tmp == iov);
270
    g_assert(iov_cnt_tmp == iov_cnt);
271
    iov_free(iov, iov_cnt);
272

    
273
    /* Discard more bytes than vector size */
274
    iov_random(&iov, &iov_cnt);
275
    iov_tmp = iov;
276
    iov_cnt_tmp = iov_cnt;
277
    size = iov_size(iov, iov_cnt);
278
    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
279
    g_assert(ret == size);
280
    g_assert(iov_cnt_tmp == 0);
281
    iov_free(iov, iov_cnt);
282

    
283
    /* Discard entire vector */
284
    iov_random(&iov, &iov_cnt);
285
    iov_tmp = iov;
286
    iov_cnt_tmp = iov_cnt;
287
    size = iov_size(iov, iov_cnt);
288
    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
289
    g_assert(ret == size);
290
    g_assert(iov_cnt_tmp == 0);
291
    iov_free(iov, iov_cnt);
292

    
293
    /* Discard within first element */
294
    iov_random(&iov, &iov_cnt);
295
    iov_tmp = iov;
296
    iov_cnt_tmp = iov_cnt;
297
    old_base = iov->iov_base;
298
    size = g_test_rand_int_range(1, iov->iov_len);
299
    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
300
    g_assert(ret == size);
301
    g_assert(iov_tmp == iov);
302
    g_assert(iov_cnt_tmp == iov_cnt);
303
    g_assert(iov_tmp->iov_base == old_base + size);
304
    iov_tmp->iov_base = old_base; /* undo before g_free() */
305
    iov_free(iov, iov_cnt);
306

    
307
    /* Discard entire first element */
308
    iov_random(&iov, &iov_cnt);
309
    iov_tmp = iov;
310
    iov_cnt_tmp = iov_cnt;
311
    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
312
    g_assert(ret == iov->iov_len);
313
    g_assert(iov_tmp == iov + 1);
314
    g_assert(iov_cnt_tmp == iov_cnt - 1);
315
    iov_free(iov, iov_cnt);
316

    
317
    /* Discard within second element */
318
    iov_random(&iov, &iov_cnt);
319
    iov_tmp = iov;
320
    iov_cnt_tmp = iov_cnt;
321
    old_base = iov[1].iov_base;
322
    size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
323
    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
324
    g_assert(ret == size);
325
    g_assert(iov_tmp == iov + 1);
326
    g_assert(iov_cnt_tmp == iov_cnt - 1);
327
    g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
328
    iov_tmp->iov_base = old_base; /* undo before g_free() */
329
    iov_free(iov, iov_cnt);
330
}
331

    
332
static void test_discard_back(void)
333
{
334
    struct iovec *iov;
335
    unsigned int iov_cnt;
336
    unsigned int iov_cnt_tmp;
337
    void *old_base;
338
    size_t size;
339
    size_t ret;
340

    
341
    /* Discard zero bytes */
342
    iov_random(&iov, &iov_cnt);
343
    iov_cnt_tmp = iov_cnt;
344
    ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
345
    g_assert(ret == 0);
346
    g_assert(iov_cnt_tmp == iov_cnt);
347
    iov_free(iov, iov_cnt);
348

    
349
    /* Discard more bytes than vector size */
350
    iov_random(&iov, &iov_cnt);
351
    iov_cnt_tmp = iov_cnt;
352
    size = iov_size(iov, iov_cnt);
353
    ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
354
    g_assert(ret == size);
355
    g_assert(iov_cnt_tmp == 0);
356
    iov_free(iov, iov_cnt);
357

    
358
    /* Discard entire vector */
359
    iov_random(&iov, &iov_cnt);
360
    iov_cnt_tmp = iov_cnt;
361
    size = iov_size(iov, iov_cnt);
362
    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
363
    g_assert(ret == size);
364
    g_assert(iov_cnt_tmp == 0);
365
    iov_free(iov, iov_cnt);
366

    
367
    /* Discard within last element */
368
    iov_random(&iov, &iov_cnt);
369
    iov_cnt_tmp = iov_cnt;
370
    old_base = iov[iov_cnt - 1].iov_base;
371
    size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
372
    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
373
    g_assert(ret == size);
374
    g_assert(iov_cnt_tmp == iov_cnt);
375
    g_assert(iov[iov_cnt - 1].iov_base == old_base);
376
    iov_free(iov, iov_cnt);
377

    
378
    /* Discard entire last element */
379
    iov_random(&iov, &iov_cnt);
380
    iov_cnt_tmp = iov_cnt;
381
    old_base = iov[iov_cnt - 1].iov_base;
382
    size = iov[iov_cnt - 1].iov_len;
383
    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
384
    g_assert(ret == size);
385
    g_assert(iov_cnt_tmp == iov_cnt - 1);
386
    iov_free(iov, iov_cnt);
387

    
388
    /* Discard within second-to-last element */
389
    iov_random(&iov, &iov_cnt);
390
    iov_cnt_tmp = iov_cnt;
391
    old_base = iov[iov_cnt - 2].iov_base;
392
    size = iov[iov_cnt - 1].iov_len +
393
           g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
394
    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
395
    g_assert(ret == size);
396
    g_assert(iov_cnt_tmp == iov_cnt - 1);
397
    g_assert(iov[iov_cnt - 2].iov_base == old_base);
398
    iov_free(iov, iov_cnt);
399
}
400

    
401
int main(int argc, char **argv)
402
{
403
    g_test_init(&argc, &argv, NULL);
404
    g_test_rand_int();
405
    g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
406
    g_test_add_func("/basic/iov/io", test_io);
407
    g_test_add_func("/basic/iov/discard-front", test_discard_front);
408
    g_test_add_func("/basic/iov/discard-back", test_discard_back);
409
    return g_test_run();
410
}