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