diff --git a/test/lib/test_env.c b/test/lib/test_env.c index f2f5727ef..d649fa126 100644 --- a/test/lib/test_env.c +++ b/test/lib/test_env.c @@ -33,8 +33,22 @@ #include "spdk/stdinc.h" +#include "spdk_internal/mock.h" + #include "spdk/env.h" +/* + * NOTE: + * Functions in this file are mocks for SPDK based functions + * and work conceptually in the same way that mocks work in + * /lib/ut_mock. However, the globals that control the behavior + * of the mock are defined here, with each function, as + * opposed to being defined as part of the macro that defines + * the stub or wrapper for other types of functions. Be sure + * to use the correct global variable naming convention when + * working with these functions. See /lib/ut_mock for details. + */ + void * spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr) { @@ -48,15 +62,22 @@ spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr) return buf; } +int ut_spdk_dma_zmalloc = (int)MOCK_PASS_THRU; +void *ut_p_spdk_dma_zmalloc = &ut_spdk_dma_zmalloc; void * spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr) { - void *buf = spdk_dma_malloc(size, align, phys_addr); + if (ut_p_spdk_dma_zmalloc && + ut_spdk_dma_zmalloc == (int)MOCK_PASS_THRU) { + void *buf = spdk_dma_malloc(size, align, phys_addr); - if (buf != NULL) { - memset(buf, 0, size); + if (buf != NULL) { + memset(buf, 0, size); + } + return buf; + } else { + return ut_p_spdk_dma_zmalloc; } - return buf; } void * @@ -79,7 +100,10 @@ spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr) void spdk_dma_free(void *buf) { - free(buf); + if (ut_p_spdk_dma_zmalloc && + ut_spdk_dma_zmalloc == (int)MOCK_PASS_THRU) { + free(buf); + } } bool ut_fail_vtophys = false; diff --git a/test/unit/lib/nvme/nvme.c/nvme_ut.c b/test/unit/lib/nvme/nvme.c/nvme_ut.c index ab3647334..f4788246a 100644 --- a/test/unit/lib/nvme/nvme.c/nvme_ut.c +++ b/test/unit/lib/nvme/nvme.c/nvme_ut.c @@ -108,6 +108,68 @@ memset_trid(struct spdk_nvme_transport_id *trid1, struct spdk_nvme_transport_id memset(trid2, 0, sizeof(struct spdk_nvme_transport_id)); } +static void +test_nvme_allocate_request_user_copy(void) +{ + struct spdk_nvme_qpair qpair; + spdk_nvme_cmd_cb cb_fn = (spdk_nvme_cmd_cb)0x12345; + void *cb_arg = (void *)0x12345; + bool host_to_controller = true; + struct nvme_request *req; + struct nvme_request dummy_req; + int test_data = 0xdeadbeef; + void *buffer = NULL; + uint32_t payload_size = sizeof(int); + + STAILQ_INIT(&qpair.free_req); + STAILQ_INIT(&qpair.queued_req); + + /* no buffer or valid payload size, early NULL return */ + req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, + cb_arg, host_to_controller); + CU_ASSERT(req == NULL); + + /* good buffer and valid payload size */ + buffer = malloc(payload_size); + SPDK_CU_ASSERT_FATAL(buffer != NULL); + memcpy(buffer, &test_data, payload_size); + + /* put a dummy on the queue */ + STAILQ_INSERT_HEAD(&qpair.free_req, &dummy_req, stailq); + + req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, + cb_arg, host_to_controller); + CU_ASSERT(req->user_cb_fn == cb_fn); + CU_ASSERT(req->user_cb_arg == cb_arg); + CU_ASSERT(req->user_buffer == buffer); + CU_ASSERT(req->cb_arg == req); + CU_ASSERT(memcmp(req->payload.u.contig, buffer, payload_size) == 0); + spdk_dma_free(req->payload.u.contig); + + /* same thing but additional path coverage, no copy */ + host_to_controller = false; + STAILQ_INSERT_HEAD(&qpair.free_req, &dummy_req, stailq); + + req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, + cb_arg, host_to_controller); + CU_ASSERT(req->user_cb_fn == cb_fn); + CU_ASSERT(req->user_cb_arg == cb_arg); + CU_ASSERT(req->user_buffer == buffer); + CU_ASSERT(req->cb_arg == req); + CU_ASSERT(memcmp(req->payload.u.contig, buffer, payload_size) != 0); + spdk_dma_free(req->payload.u.contig); + + /* good buffer and valid payload size but make spdk_dma_zmalloc fail */ + /* set the mock pointer to NULL for spdk_dma_zmalloc */ + MOCK_SET_P(spdk_dma_zmalloc, void *, NULL); + req = nvme_allocate_request_user_copy(&qpair, buffer, payload_size, cb_fn, + cb_arg, host_to_controller); + CU_ASSERT(req == NULL); + free(buffer); + /* restore mock function back to the way it was */ + MOCK_SET_P(spdk_dma_zmalloc, void *, &ut_spdk_dma_zmalloc); +} + static void test_nvme_ctrlr_probe(void) { @@ -460,6 +522,8 @@ int main(int argc, char **argv) test_trid_adrfam_str) == NULL || CU_add_test(suite, "test_nvme_ctrlr_probe", test_nvme_ctrlr_probe) == NULL || + CU_add_test(suite, "test_nvme_allocate_request_user_copy", + test_nvme_allocate_request_user_copy) == NULL || CU_add_test(suite, "test_nvme_robust_mutex_init_shared", test_nvme_robust_mutex_init_shared) == NULL ) {