1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "CUnit/Basic.h" 37 #include "spdk_cunit.h" 38 39 #include "spdk/util.h" 40 41 #include "scsi/dev.c" 42 #include "scsi/port.c" 43 44 /* Unit test bdev mockup */ 45 struct spdk_bdev { 46 char name[100]; 47 }; 48 49 static struct spdk_bdev g_bdevs[] = { 50 {"malloc0"}, 51 {"malloc1"}, 52 }; 53 54 const char * 55 spdk_bdev_get_name(const struct spdk_bdev *bdev) 56 { 57 return bdev->name; 58 } 59 60 static struct spdk_scsi_task * 61 spdk_get_task(uint32_t *owner_task_ctr) 62 { 63 struct spdk_scsi_task *task; 64 65 task = calloc(1, sizeof(*task)); 66 if (!task) { 67 return NULL; 68 } 69 70 return task; 71 } 72 73 void 74 spdk_scsi_task_put(struct spdk_scsi_task *task) 75 { 76 free(task); 77 } 78 79 _spdk_scsi_lun * 80 spdk_scsi_lun_construct(struct spdk_bdev *bdev, 81 void (*hotremove_cb)(const struct spdk_scsi_lun *, void *), 82 void *hotremove_ctx) 83 { 84 struct spdk_scsi_lun *lun; 85 86 lun = calloc(1, sizeof(struct spdk_scsi_lun)); 87 SPDK_CU_ASSERT_FATAL(lun != NULL); 88 89 lun->bdev = bdev; 90 91 return lun; 92 } 93 94 void 95 spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun) 96 { 97 free(lun); 98 } 99 100 struct spdk_bdev * 101 spdk_bdev_get_by_name(const char *bdev_name) 102 { 103 size_t i; 104 105 for (i = 0; i < SPDK_COUNTOF(g_bdevs); i++) { 106 if (strcmp(bdev_name, g_bdevs[i].name) == 0) { 107 return &g_bdevs[i]; 108 } 109 } 110 111 return NULL; 112 } 113 114 void 115 spdk_scsi_lun_append_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) 116 { 117 } 118 119 void 120 spdk_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun) 121 { 122 } 123 124 bool 125 spdk_scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun) 126 { 127 return false; 128 } 129 130 void 131 spdk_scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) 132 { 133 } 134 135 void 136 spdk_scsi_lun_execute_tasks(struct spdk_scsi_lun *lun) 137 { 138 } 139 140 int 141 _spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun) 142 { 143 return 0; 144 } 145 146 void 147 _spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun *lun) 148 { 149 } 150 151 bool 152 spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun) 153 { 154 return false; 155 } 156 157 static void 158 dev_destruct_null_dev(void) 159 { 160 /* pass null for the dev */ 161 spdk_scsi_dev_destruct(NULL); 162 } 163 164 static void 165 dev_destruct_zero_luns(void) 166 { 167 struct spdk_scsi_dev dev = { .is_allocated = 1 }; 168 169 /* No luns attached to the dev */ 170 171 /* free the dev */ 172 spdk_scsi_dev_destruct(&dev); 173 } 174 175 static void 176 dev_destruct_null_lun(void) 177 { 178 struct spdk_scsi_dev dev = { .is_allocated = 1 }; 179 180 /* pass null for the lun */ 181 dev.lun[0] = NULL; 182 183 /* free the dev */ 184 spdk_scsi_dev_destruct(&dev); 185 } 186 187 static void 188 dev_destruct_success(void) 189 { 190 struct spdk_scsi_dev dev = { .is_allocated = 1 }; 191 int rc; 192 193 /* dev with a single lun */ 194 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL); 195 196 CU_ASSERT(rc == 0); 197 198 /* free the dev */ 199 spdk_scsi_dev_destruct(&dev); 200 201 } 202 203 static void 204 dev_construct_num_luns_zero(void) 205 { 206 struct spdk_scsi_dev *dev; 207 const char *bdev_name_list[1] = {}; 208 int lun_id_list[1] = { 0 }; 209 210 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 0, 211 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 212 213 /* dev should be null since we passed num_luns = 0 */ 214 CU_ASSERT_TRUE(dev == NULL); 215 } 216 217 static void 218 dev_construct_no_lun_zero(void) 219 { 220 struct spdk_scsi_dev *dev; 221 const char *bdev_name_list[1] = {}; 222 int lun_id_list[1] = { 0 }; 223 224 lun_id_list[0] = 1; 225 226 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 227 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 228 229 /* dev should be null since no LUN0 was specified (lun_id_list[0] = 1) */ 230 CU_ASSERT_TRUE(dev == NULL); 231 } 232 233 static void 234 dev_construct_null_lun(void) 235 { 236 struct spdk_scsi_dev *dev; 237 const char *bdev_name_list[1] = {}; 238 int lun_id_list[1] = { 0 }; 239 240 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 241 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 242 243 /* dev should be null since no LUN0 was specified (lun_list[0] = NULL) */ 244 CU_ASSERT_TRUE(dev == NULL); 245 } 246 247 static void 248 dev_construct_name_too_long(void) 249 { 250 struct spdk_scsi_dev *dev; 251 const char *bdev_name_list[1] = {"malloc0"}; 252 int lun_id_list[1] = { 0 }; 253 char name[SPDK_SCSI_DEV_MAX_NAME + 1 + 1]; 254 255 /* Try to construct a dev with a name that is one byte longer than allowed. */ 256 memset(name, 'x', sizeof(name) - 1); 257 name[sizeof(name) - 1] = '\0'; 258 259 dev = spdk_scsi_dev_construct(name, bdev_name_list, lun_id_list, 1, 260 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 261 262 CU_ASSERT(dev == NULL); 263 } 264 265 static void 266 dev_construct_success(void) 267 { 268 struct spdk_scsi_dev *dev; 269 const char *bdev_name_list[1] = {"malloc0"}; 270 int lun_id_list[1] = { 0 }; 271 272 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 273 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 274 275 /* Successfully constructs and returns a dev */ 276 CU_ASSERT_TRUE(dev != NULL); 277 278 /* free the dev */ 279 spdk_scsi_dev_destruct(dev); 280 } 281 282 static void 283 dev_construct_success_lun_zero_not_first(void) 284 { 285 struct spdk_scsi_dev *dev; 286 const char *bdev_name_list[2] = {"malloc1", "malloc0"}; 287 int lun_id_list[2] = { 1, 0 }; 288 289 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 2, 290 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 291 292 /* Successfully constructs and returns a dev */ 293 CU_ASSERT_TRUE(dev != NULL); 294 295 /* free the dev */ 296 spdk_scsi_dev_destruct(dev); 297 } 298 299 static void 300 dev_queue_mgmt_task_success(void) 301 { 302 struct spdk_scsi_dev *dev; 303 const char *bdev_name_list[1] = {"malloc0"}; 304 int lun_id_list[1] = { 0 }; 305 struct spdk_scsi_task *task; 306 307 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 308 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 309 310 /* Successfully constructs and returns a dev */ 311 CU_ASSERT_TRUE(dev != NULL); 312 313 task = spdk_get_task(NULL); 314 315 task->function = SPDK_SCSI_TASK_FUNC_LUN_RESET; 316 spdk_scsi_dev_queue_mgmt_task(dev, task); 317 318 spdk_scsi_task_put(task); 319 320 spdk_scsi_dev_destruct(dev); 321 } 322 323 static void 324 dev_queue_task_success(void) 325 { 326 struct spdk_scsi_dev *dev; 327 const char *bdev_name_list[1] = {"malloc0"}; 328 int lun_id_list[1] = { 0 }; 329 struct spdk_scsi_task *task; 330 331 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 332 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 333 334 /* Successfully constructs and returns a dev */ 335 CU_ASSERT_TRUE(dev != NULL); 336 337 task = spdk_get_task(NULL); 338 339 spdk_scsi_dev_queue_task(dev, task); 340 341 spdk_scsi_task_put(task); 342 343 spdk_scsi_dev_destruct(dev); 344 } 345 346 static void 347 dev_stop_success(void) 348 { 349 struct spdk_scsi_dev dev = { 0 }; 350 struct spdk_scsi_task *task; 351 struct spdk_scsi_task *task_mgmt; 352 353 task = spdk_get_task(NULL); 354 355 spdk_scsi_dev_queue_task(&dev, task); 356 357 task_mgmt = spdk_get_task(NULL); 358 359 /* Enqueue the tasks into dev->task_mgmt_submit_queue */ 360 task->function = SPDK_SCSI_TASK_FUNC_LUN_RESET; 361 spdk_scsi_dev_queue_mgmt_task(&dev, task_mgmt); 362 363 spdk_scsi_task_put(task); 364 spdk_scsi_task_put(task_mgmt); 365 } 366 367 static void 368 dev_add_port_max_ports(void) 369 { 370 struct spdk_scsi_dev dev = { 0 }; 371 const char *name; 372 int id, rc; 373 374 /* dev is set to SPDK_SCSI_DEV_MAX_PORTS */ 375 dev.num_ports = SPDK_SCSI_DEV_MAX_PORTS; 376 name = "Name of Port"; 377 id = 1; 378 379 rc = spdk_scsi_dev_add_port(&dev, id, name); 380 381 /* returns -1; since the dev already has maximum 382 * number of ports (SPDK_SCSI_DEV_MAX_PORTS) */ 383 CU_ASSERT_TRUE(rc < 0); 384 } 385 386 static void 387 dev_add_port_construct_failure1(void) 388 { 389 struct spdk_scsi_dev dev = { 0 }; 390 const int port_name_length = SPDK_SCSI_PORT_MAX_NAME_LENGTH + 2; 391 char name[port_name_length]; 392 uint64_t id; 393 int rc; 394 395 dev.num_ports = 1; 396 /* Set the name such that the length exceeds SPDK_SCSI_PORT_MAX_NAME_LENGTH 397 * SPDK_SCSI_PORT_MAX_NAME_LENGTH = 256 */ 398 memset(name, 'a', port_name_length - 1); 399 name[port_name_length - 1] = '\0'; 400 id = 1; 401 402 rc = spdk_scsi_dev_add_port(&dev, id, name); 403 404 /* returns -1; since the length of the name exceeds 405 * SPDK_SCSI_PORT_MAX_NAME_LENGTH */ 406 CU_ASSERT_TRUE(rc < 0); 407 } 408 409 static void 410 dev_add_port_construct_failure2(void) 411 { 412 struct spdk_scsi_dev dev = { 0 }; 413 const char *name; 414 uint64_t id; 415 int rc; 416 417 dev.num_ports = 1; 418 name = "Name of Port"; 419 id = 1; 420 421 /* Initialize port[0] to be valid and its index is set to 1 */ 422 dev.port[0].id = id; 423 dev.port[0].is_used = 1; 424 425 rc = spdk_scsi_dev_add_port(&dev, id, name); 426 427 /* returns -1; since the dev already has a port whose index to be 1 */ 428 CU_ASSERT_TRUE(rc < 0); 429 } 430 431 static void 432 dev_add_port_success1(void) 433 { 434 struct spdk_scsi_dev dev = { 0 }; 435 const char *name; 436 int id, rc; 437 438 dev.num_ports = 1; 439 name = "Name of Port"; 440 id = 1; 441 442 rc = spdk_scsi_dev_add_port(&dev, id, name); 443 444 /* successfully adds a port */ 445 CU_ASSERT_EQUAL(rc, 0); 446 /* Assert num_ports has been incremented to 2 */ 447 CU_ASSERT_EQUAL(dev.num_ports, 2); 448 } 449 450 static void 451 dev_add_port_success2(void) 452 { 453 struct spdk_scsi_dev dev = { 0 }; 454 const char *name; 455 uint64_t id; 456 int rc; 457 458 dev.num_ports = 1; 459 name = "Name of Port"; 460 id = 1; 461 /* set id of invalid port[0] to 1. This must be ignored */ 462 dev.port[0].id = id; 463 dev.port[0].is_used = 0; 464 465 rc = spdk_scsi_dev_add_port(&dev, id, name); 466 467 /* successfully adds a port */ 468 CU_ASSERT_EQUAL(rc, 0); 469 /* Assert num_ports has been incremented to 1 */ 470 CU_ASSERT_EQUAL(dev.num_ports, 2); 471 } 472 473 static void 474 dev_add_port_success3(void) 475 { 476 struct spdk_scsi_dev dev = { 0 }; 477 const char *name; 478 uint64_t add_id; 479 int rc; 480 481 dev.num_ports = 1; 482 name = "Name of Port"; 483 dev.port[0].id = 1; 484 dev.port[0].is_used = 1; 485 add_id = 2; 486 487 /* Add a port with id = 2 */ 488 rc = spdk_scsi_dev_add_port(&dev, add_id, name); 489 490 /* successfully adds a port */ 491 CU_ASSERT_EQUAL(rc, 0); 492 /* Assert num_ports has been incremented to 2 */ 493 CU_ASSERT_EQUAL(dev.num_ports, 2); 494 } 495 496 static void 497 dev_find_port_by_id_num_ports_zero(void) 498 { 499 struct spdk_scsi_dev dev = { 0 }; 500 struct spdk_scsi_port *rp_port; 501 uint64_t id; 502 503 dev.num_ports = 0; 504 id = 1; 505 506 rp_port = spdk_scsi_dev_find_port_by_id(&dev, id); 507 508 /* returns null; since dev's num_ports is 0 */ 509 CU_ASSERT_TRUE(rp_port == NULL); 510 } 511 512 static void 513 dev_find_port_by_id_id_not_found_failure(void) 514 { 515 struct spdk_scsi_dev dev = { 0 }; 516 struct spdk_scsi_port *rp_port; 517 const char *name; 518 int rc; 519 uint64_t id, find_id; 520 521 id = 1; 522 dev.num_ports = 1; 523 name = "Name of Port"; 524 find_id = 2; 525 526 /* Add a port with id = 1 */ 527 rc = spdk_scsi_dev_add_port(&dev, id, name); 528 529 CU_ASSERT_EQUAL(rc, 0); 530 531 /* Find port with id = 2 */ 532 rp_port = spdk_scsi_dev_find_port_by_id(&dev, find_id); 533 534 /* returns null; failed to find port specified by id = 2 */ 535 CU_ASSERT_TRUE(rp_port == NULL); 536 } 537 538 static void 539 dev_find_port_by_id_success(void) 540 { 541 struct spdk_scsi_dev dev = { 0 }; 542 struct spdk_scsi_port *rp_port; 543 const char *name; 544 int rc; 545 uint64_t id; 546 547 id = 1; 548 dev.num_ports = 1; 549 name = "Name of Port"; 550 551 /* Add a port */ 552 rc = spdk_scsi_dev_add_port(&dev, id, name); 553 554 CU_ASSERT_EQUAL(rc, 0); 555 556 /* Find port by the same id as the one added above */ 557 rp_port = spdk_scsi_dev_find_port_by_id(&dev, id); 558 559 /* Successfully found port specified by id */ 560 CU_ASSERT_TRUE(rp_port != NULL); 561 if (rp_port != NULL) { 562 /* Assert the found port's id and name are same as 563 * the port added. */ 564 CU_ASSERT_EQUAL(rp_port->id, 1); 565 CU_ASSERT_STRING_EQUAL(rp_port->name, "Name of Port"); 566 } 567 } 568 569 static void 570 dev_add_lun_bdev_not_found(void) 571 { 572 int rc; 573 struct spdk_scsi_dev dev = {0}; 574 575 rc = spdk_scsi_dev_add_lun(&dev, "malloc2", 0, NULL, NULL); 576 577 SPDK_CU_ASSERT_FATAL(dev.lun[0] == NULL); 578 CU_ASSERT_NOT_EQUAL(rc, 0); 579 } 580 581 static void 582 dev_add_lun_no_free_lun_id(void) 583 { 584 int rc; 585 int i; 586 struct spdk_scsi_dev dev = {0}; 587 struct spdk_scsi_lun lun; 588 589 for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) { 590 dev.lun[i] = &lun; 591 } 592 593 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL); 594 595 CU_ASSERT_NOT_EQUAL(rc, 0); 596 } 597 598 static void 599 dev_add_lun_success1(void) 600 { 601 int rc; 602 struct spdk_scsi_dev dev = {0}; 603 604 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL); 605 606 CU_ASSERT_EQUAL(rc, 0); 607 608 spdk_scsi_dev_destruct(&dev); 609 } 610 611 static void 612 dev_add_lun_success2(void) 613 { 614 int rc; 615 struct spdk_scsi_dev dev = {0}; 616 617 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL); 618 619 CU_ASSERT_EQUAL(rc, 0); 620 621 spdk_scsi_dev_destruct(&dev); 622 } 623 624 int 625 main(int argc, char **argv) 626 { 627 CU_pSuite suite = NULL; 628 unsigned int num_failures; 629 630 if (CU_initialize_registry() != CUE_SUCCESS) { 631 return CU_get_error(); 632 } 633 634 suite = CU_add_suite("dev_suite", NULL, NULL); 635 if (suite == NULL) { 636 CU_cleanup_registry(); 637 return CU_get_error(); 638 } 639 640 if ( 641 CU_add_test(suite, "destruct - null dev", 642 dev_destruct_null_dev) == NULL 643 || CU_add_test(suite, "destruct - zero luns", dev_destruct_zero_luns) == NULL 644 || CU_add_test(suite, "destruct - null lun", dev_destruct_null_lun) == NULL 645 || CU_add_test(suite, "destruct - success", dev_destruct_success) == NULL 646 || CU_add_test(suite, "construct - queue depth gt max depth", 647 dev_construct_num_luns_zero) == NULL 648 || CU_add_test(suite, "construct - no lun0", 649 dev_construct_no_lun_zero) == NULL 650 || CU_add_test(suite, "construct - null lun", 651 dev_construct_null_lun) == NULL 652 || CU_add_test(suite, "construct - name too long", dev_construct_name_too_long) == NULL 653 || CU_add_test(suite, "construct - success", dev_construct_success) == NULL 654 || CU_add_test(suite, "construct - success - LUN zero not first", 655 dev_construct_success_lun_zero_not_first) == NULL 656 || CU_add_test(suite, "dev queue task mgmt - success", 657 dev_queue_mgmt_task_success) == NULL 658 || CU_add_test(suite, "dev queue task - success", 659 dev_queue_task_success) == NULL 660 || CU_add_test(suite, "dev stop - success", dev_stop_success) == NULL 661 || CU_add_test(suite, "dev add port - max ports", 662 dev_add_port_max_ports) == NULL 663 || CU_add_test(suite, "dev add port - construct port failure 1", 664 dev_add_port_construct_failure1) == NULL 665 || CU_add_test(suite, "dev add port - construct port failure 2", 666 dev_add_port_construct_failure2) == NULL 667 || CU_add_test(suite, "dev add port - success 1", 668 dev_add_port_success1) == NULL 669 || CU_add_test(suite, "dev add port - success 2", 670 dev_add_port_success2) == NULL 671 || CU_add_test(suite, "dev add port - success 3", 672 dev_add_port_success3) == NULL 673 || CU_add_test(suite, "dev find port by id - num ports zero", 674 dev_find_port_by_id_num_ports_zero) == NULL 675 || CU_add_test(suite, "dev find port by id - different port id failure", 676 dev_find_port_by_id_id_not_found_failure) == NULL 677 || CU_add_test(suite, "dev find port by id - success", 678 dev_find_port_by_id_success) == NULL 679 || CU_add_test(suite, "dev add lun - bdev not found", 680 dev_add_lun_bdev_not_found) == NULL 681 || CU_add_test(suite, "dev add lun - no free lun id", 682 dev_add_lun_no_free_lun_id) == NULL 683 || CU_add_test(suite, "dev add lun - success 1", 684 dev_add_lun_success1) == NULL 685 || CU_add_test(suite, "dev add lun - success 2", 686 dev_add_lun_success2) == NULL 687 ) { 688 CU_cleanup_registry(); 689 return CU_get_error(); 690 } 691 692 CU_basic_set_mode(CU_BRM_VERBOSE); 693 CU_basic_run_tests(); 694 num_failures = CU_get_number_of_failures(); 695 CU_cleanup_registry(); 696 697 return num_failures; 698 } 699