From 043d541132d566d7340d20dbed8da6bae3c1300e Mon Sep 17 00:00:00 2001 From: Paul Luse Date: Mon, 19 Jun 2017 13:58:28 -0700 Subject: [PATCH] tests: macro-ize the creation and use of wrappers and stubs Includes macros for wrappers (for syscalls) and stubs (for SPDK functions) including an example of syscall wrapper as well as a stub with both pointer and non pointer values. Change-Id: I9b19d81d5b9cbf2bbb327f58dbf985b3b253e800 Signed-off-by: Paul Luse Reviewed-on: https://review.gerrithub.io/366348 Reviewed-by: Jim Harris Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp --- include/spdk_internal/{spdk_mock.h => mock.h} | 59 ++++++++++++-- lib/ut_mock/Makefile | 2 +- lib/ut_mock/{spdk_mock.c => mock.c} | 27 ++----- test/unit/lib/nvme/nvme.c/nvme_ut.c | 78 +++++++++++++++---- 4 files changed, 123 insertions(+), 43 deletions(-) rename include/spdk_internal/{spdk_mock.h => mock.h} (59%) rename lib/ut_mock/{spdk_mock.c => mock.c} (75%) diff --git a/include/spdk_internal/spdk_mock.h b/include/spdk_internal/mock.h similarity index 59% rename from include/spdk_internal/spdk_mock.h rename to include/spdk_internal/mock.h index 4666a3bb0..34f17b9eb 100644 --- a/include/spdk_internal/spdk_mock.h +++ b/include/spdk_internal/mock.h @@ -36,15 +36,64 @@ #include "spdk/stdinc.h" -#define DECLARE_WRAPPER(fn, ret, args) \ - ret __wrap_ ## fn args; ret __real_ ## fn args; +/* used to signify pass through */ +#define MOCK_PASS_THRU (0xdeadbeef) -/* define new wrappers (alphabetically please) here using above helper macro */ -extern int ut_fake_pthread_mutex_init; +/* for controlling mocked function behavior, setting */ +/* and getting values from the stub, the _P macros are */ +/* for mocking functions that return pointer values */ +#define MOCK_SET(fn, ret, val) \ + ut_ ## fn = (ret){val}; + +#define MOCK_SET_P(fn, ret, val) \ + ut_p_ ## fn = (ret){val}; + +#define MOCK_GET(fn) \ + ut_ ## fn + +#define MOCK_GET_P(fn) \ + ut_p_ ## fn + +/* for declaring function protoypes for wrappers */ +#define DECLARE_WRAPPER(fn, ret, args) \ + extern ret ut_ ## fn; \ + ret __wrap_ ## fn args; ret __real_ ## fn args; + +/* for defining the implmentation of wrappers for syscalls */ +#define DEFINE_WRAPPER(fn, ret, dargs, pargs, val) \ + ret ut_ ## fn = val; \ + ret __wrap_ ## fn dargs \ + { \ + if (ut_ ## fn == (ret)MOCK_PASS_THRU) { \ + return __real_ ## fn pargs; \ + } else { \ + return MOCK_GET(fn); \ + } \ + } + +/* for defining the implmentation of stubs for SPDK funcs */ +/* the _P macro is for stubs that return pointer values */ +#define DEFINE_STUB(fn, ret, dargs, val) \ + ret ut_ ## fn = val; \ + ret fn dargs; \ + ret fn dargs \ + { \ + return MOCK_GET(fn); \ + } + +#define DEFINE_STUB_P(fn, ret, dargs, val) \ + ret ut_ ## fn = val; \ + ret* ut_p_ ## fn = &(ut_ ## fn); \ + ret* fn dargs; \ + ret* fn dargs \ + { \ + return MOCK_GET_P(fn); \ + } + +/* declare wrapper protos (alphabetically please) here */ DECLARE_WRAPPER(pthread_mutex_init, int, (pthread_mutex_t *mtx, const pthread_mutexattr_t *attr)); -extern int ut_fake_pthread_mutexattr_init; DECLARE_WRAPPER(pthread_mutexattr_init, int, (pthread_mutexattr_t *attr)); diff --git a/lib/ut_mock/Makefile b/lib/ut_mock/Makefile index 3efb57f7e..995841810 100644 --- a/lib/ut_mock/Makefile +++ b/lib/ut_mock/Makefile @@ -34,7 +34,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -C_SRCS = spdk_mock.c +C_SRCS = mock.c LIBNAME = spdk_mock include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk diff --git a/lib/ut_mock/spdk_mock.c b/lib/ut_mock/mock.c similarity index 75% rename from lib/ut_mock/spdk_mock.c rename to lib/ut_mock/mock.c index 3826a7539..118ff6749 100644 --- a/lib/ut_mock/spdk_mock.c +++ b/lib/ut_mock/mock.c @@ -31,26 +31,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "spdk_internal/spdk_mock.h" +#include "spdk_internal/mock.h" -int ut_fake_pthread_mutex_init = 0; -int -__wrap_pthread_mutex_init(pthread_mutex_t *mtx, const pthread_mutexattr_t *attr) -{ - if (ut_fake_pthread_mutex_init == 0) { - return __real_pthread_mutex_init(mtx, attr); - } else { - return ut_fake_pthread_mutex_init; - } -} +DEFINE_WRAPPER(pthread_mutex_init, int, + (pthread_mutex_t *mtx, const pthread_mutexattr_t *attr), + (mtx, attr), MOCK_PASS_THRU) -int ut_fake_pthread_mutexattr_init = 0; -int -__wrap_pthread_mutexattr_init(pthread_mutexattr_t *attr) -{ - if (ut_fake_pthread_mutexattr_init == 0) { - return __real_pthread_mutexattr_init(attr); - } else { - return ut_fake_pthread_mutexattr_init; - } -} +DEFINE_WRAPPER(pthread_mutexattr_init, int, + (pthread_mutexattr_t *attr), (attr), MOCK_PASS_THRU) diff --git a/test/unit/lib/nvme/nvme.c/nvme_ut.c b/test/unit/lib/nvme/nvme.c/nvme_ut.c index 059a86d91..cd65059a0 100644 --- a/test/unit/lib/nvme/nvme.c/nvme_ut.c +++ b/test/unit/lib/nvme/nvme.c/nvme_ut.c @@ -39,7 +39,7 @@ #include "lib/test_env.c" -#include "spdk_internal/spdk_mock.h" +#include "spdk_internal/mock.h" int spdk_pci_nvme_enumerate(spdk_pci_enum_cb enum_cb, void *enum_ctx) @@ -63,13 +63,6 @@ spdk_nvme_transport_available(enum spdk_nvme_transport_type trtype) return true; } -struct spdk_nvme_ctrlr *nvme_transport_ctrlr_construct(const struct spdk_nvme_transport_id *trid, - const struct spdk_nvme_ctrlr_opts *opts, - void *devhandle) -{ - return NULL; -} - int nvme_transport_ctrlr_scan(const struct spdk_nvme_transport_id *trid, void *cb_ctx, @@ -153,19 +146,66 @@ memset_trid(struct spdk_nvme_transport_id *trid1, struct spdk_nvme_transport_id memset(trid2, 0, sizeof(struct spdk_nvme_transport_id)); } +DEFINE_STUB_P(nvme_transport_ctrlr_construct, struct spdk_nvme_ctrlr, + (const struct spdk_nvme_transport_id *trid, + const struct spdk_nvme_ctrlr_opts *opts, + void *devhandle), {0}) + +DEFINE_STUB(dummy_probe_cb, bool, + (void *cb_ctx, const struct spdk_nvme_transport_id *trid, + struct spdk_nvme_ctrlr_opts *opts), false) + +static void +test_nvme_ctrlr_probe(void) +{ + int rc = 0; + const struct spdk_nvme_transport_id *trid = NULL; + void *devhandle = NULL; + void *cb_ctx = NULL; + struct spdk_nvme_ctrlr *dummy = NULL; + + /* test when probe_cb returns false */ + MOCK_SET(dummy_probe_cb, bool, false) + rc = nvme_ctrlr_probe(trid, devhandle, dummy_probe_cb, cb_ctx); + CU_ASSERT(rc == 1); + + /* probe_cb returns true but we can't construct a ctrl */ + MOCK_SET(dummy_probe_cb, bool, true) + MOCK_SET_P(nvme_transport_ctrlr_construct, + struct spdk_nvme_ctrlr *, NULL) + rc = nvme_ctrlr_probe(trid, devhandle, dummy_probe_cb, cb_ctx); + CU_ASSERT(rc == -1); + + /* happy path */ + g_spdk_nvme_driver = malloc(sizeof(struct nvme_driver)); + SPDK_CU_ASSERT_FATAL(g_spdk_nvme_driver != NULL); + MOCK_SET(dummy_probe_cb, bool, true) + MOCK_SET_P(nvme_transport_ctrlr_construct, + struct spdk_nvme_ctrlr *, &ut_nvme_transport_ctrlr_construct); + TAILQ_INIT(&g_spdk_nvme_driver->init_ctrlrs); + rc = nvme_ctrlr_probe(trid, devhandle, dummy_probe_cb, cb_ctx); + CU_ASSERT(rc == 0); + dummy = TAILQ_FIRST(&g_spdk_nvme_driver->init_ctrlrs); + CU_ASSERT(dummy == &ut_nvme_transport_ctrlr_construct); + + free(g_spdk_nvme_driver); +} + static void test_nvme_robust_mutex_init_shared(void) { pthread_mutex_t mtx; int rc = 0; - ut_fake_pthread_mutexattr_init = 0; - ut_fake_pthread_mutex_init = 0; + /* test where both pthread calls succeed */ + MOCK_SET(pthread_mutexattr_init, int, 0) + MOCK_SET(pthread_mutex_init, int, 0) rc = nvme_robust_mutex_init_shared(&mtx); CU_ASSERT(rc == 0); - ut_fake_pthread_mutexattr_init = -1; - ut_fake_pthread_mutex_init = 0; + /* test where we can't init attr's but init mutex works */ + MOCK_SET(pthread_mutexattr_init, int, -1) + MOCK_SET(pthread_mutex_init, int, 0) rc = nvme_robust_mutex_init_shared(&mtx); /* for FreeBSD the only possible return value is 0 */ #ifndef __FreeBSD__ @@ -174,9 +214,11 @@ test_nvme_robust_mutex_init_shared(void) CU_ASSERT(rc == 0); #endif - ut_fake_pthread_mutexattr_init = 0; - ut_fake_pthread_mutex_init = -1; + /* test where we can init attr's but the mutex init fails */ + MOCK_SET(pthread_mutexattr_init, int, 0) + MOCK_SET(pthread_mutex_init, int, -1) rc = nvme_robust_mutex_init_shared(&mtx); + /* for FreeBSD the only possible return value is 0 */ #ifndef __FreeBSD__ CU_ASSERT(rc != 0); #else @@ -447,8 +489,12 @@ int main(int argc, char **argv) test_spdk_nvme_transport_id_parse_adrfam) == NULL || CU_add_test(suite, "test_trid_parse_and_compare", test_trid_parse_and_compare) == NULL || - CU_add_test(suite, "test_trid_trtype_str", test_trid_trtype_str) == NULL || - CU_add_test(suite, "test_trid_adrfam_str", test_trid_adrfam_str) == NULL || + CU_add_test(suite, "test_trid_trtype_str", + test_trid_trtype_str) == NULL || + CU_add_test(suite, "test_trid_adrfam_str", + test_trid_adrfam_str) == NULL || + CU_add_test(suite, "test_nvme_ctrlr_probe", + test_nvme_ctrlr_probe) == NULL || CU_add_test(suite, "test_nvme_robust_mutex_init_shared", test_nvme_robust_mutex_init_shared) == NULL ) {