root / tests / test-iov.c @ 25e5e4c7
History | View | Annotate | Download (7.2 kB)
1 | 2278a69e | Michael Tokarev | #include <glib.h> |
---|---|---|---|
2 | 2278a69e | Michael Tokarev | #include "qemu-common.h" |
3 | 2278a69e | Michael Tokarev | #include "iov.h" |
4 | 25e5e4c7 | Michael Tokarev | #include "qemu_socket.h" |
5 | 2278a69e | Michael Tokarev | |
6 | 2278a69e | Michael Tokarev | /* create a randomly-sized iovec with random vectors */
|
7 | 2278a69e | Michael Tokarev | static void iov_random(struct iovec **iovp, unsigned *iov_cntp) |
8 | 2278a69e | Michael Tokarev | { |
9 | 2278a69e | Michael Tokarev | unsigned niov = g_test_rand_int_range(3,8); |
10 | 2278a69e | Michael Tokarev | struct iovec *iov = g_malloc(niov * sizeof(*iov)); |
11 | 2278a69e | Michael Tokarev | unsigned i;
|
12 | 2278a69e | Michael Tokarev | for (i = 0; i < niov; ++i) { |
13 | 2278a69e | Michael Tokarev | iov[i].iov_len = g_test_rand_int_range(5,20); |
14 | 2278a69e | Michael Tokarev | iov[i].iov_base = g_malloc(iov[i].iov_len); |
15 | 2278a69e | Michael Tokarev | } |
16 | 2278a69e | Michael Tokarev | *iovp = iov; |
17 | 2278a69e | Michael Tokarev | *iov_cntp = niov; |
18 | 2278a69e | Michael Tokarev | } |
19 | 2278a69e | Michael Tokarev | |
20 | 2278a69e | Michael Tokarev | static void iov_free(struct iovec *iov, unsigned niov) |
21 | 2278a69e | Michael Tokarev | { |
22 | 2278a69e | Michael Tokarev | unsigned i;
|
23 | 2278a69e | Michael Tokarev | for (i = 0; i < niov; ++i) { |
24 | 2278a69e | Michael Tokarev | g_free(iov[i].iov_base); |
25 | 2278a69e | Michael Tokarev | } |
26 | 2278a69e | Michael Tokarev | g_free(iov); |
27 | 2278a69e | Michael Tokarev | } |
28 | 2278a69e | Michael Tokarev | |
29 | 2278a69e | Michael Tokarev | static void test_iov_bytes(struct iovec *iov, unsigned niov, |
30 | 2278a69e | Michael Tokarev | size_t offset, size_t bytes) |
31 | 2278a69e | Michael Tokarev | { |
32 | 2278a69e | Michael Tokarev | unsigned i;
|
33 | 2278a69e | Michael Tokarev | size_t j, o; |
34 | 2278a69e | Michael Tokarev | unsigned char *b; |
35 | 2278a69e | Michael Tokarev | o = 0;
|
36 | 2278a69e | Michael Tokarev | |
37 | 2278a69e | Michael Tokarev | /* we walk over all elements, */
|
38 | 2278a69e | Michael Tokarev | for (i = 0; i < niov; ++i) { |
39 | 2278a69e | Michael Tokarev | b = iov[i].iov_base; |
40 | 2278a69e | Michael Tokarev | /* over each char of each element, */
|
41 | 2278a69e | Michael Tokarev | for (j = 0; j < iov[i].iov_len; ++j) { |
42 | 2278a69e | Michael Tokarev | /* counting each of them and
|
43 | 2278a69e | Michael Tokarev | * verifying that the ones within [offset,offset+bytes)
|
44 | 2278a69e | Michael Tokarev | * range are equal to the position number (o) */
|
45 | 2278a69e | Michael Tokarev | if (o >= offset && o < offset + bytes) {
|
46 | 2278a69e | Michael Tokarev | g_assert(b[j] == (o & 255));
|
47 | 2278a69e | Michael Tokarev | } else {
|
48 | 2278a69e | Michael Tokarev | g_assert(b[j] == 0xff);
|
49 | 2278a69e | Michael Tokarev | } |
50 | 2278a69e | Michael Tokarev | ++o; |
51 | 2278a69e | Michael Tokarev | } |
52 | 2278a69e | Michael Tokarev | } |
53 | 2278a69e | Michael Tokarev | } |
54 | 2278a69e | Michael Tokarev | |
55 | 2278a69e | Michael Tokarev | static void test_to_from_buf_1(void) |
56 | 2278a69e | Michael Tokarev | { |
57 | 2278a69e | Michael Tokarev | unsigned niov;
|
58 | 2278a69e | Michael Tokarev | struct iovec *iov;
|
59 | 2278a69e | Michael Tokarev | size_t sz; |
60 | 2278a69e | Michael Tokarev | unsigned char *ibuf, *obuf; |
61 | 2278a69e | Michael Tokarev | unsigned i, j, n;
|
62 | 2278a69e | Michael Tokarev | |
63 | 2278a69e | Michael Tokarev | iov_random(&iov, &niov); |
64 | 2278a69e | Michael Tokarev | |
65 | 2278a69e | Michael Tokarev | sz = iov_size(iov, niov); |
66 | 2278a69e | Michael Tokarev | |
67 | 2278a69e | Michael Tokarev | ibuf = g_malloc(sz + 8) + 4; |
68 | 2278a69e | Michael Tokarev | memcpy(ibuf-4, "aaaa", 4); memcpy(ibuf + sz, "bbbb", 4); |
69 | 2278a69e | Michael Tokarev | obuf = g_malloc(sz + 8) + 4; |
70 | 2278a69e | Michael Tokarev | memcpy(obuf-4, "xxxx", 4); memcpy(obuf + sz, "yyyy", 4); |
71 | 2278a69e | Michael Tokarev | |
72 | 2278a69e | Michael Tokarev | /* fill in ibuf with 0123456... */
|
73 | 2278a69e | Michael Tokarev | for (i = 0; i < sz; ++i) { |
74 | 2278a69e | Michael Tokarev | ibuf[i] = i & 255;
|
75 | 2278a69e | Michael Tokarev | } |
76 | 2278a69e | Michael Tokarev | |
77 | 2278a69e | Michael Tokarev | for (i = 0; i <= sz; ++i) { |
78 | 2278a69e | Michael Tokarev | |
79 | 2278a69e | Michael Tokarev | /* Test from/to buf for offset(i) in [0..sz] up to the end of buffer.
|
80 | 2278a69e | Michael Tokarev | * For last iteration with offset == sz, the procedure should
|
81 | 2278a69e | Michael Tokarev | * skip whole vector and process exactly 0 bytes */
|
82 | 2278a69e | Michael Tokarev | |
83 | 2278a69e | Michael Tokarev | /* first set bytes [i..sz) to some "random" value */
|
84 | 2278a69e | Michael Tokarev | n = iov_memset(iov, niov, 0, 0xff, -1); |
85 | 2278a69e | Michael Tokarev | g_assert(n == sz); |
86 | 2278a69e | Michael Tokarev | |
87 | 2278a69e | Michael Tokarev | /* next copy bytes [i..sz) from ibuf to iovec */
|
88 | 2278a69e | Michael Tokarev | n = iov_from_buf(iov, niov, i, ibuf + i, -1);
|
89 | 2278a69e | Michael Tokarev | g_assert(n == sz - i); |
90 | 2278a69e | Michael Tokarev | |
91 | 2278a69e | Michael Tokarev | /* clear part of obuf */
|
92 | 2278a69e | Michael Tokarev | memset(obuf + i, 0, sz - i);
|
93 | 2278a69e | Michael Tokarev | /* and set this part of obuf to values from iovec */
|
94 | 2278a69e | Michael Tokarev | n = iov_to_buf(iov, niov, i, obuf + i, -1);
|
95 | 2278a69e | Michael Tokarev | g_assert(n == sz - i); |
96 | 2278a69e | Michael Tokarev | |
97 | 2278a69e | Michael Tokarev | /* now compare resulting buffers */
|
98 | 2278a69e | Michael Tokarev | g_assert(memcmp(ibuf, obuf, sz) == 0);
|
99 | 2278a69e | Michael Tokarev | |
100 | 2278a69e | Michael Tokarev | /* test just one char */
|
101 | 2278a69e | Michael Tokarev | n = iov_to_buf(iov, niov, i, obuf + i, 1);
|
102 | 2278a69e | Michael Tokarev | g_assert(n == (i < sz)); |
103 | 2278a69e | Michael Tokarev | if (n) {
|
104 | 2278a69e | Michael Tokarev | g_assert(obuf[i] == (i & 255));
|
105 | 2278a69e | Michael Tokarev | } |
106 | 2278a69e | Michael Tokarev | |
107 | 2278a69e | Michael Tokarev | for (j = i; j <= sz; ++j) {
|
108 | 2278a69e | Michael Tokarev | /* now test num of bytes cap up to byte no. j,
|
109 | 2278a69e | Michael Tokarev | * with j in [i..sz]. */
|
110 | 2278a69e | Michael Tokarev | |
111 | 2278a69e | Michael Tokarev | /* clear iovec */
|
112 | 2278a69e | Michael Tokarev | n = iov_memset(iov, niov, 0, 0xff, -1); |
113 | 2278a69e | Michael Tokarev | g_assert(n == sz); |
114 | 2278a69e | Michael Tokarev | |
115 | 2278a69e | Michael Tokarev | /* copy bytes [i..j) from ibuf to iovec */
|
116 | 2278a69e | Michael Tokarev | n = iov_from_buf(iov, niov, i, ibuf + i, j - i); |
117 | 2278a69e | Michael Tokarev | g_assert(n == j - i); |
118 | 2278a69e | Michael Tokarev | |
119 | 2278a69e | Michael Tokarev | /* clear part of obuf */
|
120 | 2278a69e | Michael Tokarev | memset(obuf + i, 0, j - i);
|
121 | 2278a69e | Michael Tokarev | |
122 | 2278a69e | Michael Tokarev | /* copy bytes [i..j) from iovec to obuf */
|
123 | 2278a69e | Michael Tokarev | n = iov_to_buf(iov, niov, i, obuf + i, j - i); |
124 | 2278a69e | Michael Tokarev | g_assert(n == j - i); |
125 | 2278a69e | Michael Tokarev | |
126 | 2278a69e | Michael Tokarev | /* verify result */
|
127 | 2278a69e | Michael Tokarev | g_assert(memcmp(ibuf, obuf, sz) == 0);
|
128 | 2278a69e | Michael Tokarev | |
129 | 2278a69e | Michael Tokarev | /* now actually check if the iovec contains the right data */
|
130 | 2278a69e | Michael Tokarev | test_iov_bytes(iov, niov, i, j - i); |
131 | 2278a69e | Michael Tokarev | } |
132 | 2278a69e | Michael Tokarev | } |
133 | 2278a69e | Michael Tokarev | g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4)); |
134 | 2278a69e | Michael Tokarev | g_free(ibuf-4);
|
135 | 2278a69e | Michael Tokarev | g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4)); |
136 | 2278a69e | Michael Tokarev | g_free(obuf-4);
|
137 | 2278a69e | Michael Tokarev | iov_free(iov, niov); |
138 | 2278a69e | Michael Tokarev | } |
139 | 2278a69e | Michael Tokarev | |
140 | 2278a69e | Michael Tokarev | static void test_to_from_buf(void) |
141 | 2278a69e | Michael Tokarev | { |
142 | 2278a69e | Michael Tokarev | int x;
|
143 | 2278a69e | Michael Tokarev | for (x = 0; x < 4; ++x) { |
144 | 2278a69e | Michael Tokarev | test_to_from_buf_1(); |
145 | 2278a69e | Michael Tokarev | } |
146 | 2278a69e | Michael Tokarev | } |
147 | 2278a69e | Michael Tokarev | |
148 | 25e5e4c7 | Michael Tokarev | static void test_io(void) |
149 | 25e5e4c7 | Michael Tokarev | { |
150 | 25e5e4c7 | Michael Tokarev | #ifndef _WIN32
|
151 | 25e5e4c7 | Michael Tokarev | /* socketpair(PF_UNIX) which does not exist on windows */
|
152 | 25e5e4c7 | Michael Tokarev | |
153 | 25e5e4c7 | Michael Tokarev | int sv[2]; |
154 | 25e5e4c7 | Michael Tokarev | int r;
|
155 | 25e5e4c7 | Michael Tokarev | unsigned i, j, k, s, t;
|
156 | 25e5e4c7 | Michael Tokarev | fd_set fds; |
157 | 25e5e4c7 | Michael Tokarev | unsigned niov;
|
158 | 25e5e4c7 | Michael Tokarev | struct iovec *iov, *siov;
|
159 | 25e5e4c7 | Michael Tokarev | unsigned char *buf; |
160 | 25e5e4c7 | Michael Tokarev | size_t sz; |
161 | 25e5e4c7 | Michael Tokarev | |
162 | 25e5e4c7 | Michael Tokarev | iov_random(&iov, &niov); |
163 | 25e5e4c7 | Michael Tokarev | sz = iov_size(iov, niov); |
164 | 25e5e4c7 | Michael Tokarev | buf = g_malloc(sz); |
165 | 25e5e4c7 | Michael Tokarev | for (i = 0; i < sz; ++i) { |
166 | 25e5e4c7 | Michael Tokarev | buf[i] = i & 255;
|
167 | 25e5e4c7 | Michael Tokarev | } |
168 | 25e5e4c7 | Michael Tokarev | iov_from_buf(iov, niov, 0, buf, sz);
|
169 | 25e5e4c7 | Michael Tokarev | |
170 | 25e5e4c7 | Michael Tokarev | siov = g_malloc(sizeof(*iov) * niov);
|
171 | 25e5e4c7 | Michael Tokarev | memcpy(siov, iov, sizeof(*iov) * niov);
|
172 | 25e5e4c7 | Michael Tokarev | |
173 | 25e5e4c7 | Michael Tokarev | if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) { |
174 | 25e5e4c7 | Michael Tokarev | perror("socketpair");
|
175 | 25e5e4c7 | Michael Tokarev | exit(1);
|
176 | 25e5e4c7 | Michael Tokarev | } |
177 | 25e5e4c7 | Michael Tokarev | |
178 | 25e5e4c7 | Michael Tokarev | FD_ZERO(&fds); |
179 | 25e5e4c7 | Michael Tokarev | |
180 | 25e5e4c7 | Michael Tokarev | t = 0;
|
181 | 25e5e4c7 | Michael Tokarev | if (fork() == 0) { |
182 | 25e5e4c7 | Michael Tokarev | /* writer */
|
183 | 25e5e4c7 | Michael Tokarev | |
184 | 25e5e4c7 | Michael Tokarev | close(sv[0]);
|
185 | 25e5e4c7 | Michael Tokarev | FD_SET(sv[1], &fds);
|
186 | 25e5e4c7 | Michael Tokarev | fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK);
|
187 | 25e5e4c7 | Michael Tokarev | r = g_test_rand_int_range(sz / 2, sz);
|
188 | 25e5e4c7 | Michael Tokarev | setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r)); |
189 | 25e5e4c7 | Michael Tokarev | |
190 | 25e5e4c7 | Michael Tokarev | for (i = 0; i <= sz; ++i) { |
191 | 25e5e4c7 | Michael Tokarev | for (j = i; j <= sz; ++j) {
|
192 | 25e5e4c7 | Michael Tokarev | k = i; |
193 | 25e5e4c7 | Michael Tokarev | do {
|
194 | 25e5e4c7 | Michael Tokarev | s = g_test_rand_int_range(0, j - k + 1); |
195 | 25e5e4c7 | Michael Tokarev | r = iov_send(sv[1], iov, niov, k, s);
|
196 | 25e5e4c7 | Michael Tokarev | g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0); |
197 | 25e5e4c7 | Michael Tokarev | if (r >= 0) { |
198 | 25e5e4c7 | Michael Tokarev | k += r; |
199 | 25e5e4c7 | Michael Tokarev | t += r; |
200 | 25e5e4c7 | Michael Tokarev | usleep(g_test_rand_int_range(0, 30)); |
201 | 25e5e4c7 | Michael Tokarev | } else if (errno == EAGAIN) { |
202 | 25e5e4c7 | Michael Tokarev | select(sv[1]+1, NULL, &fds, NULL, NULL); |
203 | 25e5e4c7 | Michael Tokarev | continue;
|
204 | 25e5e4c7 | Michael Tokarev | } else {
|
205 | 25e5e4c7 | Michael Tokarev | perror("send");
|
206 | 25e5e4c7 | Michael Tokarev | exit(1);
|
207 | 25e5e4c7 | Michael Tokarev | } |
208 | 25e5e4c7 | Michael Tokarev | } while(k < j);
|
209 | 25e5e4c7 | Michael Tokarev | } |
210 | 25e5e4c7 | Michael Tokarev | } |
211 | 25e5e4c7 | Michael Tokarev | exit(0);
|
212 | 25e5e4c7 | Michael Tokarev | |
213 | 25e5e4c7 | Michael Tokarev | } else {
|
214 | 25e5e4c7 | Michael Tokarev | /* reader & verifier */
|
215 | 25e5e4c7 | Michael Tokarev | |
216 | 25e5e4c7 | Michael Tokarev | close(sv[1]);
|
217 | 25e5e4c7 | Michael Tokarev | FD_SET(sv[0], &fds);
|
218 | 25e5e4c7 | Michael Tokarev | fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK);
|
219 | 25e5e4c7 | Michael Tokarev | r = g_test_rand_int_range(sz / 2, sz);
|
220 | 25e5e4c7 | Michael Tokarev | setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r)); |
221 | 25e5e4c7 | Michael Tokarev | usleep(500000);
|
222 | 25e5e4c7 | Michael Tokarev | |
223 | 25e5e4c7 | Michael Tokarev | for (i = 0; i <= sz; ++i) { |
224 | 25e5e4c7 | Michael Tokarev | for (j = i; j <= sz; ++j) {
|
225 | 25e5e4c7 | Michael Tokarev | k = i; |
226 | 25e5e4c7 | Michael Tokarev | iov_memset(iov, niov, 0, 0xff, -1); |
227 | 25e5e4c7 | Michael Tokarev | do {
|
228 | 25e5e4c7 | Michael Tokarev | s = g_test_rand_int_range(0, j - k + 1); |
229 | 25e5e4c7 | Michael Tokarev | r = iov_recv(sv[0], iov, niov, k, s);
|
230 | 25e5e4c7 | Michael Tokarev | g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0); |
231 | 25e5e4c7 | Michael Tokarev | if (r > 0) { |
232 | 25e5e4c7 | Michael Tokarev | k += r; |
233 | 25e5e4c7 | Michael Tokarev | t += r; |
234 | 25e5e4c7 | Michael Tokarev | } else if (!r) { |
235 | 25e5e4c7 | Michael Tokarev | if (s) {
|
236 | 25e5e4c7 | Michael Tokarev | break;
|
237 | 25e5e4c7 | Michael Tokarev | } |
238 | 25e5e4c7 | Michael Tokarev | } else if (errno == EAGAIN) { |
239 | 25e5e4c7 | Michael Tokarev | select(sv[0]+1, &fds, NULL, NULL, NULL); |
240 | 25e5e4c7 | Michael Tokarev | continue;
|
241 | 25e5e4c7 | Michael Tokarev | } else {
|
242 | 25e5e4c7 | Michael Tokarev | perror("recv");
|
243 | 25e5e4c7 | Michael Tokarev | exit(1);
|
244 | 25e5e4c7 | Michael Tokarev | } |
245 | 25e5e4c7 | Michael Tokarev | } while(k < j);
|
246 | 25e5e4c7 | Michael Tokarev | test_iov_bytes(iov, niov, i, j - i); |
247 | 25e5e4c7 | Michael Tokarev | } |
248 | 25e5e4c7 | Michael Tokarev | } |
249 | 25e5e4c7 | Michael Tokarev | } |
250 | 25e5e4c7 | Michael Tokarev | #endif
|
251 | 25e5e4c7 | Michael Tokarev | } |
252 | 25e5e4c7 | Michael Tokarev | |
253 | 2278a69e | Michael Tokarev | int main(int argc, char **argv) |
254 | 2278a69e | Michael Tokarev | { |
255 | 2278a69e | Michael Tokarev | g_test_init(&argc, &argv, NULL);
|
256 | 2278a69e | Michael Tokarev | g_test_rand_int(); |
257 | 2278a69e | Michael Tokarev | g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
|
258 | 25e5e4c7 | Michael Tokarev | g_test_add_func("/basic/iov/io", test_io);
|
259 | 2278a69e | Michael Tokarev | return g_test_run();
|
260 | 2278a69e | Michael Tokarev | } |