1 #include "qemu/osdep.h" 2 #include "qapi/error.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; 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_memdup2(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 if (fork() == 0) { 186 /* writer */ 187 188 close(sv[0]); 189 FD_SET(sv[1], &fds); 190 qemu_set_blocking(sv[1], false, &error_abort); 191 r = g_test_rand_int_range(sz / 2, sz); 192 setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r)); 193 194 for (i = 0; i <= sz; ++i) { 195 for (j = i; j <= sz; ++j) { 196 k = i; 197 do { 198 s = g_test_rand_int_range(0, j - k + 1); 199 r = iov_send(sv[1], iov, niov, k, s); 200 g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0); 201 if (r < 0) { 202 if (errno == EAGAIN) { 203 r = 0; 204 } else { 205 perror("send"); 206 exit(1); 207 } 208 } 209 k += r; 210 if (k < j) { 211 select(sv[1] + 1, NULL, &fds, NULL, NULL); 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 qemu_set_blocking(sv[0], false, &error_abort); 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 } else if (!r) { 242 if (s) { 243 break; 244 } 245 } else if (errno == EAGAIN) { 246 select(sv[0]+1, &fds, NULL, NULL, NULL); 247 continue; 248 } else { 249 perror("recv"); 250 exit(1); 251 } 252 } while(k < j); 253 test_iov_bytes(iov, niov, i, j - i); 254 } 255 } 256 257 iov_free(iov, niov); 258 g_free(buf); 259 g_free(siov); 260 } 261 #endif 262 } 263 264 static void test_discard_front(void) 265 { 266 struct iovec *iov; 267 struct iovec *iov_tmp; 268 unsigned int iov_cnt; 269 unsigned int iov_cnt_tmp; 270 void *old_base; 271 size_t size; 272 size_t ret; 273 274 /* Discard zero bytes */ 275 iov_random(&iov, &iov_cnt); 276 iov_tmp = iov; 277 iov_cnt_tmp = iov_cnt; 278 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0); 279 g_assert(ret == 0); 280 g_assert(iov_tmp == iov); 281 g_assert(iov_cnt_tmp == iov_cnt); 282 iov_free(iov, iov_cnt); 283 284 /* Discard more bytes than vector size */ 285 iov_random(&iov, &iov_cnt); 286 iov_tmp = iov; 287 iov_cnt_tmp = iov_cnt; 288 size = iov_size(iov, iov_cnt); 289 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1); 290 g_assert(ret == size); 291 g_assert(iov_cnt_tmp == 0); 292 iov_free(iov, iov_cnt); 293 294 /* Discard entire vector */ 295 iov_random(&iov, &iov_cnt); 296 iov_tmp = iov; 297 iov_cnt_tmp = iov_cnt; 298 size = iov_size(iov, iov_cnt); 299 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); 300 g_assert(ret == size); 301 g_assert(iov_cnt_tmp == 0); 302 iov_free(iov, iov_cnt); 303 304 /* Discard within first element */ 305 iov_random(&iov, &iov_cnt); 306 iov_tmp = iov; 307 iov_cnt_tmp = iov_cnt; 308 old_base = iov->iov_base; 309 size = g_test_rand_int_range(1, iov->iov_len); 310 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); 311 g_assert(ret == size); 312 g_assert(iov_tmp == iov); 313 g_assert(iov_cnt_tmp == iov_cnt); 314 g_assert(iov_tmp->iov_base == old_base + size); 315 iov_tmp->iov_base = old_base; /* undo before g_free() */ 316 iov_free(iov, iov_cnt); 317 318 /* Discard entire first element */ 319 iov_random(&iov, &iov_cnt); 320 iov_tmp = iov; 321 iov_cnt_tmp = iov_cnt; 322 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len); 323 g_assert(ret == iov->iov_len); 324 g_assert(iov_tmp == iov + 1); 325 g_assert(iov_cnt_tmp == iov_cnt - 1); 326 iov_free(iov, iov_cnt); 327 328 /* Discard within second element */ 329 iov_random(&iov, &iov_cnt); 330 iov_tmp = iov; 331 iov_cnt_tmp = iov_cnt; 332 old_base = iov[1].iov_base; 333 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len); 334 ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size); 335 g_assert(ret == size); 336 g_assert(iov_tmp == iov + 1); 337 g_assert(iov_cnt_tmp == iov_cnt - 1); 338 g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len)); 339 iov_tmp->iov_base = old_base; /* undo before g_free() */ 340 iov_free(iov, iov_cnt); 341 } 342 343 static void test_discard_front_undo(void) 344 { 345 IOVDiscardUndo undo; 346 struct iovec *iov; 347 struct iovec *iov_tmp; 348 struct iovec *iov_orig; 349 unsigned int iov_cnt; 350 unsigned int iov_cnt_tmp; 351 size_t size; 352 353 /* Discard zero bytes */ 354 iov_random(&iov, &iov_cnt); 355 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 356 iov_tmp = iov; 357 iov_cnt_tmp = iov_cnt; 358 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo); 359 iov_discard_undo(&undo); 360 assert(iov_equals(iov, iov_orig, iov_cnt)); 361 g_free(iov_orig); 362 iov_free(iov, iov_cnt); 363 364 /* Discard more bytes than vector size */ 365 iov_random(&iov, &iov_cnt); 366 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 367 iov_tmp = iov; 368 iov_cnt_tmp = iov_cnt; 369 size = iov_size(iov, iov_cnt); 370 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo); 371 iov_discard_undo(&undo); 372 assert(iov_equals(iov, iov_orig, iov_cnt)); 373 g_free(iov_orig); 374 iov_free(iov, iov_cnt); 375 376 /* Discard entire vector */ 377 iov_random(&iov, &iov_cnt); 378 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 379 iov_tmp = iov; 380 iov_cnt_tmp = iov_cnt; 381 size = iov_size(iov, iov_cnt); 382 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); 383 iov_discard_undo(&undo); 384 assert(iov_equals(iov, iov_orig, iov_cnt)); 385 g_free(iov_orig); 386 iov_free(iov, iov_cnt); 387 388 /* Discard within first element */ 389 iov_random(&iov, &iov_cnt); 390 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 391 iov_tmp = iov; 392 iov_cnt_tmp = iov_cnt; 393 size = g_test_rand_int_range(1, iov->iov_len); 394 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); 395 iov_discard_undo(&undo); 396 assert(iov_equals(iov, iov_orig, iov_cnt)); 397 g_free(iov_orig); 398 iov_free(iov, iov_cnt); 399 400 /* Discard entire first element */ 401 iov_random(&iov, &iov_cnt); 402 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 403 iov_tmp = iov; 404 iov_cnt_tmp = iov_cnt; 405 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo); 406 iov_discard_undo(&undo); 407 assert(iov_equals(iov, iov_orig, iov_cnt)); 408 g_free(iov_orig); 409 iov_free(iov, iov_cnt); 410 411 /* Discard within second element */ 412 iov_random(&iov, &iov_cnt); 413 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 414 iov_tmp = iov; 415 iov_cnt_tmp = iov_cnt; 416 size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len); 417 iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo); 418 iov_discard_undo(&undo); 419 assert(iov_equals(iov, iov_orig, iov_cnt)); 420 g_free(iov_orig); 421 iov_free(iov, iov_cnt); 422 } 423 424 static void test_discard_back(void) 425 { 426 struct iovec *iov; 427 unsigned int iov_cnt; 428 unsigned int iov_cnt_tmp; 429 void *old_base; 430 size_t size; 431 size_t ret; 432 433 /* Discard zero bytes */ 434 iov_random(&iov, &iov_cnt); 435 iov_cnt_tmp = iov_cnt; 436 ret = iov_discard_back(iov, &iov_cnt_tmp, 0); 437 g_assert(ret == 0); 438 g_assert(iov_cnt_tmp == iov_cnt); 439 iov_free(iov, iov_cnt); 440 441 /* Discard more bytes than vector size */ 442 iov_random(&iov, &iov_cnt); 443 iov_cnt_tmp = iov_cnt; 444 size = iov_size(iov, iov_cnt); 445 ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1); 446 g_assert(ret == size); 447 g_assert(iov_cnt_tmp == 0); 448 iov_free(iov, iov_cnt); 449 450 /* Discard entire vector */ 451 iov_random(&iov, &iov_cnt); 452 iov_cnt_tmp = iov_cnt; 453 size = iov_size(iov, iov_cnt); 454 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 455 g_assert(ret == size); 456 g_assert(iov_cnt_tmp == 0); 457 iov_free(iov, iov_cnt); 458 459 /* Discard within last element */ 460 iov_random(&iov, &iov_cnt); 461 iov_cnt_tmp = iov_cnt; 462 old_base = iov[iov_cnt - 1].iov_base; 463 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len); 464 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 465 g_assert(ret == size); 466 g_assert(iov_cnt_tmp == iov_cnt); 467 g_assert(iov[iov_cnt - 1].iov_base == old_base); 468 iov_free(iov, iov_cnt); 469 470 /* Discard entire last element */ 471 iov_random(&iov, &iov_cnt); 472 iov_cnt_tmp = iov_cnt; 473 old_base = iov[iov_cnt - 1].iov_base; 474 size = iov[iov_cnt - 1].iov_len; 475 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 476 g_assert(ret == size); 477 g_assert(iov_cnt_tmp == iov_cnt - 1); 478 iov_free(iov, iov_cnt); 479 480 /* Discard within second-to-last element */ 481 iov_random(&iov, &iov_cnt); 482 iov_cnt_tmp = iov_cnt; 483 old_base = iov[iov_cnt - 2].iov_base; 484 size = iov[iov_cnt - 1].iov_len + 485 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len); 486 ret = iov_discard_back(iov, &iov_cnt_tmp, size); 487 g_assert(ret == size); 488 g_assert(iov_cnt_tmp == iov_cnt - 1); 489 g_assert(iov[iov_cnt - 2].iov_base == old_base); 490 iov_free(iov, iov_cnt); 491 } 492 493 static void test_discard_back_undo(void) 494 { 495 IOVDiscardUndo undo; 496 struct iovec *iov; 497 struct iovec *iov_orig; 498 unsigned int iov_cnt; 499 unsigned int iov_cnt_tmp; 500 size_t size; 501 502 /* Discard zero bytes */ 503 iov_random(&iov, &iov_cnt); 504 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 505 iov_cnt_tmp = iov_cnt; 506 iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo); 507 iov_discard_undo(&undo); 508 assert(iov_equals(iov, iov_orig, iov_cnt)); 509 g_free(iov_orig); 510 iov_free(iov, iov_cnt); 511 512 /* Discard more bytes than vector size */ 513 iov_random(&iov, &iov_cnt); 514 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 515 iov_cnt_tmp = iov_cnt; 516 size = iov_size(iov, iov_cnt); 517 iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo); 518 iov_discard_undo(&undo); 519 assert(iov_equals(iov, iov_orig, iov_cnt)); 520 g_free(iov_orig); 521 iov_free(iov, iov_cnt); 522 523 /* Discard entire vector */ 524 iov_random(&iov, &iov_cnt); 525 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 526 iov_cnt_tmp = iov_cnt; 527 size = iov_size(iov, iov_cnt); 528 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 529 iov_discard_undo(&undo); 530 assert(iov_equals(iov, iov_orig, iov_cnt)); 531 g_free(iov_orig); 532 iov_free(iov, iov_cnt); 533 534 /* Discard within last element */ 535 iov_random(&iov, &iov_cnt); 536 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 537 iov_cnt_tmp = iov_cnt; 538 size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len); 539 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 540 iov_discard_undo(&undo); 541 assert(iov_equals(iov, iov_orig, iov_cnt)); 542 g_free(iov_orig); 543 iov_free(iov, iov_cnt); 544 545 /* Discard entire last element */ 546 iov_random(&iov, &iov_cnt); 547 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 548 iov_cnt_tmp = iov_cnt; 549 size = iov[iov_cnt - 1].iov_len; 550 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 551 iov_discard_undo(&undo); 552 assert(iov_equals(iov, iov_orig, iov_cnt)); 553 g_free(iov_orig); 554 iov_free(iov, iov_cnt); 555 556 /* Discard within second-to-last element */ 557 iov_random(&iov, &iov_cnt); 558 iov_orig = g_memdup2(iov, sizeof(iov[0]) * iov_cnt); 559 iov_cnt_tmp = iov_cnt; 560 size = iov[iov_cnt - 1].iov_len + 561 g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len); 562 iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo); 563 iov_discard_undo(&undo); 564 assert(iov_equals(iov, iov_orig, iov_cnt)); 565 g_free(iov_orig); 566 iov_free(iov, iov_cnt); 567 } 568 569 int main(int argc, char **argv) 570 { 571 g_test_init(&argc, &argv, NULL); 572 g_test_rand_int(); 573 g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf); 574 g_test_add_func("/basic/iov/io", test_io); 575 g_test_add_func("/basic/iov/discard-front", test_discard_front); 576 g_test_add_func("/basic/iov/discard-back", test_discard_back); 577 g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo); 578 g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo); 579 return g_test_run(); 580 } 581