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 int 115 spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task) 116 { 117 return 0; 118 } 119 120 void 121 spdk_scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) 122 { 123 } 124 125 int 126 _spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun) 127 { 128 return 0; 129 } 130 131 void 132 _spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun *lun) 133 { 134 } 135 136 bool 137 spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun) 138 { 139 return false; 140 } 141 142 static void 143 dev_destruct_null_dev(void) 144 { 145 /* pass null for the dev */ 146 spdk_scsi_dev_destruct(NULL); 147 } 148 149 static void 150 dev_destruct_zero_luns(void) 151 { 152 struct spdk_scsi_dev dev = { .is_allocated = 1 }; 153 154 /* No luns attached to the dev */ 155 156 /* free the dev */ 157 spdk_scsi_dev_destruct(&dev); 158 } 159 160 static void 161 dev_destruct_null_lun(void) 162 { 163 struct spdk_scsi_dev dev = { .is_allocated = 1 }; 164 165 /* pass null for the lun */ 166 dev.lun[0] = NULL; 167 168 /* free the dev */ 169 spdk_scsi_dev_destruct(&dev); 170 } 171 172 static void 173 dev_destruct_success(void) 174 { 175 struct spdk_scsi_dev dev = { .is_allocated = 1 }; 176 int rc; 177 178 /* dev with a single lun */ 179 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL); 180 181 CU_ASSERT(rc == 0); 182 183 /* free the dev */ 184 spdk_scsi_dev_destruct(&dev); 185 186 } 187 188 static void 189 dev_construct_num_luns_zero(void) 190 { 191 struct spdk_scsi_dev *dev; 192 const char *bdev_name_list[1] = {}; 193 int lun_id_list[1] = { 0 }; 194 195 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 0, 196 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 197 198 /* dev should be null since we passed num_luns = 0 */ 199 CU_ASSERT_TRUE(dev == NULL); 200 } 201 202 static void 203 dev_construct_no_lun_zero(void) 204 { 205 struct spdk_scsi_dev *dev; 206 const char *bdev_name_list[1] = {}; 207 int lun_id_list[1] = { 0 }; 208 209 lun_id_list[0] = 1; 210 211 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 212 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 213 214 /* dev should be null since no LUN0 was specified (lun_id_list[0] = 1) */ 215 CU_ASSERT_TRUE(dev == NULL); 216 } 217 218 static void 219 dev_construct_null_lun(void) 220 { 221 struct spdk_scsi_dev *dev; 222 const char *bdev_name_list[1] = {}; 223 int lun_id_list[1] = { 0 }; 224 225 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 226 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 227 228 /* dev should be null since no LUN0 was specified (lun_list[0] = NULL) */ 229 CU_ASSERT_TRUE(dev == NULL); 230 } 231 232 static void 233 dev_construct_name_too_long(void) 234 { 235 struct spdk_scsi_dev *dev; 236 const char *bdev_name_list[1] = {"malloc0"}; 237 int lun_id_list[1] = { 0 }; 238 char name[SPDK_SCSI_DEV_MAX_NAME + 1 + 1]; 239 240 /* Try to construct a dev with a name that is one byte longer than allowed. */ 241 memset(name, 'x', sizeof(name) - 1); 242 name[sizeof(name) - 1] = '\0'; 243 244 dev = spdk_scsi_dev_construct(name, bdev_name_list, lun_id_list, 1, 245 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 246 247 CU_ASSERT(dev == NULL); 248 } 249 250 static void 251 dev_construct_success(void) 252 { 253 struct spdk_scsi_dev *dev; 254 const char *bdev_name_list[1] = {"malloc0"}; 255 int lun_id_list[1] = { 0 }; 256 257 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 258 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 259 260 /* Successfully constructs and returns a dev */ 261 CU_ASSERT_TRUE(dev != NULL); 262 263 /* free the dev */ 264 spdk_scsi_dev_destruct(dev); 265 } 266 267 static void 268 dev_construct_success_lun_zero_not_first(void) 269 { 270 struct spdk_scsi_dev *dev; 271 const char *bdev_name_list[2] = {"malloc1", "malloc0"}; 272 int lun_id_list[2] = { 1, 0 }; 273 274 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 2, 275 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 276 277 /* Successfully constructs and returns a dev */ 278 CU_ASSERT_TRUE(dev != NULL); 279 280 /* free the dev */ 281 spdk_scsi_dev_destruct(dev); 282 } 283 284 static void 285 dev_queue_mgmt_task_success(void) 286 { 287 struct spdk_scsi_dev *dev; 288 const char *bdev_name_list[1] = {"malloc0"}; 289 int lun_id_list[1] = { 0 }; 290 struct spdk_scsi_task *task; 291 292 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 293 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 294 295 /* Successfully constructs and returns a dev */ 296 CU_ASSERT_TRUE(dev != NULL); 297 298 task = spdk_get_task(NULL); 299 300 spdk_scsi_dev_queue_mgmt_task(dev, task, SPDK_SCSI_TASK_FUNC_LUN_RESET); 301 302 spdk_scsi_task_put(task); 303 304 spdk_scsi_dev_destruct(dev); 305 } 306 307 static void 308 dev_queue_task_success(void) 309 { 310 struct spdk_scsi_dev *dev; 311 const char *bdev_name_list[1] = {"malloc0"}; 312 int lun_id_list[1] = { 0 }; 313 struct spdk_scsi_task *task; 314 315 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 316 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 317 318 /* Successfully constructs and returns a dev */ 319 CU_ASSERT_TRUE(dev != NULL); 320 321 task = spdk_get_task(NULL); 322 323 spdk_scsi_dev_queue_task(dev, task); 324 325 spdk_scsi_task_put(task); 326 327 spdk_scsi_dev_destruct(dev); 328 } 329 330 static void 331 dev_stop_success(void) 332 { 333 struct spdk_scsi_dev dev = { 0 }; 334 struct spdk_scsi_task *task; 335 struct spdk_scsi_task *task_mgmt; 336 337 task = spdk_get_task(NULL); 338 339 spdk_scsi_dev_queue_task(&dev, task); 340 341 task_mgmt = spdk_get_task(NULL); 342 343 /* Enqueue the tasks into dev->task_mgmt_submit_queue */ 344 spdk_scsi_dev_queue_mgmt_task(&dev, task_mgmt, SPDK_SCSI_TASK_FUNC_LUN_RESET); 345 346 spdk_scsi_task_put(task); 347 spdk_scsi_task_put(task_mgmt); 348 } 349 350 static void 351 dev_add_port_max_ports(void) 352 { 353 struct spdk_scsi_dev dev = { 0 }; 354 const char *name; 355 int id, rc; 356 357 /* dev is set to SPDK_SCSI_DEV_MAX_PORTS */ 358 dev.num_ports = SPDK_SCSI_DEV_MAX_PORTS; 359 name = "Name of Port"; 360 id = 1; 361 362 rc = spdk_scsi_dev_add_port(&dev, id, name); 363 364 /* returns -1; since the dev already has maximum 365 * number of ports (SPDK_SCSI_DEV_MAX_PORTS) */ 366 CU_ASSERT_TRUE(rc < 0); 367 } 368 369 static void 370 dev_add_port_construct_failure1(void) 371 { 372 struct spdk_scsi_dev dev = { 0 }; 373 const int port_name_length = SPDK_SCSI_PORT_MAX_NAME_LENGTH + 2; 374 char name[port_name_length]; 375 uint64_t id; 376 int rc; 377 378 dev.num_ports = 1; 379 /* Set the name such that the length exceeds SPDK_SCSI_PORT_MAX_NAME_LENGTH 380 * SPDK_SCSI_PORT_MAX_NAME_LENGTH = 256 */ 381 memset(name, 'a', port_name_length - 1); 382 name[port_name_length - 1] = '\0'; 383 id = 1; 384 385 rc = spdk_scsi_dev_add_port(&dev, id, name); 386 387 /* returns -1; since the length of the name exceeds 388 * SPDK_SCSI_PORT_MAX_NAME_LENGTH */ 389 CU_ASSERT_TRUE(rc < 0); 390 } 391 392 static void 393 dev_add_port_construct_failure2(void) 394 { 395 struct spdk_scsi_dev dev = { 0 }; 396 const char *name; 397 uint64_t id; 398 int rc; 399 400 dev.num_ports = 1; 401 name = "Name of Port"; 402 id = 1; 403 404 /* Initialize port[0] to be valid and its index is set to 1 */ 405 dev.port[0].id = id; 406 dev.port[0].is_used = 1; 407 408 rc = spdk_scsi_dev_add_port(&dev, id, name); 409 410 /* returns -1; since the dev already has a port whose index to be 1 */ 411 CU_ASSERT_TRUE(rc < 0); 412 } 413 414 static void 415 dev_add_port_success1(void) 416 { 417 struct spdk_scsi_dev dev = { 0 }; 418 const char *name; 419 int id, rc; 420 421 dev.num_ports = 1; 422 name = "Name of Port"; 423 id = 1; 424 425 rc = spdk_scsi_dev_add_port(&dev, id, name); 426 427 /* successfully adds a port */ 428 CU_ASSERT_EQUAL(rc, 0); 429 /* Assert num_ports has been incremented to 2 */ 430 CU_ASSERT_EQUAL(dev.num_ports, 2); 431 } 432 433 static void 434 dev_add_port_success2(void) 435 { 436 struct spdk_scsi_dev dev = { 0 }; 437 const char *name; 438 uint64_t id; 439 int rc; 440 441 dev.num_ports = 1; 442 name = "Name of Port"; 443 id = 1; 444 /* set id of invalid port[0] to 1. This must be ignored */ 445 dev.port[0].id = id; 446 dev.port[0].is_used = 0; 447 448 rc = spdk_scsi_dev_add_port(&dev, id, name); 449 450 /* successfully adds a port */ 451 CU_ASSERT_EQUAL(rc, 0); 452 /* Assert num_ports has been incremented to 1 */ 453 CU_ASSERT_EQUAL(dev.num_ports, 2); 454 } 455 456 static void 457 dev_add_port_success3(void) 458 { 459 struct spdk_scsi_dev dev = { 0 }; 460 const char *name; 461 uint64_t add_id; 462 int rc; 463 464 dev.num_ports = 1; 465 name = "Name of Port"; 466 dev.port[0].id = 1; 467 dev.port[0].is_used = 1; 468 add_id = 2; 469 470 /* Add a port with id = 2 */ 471 rc = spdk_scsi_dev_add_port(&dev, add_id, name); 472 473 /* successfully adds a port */ 474 CU_ASSERT_EQUAL(rc, 0); 475 /* Assert num_ports has been incremented to 2 */ 476 CU_ASSERT_EQUAL(dev.num_ports, 2); 477 } 478 479 static void 480 dev_find_port_by_id_num_ports_zero(void) 481 { 482 struct spdk_scsi_dev dev = { 0 }; 483 struct spdk_scsi_port *rp_port; 484 uint64_t id; 485 486 dev.num_ports = 0; 487 id = 1; 488 489 rp_port = spdk_scsi_dev_find_port_by_id(&dev, id); 490 491 /* returns null; since dev's num_ports is 0 */ 492 CU_ASSERT_TRUE(rp_port == NULL); 493 } 494 495 static void 496 dev_find_port_by_id_id_not_found_failure(void) 497 { 498 struct spdk_scsi_dev dev = { 0 }; 499 struct spdk_scsi_port *rp_port; 500 const char *name; 501 int rc; 502 uint64_t id, find_id; 503 504 id = 1; 505 dev.num_ports = 1; 506 name = "Name of Port"; 507 find_id = 2; 508 509 /* Add a port with id = 1 */ 510 rc = spdk_scsi_dev_add_port(&dev, id, name); 511 512 CU_ASSERT_EQUAL(rc, 0); 513 514 /* Find port with id = 2 */ 515 rp_port = spdk_scsi_dev_find_port_by_id(&dev, find_id); 516 517 /* returns null; failed to find port specified by id = 2 */ 518 CU_ASSERT_TRUE(rp_port == NULL); 519 } 520 521 static void 522 dev_find_port_by_id_success(void) 523 { 524 struct spdk_scsi_dev dev = { 0 }; 525 struct spdk_scsi_port *rp_port; 526 const char *name; 527 int rc; 528 uint64_t id; 529 530 id = 1; 531 dev.num_ports = 1; 532 name = "Name of Port"; 533 534 /* Add a port */ 535 rc = spdk_scsi_dev_add_port(&dev, id, name); 536 537 CU_ASSERT_EQUAL(rc, 0); 538 539 /* Find port by the same id as the one added above */ 540 rp_port = spdk_scsi_dev_find_port_by_id(&dev, id); 541 542 /* Successfully found port specified by id */ 543 CU_ASSERT_TRUE(rp_port != NULL); 544 if (rp_port != NULL) { 545 /* Assert the found port's id and name are same as 546 * the port added. */ 547 CU_ASSERT_EQUAL(rp_port->id, 1); 548 CU_ASSERT_STRING_EQUAL(rp_port->name, "Name of Port"); 549 } 550 } 551 552 static void 553 dev_add_lun_bdev_not_found(void) 554 { 555 int rc; 556 struct spdk_scsi_dev dev = {0}; 557 558 rc = spdk_scsi_dev_add_lun(&dev, "malloc2", 0, NULL, NULL); 559 560 SPDK_CU_ASSERT_FATAL(dev.lun[0] == NULL); 561 CU_ASSERT_NOT_EQUAL(rc, 0); 562 } 563 564 static void 565 dev_add_lun_no_free_lun_id(void) 566 { 567 int rc; 568 int i; 569 struct spdk_scsi_dev dev = {0}; 570 struct spdk_scsi_lun lun; 571 572 for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) { 573 dev.lun[i] = &lun; 574 } 575 576 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL); 577 578 CU_ASSERT_NOT_EQUAL(rc, 0); 579 } 580 581 static void 582 dev_add_lun_success1(void) 583 { 584 int rc; 585 struct spdk_scsi_dev dev = {0}; 586 587 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL); 588 589 CU_ASSERT_EQUAL(rc, 0); 590 591 spdk_scsi_dev_destruct(&dev); 592 } 593 594 static void 595 dev_add_lun_success2(void) 596 { 597 int rc; 598 struct spdk_scsi_dev dev = {0}; 599 600 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL); 601 602 CU_ASSERT_EQUAL(rc, 0); 603 604 spdk_scsi_dev_destruct(&dev); 605 } 606 607 int 608 main(int argc, char **argv) 609 { 610 CU_pSuite suite = NULL; 611 unsigned int num_failures; 612 613 if (CU_initialize_registry() != CUE_SUCCESS) { 614 return CU_get_error(); 615 } 616 617 suite = CU_add_suite("dev_suite", NULL, NULL); 618 if (suite == NULL) { 619 CU_cleanup_registry(); 620 return CU_get_error(); 621 } 622 623 if ( 624 CU_add_test(suite, "destruct - null dev", 625 dev_destruct_null_dev) == NULL 626 || CU_add_test(suite, "destruct - zero luns", dev_destruct_zero_luns) == NULL 627 || CU_add_test(suite, "destruct - null lun", dev_destruct_null_lun) == NULL 628 || CU_add_test(suite, "destruct - success", dev_destruct_success) == NULL 629 || CU_add_test(suite, "construct - queue depth gt max depth", 630 dev_construct_num_luns_zero) == NULL 631 || CU_add_test(suite, "construct - no lun0", 632 dev_construct_no_lun_zero) == NULL 633 || CU_add_test(suite, "construct - null lun", 634 dev_construct_null_lun) == NULL 635 || CU_add_test(suite, "construct - name too long", dev_construct_name_too_long) == NULL 636 || CU_add_test(suite, "construct - success", dev_construct_success) == NULL 637 || CU_add_test(suite, "construct - success - LUN zero not first", 638 dev_construct_success_lun_zero_not_first) == NULL 639 || CU_add_test(suite, "dev queue task mgmt - success", 640 dev_queue_mgmt_task_success) == NULL 641 || CU_add_test(suite, "dev queue task - success", 642 dev_queue_task_success) == NULL 643 || CU_add_test(suite, "dev stop - success", dev_stop_success) == NULL 644 || CU_add_test(suite, "dev add port - max ports", 645 dev_add_port_max_ports) == NULL 646 || CU_add_test(suite, "dev add port - construct port failure 1", 647 dev_add_port_construct_failure1) == NULL 648 || CU_add_test(suite, "dev add port - construct port failure 2", 649 dev_add_port_construct_failure2) == NULL 650 || CU_add_test(suite, "dev add port - success 1", 651 dev_add_port_success1) == NULL 652 || CU_add_test(suite, "dev add port - success 2", 653 dev_add_port_success2) == NULL 654 || CU_add_test(suite, "dev add port - success 3", 655 dev_add_port_success3) == NULL 656 || CU_add_test(suite, "dev find port by id - num ports zero", 657 dev_find_port_by_id_num_ports_zero) == NULL 658 || CU_add_test(suite, "dev find port by id - different port id failure", 659 dev_find_port_by_id_id_not_found_failure) == NULL 660 || CU_add_test(suite, "dev find port by id - success", 661 dev_find_port_by_id_success) == NULL 662 || CU_add_test(suite, "dev add lun - bdev not found", 663 dev_add_lun_bdev_not_found) == NULL 664 || CU_add_test(suite, "dev add lun - no free lun id", 665 dev_add_lun_no_free_lun_id) == NULL 666 || CU_add_test(suite, "dev add lun - success 1", 667 dev_add_lun_success1) == NULL 668 || CU_add_test(suite, "dev add lun - success 2", 669 dev_add_lun_success2) == NULL 670 ) { 671 CU_cleanup_registry(); 672 return CU_get_error(); 673 } 674 675 CU_basic_set_mode(CU_BRM_VERBOSE); 676 CU_basic_run_tests(); 677 num_failures = CU_get_number_of_failures(); 678 CU_cleanup_registry(); 679 680 return num_failures; 681 } 682