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