4 * Copyright (c) Intel Corporation. All rights reserved.
5 * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk_cunit.h"
38 #include "nvme/nvme.c"
40 #include "spdk_internal/mock.h"
42 #include "common/lib/test_env.c"
44 DEFINE_STUB_V(nvme_ctrlr_proc_get_ref
, (struct spdk_nvme_ctrlr
*ctrlr
));
45 DEFINE_STUB_V(nvme_ctrlr_proc_put_ref
, (struct spdk_nvme_ctrlr
*ctrlr
));
46 DEFINE_STUB_V(nvme_ctrlr_fail
, (struct spdk_nvme_ctrlr
*ctrlr
, bool hotremove
));
47 DEFINE_STUB(spdk_nvme_transport_available_by_name
, bool,
48 (const char *transport_name
), true);
49 /* return anything non-NULL, this won't be deferenced anywhere in this test */
50 DEFINE_STUB(nvme_ctrlr_get_current_process
, struct spdk_nvme_ctrlr_process
*,
51 (struct spdk_nvme_ctrlr
*ctrlr
), (struct spdk_nvme_ctrlr_process
*)(uintptr_t)0x1);
52 DEFINE_STUB(nvme_ctrlr_process_init
, int,
53 (struct spdk_nvme_ctrlr
*ctrlr
), 0);
54 DEFINE_STUB(nvme_ctrlr_get_ref_count
, int,
55 (struct spdk_nvme_ctrlr
*ctrlr
), 0);
56 DEFINE_STUB(dummy_probe_cb
, bool,
57 (void *cb_ctx
, const struct spdk_nvme_transport_id
*trid
,
58 struct spdk_nvme_ctrlr_opts
*opts
), false);
59 DEFINE_STUB(nvme_transport_ctrlr_construct
, struct spdk_nvme_ctrlr
*,
60 (const struct spdk_nvme_transport_id
*trid
,
61 const struct spdk_nvme_ctrlr_opts
*opts
,
62 void *devhandle
), NULL
);
63 DEFINE_STUB_V(nvme_io_msg_ctrlr_detach
, (struct spdk_nvme_ctrlr
*ctrlr
));
64 DEFINE_STUB(spdk_nvme_transport_available
, bool,
65 (enum spdk_nvme_transport_type trtype
), true);
66 DEFINE_STUB(nvme_uevent_connect
, int, (void), 1);
69 static bool ut_destruct_called
= false;
71 nvme_ctrlr_destruct(struct spdk_nvme_ctrlr
*ctrlr
)
73 ut_destruct_called
= true;
77 spdk_nvme_ctrlr_get_default_ctrlr_opts(struct spdk_nvme_ctrlr_opts
*opts
, size_t opts_size
)
79 memset(opts
, 0, opts_size
);
80 opts
->opts_size
= opts_size
;
84 memset_trid(struct spdk_nvme_transport_id
*trid1
, struct spdk_nvme_transport_id
*trid2
)
86 memset(trid1
, 0, sizeof(struct spdk_nvme_transport_id
));
87 memset(trid2
, 0, sizeof(struct spdk_nvme_transport_id
));
90 static bool ut_check_trtype
= false;
91 static bool ut_test_probe_internal
= false;
94 ut_nvme_pcie_ctrlr_scan(struct spdk_nvme_probe_ctx
*probe_ctx
,
97 struct spdk_nvme_ctrlr
*ctrlr
;
98 struct spdk_nvme_qpair qpair
= {};
101 if (probe_ctx
->trid
.trtype
!= SPDK_NVME_TRANSPORT_PCIE
) {
105 ctrlr
= calloc(1, sizeof(*ctrlr
));
106 CU_ASSERT(ctrlr
!= NULL
);
107 ctrlr
->adminq
= &qpair
;
109 /* happy path with first controller */
110 MOCK_SET(nvme_transport_ctrlr_construct
, ctrlr
);
111 rc
= nvme_ctrlr_probe(&probe_ctx
->trid
, probe_ctx
, NULL
);
114 /* failed with the second controller */
115 MOCK_SET(nvme_transport_ctrlr_construct
, NULL
);
116 rc
= nvme_ctrlr_probe(&probe_ctx
->trid
, probe_ctx
, NULL
);
118 MOCK_CLEAR_P(nvme_transport_ctrlr_construct
);
124 nvme_transport_ctrlr_destruct(struct spdk_nvme_ctrlr
*ctrlr
)
131 nvme_transport_ctrlr_scan(struct spdk_nvme_probe_ctx
*probe_ctx
,
134 struct spdk_nvme_ctrlr
*ctrlr
= NULL
;
136 if (ut_check_trtype
== true) {
137 CU_ASSERT(probe_ctx
->trid
.trtype
== SPDK_NVME_TRANSPORT_PCIE
);
140 if (ut_test_probe_internal
) {
141 return ut_nvme_pcie_ctrlr_scan(probe_ctx
, direct_connect
);
144 if (direct_connect
== true && probe_ctx
->probe_cb
) {
145 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
146 ctrlr
= nvme_get_ctrlr_by_trid(&probe_ctx
->trid
);
147 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
148 probe_ctx
->probe_cb(probe_ctx
->cb_ctx
, &probe_ctx
->trid
, &ctrlr
->opts
);
153 static bool ut_attach_cb_called
= false;
155 dummy_attach_cb(void *cb_ctx
, const struct spdk_nvme_transport_id
*trid
,
156 struct spdk_nvme_ctrlr
*ctrlr
, const struct spdk_nvme_ctrlr_opts
*opts
)
158 ut_attach_cb_called
= true;
162 test_spdk_nvme_probe(void)
165 const struct spdk_nvme_transport_id
*trid
= NULL
;
167 spdk_nvme_probe_cb probe_cb
= NULL
;
168 spdk_nvme_attach_cb attach_cb
= dummy_attach_cb
;
169 spdk_nvme_remove_cb remove_cb
= NULL
;
170 struct spdk_nvme_ctrlr ctrlr
;
171 pthread_mutexattr_t attr
;
172 struct nvme_driver dummy
;
173 g_spdk_nvme_driver
= &dummy
;
175 /* driver init fails */
176 MOCK_SET(spdk_process_is_primary
, false);
177 MOCK_SET(spdk_memzone_lookup
, NULL
);
178 rc
= spdk_nvme_probe(trid
, cb_ctx
, probe_cb
, attach_cb
, remove_cb
);
182 * For secondary processes, the attach_cb should automatically get
183 * called for any controllers already initialized by the primary
186 MOCK_SET(spdk_nvme_transport_available_by_name
, false);
187 MOCK_SET(spdk_process_is_primary
, true);
188 dummy
.initialized
= true;
189 g_spdk_nvme_driver
= &dummy
;
190 rc
= spdk_nvme_probe(trid
, cb_ctx
, probe_cb
, attach_cb
, remove_cb
);
193 /* driver init passes, transport available, secondary call attach_cb */
194 MOCK_SET(spdk_nvme_transport_available_by_name
, true);
195 MOCK_SET(spdk_process_is_primary
, false);
196 MOCK_SET(spdk_memzone_lookup
, g_spdk_nvme_driver
);
197 dummy
.initialized
= true;
198 memset(&ctrlr
, 0, sizeof(struct spdk_nvme_ctrlr
));
199 CU_ASSERT(pthread_mutexattr_init(&attr
) == 0);
200 CU_ASSERT(pthread_mutex_init(&dummy
.lock
, &attr
) == 0);
201 TAILQ_INIT(&dummy
.shared_attached_ctrlrs
);
202 TAILQ_INSERT_TAIL(&dummy
.shared_attached_ctrlrs
, &ctrlr
, tailq
);
203 ut_attach_cb_called
= false;
204 /* setup nvme_transport_ctrlr_scan() stub to also check the trype */
205 ut_check_trtype
= true;
206 rc
= spdk_nvme_probe(trid
, cb_ctx
, probe_cb
, attach_cb
, remove_cb
);
208 CU_ASSERT(ut_attach_cb_called
== true);
210 /* driver init passes, transport available, we are primary */
211 MOCK_SET(spdk_process_is_primary
, true);
212 rc
= spdk_nvme_probe(trid
, cb_ctx
, probe_cb
, attach_cb
, remove_cb
);
215 g_spdk_nvme_driver
= NULL
;
216 /* reset to pre-test values */
217 MOCK_CLEAR(spdk_memzone_lookup
);
218 ut_check_trtype
= false;
220 pthread_mutex_destroy(&dummy
.lock
);
221 pthread_mutexattr_destroy(&attr
);
225 test_spdk_nvme_connect(void)
227 struct spdk_nvme_ctrlr
*ret_ctrlr
= NULL
;
228 struct spdk_nvme_transport_id trid
= {};
229 struct spdk_nvme_ctrlr_opts opts
= {};
230 struct spdk_nvme_ctrlr ctrlr
;
231 pthread_mutexattr_t attr
;
232 struct nvme_driver dummy
;
234 /* initialize the variable to prepare the test */
235 dummy
.initialized
= true;
236 TAILQ_INIT(&dummy
.shared_attached_ctrlrs
);
237 g_spdk_nvme_driver
= &dummy
;
238 CU_ASSERT(pthread_mutexattr_init(&attr
) == 0);
239 CU_ASSERT(pthread_mutex_init(&g_spdk_nvme_driver
->lock
, &attr
) == 0);
241 /* set NULL trid pointer to test immediate return */
242 ret_ctrlr
= spdk_nvme_connect(NULL
, NULL
, 0);
243 CU_ASSERT(ret_ctrlr
== NULL
);
245 /* driver init passes, transport available, secondary process connects ctrlr */
246 MOCK_SET(spdk_process_is_primary
, false);
247 MOCK_SET(spdk_memzone_lookup
, g_spdk_nvme_driver
);
248 MOCK_SET(spdk_nvme_transport_available_by_name
, true);
249 memset(&trid
, 0, sizeof(trid
));
250 trid
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
251 ret_ctrlr
= spdk_nvme_connect(&trid
, NULL
, 0);
252 CU_ASSERT(ret_ctrlr
== NULL
);
254 /* driver init passes, setup one ctrlr on the attached_list */
255 memset(&ctrlr
, 0, sizeof(struct spdk_nvme_ctrlr
));
256 snprintf(ctrlr
.trid
.traddr
, sizeof(ctrlr
.trid
.traddr
), "0000:01:00.0");
257 ctrlr
.trid
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
258 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver
->shared_attached_ctrlrs
, &ctrlr
, tailq
);
259 /* get the ctrlr from the attached list */
260 snprintf(trid
.traddr
, sizeof(trid
.traddr
), "0000:01:00.0");
261 ret_ctrlr
= spdk_nvme_connect(&trid
, NULL
, 0);
262 CU_ASSERT(ret_ctrlr
== &ctrlr
);
263 /* get the ctrlr from the attached list with default ctrlr opts */
264 ctrlr
.opts
.num_io_queues
= DEFAULT_MAX_IO_QUEUES
;
265 ret_ctrlr
= spdk_nvme_connect(&trid
, NULL
, 0);
266 CU_ASSERT(ret_ctrlr
== &ctrlr
);
267 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.num_io_queues
, DEFAULT_MAX_IO_QUEUES
);
268 /* get the ctrlr from the attached list with default ctrlr opts and consistent opts_size */
269 opts
.num_io_queues
= 1;
270 ret_ctrlr
= spdk_nvme_connect(&trid
, &opts
, sizeof(opts
));
271 CU_ASSERT(ret_ctrlr
== &ctrlr
);
272 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.num_io_queues
, 1);
273 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.opts_size
, sizeof(opts
));
276 ret_ctrlr
= spdk_nvme_connect(&trid
, &opts
, 0);
277 CU_ASSERT(ret_ctrlr
== &ctrlr
);
278 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.opts_size
, 0);
280 /* opts_size is less than sizeof(*opts) if opts != NULL */
281 ret_ctrlr
= spdk_nvme_connect(&trid
, &opts
, 4);
282 CU_ASSERT(ret_ctrlr
== &ctrlr
);
283 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.num_io_queues
, 1);
284 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.opts_size
, 4);
285 /* remove the attached ctrlr on the attached_list */
286 CU_ASSERT(spdk_nvme_detach(&ctrlr
) == 0);
287 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver
->shared_attached_ctrlrs
));
289 /* driver init passes, transport available, primary process connects ctrlr */
290 MOCK_SET(spdk_process_is_primary
, true);
291 /* setup one ctrlr on the attached_list */
292 memset(&ctrlr
, 0, sizeof(struct spdk_nvme_ctrlr
));
293 snprintf(ctrlr
.trid
.traddr
, sizeof(ctrlr
.trid
.traddr
), "0000:02:00.0");
294 ctrlr
.trid
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
295 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver
->shared_attached_ctrlrs
, &ctrlr
, tailq
);
296 /* get the ctrlr from the attached list */
297 snprintf(trid
.traddr
, sizeof(trid
.traddr
), "0000:02:00.0");
298 ret_ctrlr
= spdk_nvme_connect(&trid
, NULL
, 0);
299 CU_ASSERT(ret_ctrlr
== &ctrlr
);
300 /* get the ctrlr from the attached list with default ctrlr opts */
301 ctrlr
.opts
.num_io_queues
= DEFAULT_MAX_IO_QUEUES
;
302 ret_ctrlr
= spdk_nvme_connect(&trid
, NULL
, 0);
303 CU_ASSERT(ret_ctrlr
== &ctrlr
);
304 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.num_io_queues
, DEFAULT_MAX_IO_QUEUES
);
305 /* get the ctrlr from the attached list with default ctrlr opts and consistent opts_size */
306 opts
.num_io_queues
= 2;
307 ret_ctrlr
= spdk_nvme_connect(&trid
, &opts
, sizeof(opts
));
308 CU_ASSERT(ret_ctrlr
== &ctrlr
);
309 CU_ASSERT_EQUAL(ret_ctrlr
->opts
.num_io_queues
, 2);
310 /* remove the attached ctrlr on the attached_list */
311 CU_ASSERT(spdk_nvme_detach(ret_ctrlr
) == 0);
312 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver
->shared_attached_ctrlrs
));
314 /* test driver init failure return */
315 MOCK_SET(spdk_process_is_primary
, false);
316 MOCK_SET(spdk_memzone_lookup
, NULL
);
317 ret_ctrlr
= spdk_nvme_connect(&trid
, NULL
, 0);
318 CU_ASSERT(ret_ctrlr
== NULL
);
321 static struct spdk_nvme_probe_ctx
*
322 test_nvme_init_get_probe_ctx(void)
324 struct spdk_nvme_probe_ctx
*probe_ctx
;
326 probe_ctx
= calloc(1, sizeof(*probe_ctx
));
327 SPDK_CU_ASSERT_FATAL(probe_ctx
!= NULL
);
328 TAILQ_INIT(&probe_ctx
->init_ctrlrs
);
334 test_nvme_init_controllers(void)
337 struct nvme_driver test_driver
;
339 spdk_nvme_attach_cb attach_cb
= dummy_attach_cb
;
340 struct spdk_nvme_probe_ctx
*probe_ctx
;
341 struct spdk_nvme_ctrlr
*ctrlr
;
342 pthread_mutexattr_t attr
;
344 g_spdk_nvme_driver
= &test_driver
;
345 ctrlr
= calloc(1, sizeof(*ctrlr
));
346 SPDK_CU_ASSERT_FATAL(ctrlr
!= NULL
);
347 ctrlr
->trid
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
348 CU_ASSERT(pthread_mutexattr_init(&attr
) == 0);
349 CU_ASSERT(pthread_mutex_init(&test_driver
.lock
, &attr
) == 0);
350 TAILQ_INIT(&test_driver
.shared_attached_ctrlrs
);
353 * Try to initialize, but nvme_ctrlr_process_init will fail.
354 * Verify correct behavior when it does.
356 MOCK_SET(nvme_ctrlr_process_init
, 1);
357 MOCK_SET(spdk_process_is_primary
, 1);
358 g_spdk_nvme_driver
->initialized
= false;
359 ut_destruct_called
= false;
360 probe_ctx
= test_nvme_init_get_probe_ctx();
361 TAILQ_INSERT_TAIL(&probe_ctx
->init_ctrlrs
, ctrlr
, tailq
);
362 probe_ctx
->cb_ctx
= cb_ctx
;
363 probe_ctx
->attach_cb
= attach_cb
;
364 probe_ctx
->trid
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
365 rc
= nvme_init_controllers(probe_ctx
);
367 CU_ASSERT(g_spdk_nvme_driver
->initialized
== true);
368 CU_ASSERT(ut_destruct_called
== true);
371 * Controller init OK, need to move the controller state machine
372 * forward by setting the ctrl state so that it can be moved
373 * the shared_attached_ctrlrs list.
375 probe_ctx
= test_nvme_init_get_probe_ctx();
376 TAILQ_INSERT_TAIL(&probe_ctx
->init_ctrlrs
, ctrlr
, tailq
);
377 ctrlr
->state
= NVME_CTRLR_STATE_READY
;
378 MOCK_SET(nvme_ctrlr_process_init
, 0);
379 rc
= nvme_init_controllers(probe_ctx
);
381 CU_ASSERT(ut_attach_cb_called
== true);
382 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs
));
383 CU_ASSERT(TAILQ_FIRST(&g_spdk_nvme_driver
->shared_attached_ctrlrs
) == ctrlr
);
384 TAILQ_REMOVE(&g_spdk_nvme_driver
->shared_attached_ctrlrs
, ctrlr
, tailq
);
387 * Non-PCIe controllers should be added to the per-process list, not the shared list.
389 memset(ctrlr
, 0, sizeof(struct spdk_nvme_ctrlr
));
390 ctrlr
->trid
.trtype
= SPDK_NVME_TRANSPORT_RDMA
;
391 probe_ctx
= test_nvme_init_get_probe_ctx();
392 TAILQ_INSERT_TAIL(&probe_ctx
->init_ctrlrs
, ctrlr
, tailq
);
393 ctrlr
->state
= NVME_CTRLR_STATE_READY
;
394 MOCK_SET(nvme_ctrlr_process_init
, 0);
395 rc
= nvme_init_controllers(probe_ctx
);
397 CU_ASSERT(ut_attach_cb_called
== true);
398 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver
->shared_attached_ctrlrs
));
399 CU_ASSERT(TAILQ_FIRST(&g_nvme_attached_ctrlrs
) == ctrlr
);
400 TAILQ_REMOVE(&g_nvme_attached_ctrlrs
, ctrlr
, tailq
);
402 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs
));
404 g_spdk_nvme_driver
= NULL
;
405 pthread_mutexattr_destroy(&attr
);
406 pthread_mutex_destroy(&test_driver
.lock
);
410 test_nvme_driver_init(void)
413 struct nvme_driver dummy
;
414 g_spdk_nvme_driver
= &dummy
;
416 /* adjust this so testing doesn't take so long */
417 g_nvme_driver_timeout_ms
= 100;
419 /* process is primary and mem already reserved */
420 MOCK_SET(spdk_process_is_primary
, true);
421 dummy
.initialized
= true;
422 rc
= nvme_driver_init();
426 * Process is primary and mem not yet reserved but the call
427 * to spdk_memzone_reserve() returns NULL.
429 g_spdk_nvme_driver
= NULL
;
430 MOCK_SET(spdk_process_is_primary
, true);
431 MOCK_SET(spdk_memzone_reserve
, NULL
);
432 rc
= nvme_driver_init();
435 /* process is not primary, no mem already reserved */
436 MOCK_SET(spdk_process_is_primary
, false);
437 MOCK_SET(spdk_memzone_lookup
, NULL
);
438 g_spdk_nvme_driver
= NULL
;
439 rc
= nvme_driver_init();
442 /* process is not primary, mem is already reserved & init'd */
443 MOCK_SET(spdk_process_is_primary
, false);
444 MOCK_SET(spdk_memzone_lookup
, (void *)&dummy
);
445 dummy
.initialized
= true;
446 rc
= nvme_driver_init();
449 /* process is not primary, mem is reserved but not initialized */
451 MOCK_SET(spdk_process_is_primary
, false);
452 MOCK_SET(spdk_memzone_reserve
, (void *)&dummy
);
453 dummy
.initialized
= false;
454 rc
= nvme_driver_init();
457 /* process is primary, got mem but mutex won't init */
458 MOCK_SET(spdk_process_is_primary
, true);
459 MOCK_SET(spdk_memzone_reserve
, (void *)&dummy
);
460 MOCK_SET(pthread_mutexattr_init
, -1);
461 g_spdk_nvme_driver
= NULL
;
462 dummy
.initialized
= true;
463 rc
= nvme_driver_init();
464 /* for FreeBSD we can't can't effectively mock this path */
471 /* process is primary, got mem, mutex OK */
472 MOCK_SET(spdk_process_is_primary
, true);
473 MOCK_CLEAR(pthread_mutexattr_init
);
474 g_spdk_nvme_driver
= NULL
;
475 rc
= nvme_driver_init();
476 CU_ASSERT(g_spdk_nvme_driver
->initialized
== false);
477 CU_ASSERT(TAILQ_EMPTY(&g_spdk_nvme_driver
->shared_attached_ctrlrs
));
480 g_spdk_nvme_driver
= NULL
;
481 MOCK_CLEAR(spdk_memzone_reserve
);
482 MOCK_CLEAR(spdk_memzone_lookup
);
486 test_spdk_nvme_detach(void)
489 struct spdk_nvme_ctrlr ctrlr
;
490 struct spdk_nvme_ctrlr
*ret_ctrlr
;
491 struct nvme_driver test_driver
;
493 memset(&ctrlr
, 0, sizeof(ctrlr
));
494 ctrlr
.trid
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
496 g_spdk_nvme_driver
= &test_driver
;
497 TAILQ_INIT(&test_driver
.shared_attached_ctrlrs
);
498 TAILQ_INSERT_TAIL(&test_driver
.shared_attached_ctrlrs
, &ctrlr
, tailq
);
499 CU_ASSERT(pthread_mutex_init(&test_driver
.lock
, NULL
) == 0);
502 * Controllers are ref counted so mock the function that returns
503 * the ref count so that detach will actually call the destruct
504 * function which we've mocked simply to verify that it gets
505 * called (we aren't testing what the real destruct function does
508 MOCK_SET(nvme_ctrlr_get_ref_count
, 0);
509 rc
= spdk_nvme_detach(&ctrlr
);
510 ret_ctrlr
= TAILQ_FIRST(&test_driver
.shared_attached_ctrlrs
);
511 CU_ASSERT(ret_ctrlr
== NULL
);
512 CU_ASSERT(ut_destruct_called
== true);
516 * Mock the ref count to 1 so we confirm that the destruct
517 * function is not called and that attached ctrl list is
520 MOCK_SET(nvme_ctrlr_get_ref_count
, 1);
521 TAILQ_INSERT_TAIL(&test_driver
.shared_attached_ctrlrs
, &ctrlr
, tailq
);
522 ut_destruct_called
= false;
523 rc
= spdk_nvme_detach(&ctrlr
);
524 ret_ctrlr
= TAILQ_FIRST(&test_driver
.shared_attached_ctrlrs
);
525 CU_ASSERT(ret_ctrlr
!= NULL
);
526 CU_ASSERT(ut_destruct_called
== false);
530 * Non-PCIe controllers should be on the per-process attached_ctrlrs list, not the
531 * shared_attached_ctrlrs list. Test an RDMA controller and ensure it is removed
532 * from the correct list.
534 memset(&ctrlr
, 0, sizeof(ctrlr
));
535 ctrlr
.trid
.trtype
= SPDK_NVME_TRANSPORT_RDMA
;
536 TAILQ_INIT(&g_nvme_attached_ctrlrs
);
537 TAILQ_INSERT_TAIL(&g_nvme_attached_ctrlrs
, &ctrlr
, tailq
);
538 MOCK_SET(nvme_ctrlr_get_ref_count
, 0);
539 rc
= spdk_nvme_detach(&ctrlr
);
540 CU_ASSERT(TAILQ_EMPTY(&g_nvme_attached_ctrlrs
));
541 CU_ASSERT(ut_destruct_called
== true);
544 g_spdk_nvme_driver
= NULL
;
545 pthread_mutex_destroy(&test_driver
.lock
);
549 test_nvme_completion_poll_cb(void)
551 struct nvme_completion_poll_status
*status
;
552 struct spdk_nvme_cpl cpl
;
554 status
= calloc(1, sizeof(*status
));
555 SPDK_CU_ASSERT_FATAL(status
!= NULL
);
557 memset(&cpl
, 0xff, sizeof(cpl
));
559 nvme_completion_poll_cb(status
, &cpl
);
560 CU_ASSERT(status
->done
== true);
561 CU_ASSERT(memcmp(&cpl
, &status
->cpl
,
562 sizeof(struct spdk_nvme_cpl
)) == 0);
567 /* stub callback used by test_nvme_user_copy_cmd_complete() */
568 static struct spdk_nvme_cpl ut_spdk_nvme_cpl
= {0};
570 dummy_cb(void *user_cb_arg
, struct spdk_nvme_cpl
*cpl
)
572 ut_spdk_nvme_cpl
= *cpl
;
576 test_nvme_user_copy_cmd_complete(void)
578 struct nvme_request req
;
579 int test_data
= 0xdeadbeef;
580 int buff_size
= sizeof(int);
582 static struct spdk_nvme_cpl cpl
;
584 memset(&req
, 0, sizeof(req
));
585 memset(&cpl
, 0x5a, sizeof(cpl
));
587 /* test without a user buffer provided */
588 req
.user_cb_fn
= (void *)dummy_cb
;
589 nvme_user_copy_cmd_complete(&req
, &cpl
);
590 CU_ASSERT(memcmp(&ut_spdk_nvme_cpl
, &cpl
, sizeof(cpl
)) == 0);
592 /* test with a user buffer provided */
593 req
.user_buffer
= malloc(buff_size
);
594 SPDK_CU_ASSERT_FATAL(req
.user_buffer
!= NULL
);
595 memset(req
.user_buffer
, 0, buff_size
);
596 req
.payload_size
= buff_size
;
597 buff
= spdk_zmalloc(buff_size
, 0x100, NULL
, SPDK_ENV_LCORE_ID_ANY
, SPDK_MALLOC_DMA
);
598 SPDK_CU_ASSERT_FATAL(buff
!= NULL
);
599 req
.payload
= NVME_PAYLOAD_CONTIG(buff
, NULL
);
600 memcpy(buff
, &test_data
, buff_size
);
601 req
.cmd
.opc
= SPDK_NVME_OPC_GET_LOG_PAGE
;
604 /* zero out the test value set in the callback */
605 memset(&ut_spdk_nvme_cpl
, 0, sizeof(ut_spdk_nvme_cpl
));
607 nvme_user_copy_cmd_complete(&req
, &cpl
);
608 CU_ASSERT(memcmp(req
.user_buffer
, &test_data
, buff_size
) == 0);
609 CU_ASSERT(memcmp(&ut_spdk_nvme_cpl
, &cpl
, sizeof(cpl
)) == 0);
612 * Now test the same path as above but this time choose an opc
613 * that results in a different data transfer type.
615 memset(&ut_spdk_nvme_cpl
, 0, sizeof(ut_spdk_nvme_cpl
));
616 memset(req
.user_buffer
, 0, buff_size
);
617 buff
= spdk_zmalloc(buff_size
, 0x100, NULL
, SPDK_ENV_LCORE_ID_ANY
, SPDK_MALLOC_DMA
);
618 SPDK_CU_ASSERT_FATAL(buff
!= NULL
);
619 req
.payload
= NVME_PAYLOAD_CONTIG(buff
, NULL
);
620 memcpy(buff
, &test_data
, buff_size
);
621 req
.cmd
.opc
= SPDK_NVME_OPC_SET_FEATURES
;
622 nvme_user_copy_cmd_complete(&req
, &cpl
);
623 CU_ASSERT(memcmp(req
.user_buffer
, &test_data
, buff_size
) != 0);
624 CU_ASSERT(memcmp(&ut_spdk_nvme_cpl
, &cpl
, sizeof(cpl
)) == 0);
627 free(req
.user_buffer
);
631 test_nvme_allocate_request_null(void)
633 struct spdk_nvme_qpair qpair
;
634 spdk_nvme_cmd_cb cb_fn
= (spdk_nvme_cmd_cb
)0x1234;
635 void *cb_arg
= (void *)0x5678;
636 struct nvme_request
*req
= NULL
;
637 struct nvme_request dummy_req
;
639 STAILQ_INIT(&qpair
.free_req
);
640 STAILQ_INIT(&qpair
.queued_req
);
643 * Put a dummy on the queue so we can make a request
644 * and confirm that what comes back is what we expect.
646 STAILQ_INSERT_HEAD(&qpair
.free_req
, &dummy_req
, stailq
);
648 req
= nvme_allocate_request_null(&qpair
, cb_fn
, cb_arg
);
651 * Compare the req with the parmaters that we passed in
652 * as well as what the function is supposed to update.
654 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
655 CU_ASSERT(req
->cb_fn
== cb_fn
);
656 CU_ASSERT(req
->cb_arg
== cb_arg
);
657 CU_ASSERT(req
->pid
== getpid());
658 CU_ASSERT(nvme_payload_type(&req
->payload
) == NVME_PAYLOAD_TYPE_CONTIG
);
659 CU_ASSERT(req
->payload
.md
== NULL
);
660 CU_ASSERT(req
->payload
.contig_or_cb_arg
== NULL
);
664 test_nvme_allocate_request(void)
666 struct spdk_nvme_qpair qpair
;
667 struct nvme_payload payload
;
668 uint32_t payload_struct_size
= sizeof(payload
);
669 spdk_nvme_cmd_cb cb_fn
= (spdk_nvme_cmd_cb
)0x1234;
670 void *cb_arg
= (void *)0x6789;
671 struct nvme_request
*req
= NULL
;
672 struct nvme_request dummy_req
;
674 /* Fill the whole payload struct with a known pattern */
675 memset(&payload
, 0x5a, payload_struct_size
);
676 STAILQ_INIT(&qpair
.free_req
);
677 STAILQ_INIT(&qpair
.queued_req
);
679 /* Test trying to allocate a request when no requests are available */
680 req
= nvme_allocate_request(&qpair
, &payload
, payload_struct_size
, 0,
682 CU_ASSERT(req
== NULL
);
684 /* put a dummy on the queue, and then allocate one */
685 STAILQ_INSERT_HEAD(&qpair
.free_req
, &dummy_req
, stailq
);
686 req
= nvme_allocate_request(&qpair
, &payload
, payload_struct_size
, 0,
689 /* all the req elements should now match the passed in parameters */
690 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
691 CU_ASSERT(req
->cb_fn
== cb_fn
);
692 CU_ASSERT(req
->cb_arg
== cb_arg
);
693 CU_ASSERT(memcmp(&req
->payload
, &payload
, payload_struct_size
) == 0);
694 CU_ASSERT(req
->payload_size
== payload_struct_size
);
695 CU_ASSERT(req
->pid
== getpid());
699 test_nvme_free_request(void)
701 struct nvme_request match_req
;
702 struct spdk_nvme_qpair qpair
;
703 struct nvme_request
*req
;
705 /* put a req on the Q, take it off and compare */
706 memset(&match_req
.cmd
, 0x5a, sizeof(struct spdk_nvme_cmd
));
707 match_req
.qpair
= &qpair
;
708 /* the code under tests asserts this condition */
709 match_req
.num_children
= 0;
710 STAILQ_INIT(&qpair
.free_req
);
712 nvme_free_request(&match_req
);
713 req
= STAILQ_FIRST(&match_req
.qpair
->free_req
);
714 CU_ASSERT(req
== &match_req
);
718 test_nvme_allocate_request_user_copy(void)
720 struct spdk_nvme_qpair qpair
;
721 spdk_nvme_cmd_cb cb_fn
= (spdk_nvme_cmd_cb
)0x12345;
722 void *cb_arg
= (void *)0x12345;
723 bool host_to_controller
= true;
724 struct nvme_request
*req
;
725 struct nvme_request dummy_req
;
726 int test_data
= 0xdeadbeef;
728 uint32_t payload_size
= sizeof(int);
730 STAILQ_INIT(&qpair
.free_req
);
731 STAILQ_INIT(&qpair
.queued_req
);
733 /* no buffer or valid payload size, early NULL return */
734 req
= nvme_allocate_request_user_copy(&qpair
, buffer
, payload_size
, cb_fn
,
735 cb_arg
, host_to_controller
);
736 CU_ASSERT(req
== NULL
);
738 /* good buffer and valid payload size */
739 buffer
= malloc(payload_size
);
740 SPDK_CU_ASSERT_FATAL(buffer
!= NULL
);
741 memcpy(buffer
, &test_data
, payload_size
);
743 /* put a dummy on the queue */
744 STAILQ_INSERT_HEAD(&qpair
.free_req
, &dummy_req
, stailq
);
746 MOCK_CLEAR(spdk_malloc
);
747 MOCK_CLEAR(spdk_zmalloc
);
748 req
= nvme_allocate_request_user_copy(&qpair
, buffer
, payload_size
, cb_fn
,
749 cb_arg
, host_to_controller
);
750 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
751 CU_ASSERT(req
->user_cb_fn
== cb_fn
);
752 CU_ASSERT(req
->user_cb_arg
== cb_arg
);
753 CU_ASSERT(req
->user_buffer
== buffer
);
754 CU_ASSERT(req
->cb_arg
== req
);
755 CU_ASSERT(memcmp(req
->payload
.contig_or_cb_arg
, buffer
, payload_size
) == 0);
756 spdk_free(req
->payload
.contig_or_cb_arg
);
758 /* same thing but additional path coverage, no copy */
759 host_to_controller
= false;
760 STAILQ_INSERT_HEAD(&qpair
.free_req
, &dummy_req
, stailq
);
762 req
= nvme_allocate_request_user_copy(&qpair
, buffer
, payload_size
, cb_fn
,
763 cb_arg
, host_to_controller
);
764 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
765 CU_ASSERT(req
->user_cb_fn
== cb_fn
);
766 CU_ASSERT(req
->user_cb_arg
== cb_arg
);
767 CU_ASSERT(req
->user_buffer
== buffer
);
768 CU_ASSERT(req
->cb_arg
== req
);
769 CU_ASSERT(memcmp(req
->payload
.contig_or_cb_arg
, buffer
, payload_size
) != 0);
770 spdk_free(req
->payload
.contig_or_cb_arg
);
772 /* good buffer and valid payload size but make spdk_zmalloc fail */
773 /* set the mock pointer to NULL for spdk_zmalloc */
774 MOCK_SET(spdk_zmalloc
, NULL
);
775 req
= nvme_allocate_request_user_copy(&qpair
, buffer
, payload_size
, cb_fn
,
776 cb_arg
, host_to_controller
);
777 CU_ASSERT(req
== NULL
);
779 MOCK_CLEAR(spdk_zmalloc
);
783 test_nvme_ctrlr_probe(void)
786 struct spdk_nvme_ctrlr ctrlr
= {};
787 struct spdk_nvme_qpair qpair
= {};
788 const struct spdk_nvme_transport_id trid
= {};
789 struct spdk_nvme_probe_ctx probe_ctx
= {};
790 void *devhandle
= NULL
;
792 struct spdk_nvme_ctrlr
*dummy
= NULL
;
794 ctrlr
.adminq
= &qpair
;
796 TAILQ_INIT(&probe_ctx
.init_ctrlrs
);
799 /* test when probe_cb returns false */
801 MOCK_SET(dummy_probe_cb
, false);
802 nvme_probe_ctx_init(&probe_ctx
, &trid
, cb_ctx
, dummy_probe_cb
, NULL
, NULL
);
803 rc
= nvme_ctrlr_probe(&trid
, &probe_ctx
, devhandle
);
806 /* probe_cb returns true but we can't construct a ctrl */
807 MOCK_SET(dummy_probe_cb
, true);
808 MOCK_SET(nvme_transport_ctrlr_construct
, NULL
);
809 nvme_probe_ctx_init(&probe_ctx
, &trid
, cb_ctx
, dummy_probe_cb
, NULL
, NULL
);
810 rc
= nvme_ctrlr_probe(&trid
, &probe_ctx
, devhandle
);
814 MOCK_SET(dummy_probe_cb
, true);
815 MOCK_SET(nvme_transport_ctrlr_construct
, &ctrlr
);
816 nvme_probe_ctx_init(&probe_ctx
, &trid
, cb_ctx
, dummy_probe_cb
, NULL
, NULL
);
817 rc
= nvme_ctrlr_probe(&trid
, &probe_ctx
, devhandle
);
819 dummy
= TAILQ_FIRST(&probe_ctx
.init_ctrlrs
);
820 SPDK_CU_ASSERT_FATAL(dummy
!= NULL
);
821 CU_ASSERT(dummy
== ut_nvme_transport_ctrlr_construct
);
822 TAILQ_REMOVE(&probe_ctx
.init_ctrlrs
, dummy
, tailq
);
823 MOCK_CLEAR_P(nvme_transport_ctrlr_construct
);
825 free(g_spdk_nvme_driver
);
829 test_nvme_robust_mutex_init_shared(void)
834 /* test where both pthread calls succeed */
835 MOCK_SET(pthread_mutexattr_init
, 0);
836 MOCK_SET(pthread_mutex_init
, 0);
837 rc
= nvme_robust_mutex_init_shared(&mtx
);
840 /* test where we can't init attr's but init mutex works */
841 MOCK_SET(pthread_mutexattr_init
, -1);
842 MOCK_SET(pthread_mutex_init
, 0);
843 rc
= nvme_robust_mutex_init_shared(&mtx
);
844 /* for FreeBSD the only possible return value is 0 */
851 /* test where we can init attr's but the mutex init fails */
852 MOCK_SET(pthread_mutexattr_init
, 0);
853 MOCK_SET(pthread_mutex_init
, -1);
854 rc
= nvme_robust_mutex_init_shared(&mtx
);
855 /* for FreeBSD the only possible return value is 0 */
864 test_opc_data_transfer(void)
866 enum spdk_nvme_data_transfer xfer
;
868 xfer
= spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_FLUSH
);
869 CU_ASSERT(xfer
== SPDK_NVME_DATA_NONE
);
871 xfer
= spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_WRITE
);
872 CU_ASSERT(xfer
== SPDK_NVME_DATA_HOST_TO_CONTROLLER
);
874 xfer
= spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_READ
);
875 CU_ASSERT(xfer
== SPDK_NVME_DATA_CONTROLLER_TO_HOST
);
877 xfer
= spdk_nvme_opc_get_data_transfer(SPDK_NVME_OPC_GET_LOG_PAGE
);
878 CU_ASSERT(xfer
== SPDK_NVME_DATA_CONTROLLER_TO_HOST
);
882 test_trid_parse_and_compare(void)
884 struct spdk_nvme_transport_id trid1
, trid2
;
887 /* set trid1 trid2 value to id parse */
888 ret
= spdk_nvme_transport_id_parse(NULL
, "trtype:PCIe traddr:0000:04:00.0");
889 CU_ASSERT(ret
== -EINVAL
);
890 memset(&trid1
, 0, sizeof(trid1
));
891 ret
= spdk_nvme_transport_id_parse(&trid1
, NULL
);
892 CU_ASSERT(ret
== -EINVAL
);
893 ret
= spdk_nvme_transport_id_parse(NULL
, NULL
);
894 CU_ASSERT(ret
== -EINVAL
);
895 memset(&trid1
, 0, sizeof(trid1
));
896 ret
= spdk_nvme_transport_id_parse(&trid1
, "trtype-PCIe traddr-0000-04-00.0");
897 CU_ASSERT(ret
== -EINVAL
);
898 memset(&trid1
, 0, sizeof(trid1
));
899 ret
= spdk_nvme_transport_id_parse(&trid1
, "trtype-PCIe traddr-0000-04-00.0-:");
900 CU_ASSERT(ret
== -EINVAL
);
901 memset(&trid1
, 0, sizeof(trid1
));
902 ret
= spdk_nvme_transport_id_parse(&trid1
, " \t\n:");
903 CU_ASSERT(ret
== -EINVAL
);
904 memset(&trid1
, 0, sizeof(trid1
));
905 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1
,
908 "traddr:192.168.100.8\n"
910 "subnqn:nqn.2014-08.org.nvmexpress.discovery") == 0);
911 CU_ASSERT(trid1
.trtype
== SPDK_NVME_TRANSPORT_RDMA
);
912 CU_ASSERT(trid1
.adrfam
== SPDK_NVMF_ADRFAM_IPV4
);
913 CU_ASSERT(strcmp(trid1
.traddr
, "192.168.100.8") == 0);
914 CU_ASSERT(strcmp(trid1
.trsvcid
, "4420") == 0);
915 CU_ASSERT(strcmp(trid1
.subnqn
, "nqn.2014-08.org.nvmexpress.discovery") == 0);
917 memset(&trid2
, 0, sizeof(trid2
));
918 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2
, "trtype:PCIe traddr:0000:04:00.0") == 0);
919 CU_ASSERT(trid2
.trtype
== SPDK_NVME_TRANSPORT_PCIE
);
920 CU_ASSERT(strcmp(trid2
.traddr
, "0000:04:00.0") == 0);
922 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1
, &trid2
) != 0);
924 /* set trid1 trid2 and test id_compare */
925 memset_trid(&trid1
, &trid2
);
926 trid1
.adrfam
= SPDK_NVMF_ADRFAM_IPV6
;
927 trid2
.adrfam
= SPDK_NVMF_ADRFAM_IPV4
;
928 ret
= spdk_nvme_transport_id_compare(&trid1
, &trid2
);
931 memset_trid(&trid1
, &trid2
);
932 snprintf(trid1
.traddr
, sizeof(trid1
.traddr
), "192.168.100.8");
933 snprintf(trid2
.traddr
, sizeof(trid2
.traddr
), "192.168.100.9");
934 ret
= spdk_nvme_transport_id_compare(&trid1
, &trid2
);
937 memset_trid(&trid1
, &trid2
);
938 snprintf(trid1
.trsvcid
, sizeof(trid1
.trsvcid
), "4420");
939 snprintf(trid2
.trsvcid
, sizeof(trid2
.trsvcid
), "4421");
940 ret
= spdk_nvme_transport_id_compare(&trid1
, &trid2
);
943 memset_trid(&trid1
, &trid2
);
944 snprintf(trid1
.subnqn
, sizeof(trid1
.subnqn
), "subnqn:nqn.2016-08.org.nvmexpress.discovery");
945 snprintf(trid2
.subnqn
, sizeof(trid2
.subnqn
), "subnqn:nqn.2017-08.org.nvmexpress.discovery");
946 ret
= spdk_nvme_transport_id_compare(&trid1
, &trid2
);
949 memset_trid(&trid1
, &trid2
);
950 snprintf(trid1
.subnqn
, sizeof(trid1
.subnqn
), "subnqn:nqn.2016-08.org.nvmexpress.discovery");
951 snprintf(trid2
.subnqn
, sizeof(trid2
.subnqn
), "subnqn:nqn.2016-08.org.nvmexpress.discovery");
952 ret
= spdk_nvme_transport_id_compare(&trid1
, &trid2
);
955 memset_trid(&trid1
, &trid2
);
956 snprintf(trid1
.subnqn
, sizeof(trid1
.subnqn
), "subnqn:nqn.2016-08.org.nvmexpress.discovery");
957 snprintf(trid2
.subnqn
, sizeof(trid2
.subnqn
), "subnqn:nqn.2016-08.org.Nvmexpress.discovery");
958 ret
= spdk_nvme_transport_id_compare(&trid1
, &trid2
);
961 memset_trid(&trid1
, &trid2
);
962 ret
= spdk_nvme_transport_id_compare(&trid1
, &trid2
);
965 /* Compare PCI addresses via spdk_pci_addr_compare (rather than as strings) */
966 memset_trid(&trid1
, &trid2
);
967 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1
, "trtype:PCIe traddr:0000:04:00.0") == 0);
968 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2
, "trtype:PCIe traddr:04:00.0") == 0);
969 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1
, &trid2
) == 0);
971 memset_trid(&trid1
, &trid2
);
972 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1
, "trtype:PCIe traddr:0000:05:00.0") == 0);
973 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2
, "trtype:PCIe traddr:04:00.0") == 0);
974 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1
, &trid2
) > 0);
976 memset_trid(&trid1
, &trid2
);
977 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1
, "trtype:PCIe traddr:0000:04:00.0") == 0);
978 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2
, "trtype:PCIe traddr:05:00.0") == 0);
979 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1
, &trid2
) < 0);
981 memset_trid(&trid1
, &trid2
);
982 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1
, "trtype=PCIe traddr=0000:04:00.0") == 0);
983 CU_ASSERT(spdk_nvme_transport_id_parse(&trid2
, "trtype=PCIe traddr=05:00.0") == 0);
984 CU_ASSERT(spdk_nvme_transport_id_compare(&trid1
, &trid2
) < 0);
986 CU_ASSERT(spdk_nvme_transport_id_parse(&trid1
,
989 "traddr:192.168.100.8\n"
992 "subnqn:nqn.2014-08.org.nvmexpress.discovery") == 0);
993 CU_ASSERT(trid1
.priority
== 2);
997 test_spdk_nvme_transport_id_parse_trtype(void)
1000 enum spdk_nvme_transport_type
*trtype
;
1001 enum spdk_nvme_transport_type sct
;
1007 /* test function returned value when trtype is NULL but str not NULL */
1008 CU_ASSERT(spdk_nvme_transport_id_parse_trtype(trtype
, str
) == (-EINVAL
));
1010 /* test function returned value when str is NULL but trtype not NULL */
1013 CU_ASSERT(spdk_nvme_transport_id_parse_trtype(trtype
, str
) == (-EINVAL
));
1015 /* test function returned value when str and strtype not NULL, but str value
1016 * not "PCIe" or "RDMA" */
1018 CU_ASSERT(spdk_nvme_transport_id_parse_trtype(trtype
, str
) == 0);
1019 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_CUSTOM
);
1021 /* test trtype value when use function "strcasecmp" to compare str and "PCIe",not case-sensitive */
1023 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1024 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_PCIE
);
1027 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1028 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_PCIE
);
1030 /* test trtype value when use function "strcasecmp" to compare str and "RDMA",not case-sensitive */
1032 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1033 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_RDMA
);
1036 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1037 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_RDMA
);
1039 /* test trtype value when use function "strcasecmp" to compare str and "FC",not case-sensitive */
1041 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1042 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_FC
);
1045 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1046 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_FC
);
1048 /* test trtype value when use function "strcasecmp" to compare str and "TCP",not case-sensitive */
1050 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1051 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_TCP
);
1054 spdk_nvme_transport_id_parse_trtype(trtype
, str
);
1055 CU_ASSERT((*trtype
) == SPDK_NVME_TRANSPORT_TCP
);
1059 test_spdk_nvme_transport_id_parse_adrfam(void)
1062 enum spdk_nvmf_adrfam
*adrfam
;
1063 enum spdk_nvmf_adrfam sct
;
1069 /* test function returned value when adrfam is NULL but str not NULL */
1070 CU_ASSERT(spdk_nvme_transport_id_parse_adrfam(adrfam
, str
) == (-EINVAL
));
1072 /* test function returned value when str is NULL but adrfam not NULL */
1075 CU_ASSERT(spdk_nvme_transport_id_parse_adrfam(adrfam
, str
) == (-EINVAL
));
1077 /* test function returned value when str and adrfam not NULL, but str value
1078 * not "IPv4" or "IPv6" or "IB" or "FC" */
1080 CU_ASSERT(spdk_nvme_transport_id_parse_adrfam(adrfam
, str
) == (-ENOENT
));
1082 /* test adrfam value when use function "strcasecmp" to compare str and "IPv4",not case-sensitive */
1084 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1085 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_IPV4
);
1088 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1089 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_IPV4
);
1091 /* test adrfam value when use function "strcasecmp" to compare str and "IPv6",not case-sensitive */
1093 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1094 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_IPV6
);
1097 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1098 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_IPV6
);
1100 /* test adrfam value when use function "strcasecmp" to compare str and "IB",not case-sensitive */
1102 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1103 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_IB
);
1106 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1107 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_IB
);
1109 /* test adrfam value when use function "strcasecmp" to compare str and "FC",not case-sensitive */
1111 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1112 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_FC
);
1115 spdk_nvme_transport_id_parse_adrfam(adrfam
, str
);
1116 CU_ASSERT((*adrfam
) == SPDK_NVMF_ADRFAM_FC
);
1121 test_trid_trtype_str(void)
1125 s
= spdk_nvme_transport_id_trtype_str(-5);
1126 CU_ASSERT(s
== NULL
);
1128 s
= spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_PCIE
);
1129 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1130 CU_ASSERT(strcmp(s
, "PCIe") == 0);
1132 s
= spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA
);
1133 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1134 CU_ASSERT(strcmp(s
, "RDMA") == 0);
1136 s
= spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_FC
);
1137 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1138 CU_ASSERT(strcmp(s
, "FC") == 0);
1140 s
= spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_TCP
);
1141 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1142 CU_ASSERT(strcmp(s
, "TCP") == 0);
1146 test_trid_adrfam_str(void)
1150 s
= spdk_nvme_transport_id_adrfam_str(-5);
1151 CU_ASSERT(s
== NULL
);
1153 s
= spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_IPV4
);
1154 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1155 CU_ASSERT(strcmp(s
, "IPv4") == 0);
1157 s
= spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_IPV6
);
1158 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1159 CU_ASSERT(strcmp(s
, "IPv6") == 0);
1161 s
= spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_IB
);
1162 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1163 CU_ASSERT(strcmp(s
, "IB") == 0);
1165 s
= spdk_nvme_transport_id_adrfam_str(SPDK_NVMF_ADRFAM_FC
);
1166 SPDK_CU_ASSERT_FATAL(s
!= NULL
);
1167 CU_ASSERT(strcmp(s
, "FC") == 0);
1170 /* stub callback used by the test_nvme_request_check_timeout */
1171 static bool ut_timeout_cb_call
= false;
1173 dummy_timeout_cb(void *cb_arg
, struct spdk_nvme_ctrlr
*ctrlr
,
1174 struct spdk_nvme_qpair
*qpair
, uint16_t cid
)
1176 ut_timeout_cb_call
= true;
1180 test_nvme_request_check_timeout(void)
1183 struct spdk_nvme_qpair qpair
;
1184 struct nvme_request req
;
1185 struct spdk_nvme_ctrlr_process active_proc
;
1187 uint64_t now_tick
= 0;
1189 memset(&qpair
, 0x0, sizeof(qpair
));
1190 memset(&req
, 0x0, sizeof(req
));
1191 memset(&active_proc
, 0x0, sizeof(active_proc
));
1193 active_proc
.timeout_cb_fn
= dummy_timeout_cb
;
1195 /* if have called timeout_cb_fn then return directly */
1196 req
.timed_out
= true;
1197 rc
= nvme_request_check_timeout(&req
, cid
, &active_proc
, now_tick
);
1199 CU_ASSERT(ut_timeout_cb_call
== false);
1201 /* if timeout isn't enabled then return directly */
1202 req
.timed_out
= false;
1203 req
.submit_tick
= 0;
1204 rc
= nvme_request_check_timeout(&req
, cid
, &active_proc
, now_tick
);
1206 CU_ASSERT(ut_timeout_cb_call
== false);
1208 /* req->pid isn't right then return directly */
1209 req
.submit_tick
= 1;
1210 req
.pid
= g_spdk_nvme_pid
+ 1;
1211 rc
= nvme_request_check_timeout(&req
, cid
, &active_proc
, now_tick
);
1213 CU_ASSERT(ut_timeout_cb_call
== false);
1215 /* AER command has no timeout */
1216 req
.pid
= g_spdk_nvme_pid
;
1217 req
.cmd
.opc
= SPDK_NVME_OPC_ASYNC_EVENT_REQUEST
;
1218 rc
= nvme_request_check_timeout(&req
, cid
, &active_proc
, now_tick
);
1220 CU_ASSERT(ut_timeout_cb_call
== false);
1222 /* time isn't out */
1224 rc
= nvme_request_check_timeout(&req
, cid
, &active_proc
, now_tick
);
1226 CU_ASSERT(ut_timeout_cb_call
== false);
1229 rc
= nvme_request_check_timeout(&req
, cid
, &active_proc
, now_tick
);
1230 CU_ASSERT(req
.timed_out
== true);
1231 CU_ASSERT(ut_timeout_cb_call
== true);
1235 struct nvme_completion_poll_status g_status
;
1236 uint64_t completion_delay
, timeout_in_secs
;
1237 int g_process_comp_result
;
1240 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair
*qpair
, uint32_t max_completions
)
1242 spdk_delay_us(completion_delay
* spdk_get_ticks_hz());
1244 g_status
.done
= completion_delay
< timeout_in_secs
&& g_process_comp_result
== 0 ? true : false;
1246 return g_process_comp_result
;
1250 test_nvme_wait_for_completion(void)
1252 struct spdk_nvme_qpair qpair
;
1255 memset(&qpair
, 0, sizeof(qpair
));
1257 /* completion timeout */
1258 memset(&g_status
, 0, sizeof(g_status
));
1259 completion_delay
= 2;
1260 timeout_in_secs
= 1;
1261 rc
= nvme_wait_for_completion_timeout(&qpair
, &g_status
, timeout_in_secs
);
1262 CU_ASSERT(g_status
.timed_out
== true);
1263 CU_ASSERT(g_status
.done
== false);
1264 CU_ASSERT(rc
== -ECANCELED
);
1266 /* spdk_nvme_qpair_process_completions returns error */
1267 memset(&g_status
, 0, sizeof(g_status
));
1268 g_process_comp_result
= -1;
1269 completion_delay
= 1;
1270 timeout_in_secs
= 2;
1271 rc
= nvme_wait_for_completion_timeout(&qpair
, &g_status
, timeout_in_secs
);
1272 CU_ASSERT(rc
== -ECANCELED
);
1273 CU_ASSERT(g_status
.timed_out
== true);
1274 CU_ASSERT(g_status
.done
== false);
1275 CU_ASSERT(g_status
.cpl
.status
.sct
== SPDK_NVME_SCT_GENERIC
);
1276 CU_ASSERT(g_status
.cpl
.status
.sc
== SPDK_NVME_SC_ABORTED_SQ_DELETION
);
1278 g_process_comp_result
= 0;
1280 /* complete in time */
1281 memset(&g_status
, 0, sizeof(g_status
));
1282 completion_delay
= 1;
1283 timeout_in_secs
= 2;
1284 rc
= nvme_wait_for_completion_timeout(&qpair
, &g_status
, timeout_in_secs
);
1285 CU_ASSERT(g_status
.timed_out
== false);
1286 CU_ASSERT(g_status
.done
== true);
1289 /* nvme_wait_for_completion */
1290 /* spdk_nvme_qpair_process_completions returns error */
1291 memset(&g_status
, 0, sizeof(g_status
));
1292 g_process_comp_result
= -1;
1293 rc
= nvme_wait_for_completion(&qpair
, &g_status
);
1294 CU_ASSERT(rc
== -ECANCELED
);
1295 CU_ASSERT(g_status
.timed_out
== true);
1296 CU_ASSERT(g_status
.done
== false);
1297 CU_ASSERT(g_status
.cpl
.status
.sct
== SPDK_NVME_SCT_GENERIC
);
1298 CU_ASSERT(g_status
.cpl
.status
.sc
== SPDK_NVME_SC_ABORTED_SQ_DELETION
);
1300 /* successful completion */
1301 memset(&g_status
, 0, sizeof(g_status
));
1302 g_process_comp_result
= 0;
1303 rc
= nvme_wait_for_completion(&qpair
, &g_status
);
1305 CU_ASSERT(g_status
.timed_out
== false);
1306 CU_ASSERT(g_status
.done
== true);
1310 test_nvme_ctrlr_probe_internal(void)
1312 struct spdk_nvme_probe_ctx
*probe_ctx
;
1313 struct spdk_nvme_transport_id trid
= {};
1314 struct nvme_driver dummy
;
1317 probe_ctx
= calloc(1, sizeof(*probe_ctx
));
1318 CU_ASSERT(probe_ctx
!= NULL
);
1320 MOCK_SET(spdk_process_is_primary
, true);
1321 MOCK_SET(spdk_memzone_reserve
, (void *)&dummy
);
1322 g_spdk_nvme_driver
= NULL
;
1323 rc
= nvme_driver_init();
1326 ut_test_probe_internal
= true;
1327 MOCK_SET(dummy_probe_cb
, true);
1328 trid
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
1329 nvme_probe_ctx_init(probe_ctx
, &trid
, NULL
, dummy_probe_cb
, NULL
, NULL
);
1330 rc
= nvme_probe_internal(probe_ctx
, false);
1332 CU_ASSERT(TAILQ_EMPTY(&probe_ctx
->init_ctrlrs
));
1335 ut_test_probe_internal
= false;
1338 int main(int argc
, char **argv
)
1340 CU_pSuite suite
= NULL
;
1341 unsigned int num_failures
;
1343 CU_set_error_action(CUEA_ABORT
);
1344 CU_initialize_registry();
1346 suite
= CU_add_suite("nvme", NULL
, NULL
);
1348 CU_ADD_TEST(suite
, test_opc_data_transfer
);
1349 CU_ADD_TEST(suite
, test_spdk_nvme_transport_id_parse_trtype
);
1350 CU_ADD_TEST(suite
, test_spdk_nvme_transport_id_parse_adrfam
);
1351 CU_ADD_TEST(suite
, test_trid_parse_and_compare
);
1352 CU_ADD_TEST(suite
, test_trid_trtype_str
);
1353 CU_ADD_TEST(suite
, test_trid_adrfam_str
);
1354 CU_ADD_TEST(suite
, test_nvme_ctrlr_probe
);
1355 CU_ADD_TEST(suite
, test_spdk_nvme_probe
);
1356 CU_ADD_TEST(suite
, test_spdk_nvme_connect
);
1357 CU_ADD_TEST(suite
, test_nvme_ctrlr_probe_internal
);
1358 CU_ADD_TEST(suite
, test_nvme_init_controllers
);
1359 CU_ADD_TEST(suite
, test_nvme_driver_init
);
1360 CU_ADD_TEST(suite
, test_spdk_nvme_detach
);
1361 CU_ADD_TEST(suite
, test_nvme_completion_poll_cb
);
1362 CU_ADD_TEST(suite
, test_nvme_user_copy_cmd_complete
);
1363 CU_ADD_TEST(suite
, test_nvme_allocate_request_null
);
1364 CU_ADD_TEST(suite
, test_nvme_allocate_request
);
1365 CU_ADD_TEST(suite
, test_nvme_free_request
);
1366 CU_ADD_TEST(suite
, test_nvme_allocate_request_user_copy
);
1367 CU_ADD_TEST(suite
, test_nvme_robust_mutex_init_shared
);
1368 CU_ADD_TEST(suite
, test_nvme_request_check_timeout
);
1369 CU_ADD_TEST(suite
, test_nvme_wait_for_completion
);
1371 CU_basic_set_mode(CU_BRM_VERBOSE
);
1372 CU_basic_run_tests();
1373 num_failures
= CU_get_number_of_failures();
1374 CU_cleanup_registry();
1375 return num_failures
;