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, enum spdk_scsi_task_func func) 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_success(void) 234 { 235 struct spdk_scsi_dev *dev; 236 const char *bdev_name_list[1] = {"malloc0"}; 237 int lun_id_list[1] = { 0 }; 238 239 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 240 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 241 242 /* Successfully constructs and returns a dev */ 243 CU_ASSERT_TRUE(dev != NULL); 244 245 /* free the dev */ 246 spdk_scsi_dev_destruct(dev); 247 } 248 249 static void 250 dev_construct_success_lun_zero_not_first(void) 251 { 252 struct spdk_scsi_dev *dev; 253 const char *bdev_name_list[2] = {"malloc1", "malloc0"}; 254 int lun_id_list[2] = { 1, 0 }; 255 256 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 2, 257 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 258 259 /* Successfully constructs and returns a dev */ 260 CU_ASSERT_TRUE(dev != NULL); 261 262 /* free the dev */ 263 spdk_scsi_dev_destruct(dev); 264 } 265 266 static void 267 dev_queue_mgmt_task_success(void) 268 { 269 struct spdk_scsi_dev *dev; 270 const char *bdev_name_list[1] = {"malloc0"}; 271 int lun_id_list[1] = { 0 }; 272 struct spdk_scsi_task *task; 273 274 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 275 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 276 277 /* Successfully constructs and returns a dev */ 278 CU_ASSERT_TRUE(dev != NULL); 279 280 task = spdk_get_task(NULL); 281 282 spdk_scsi_dev_queue_mgmt_task(dev, task, SPDK_SCSI_TASK_FUNC_LUN_RESET); 283 284 spdk_scsi_task_put(task); 285 286 spdk_scsi_dev_destruct(dev); 287 } 288 289 static void 290 dev_queue_task_success(void) 291 { 292 struct spdk_scsi_dev *dev; 293 const char *bdev_name_list[1] = {"malloc0"}; 294 int lun_id_list[1] = { 0 }; 295 struct spdk_scsi_task *task; 296 297 dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1, 298 SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); 299 300 /* Successfully constructs and returns a dev */ 301 CU_ASSERT_TRUE(dev != NULL); 302 303 task = spdk_get_task(NULL); 304 305 spdk_scsi_dev_queue_task(dev, task); 306 307 spdk_scsi_task_put(task); 308 309 spdk_scsi_dev_destruct(dev); 310 } 311 312 static void 313 dev_stop_success(void) 314 { 315 struct spdk_scsi_dev dev = { 0 }; 316 struct spdk_scsi_task *task; 317 struct spdk_scsi_task *task_mgmt; 318 319 task = spdk_get_task(NULL); 320 321 spdk_scsi_dev_queue_task(&dev, task); 322 323 task_mgmt = spdk_get_task(NULL); 324 325 /* Enqueue the tasks into dev->task_mgmt_submit_queue */ 326 spdk_scsi_dev_queue_mgmt_task(&dev, task_mgmt, SPDK_SCSI_TASK_FUNC_LUN_RESET); 327 328 spdk_scsi_task_put(task); 329 spdk_scsi_task_put(task_mgmt); 330 } 331 332 static void 333 dev_add_port_max_ports(void) 334 { 335 struct spdk_scsi_dev dev = { 0 }; 336 const char *name; 337 int id, rc; 338 339 /* dev is set to SPDK_SCSI_DEV_MAX_PORTS */ 340 dev.num_ports = SPDK_SCSI_DEV_MAX_PORTS; 341 name = "Name of Port"; 342 id = 1; 343 344 rc = spdk_scsi_dev_add_port(&dev, id, name); 345 346 /* returns -1; since the dev already has maximum 347 * number of ports (SPDK_SCSI_DEV_MAX_PORTS) */ 348 CU_ASSERT_TRUE(rc < 0); 349 } 350 351 static void 352 dev_add_port_construct_failure1(void) 353 { 354 struct spdk_scsi_dev dev = { 0 }; 355 const int port_name_length = SPDK_SCSI_PORT_MAX_NAME_LENGTH + 2; 356 char name[port_name_length]; 357 uint64_t id; 358 int rc; 359 360 dev.num_ports = 1; 361 /* Set the name such that the length exceeds SPDK_SCSI_PORT_MAX_NAME_LENGTH 362 * SPDK_SCSI_PORT_MAX_NAME_LENGTH = 256 */ 363 memset(name, 'a', port_name_length - 1); 364 name[port_name_length - 1] = '\0'; 365 id = 1; 366 367 rc = spdk_scsi_dev_add_port(&dev, id, name); 368 369 /* returns -1; since the length of the name exceeds 370 * SPDK_SCSI_PORT_MAX_NAME_LENGTH */ 371 CU_ASSERT_TRUE(rc < 0); 372 } 373 374 static void 375 dev_add_port_construct_failure2(void) 376 { 377 struct spdk_scsi_dev dev = { 0 }; 378 const char *name; 379 uint64_t id; 380 int rc; 381 382 dev.num_ports = 1; 383 name = "Name of Port"; 384 id = 1; 385 386 /* Initialize port[0] to be valid and its index is set to 1 */ 387 dev.port[0].id = id; 388 dev.port[0].is_used = 1; 389 390 rc = spdk_scsi_dev_add_port(&dev, id, name); 391 392 /* returns -1; since the dev already has a port whose index to be 1 */ 393 CU_ASSERT_TRUE(rc < 0); 394 } 395 396 static void 397 dev_add_port_success1(void) 398 { 399 struct spdk_scsi_dev dev = { 0 }; 400 const char *name; 401 int id, rc; 402 403 dev.num_ports = 1; 404 name = "Name of Port"; 405 id = 1; 406 407 rc = spdk_scsi_dev_add_port(&dev, id, name); 408 409 /* successfully adds a port */ 410 CU_ASSERT_EQUAL(rc, 0); 411 /* Assert num_ports has been incremented to 2 */ 412 CU_ASSERT_EQUAL(dev.num_ports, 2); 413 } 414 415 static void 416 dev_add_port_success2(void) 417 { 418 struct spdk_scsi_dev dev = { 0 }; 419 const char *name; 420 uint64_t id; 421 int rc; 422 423 dev.num_ports = 1; 424 name = "Name of Port"; 425 id = 1; 426 /* set id of invalid port[0] to 1. This must be ignored */ 427 dev.port[0].id = id; 428 dev.port[0].is_used = 0; 429 430 rc = spdk_scsi_dev_add_port(&dev, id, name); 431 432 /* successfully adds a port */ 433 CU_ASSERT_EQUAL(rc, 0); 434 /* Assert num_ports has been incremented to 1 */ 435 CU_ASSERT_EQUAL(dev.num_ports, 2); 436 } 437 438 static void 439 dev_add_port_success3(void) 440 { 441 struct spdk_scsi_dev dev = { 0 }; 442 const char *name; 443 uint64_t add_id; 444 int rc; 445 446 dev.num_ports = 1; 447 name = "Name of Port"; 448 dev.port[0].id = 1; 449 dev.port[0].is_used = 1; 450 add_id = 2; 451 452 /* Add a port with id = 2 */ 453 rc = spdk_scsi_dev_add_port(&dev, add_id, name); 454 455 /* successfully adds a port */ 456 CU_ASSERT_EQUAL(rc, 0); 457 /* Assert num_ports has been incremented to 2 */ 458 CU_ASSERT_EQUAL(dev.num_ports, 2); 459 } 460 461 static void 462 dev_find_port_by_id_num_ports_zero(void) 463 { 464 struct spdk_scsi_dev dev = { 0 }; 465 struct spdk_scsi_port *rp_port; 466 uint64_t id; 467 468 dev.num_ports = 0; 469 id = 1; 470 471 rp_port = spdk_scsi_dev_find_port_by_id(&dev, id); 472 473 /* returns null; since dev's num_ports is 0 */ 474 CU_ASSERT_TRUE(rp_port == NULL); 475 } 476 477 static void 478 dev_find_port_by_id_id_not_found_failure(void) 479 { 480 struct spdk_scsi_dev dev = { 0 }; 481 struct spdk_scsi_port *rp_port; 482 const char *name; 483 int rc; 484 uint64_t id, find_id; 485 486 id = 1; 487 dev.num_ports = 1; 488 name = "Name of Port"; 489 find_id = 2; 490 491 /* Add a port with id = 1 */ 492 rc = spdk_scsi_dev_add_port(&dev, id, name); 493 494 CU_ASSERT_EQUAL(rc, 0); 495 496 /* Find port with id = 2 */ 497 rp_port = spdk_scsi_dev_find_port_by_id(&dev, find_id); 498 499 /* returns null; failed to find port specified by id = 2 */ 500 CU_ASSERT_TRUE(rp_port == NULL); 501 } 502 503 static void 504 dev_find_port_by_id_success(void) 505 { 506 struct spdk_scsi_dev dev = { 0 }; 507 struct spdk_scsi_port *rp_port; 508 const char *name; 509 int rc; 510 uint64_t id; 511 512 id = 1; 513 dev.num_ports = 1; 514 name = "Name of Port"; 515 516 /* Add a port */ 517 rc = spdk_scsi_dev_add_port(&dev, id, name); 518 519 CU_ASSERT_EQUAL(rc, 0); 520 521 /* Find port by the same id as the one added above */ 522 rp_port = spdk_scsi_dev_find_port_by_id(&dev, id); 523 524 /* Successfully found port specified by id */ 525 CU_ASSERT_TRUE(rp_port != NULL); 526 if (rp_port != NULL) { 527 /* Assert the found port's id and name are same as 528 * the port added. */ 529 CU_ASSERT_EQUAL(rp_port->id, 1); 530 CU_ASSERT_STRING_EQUAL(rp_port->name, "Name of Port"); 531 } 532 } 533 534 static void 535 dev_add_lun_bdev_not_found(void) 536 { 537 int rc; 538 struct spdk_scsi_dev dev = {0}; 539 540 rc = spdk_scsi_dev_add_lun(&dev, "malloc2", -1, NULL, NULL); 541 542 CU_ASSERT_NOT_EQUAL(rc, 0); 543 } 544 545 static void 546 dev_add_lun_no_free_lun_id(void) 547 { 548 int rc; 549 int i; 550 struct spdk_scsi_dev dev = {0}; 551 struct spdk_scsi_lun lun; 552 553 for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) { 554 dev.lun[i] = &lun; 555 } 556 557 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL); 558 559 CU_ASSERT_NOT_EQUAL(rc, 0); 560 } 561 562 static void 563 dev_add_lun_success1(void) 564 { 565 int rc; 566 struct spdk_scsi_dev dev = {0}; 567 568 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL); 569 570 CU_ASSERT_EQUAL(rc, 0); 571 572 spdk_scsi_dev_destruct(&dev); 573 } 574 575 static void 576 dev_add_lun_success2(void) 577 { 578 int rc; 579 struct spdk_scsi_dev dev = {0}; 580 581 rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL); 582 583 CU_ASSERT_EQUAL(rc, 0); 584 585 spdk_scsi_dev_destruct(&dev); 586 } 587 588 int 589 main(int argc, char **argv) 590 { 591 CU_pSuite suite = NULL; 592 unsigned int num_failures; 593 594 if (CU_initialize_registry() != CUE_SUCCESS) { 595 return CU_get_error(); 596 } 597 598 suite = CU_add_suite("dev_suite", NULL, NULL); 599 if (suite == NULL) { 600 CU_cleanup_registry(); 601 return CU_get_error(); 602 } 603 604 if ( 605 CU_add_test(suite, "destruct - null dev", 606 dev_destruct_null_dev) == NULL 607 || CU_add_test(suite, "destruct - zero luns", dev_destruct_zero_luns) == NULL 608 || CU_add_test(suite, "destruct - null lun", dev_destruct_null_lun) == NULL 609 || CU_add_test(suite, "destruct - success", dev_destruct_success) == NULL 610 || CU_add_test(suite, "construct - queue depth gt max depth", 611 dev_construct_num_luns_zero) == NULL 612 || CU_add_test(suite, "construct - no lun0", 613 dev_construct_no_lun_zero) == NULL 614 || CU_add_test(suite, "construct - null lun", 615 dev_construct_null_lun) == NULL 616 || CU_add_test(suite, "construct - success", dev_construct_success) == NULL 617 || CU_add_test(suite, "construct - success - LUN zero not first", 618 dev_construct_success_lun_zero_not_first) == NULL 619 || CU_add_test(suite, "dev queue task mgmt - success", 620 dev_queue_mgmt_task_success) == NULL 621 || CU_add_test(suite, "dev queue task - success", 622 dev_queue_task_success) == NULL 623 || CU_add_test(suite, "dev stop - success", dev_stop_success) == NULL 624 || CU_add_test(suite, "dev add port - max ports", 625 dev_add_port_max_ports) == NULL 626 || CU_add_test(suite, "dev add port - construct port failure 1", 627 dev_add_port_construct_failure1) == NULL 628 || CU_add_test(suite, "dev add port - construct port failure 2", 629 dev_add_port_construct_failure2) == NULL 630 || CU_add_test(suite, "dev add port - success 1", 631 dev_add_port_success1) == NULL 632 || CU_add_test(suite, "dev add port - success 2", 633 dev_add_port_success2) == NULL 634 || CU_add_test(suite, "dev add port - success 3", 635 dev_add_port_success3) == NULL 636 || CU_add_test(suite, "dev find port by id - num ports zero", 637 dev_find_port_by_id_num_ports_zero) == NULL 638 || CU_add_test(suite, "dev find port by id - different port id failure", 639 dev_find_port_by_id_id_not_found_failure) == NULL 640 || CU_add_test(suite, "dev find port by id - success", 641 dev_find_port_by_id_success) == NULL 642 || CU_add_test(suite, "dev add lun - bdev not found", 643 dev_add_lun_bdev_not_found) == NULL 644 || CU_add_test(suite, "dev add lun - no free lun id", 645 dev_add_lun_no_free_lun_id) == NULL 646 || CU_add_test(suite, "dev add lun - success 1", 647 dev_add_lun_success1) == NULL 648 || CU_add_test(suite, "dev add lun - success 2", 649 dev_add_lun_success2) == NULL 650 ) { 651 CU_cleanup_registry(); 652 return CU_get_error(); 653 } 654 655 CU_basic_set_mode(CU_BRM_VERBOSE); 656 CU_basic_run_tests(); 657 num_failures = CU_get_number_of_failures(); 658 CU_cleanup_registry(); 659 660 return num_failures; 661 } 662