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