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 |
} |