Statistics
| Branch: | Revision:

root / tests / test-iov.c @ 25e5e4c7

History | View | Annotate | Download (7.2 kB)

1
#include <glib.h>
2
#include "qemu-common.h"
3
#include "iov.h"
4
#include "qemu_socket.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
int main(int argc, char **argv)
254
{
255
    g_test_init(&argc, &argv, NULL);
256
    g_test_rand_int();
257
    g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
258
    g_test_add_func("/basic/iov/io", test_io);
259
    return g_test_run();
260
}