1 #include "qemu/osdep.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 bool iov_equals(const struct iovec *a, const struct iovec *b, 30 unsigned niov) 31 { 32 return memcmp(a, b, sizeof(a[0]) * niov) == 0; 33 } 34 35 static void test_iov_bytes(struct iovec *iov, unsigned niov, 36 size_t offset, size_t bytes) 37 { 38 unsigned i; 39 size_t j, o; 40 unsigned char *b; 41 o = 0; 42 43 /* we walk over all elements, */ 44 for (i = 0; i < niov; ++i) { 45 b = iov[i].iov_base; 46 /* over each char of each element, */ 47 for (j = 0; j < iov[i].iov_len; ++j) { 48 /* counting each of them and 49 * verifying that the ones within [offset,offset+bytes) 50 * range are equal to the position number (o) */ 51 if (o >= offset && o < offset + bytes) { 52 g_assert(b[j] == (o & 255)); 53 } else { 54 g_assert(b[j] == 0xff); 55 } 56 ++o; 57 } 58 } 59 } 60 61 static void test_to_from_buf_1(void) 62 { 63 unsigned niov; 64 struct iovec *iov; 65 size_t sz; 66 unsigned char *ibuf, *obuf; 67 unsigned i, j, n; 68 69 iov_random(&iov, &niov); 70 71 sz = iov_size(iov, niov); 72 73 ibuf = g_malloc(sz + 8) + 4; 74 memcpy(ibuf-4, "aaaa", 4); memcpy(ibuf + sz, "bbbb", 4); 75 obuf = g_malloc(sz + 8) + 4; 76 memcpy(obuf-4, "xxxx", 4); memcpy(obuf + sz, "yyyy", 4); 77 78 /* fill in ibuf with 0123456... */ 79 for (i = 0; i < sz; ++i) { 80 ibuf[i] = i & 255; 81 } 82 83 for (i = 0; i <= sz; ++i) { 84 85 /* Test from/to buf for offset(i) in [0..sz] up to the end of buffer. 86 * For last iteration with offset == sz, the procedure should 87 * skip whole vector and process exactly 0 bytes */ 88 89 /* first set bytes [i..sz) to some "random" value */ 90 n = iov_memset(iov, niov, 0, 0xff, sz); 91 g_assert(n == sz); 92 93 /* next copy bytes [i..sz) from ibuf to iovec */ 94 n = iov_from_buf(iov, niov, i, ibuf + i, sz - i); 95 g_assert(n == sz - i); 96 97 /* clear part of obuf */ 98 memset(obuf + i, 0, sz - i); 99 /* and set this part of obuf to values from iovec */ 100 n = iov_to_buf(iov, niov, i, obuf + i, sz - i); 101 g_assert(n == sz - i); 102 103 /* now compare resulting buffers */ 104 g_assert(memcmp(ibuf, obuf, sz) == 0); 105 106 /* test just one char */ 107 n = iov_to_buf(iov, niov, i, obuf + i, 1); 108 g_assert(n == (i < sz)); 109 if (n) { 110 g_assert(obuf[i] == (i & 255)); 111 } 112 113 for (j = i; j <= sz; ++j) { 114 /* now test num of bytes cap up to byte no. j, 115 * with j in [i..sz]. */ 116 117 /* clear iovec */ 118 n = iov_memset(iov, niov, 0, 0xff, sz); 119 g_assert(n == sz); 120 121 /* copy bytes [i..j) from ibuf to iovec */ 122 n = iov_from_buf(iov, niov, i, ibuf + i, j - i); 123 g_assert(n == j - i); 124 125 /* clear part of obuf */ 126 memset(obuf + i, 0, j - i); 127 128 /* copy bytes [i..j) from iovec to obuf */ 129 n = iov_to_buf(iov, niov, i, obuf + i, j - i); 130 g_assert(n == j - i); 131 132 /* verify result */ 133 g_assert(memcmp(ibuf, obuf, sz) == 0); 134 135 /* now actually check if the iovec contains the right data */ 136 test_iov_bytes(iov, niov, i, j - i); 137 } 138 } 139 g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4)); 140 g_free(ibuf-4); 141 g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4)); 142 g_free(obuf-4); 143 iov_free(iov, niov); 144 } 145 146 static void test_to_from_buf(void) 147 { 148 int x; 149 for (x = 0; x < 4; ++x) { 150 test_to_from_buf_1(); 151 } 152 } 153 154 static void test_io(void) 155 { 156 #ifndef _WIN32 157 /* socketpair(PF_UNIX) which does not exist on windows */ 158 159 int sv[2]; 160 int r; 161 unsigned i, j, k, s, t; 162 fd_set fds; 163 unsigned niov; 164 struct iovec *iov, *siov; 165 unsigned char *buf; 166 size_t sz; 167 168 iov_random(&iov, &niov); 169 sz = iov_size(iov, niov); 170 buf = g_malloc(sz); 171 for (i = 0; i < sz; ++i) { 172 buf[i] = i & 255; 173 } 174 iov_from_buf(iov, niov, 0, buf, sz); 175 176 siov = g_memdup(iov, sizeof(*iov) * niov); 177 178 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) { 179 perror("socketpair"); 180 exit(1); 181 } 182 183 FD_ZERO(&fds); 184 185 t = 0; 186 if (fork() == 0) { 187 /* writer */ 188 189 close(sv[0]); 190 FD_SET(sv[1], &fds); 191 fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK); 192 r = g_test_rand_int_range(sz / 2, sz); 193 setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r)); 194 195 for (i = 0; i <= sz; ++i) { 196 for (j = i; j <= sz; ++j) { 197 k = i; 198 do { 199 s = g_test_rand_int_range(0, j - k + 1); 200 r = iov_send(sv[1], iov, niov, k, s); 201 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0); 202 if (r >= 0) { 203 k += r; 204 t += r; 205 usleep(g_test_rand_int_range(0, 30)); 206 } else if (errno == EAGAIN) { 207 select(sv[1]+1, NULL, &fds, NULL, NULL); 208 continue; 209 } else { 210 perror("send"); 211 exit(1); 212 } 213 } while(k < j); 214 } 215 } 216 iov_free(iov, niov); 217 g_free(buf); 218 g_free(siov); 219 exit(0); 220 221 } else { 222 /* reader & verifier */ 223 224 close(sv[1]); 225 FD_SET(sv[0], &fds); 226 fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK); 227 r = g_test_rand_int_range(sz / 2, sz); 228 setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r)); 229 usleep(500000); 230 231 for (i = 0; i <= sz; ++i) { 232 for (j = i; j <= sz; ++j) { 233 k = i; 234 iov_memset(iov, niov, 0, 0xff, sz); 235 do { 236 s = g_test_rand_int_range(0, j - k + 1); 237 r = iov_recv(sv[0], iov, niov, k, s); 238 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0); 239 if (r > 0) { 240 k += r; 241 t += r; 242 } else if (!r) { 243 if (s) { 244 break; 245 } 246 } else if (errno == EAGAIN) { 247 select(sv[0]+1, &fds, NULL, NULL, NULL); 248 continue; 249 } else { 250 perror("recv"); 251 exit(1); 252 } 253 } while(k < j); 254 test_iov_bytes(iov, niov, i, j - i); 255 } 256 } 257 258 iov_free(iov, niov); 259 g_free(buf); 260 g_free(siov); 261 } 262 #endif 263 } 264 265 static void test_discard_front(void) 266 { 267 struct iovec *iov; 268 struct iovec *iov_tmp; 269 unsigned int iov_cnt; 270 unsigned int iov_cnt_tmp; 271 void *old_base; 272 size_t size; 273 size_t ret; 274 275 /* Discard zero bytes */ 276 iov_random(&iov, &iov_cnt); 277 iov_tmp = iov; 278 iov_cnt_tmp = iov_cnt; 279 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0); 280 g_assert(ret == 0); 281 g_assert(iov_tmp == iov); 282 g_assert(iov_cnt_tmp == iov_cnt); 283 iov_free(iov, iov_cnt); 284 285 /* Discard more bytes than vector size */ 286 iov_random(&iov, &iov_cnt); 287 iov_tmp = iov; 288 iov_cnt_tmp = iov_cnt; 289 size = iov_size(iov, iov_cnt); 290 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1); 291 g_assert(ret == size); 292 g_assert(iov_cnt_tmp == 0); 293 iov_free(iov, iov_cnt); 294 295 /* Discard entire vector */ 296 iov_random(&iov, &iov_cnt); 297 iov_tmp = iov; 298 iov_cnt_tmp = iov_cnt; 299 size = iov_size(iov, iov_cnt); 300 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); 301 g_assert(ret == size); 302 g_assert(iov_cnt_tmp == 0); 303 iov_free(iov, iov_cnt); 304 305 /* Discard within first element */ 306 iov_random(&iov, &iov_cnt); 307 iov_tmp = iov; 308 iov_cnt_tmp = iov_cnt; 309 old_base = iov->iov_base; 310 size = g_test_rand_int_range(1, iov->iov_len); 311 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); 312 g_assert(ret == size); 313 g_assert(iov_tmp == iov); 314 g_assert(iov_cnt_tmp == iov_cnt); 315 g_assert(iov_tmp->iov_base == old_base + size); 316 iov_tmp->iov_base = old_base; /* undo before g_free() */ 317 iov_free(iov, iov_cnt); 318 319 /* Discard entire first element */ 320 iov_random(&iov, &iov_cnt); 321 iov_tmp = iov; 322 iov_cnt_tmp = iov_cnt; 323 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len); 324 g_assert(ret == iov->iov_len); 325 g_assert(iov_tmp == iov + 1); 326 g_assert(iov_cnt_tmp == iov_cnt - 1); 327 iov_free(iov, iov_cnt); 328 329 /* Discard within second element */ 330 iov_random(&iov, &iov_cnt); 331 iov_tmp = iov; 332 iov_cnt_tmp = iov_cnt; 333 old_base = iov[1].iov_base; 334 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len); 335 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); 336 g_assert(ret == size); 337 g_assert(iov_tmp == iov + 1); 338 g_assert(iov_cnt_tmp == iov_cnt - 1); 339 g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len)); 340 iov_tmp->iov_base = old_base; /* undo before g_free() */ 341 iov_free(iov, iov_cnt); 342 } 343 344 static void test_discard_front_undo(void) 345 { 346 IOVDiscardUndo undo; 347 struct iovec *iov; 348 struct iovec *iov_tmp; 349 struct iovec *iov_orig; 350 unsigned int iov_cnt; 351 unsigned int iov_cnt_tmp; 352 size_t size; 353 354 /* Discard zero bytes */ 355 iov_random(&iov, &iov_cnt); 356 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 357 iov_tmp = iov; 358 iov_cnt_tmp = iov_cnt; 359 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo); 360 iov_discard_undo(&undo); 361 assert(iov_equals(iov, iov_orig, iov_cnt)); 362 g_free(iov_orig); 363 iov_free(iov, iov_cnt); 364 365 /* Discard more bytes than vector size */ 366 iov_random(&iov, &iov_cnt); 367 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 368 iov_tmp = iov; 369 iov_cnt_tmp = iov_cnt; 370 size = iov_size(iov, iov_cnt); 371 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo); 372 iov_discard_undo(&undo); 373 assert(iov_equals(iov, iov_orig, iov_cnt)); 374 g_free(iov_orig); 375 iov_free(iov, iov_cnt); 376 377 /* Discard entire vector */ 378 iov_random(&iov, &iov_cnt); 379 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 380 iov_tmp = iov; 381 iov_cnt_tmp = iov_cnt; 382 size = iov_size(iov, iov_cnt); 383 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); 384 iov_discard_undo(&undo); 385 assert(iov_equals(iov, iov_orig, iov_cnt)); 386 g_free(iov_orig); 387 iov_free(iov, iov_cnt); 388 389 /* Discard within first element */ 390 iov_random(&iov, &iov_cnt); 391 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 392 iov_tmp = iov; 393 iov_cnt_tmp = iov_cnt; 394 size = g_test_rand_int_range(1, iov->iov_len); 395 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); 396 iov_discard_undo(&undo); 397 assert(iov_equals(iov, iov_orig, iov_cnt)); 398 g_free(iov_orig); 399 iov_free(iov, iov_cnt); 400 401 /* Discard entire first element */ 402 iov_random(&iov, &iov_cnt); 403 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 404 iov_tmp = iov; 405 iov_cnt_tmp = iov_cnt; 406 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo); 407 iov_discard_undo(&undo); 408 assert(iov_equals(iov, iov_orig, iov_cnt)); 409 g_free(iov_orig); 410 iov_free(iov, iov_cnt); 411 412 /* Discard within second element */ 413 iov_random(&iov, &iov_cnt); 414 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 415 iov_tmp = iov; 416 iov_cnt_tmp = iov_cnt; 417 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len); 418 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); 419 iov_discard_undo(&undo); 420 assert(iov_equals(iov, iov_orig, iov_cnt)); 421 g_free(iov_orig); 422 iov_free(iov, iov_cnt); 423 } 424 425 static void test_discard_back(void) 426 { 427 struct iovec *iov; 428 unsigned int iov_cnt; 429 unsigned int iov_cnt_tmp; 430 void *old_base; 431 size_t size; 432 size_t ret; 433 434 /* Discard zero bytes */ 435 iov_random(&iov, &iov_cnt); 436 iov_cnt_tmp = iov_cnt; 437 ret = iov_discard_back(iov, &iov_cnt_tmp, 0); 438 g_assert(ret == 0); 439 g_assert(iov_cnt_tmp == iov_cnt); 440 iov_free(iov, iov_cnt); 441 442 /* Discard more bytes than vector size */ 443 iov_random(&iov, &iov_cnt); 444 iov_cnt_tmp = iov_cnt; 445 size = iov_size(iov, iov_cnt); 446 ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1); 447 g_assert(ret == size); 448 g_assert(iov_cnt_tmp == 0); 449 iov_free(iov, iov_cnt); 450 451 /* Discard entire vector */ 452 iov_random(&iov, &iov_cnt); 453 iov_cnt_tmp = iov_cnt; 454 size = iov_size(iov, iov_cnt); 455 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 456 g_assert(ret == size); 457 g_assert(iov_cnt_tmp == 0); 458 iov_free(iov, iov_cnt); 459 460 /* Discard within last element */ 461 iov_random(&iov, &iov_cnt); 462 iov_cnt_tmp = iov_cnt; 463 old_base = iov[iov_cnt - 1].iov_base; 464 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len); 465 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 466 g_assert(ret == size); 467 g_assert(iov_cnt_tmp == iov_cnt); 468 g_assert(iov[iov_cnt - 1].iov_base == old_base); 469 iov_free(iov, iov_cnt); 470 471 /* Discard entire last element */ 472 iov_random(&iov, &iov_cnt); 473 iov_cnt_tmp = iov_cnt; 474 old_base = iov[iov_cnt - 1].iov_base; 475 size = iov[iov_cnt - 1].iov_len; 476 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 477 g_assert(ret == size); 478 g_assert(iov_cnt_tmp == iov_cnt - 1); 479 iov_free(iov, iov_cnt); 480 481 /* Discard within second-to-last element */ 482 iov_random(&iov, &iov_cnt); 483 iov_cnt_tmp = iov_cnt; 484 old_base = iov[iov_cnt - 2].iov_base; 485 size = iov[iov_cnt - 1].iov_len + 486 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len); 487 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 488 g_assert(ret == size); 489 g_assert(iov_cnt_tmp == iov_cnt - 1); 490 g_assert(iov[iov_cnt - 2].iov_base == old_base); 491 iov_free(iov, iov_cnt); 492 } 493 494 static void test_discard_back_undo(void) 495 { 496 IOVDiscardUndo undo; 497 struct iovec *iov; 498 struct iovec *iov_orig; 499 unsigned int iov_cnt; 500 unsigned int iov_cnt_tmp; 501 size_t size; 502 503 /* Discard zero bytes */ 504 iov_random(&iov, &iov_cnt); 505 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 506 iov_cnt_tmp = iov_cnt; 507 iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo); 508 iov_discard_undo(&undo); 509 assert(iov_equals(iov, iov_orig, iov_cnt)); 510 g_free(iov_orig); 511 iov_free(iov, iov_cnt); 512 513 /* Discard more bytes than vector size */ 514 iov_random(&iov, &iov_cnt); 515 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 516 iov_cnt_tmp = iov_cnt; 517 size = iov_size(iov, iov_cnt); 518 iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo); 519 iov_discard_undo(&undo); 520 assert(iov_equals(iov, iov_orig, iov_cnt)); 521 g_free(iov_orig); 522 iov_free(iov, iov_cnt); 523 524 /* Discard entire vector */ 525 iov_random(&iov, &iov_cnt); 526 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 527 iov_cnt_tmp = iov_cnt; 528 size = iov_size(iov, iov_cnt); 529 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 530 iov_discard_undo(&undo); 531 assert(iov_equals(iov, iov_orig, iov_cnt)); 532 g_free(iov_orig); 533 iov_free(iov, iov_cnt); 534 535 /* Discard within last element */ 536 iov_random(&iov, &iov_cnt); 537 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 538 iov_cnt_tmp = iov_cnt; 539 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len); 540 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 541 iov_discard_undo(&undo); 542 assert(iov_equals(iov, iov_orig, iov_cnt)); 543 g_free(iov_orig); 544 iov_free(iov, iov_cnt); 545 546 /* Discard entire last element */ 547 iov_random(&iov, &iov_cnt); 548 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 549 iov_cnt_tmp = iov_cnt; 550 size = iov[iov_cnt - 1].iov_len; 551 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 552 iov_discard_undo(&undo); 553 assert(iov_equals(iov, iov_orig, iov_cnt)); 554 g_free(iov_orig); 555 iov_free(iov, iov_cnt); 556 557 /* Discard within second-to-last element */ 558 iov_random(&iov, &iov_cnt); 559 iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt); 560 iov_cnt_tmp = iov_cnt; 561 size = iov[iov_cnt - 1].iov_len + 562 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len); 563 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 564 iov_discard_undo(&undo); 565 assert(iov_equals(iov, iov_orig, iov_cnt)); 566 g_free(iov_orig); 567 iov_free(iov, iov_cnt); 568 } 569 570 int main(int argc, char **argv) 571 { 572 g_test_init(&argc, &argv, NULL); 573 g_test_rand_int(); 574 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf); 575 g_test_add_func("/basic/iov/io", test_io); 576 g_test_add_func("/basic/iov/discard-front", test_discard_front); 577 g_test_add_func("/basic/iov/discard-back", test_discard_back); 578 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo); 579 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo); 580 return g_test_run(); 581 } 582