diff --git a/src/include/daos_srv/dlck.h b/src/include/daos_srv/dlck.h index bcd19874820..f7ef07eccbd 100644 --- a/src/include/daos_srv/dlck.h +++ b/src/include/daos_srv/dlck.h @@ -70,4 +70,23 @@ dlck_dtx_act_recs_remove(daos_handle_t coh); int dlck_dtx_act_recs_set(daos_handle_t coh, d_vector_t *dv); +#ifdef DLCK_UT_BUILD +#define DLCK_STATIC +#else +#define DLCK_STATIC static +#endif + +/** + * \struct dlck_iter_bundle + * + * \brief A bundle of arguments passed to vos_iterate() by the DLCK interfaces. + * + * Exposed for testing purposes. + */ +struct dlck_iter_bundle { + daos_handle_t coh; + d_vector_t *dv; + struct dlck_stats *ds; +}; + #endif /* __DAOS_DLCK_H__ */ diff --git a/src/utils/dlck/dlck_dtx_act_recs_recover.c b/src/utils/dlck/dlck_dtx_act_recs_recover.c index 9eda8b6b387..fea1f6a3083 100644 --- a/src/utils/dlck/dlck_dtx_act_recs_recover.c +++ b/src/utils/dlck/dlck_dtx_act_recs_recover.c @@ -13,12 +13,6 @@ #include "dlck_pool.h" #include "dlck_internal.h" -#ifdef DLCK_UT_BUILD -#define DLCK_STATIC -#else -#define DLCK_STATIC static -#endif - /** * Process a single container. * diff --git a/src/utils/dlck/tests/SConscript b/src/utils/dlck/tests/SConscript index 6616f862d3c..2e9db925b6c 100644 --- a/src/utils/dlck/tests/SConscript +++ b/src/utils/dlck/tests/SConscript @@ -14,7 +14,7 @@ def build_dlck_d_vector_ut(venv): def build_dlck_dtx_act_recs_recover_ut(venv): """Build dlck_dtx_act_recs_recover.c unit test""" venv.Append(OBJPREFIX="dlck_ut_") - venv.Append(CPPDEFINES={'DLCK_UT_BUILD': '1'}) + venv.Append(CPPDEFINES=['-DDLCK_UT_BUILD']) venv.AppendUnique(RPATH_FULL=['$PREFIX/lib64/daos_srv']) venv.AppendUnique(LINKFLAGS=['-Wl,--wrap=d_calloc']) venv.AppendUnique(LINKFLAGS=['-Wl,--wrap=vos_cont_open']) @@ -34,6 +34,27 @@ def build_dlck_dtx_act_recs_recover_ut(venv): venv.Install('$PREFIX/bin/', program) +def build_dlck_vos_cont_recs_get_active(venv): + """Build dlck_vos_cont_recs_get_active() unit test""" + venv.Append(OBJPREFIX="dlck_ut_") + venv.Append(CPPDEFINES=['-DDAOS_PMEM_BUILD', '-DDLCK_UT_BUILD']) + venv.AppendUnique(RPATH_FULL=['$PREFIX/lib64/daos_srv']) + venv.require('cmocka', 'argobots') + libs = ['cmocka', 'gurt', 'uuid', 'daos_common_pmem', 'abt', 'vea', 'bio'] + srcs = [ + 'dlck_vos_cont_recs_get_active_ut.c', + 'vos_mocks.c', + '../../../vos/vos_container.c', + '../../../vos/vos_gc.c', + '../../../vos/vos_space.c', + '../../../vos/lru_array.c', + '../../../vos/evtree.c', + ] + + program = venv.d_test_program('dlck_vos_cont_recs_get_active_ut', srcs, LIBS=libs) + venv.Install('$PREFIX/bin/', program) + + def build_dlck_test_helper(henv): """Build dlck_test_helper""" henv.Append(OBJPREFIX="dlck_ut_helper_") @@ -71,6 +92,7 @@ def scons(): build_dlck_d_vector_ut(env.Clone()) build_dlck_dtx_act_recs_recover_ut(env.Clone()) + build_dlck_vos_cont_recs_get_active(env.Clone()) build_dlck_test_helper(env.Clone()) diff --git a/src/utils/dlck/tests/dlck_dtx_act_recs_recover_ut.c b/src/utils/dlck/tests/dlck_dtx_act_recs_recover_ut.c index 204c8c3aa18..643fe3224c4 100644 --- a/src/utils/dlck/tests/dlck_dtx_act_recs_recover_ut.c +++ b/src/utils/dlck/tests/dlck_dtx_act_recs_recover_ut.c @@ -13,6 +13,7 @@ #include +#include "dlck_tests_common.h" #include "../dlck_args.h" #include "../dlck_cmds.h" #include "../dlck_engine.h" @@ -20,7 +21,6 @@ #include "../dlck_pool.h" #define NO_FILES_RC (-DER_ENOENT) -#define GENERIC_ERROR_RC (-DER_MISC) #define RANDOM_INT_A 17 #define RANDOM_INT_B 45 #define OPEN_MTX_PTR ((void *)0x310) diff --git a/src/utils/dlck/tests/dlck_tests_common.h b/src/utils/dlck/tests/dlck_tests_common.h new file mode 100644 index 00000000000..192ad2992fa --- /dev/null +++ b/src/utils/dlck/tests/dlck_tests_common.h @@ -0,0 +1,12 @@ +/** + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + */ + +#ifndef __DLCK_TESTS_COMMON__ +#define __DLCK_TESTS_COMMON__ + +#define GENERIC_ERROR_RC (-DER_MISC) + +#endif /** __DLCK_TESTS_COMMON__ */ diff --git a/src/utils/dlck/tests/dlck_vos_cont_recs_get_active_ut.c b/src/utils/dlck/tests/dlck_vos_cont_recs_get_active_ut.c new file mode 100644 index 00000000000..258e09945f1 --- /dev/null +++ b/src/utils/dlck/tests/dlck_vos_cont_recs_get_active_ut.c @@ -0,0 +1,197 @@ +/** + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + */ + +#define D_LOGFAC DD_FAC(tests) + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "dlck_tests_common.h" + +/** non-public definitions */ + +int +dlck_rec_get_active_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, + vos_iter_param_t *param, void *cb_arg, unsigned int *acts); + +/** mocks */ + +#define COH_MOCK_INIT \ + { \ + .cookie = 0x300413 \ + } +#define ENTRY_MOCK ((vos_iter_entry_t *)0xE4141) +#define PARAM_MOCK ((vos_iter_param_t *)0x5A4A3) +#define ACTS_MOCK ((unsigned int *)0xAC15) +#define VOS_ITER_MOCK ((struct vos_iterator *)0xC0511E4) +#define DV_MOCK ((d_vector_t *)0xDCE0C4) + +/** globals */ + +static const daos_handle_t Coh = COH_MOCK_INIT; +static struct dlck_stats Stats; +static const vos_iter_param_t Param = { + .ip_hdl = COH_MOCK_INIT, + .ip_epr = {.epr_hi = DAOS_EPOCH_MAX}, + .ip_flags = VOS_IT_FOR_CHECK, +}; +static const struct vos_iter_anchors Anchors_zeroed; +static const struct dlck_iter_bundle Bundle = {.coh = COH_MOCK_INIT, .ds = &Stats, .dv = DV_MOCK}; +static const daos_handle_t Ih = {.cookie = (uint64_t)VOS_ITER_MOCK}; + +/** mocks */ + +struct vos_iterator; +struct dtx_handle; + +int +dlck_obj_get_active(daos_handle_t coh, struct vos_iterator *iter, d_vector_t *dv) +{ + assert_int_equal(coh.cookie, Coh.cookie); + assert_ptr_equal(iter, VOS_ITER_MOCK); + assert_ptr_equal(dv, DV_MOCK); + return mock_type(int); +} + +int +dlck_irec_get_active(daos_handle_t coh, struct vos_iterator *iter, d_vector_t *dv) +{ + assert_int_equal(coh.cookie, Coh.cookie); + assert_ptr_equal(iter, VOS_ITER_MOCK); + assert_ptr_equal(dv, DV_MOCK); + return mock_type(int); +} + +int +dlck_sv_add_if_active(daos_handle_t coh, struct vos_iterator *iter, d_vector_t *dv) +{ + assert_int_equal(coh.cookie, Coh.cookie); + assert_ptr_equal(iter, VOS_ITER_MOCK); + assert_ptr_equal(dv, DV_MOCK); + return mock_type(int); +} + +int +dlck_ev_add_if_active(daos_handle_t coh, struct vos_iterator *iter, d_vector_t *dv) +{ + assert_int_equal(coh.cookie, Coh.cookie); + assert_ptr_equal(iter, VOS_ITER_MOCK); + assert_ptr_equal(dv, DV_MOCK); + return mock_type(int); +} + +int +vos_iterate(vos_iter_param_t *param, vos_iter_type_t type, bool recursive, + struct vos_iter_anchors *anchors, vos_iter_cb_t pre_cb, vos_iter_cb_t post_cb, + void *arg, struct dtx_handle *dth) +{ + struct dlck_iter_bundle *bundle = arg; + + assert_ptr_not_equal(param, NULL); + assert_true(memcmp(param, &Param, sizeof(Param)) == 0); + assert_int_equal(type, VOS_ITER_OBJ); + assert_true(recursive); + assert_ptr_not_equal(anchors, NULL); + assert_true(memcmp(anchors, &Anchors_zeroed, sizeof(Anchors_zeroed)) == 0); + assert_ptr_equal(pre_cb, dlck_rec_get_active_cb); + assert_ptr_equal(post_cb, NULL); + assert_ptr_not_equal(bundle, NULL); + assert_true(memcmp(bundle, &Bundle, sizeof(Bundle)) == 0); + assert_ptr_equal(dth, NULL); + + return mock_type(int); +} + +/** tests */ + +static void +test_vos_iterate_fails(void **unused) +{ + int rc; + + will_return(vos_iterate, GENERIC_ERROR_RC); + rc = dlck_vos_cont_recs_get_active(Coh, DV_MOCK, &Stats); + assert_int_equal(rc, GENERIC_ERROR_RC); +} + +#define DLCK_REC_GET_ACTIVE_CB(RC, TYPE) \ + (RC) = \ + dlck_rec_get_active_cb(Ih, ENTRY_MOCK, (TYPE), PARAM_MOCK, (void *)&Bundle, ACTS_MOCK) + +static void +test_dlck_obj_get_active_fails(void **unused) +{ + int rc; + + will_return(dlck_obj_get_active, GENERIC_ERROR_RC); + DLCK_REC_GET_ACTIVE_CB(rc, VOS_ITER_OBJ); + assert_int_equal(rc, GENERIC_ERROR_RC); +} + +static void +test_dlck_irec_get_active_AKEY_fails(void **unused) +{ + int rc; + + will_return(dlck_irec_get_active, GENERIC_ERROR_RC); + DLCK_REC_GET_ACTIVE_CB(rc, VOS_ITER_AKEY); + assert_int_equal(rc, GENERIC_ERROR_RC); +} + +static void +test_dlck_irec_get_active_DKEY_fails(void **unused) +{ + int rc; + + will_return(dlck_irec_get_active, GENERIC_ERROR_RC); + DLCK_REC_GET_ACTIVE_CB(rc, VOS_ITER_DKEY); + assert_int_equal(rc, GENERIC_ERROR_RC); +} + +static void +test_dlck_sv_add_if_active_fails(void **unused) +{ + int rc; + + will_return(dlck_sv_add_if_active, GENERIC_ERROR_RC); + DLCK_REC_GET_ACTIVE_CB(rc, VOS_ITER_SINGLE); + assert_int_equal(rc, GENERIC_ERROR_RC); +} + +static void +test_dlck_ev_add_if_active_fails(void **unused) +{ + int rc; + + will_return(dlck_ev_add_if_active, GENERIC_ERROR_RC); + DLCK_REC_GET_ACTIVE_CB(rc, VOS_ITER_RECX); + assert_int_equal(rc, GENERIC_ERROR_RC); +} + +static const struct CMUnitTest tests_all[] = { + {"D100: vos_iterate() fails", test_vos_iterate_fails, NULL, NULL}, + {"D101: dlck_obj_get_active() fails", test_dlck_obj_get_active_fails, NULL, NULL}, + {"D102: dlck_irec_get_active() fails [AKEY]", test_dlck_irec_get_active_AKEY_fails, NULL, NULL}, + {"D103: dlck_irec_get_active() fails [DKEY]", test_dlck_irec_get_active_DKEY_fails, NULL, NULL}, + {"D104: dlck_sv_add_if_active() fails", test_dlck_sv_add_if_active_fails, NULL, NULL}, + {"D105: dlck_ev_add_if_active() fails", test_dlck_ev_add_if_active_fails, NULL, NULL}, +}; + +int +main(int argc, char **argv) +{ + const char *test_name = "dlck_vos_cont_recs_get_active() tests"; + + return cmocka_run_group_tests_name(test_name, tests_all, NULL, NULL); +} diff --git a/src/utils/dlck/tests/vos_mocks.c b/src/utils/dlck/tests/vos_mocks.c new file mode 100644 index 00000000000..a58eb97c7f6 --- /dev/null +++ b/src/utils/dlck/tests/vos_mocks.c @@ -0,0 +1,79 @@ +/** + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + */ + +#define D_LOGFAC DD_FAC(tests) + +#include +#include +#include +#include +#include +#include + +#include + +#include "dlck_tests_common.h" + +/** mocks - just to make the module under test compile */ + +struct vos_container; +struct vos_cont_df; +struct evt_desc_cbs; +struct vos_pool; +struct vos_object; +uint32_t vos_agg_gap; + +struct vos_tls * +vos_tls_get(bool standalone) +{ + assert_true(false); + return NULL; +} + +void +vos_lru_alloc_track(void *arg, daos_size_t size) +{ + assert_true(false); +} + +void +vos_lru_free_track(void *arg, daos_size_t size) +{ + assert_true(false); +} + +int +vos_dtx_act_reindex(struct vos_container *cont) +{ + assert_true(false); + return GENERIC_ERROR_RC; +} + +void +vos_obj_cache_evict(struct vos_container *cont) +{ + assert_true(false); +} + +int +vos_dtx_table_destroy(struct umem_instance *umm, struct vos_cont_df *cont_df) +{ + assert_true(false); + return GENERIC_ERROR_RC; +} + +void +vos_evt_desc_cbs_init(struct evt_desc_cbs *cbs, struct vos_pool *pool, daos_handle_t coh, + struct vos_object *obj) +{ + assert_true(false); +} + +void +vos_dedup_invalidate(struct vos_pool *pool) +{ + assert_true(false); +} diff --git a/src/vos/vos_container.c b/src/vos/vos_container.c index 25750b632b5..ebbb3320468 100644 --- a/src/vos/vos_container.c +++ b/src/vos/vos_container.c @@ -1030,13 +1030,7 @@ vos_cont_set_mod_bound(daos_handle_t coh, uint64_t epoch) return 0; } -struct dlck_iter_bundle { - daos_handle_t coh; - d_vector_t *dv; - struct dlck_stats *ds; -}; - -static int +DLCK_STATIC int dlck_rec_get_active_cb(daos_handle_t ih, vos_iter_entry_t *entry, vos_iter_type_t type, vos_iter_param_t *param, void *cb_arg, unsigned int *acts) {