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