xref: /spdk/test/unit/lib/scsi/dev.c/dev_ut.c (revision 66fc591ff7b1188e86b720feee0610a4b1f4fbe6)
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