2 #include "qemu-common.h"
4 #include "qemu_socket.h"
6 /* create a randomly-sized iovec with random vectors */
7 static void iov_random(struct iovec **iovp, unsigned *iov_cntp)
9 unsigned niov = g_test_rand_int_range(3,8);
10 struct iovec *iov = g_malloc(niov * sizeof(*iov));
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);
20 static void iov_free(struct iovec *iov, unsigned niov)
23 for (i = 0; i < niov; ++i) {
24 g_free(iov[i].iov_base);
29 static void test_iov_bytes(struct iovec *iov, unsigned niov,
30 size_t offset, size_t bytes)
37 /* we walk over all elements, */
38 for (i = 0; i < niov; ++i) {
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));
48 g_assert(b[j] == 0xff);
55 static void test_to_from_buf_1(void)
60 unsigned char *ibuf, *obuf;
63 iov_random(&iov, &niov);
65 sz = iov_size(iov, niov);
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);
72 /* fill in ibuf with 0123456... */
73 for (i = 0; i < sz; ++i) {
77 for (i = 0; i <= sz; ++i) {
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 */
83 /* first set bytes [i..sz) to some "random" value */
84 n = iov_memset(iov, niov, 0, 0xff, -1);
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);
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);
97 /* now compare resulting buffers */
98 g_assert(memcmp(ibuf, obuf, sz) == 0);
100 /* test just one char */
101 n = iov_to_buf(iov, niov, i, obuf + i, 1);
102 g_assert(n == (i < sz));
104 g_assert(obuf[i] == (i & 255));
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]. */
112 n = iov_memset(iov, niov, 0, 0xff, -1);
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);
119 /* clear part of obuf */
120 memset(obuf + i, 0, j - i);
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);
127 g_assert(memcmp(ibuf, obuf, sz) == 0);
129 /* now actually check if the iovec contains the right data */
130 test_iov_bytes(iov, niov, i, j - i);
133 g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4));
135 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
140 static void test_to_from_buf(void)
143 for (x = 0; x < 4; ++x) {
144 test_to_from_buf_1();
148 static void test_io(void)
151 /* socketpair(PF_UNIX) which does not exist on windows */
155 unsigned i, j, k, s, t;
158 struct iovec *iov, *siov;
162 iov_random(&iov, &niov);
163 sz = iov_size(iov, niov);
165 for (i = 0; i < sz; ++i) {
168 iov_from_buf(iov, niov, 0, buf, sz);
170 siov = g_malloc(sizeof(*iov) * niov);
171 memcpy(siov, iov, sizeof(*iov) * niov);
173 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
174 perror("socketpair");
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));
190 for (i = 0; i <= sz; ++i) {
191 for (j = i; j <= sz; ++j) {
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);
200 usleep(g_test_rand_int_range(0, 30));
201 } else if (errno == EAGAIN) {
202 select(sv[1]+1, NULL, &fds, NULL, NULL);
214 /* reader & verifier */
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));
223 for (i = 0; i <= sz; ++i) {
224 for (j = i; j <= sz; ++j) {
226 iov_memset(iov, niov, 0, 0xff, -1);
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);
238 } else if (errno == EAGAIN) {
239 select(sv[0]+1, &fds, NULL, NULL, NULL);
246 test_iov_bytes(iov, niov, i, j - i);
253 int main(int argc, char **argv)
255 g_test_init(&argc, &argv, NULL);
257 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
258 g_test_add_func("/basic/iov/io", test_io);