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