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