diff --git a/src/common/tests/btree.c b/src/common/tests/btree.c index 69a595d6109..c60c0bdebc8 100644 --- a/src/common/tests/btree.c +++ b/src/common/tests/btree.c @@ -1,5 +1,6 @@ /** * (C) Copyright 2016-2022 Intel Corporation. + * (C) Copyright 2025 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -62,9 +63,10 @@ struct ik_rec { umem_off_t ir_val_off; }; -static char **test_group_args; -static int test_group_start; -static int test_group_stop; +struct btr_test_state { + int argc; + char **argv; +}; #define IK_TREE_CLASS 100 #define POOL_NAME "/mnt/daos/btree-test" @@ -834,7 +836,6 @@ ik_btr_perf(void **state) D_FREE(arr); } - static void ik_btr_drain(void **state) { @@ -884,52 +885,98 @@ ik_btr_drain(void **state) D_FREE(arr); } -static struct option btr_ops[] = { - { "create", required_argument, NULL, 'C' }, - { "destroy", no_argument, NULL, 'D' }, - { "drain", no_argument, NULL, 'e' }, - { "open", no_argument, NULL, 'o' }, - { "close", no_argument, NULL, 'c' }, - { "update", required_argument, NULL, 'u' }, - { "find", required_argument, NULL, 'f' }, - { "dyn_tree", no_argument, NULL, 't' }, - { "delete", required_argument, NULL, 'd' }, - { "del_retain", required_argument, NULL, 'r' }, - { "query", no_argument, NULL, 'q' }, - { "iterate", required_argument, NULL, 'i' }, - { "batch", required_argument, NULL, 'b' }, - { "perf", required_argument, NULL, 'p' }, - { NULL, 0, NULL, 0 }, -}; - -static int -use_pmem() { +static void +ik_btr_memory_register(char *pmem_flag) +{ + int rc = 0; + if (pmem_flag && *pmem_flag != 'p') { + fail_msg("Invalid value of -M parameter: %c\n", *pmem_flag); + } + if (pmem_flag) { + D_PRINT("Using pmem\n"); + rc = utest_pmem_create(POOL_NAME, POOL_SIZE, sizeof(*ik_root), NULL, &ik_utx); + if (rc) { + fail_msg("Cannot setup pmem: %d\n", rc); + } + } else { + D_PRINT("Using vmem\n"); + rc = utest_vmem_create(sizeof(*ik_root), &ik_utx); + if (rc) { + fail_msg("Cannot setup vmem: %d\n", rc); + } + } - int rc; + ik_root = utest_utx2root(ik_utx); + ik_uma = utest_utx2uma(ik_utx); +} - D_PRINT("Using pmem\n"); - rc = utest_pmem_create(POOL_NAME, POOL_SIZE, - sizeof(*ik_root), NULL, - &ik_utx); - D_ASSERT(rc == 0); - return rc; +static void +ik_btr_class_register(char *dynamic_flag) +{ + if (dynamic_flag && *dynamic_flag != 'd') { + fail_msg("Invalid value of -R parameter: %c\n", *dynamic_flag); + } + if (dynamic_flag) { + D_PRINT("Using dynamic tree order\n"); + } + int rc = dbtree_class_register(IK_TREE_CLASS, + (dynamic_flag ? BTR_FEAT_DYNAMIC_ROOT : 0) | + BTR_FEAT_EMBED_FIRST | BTR_FEAT_UINT_KEY, + &ik_ops); + if (rc) { + fail_msg("Cannot register memory class: %d\n", rc); + } } +static struct option btr_ops[] = { + {"start-test", required_argument, NULL, 'S'}, + {"reg-class", optional_argument, NULL, 'R'}, + {"reg-memory", optional_argument, NULL, 'M'}, + {"create", required_argument, NULL, 'C'}, + {"destroy", no_argument, NULL, 'D'}, + {"drain", no_argument, NULL, 'e'}, + {"open", no_argument, NULL, 'o'}, + {"close", no_argument, NULL, 'c'}, + {"update", required_argument, NULL, 'u'}, + {"find", required_argument, NULL, 'f'}, + {"delete", required_argument, NULL, 'd'}, + {"del_retain", required_argument, NULL, 'r'}, + {"query", no_argument, NULL, 'q'}, + {"iterate", required_argument, NULL, 'i'}, + {"batch", required_argument, NULL, 'b'}, + {"perf", required_argument, NULL, 'p'}, + {NULL, 0, NULL, 0}, +}; + +#define BTR_SHORTOPTS "+S:R::M::C:Deocqu:f:d:r:qi:b:p:" + +/** + * Execute test based on the given sequence of steps. + * -S/--start-test option is ignored + * -R and -M options must be provided before -C option. + * Each argument of the -R and -M options must be specified without a space between them (e.g. -Rd). + */ static void ts_group(void **state) { + struct btr_test_state *test_state = (struct btr_test_state *)*state; + int opt = 0; + void **st = NULL; - int opt = 0; - void **st = NULL; - - while ((opt = getopt_long(test_group_stop-test_group_start+1, - test_group_args+test_group_start, - "tmC:Deocqu:d:r:f:i:b:p:", - btr_ops, + while ((opt = getopt_long(test_state->argc, test_state->argv, BTR_SHORTOPTS, btr_ops, NULL)) != -1) { tst_fn_val.optval = optarg; tst_fn_val.input = true; switch (opt) { + case 'S': + /* not part of the test sequence */ + break; + case 'R': + ik_btr_class_register(tst_fn_val.optval); + break; + case 'M': + ik_btr_memory_register(tst_fn_val.optval); + break; case 'C': ik_btr_open_create(st); break; @@ -978,27 +1025,18 @@ ts_group(void **state) { ik_btr_perf(st); break; default: - D_PRINT("Unsupported command %c\n", opt); - case 'm': - case 't': - /* handled previously */ - break; + fail_msg("Unsupported command %c\n", opt); } } } static int -run_cmd_line_test(char *test_name, char **args, int start_idx, int stop_idx) +run_cmd_line_test(char *test_name, struct btr_test_state *initial_state) { - const struct CMUnitTest btree_test[] = { - {test_name, ts_group, NULL, NULL}, + {test_name, ts_group, NULL, NULL, initial_state}, }; - test_group_args = args; - test_group_start = start_idx; - test_group_stop = stop_idx; - return cmocka_run_group_tests_name(test_name, btree_test, NULL, @@ -1011,82 +1049,57 @@ main(int argc, char **argv) struct timeval tv; int rc = 0; int opt; - int dynamic_flag = 0; - int start_idx; - char *test_name; - int stop_idx; + char *test_name = NULL; + struct btr_test_state initial_state = {.argc = argc, .argv = argv}; d_register_alt_assert(mock_assert); - gettimeofday(&tv, NULL); - srand(tv.tv_usec); - - ik_toh = DAOS_HDL_INVAL; - ik_root_off = UMOFF_NULL; - - rc = daos_debug_init(DAOS_LOG_DEFAULT); - if (rc != 0) - return rc; - if (argc == 1) { - print_message("Invalid format.\n"); + print_message("No parameters provided.\n"); return -1; } - stop_idx = argc-1; - if (strcmp(argv[1], "--start-test") == 0) { - start_idx = 2; - test_name = argv[2]; - if (strcmp(argv[3], "-t") == 0) { - D_PRINT("Using dynamic tree order\n"); - dynamic_flag = BTR_FEAT_DYNAMIC_ROOT; - if (strcmp(argv[4], "-m") == 0) - rc = use_pmem(); - } else if (strcmp(argv[3], "-m") == 0) { - rc = use_pmem(); - if (strcmp(argv[4], "-t") == 0) { - D_PRINT("Using dynamic tree order\n"); - dynamic_flag = BTR_FEAT_DYNAMIC_ROOT; - } - } - } else { - start_idx = 0; - test_name = "Btree testing tool"; - optind = 0; - /* Check for -m option first */ - while ((opt = getopt_long(argc, argv, "tmC:Deocqu:d:r:f:i:b:p:", - btr_ops, NULL)) != -1) { - if (opt == 'm') { - rc = use_pmem(); - break; - } - if (opt == 't') { - D_PRINT("Using dynamic tree order\n"); - dynamic_flag = BTR_FEAT_DYNAMIC_ROOT; - } + /* Check for --start-test parameter and verify that all parameters are in place */ + while ((opt = getopt_long(argc, argv, BTR_SHORTOPTS, btr_ops, NULL)) != -1) { + if (opt == 'S') { + test_name = optarg; + } else if (opt == '?') { + break; } } + if (opt == '?') { + /* invalid option - error message printed on stderr already */ + return -1; + } else if (argc != optind) { + fail_msg("Cannot interpret parameter: \"%s\" at optind: %d.\n", argv[optind], + optind); + } - rc = dbtree_class_register( - IK_TREE_CLASS, dynamic_flag | BTR_FEAT_EMBED_FIRST | BTR_FEAT_UINT_KEY, &ik_ops); - D_ASSERT(rc == 0); + /* getopt_long start over */ + optind = 1; - if (ik_utx == NULL) { - D_PRINT("Using vmem\n"); - rc = utest_vmem_create(sizeof(*ik_root), &ik_utx); - D_ASSERT(rc == 0); + if (test_name == NULL) { + test_name = "Btree testing tool"; } - ik_root = utest_utx2root(ik_utx); - ik_uma = utest_utx2uma(ik_utx); + gettimeofday(&tv, NULL); + srand(tv.tv_usec); - /* start over */ - optind = 0; - rc = run_cmd_line_test(test_name, argv, start_idx, stop_idx); + ik_toh = DAOS_HDL_INVAL; + ik_root_off = UMOFF_NULL; + + rc = daos_debug_init(DAOS_LOG_DEFAULT); + if (rc != 0) { + fail_msg("daos_debug_init() failed: %d\n", rc); + } + rc = run_cmd_line_test(test_name, &initial_state); daos_debug_fini(); - rc += utest_utx_destroy(ik_utx); - if (rc != 0) - printf("Error: %d\n", rc); + if (ik_utx) { + rc += utest_utx_destroy(ik_utx); + } + if (rc != 0) { + fail_msg("Error: %d\n", rc); + } - return rc; + return 0; } diff --git a/src/common/tests/btree.sh b/src/common/tests/btree.sh index 03a35d47f9e..1bc85b21ccb 100755 --- a/src/common/tests/btree.sh +++ b/src/common/tests/btree.sh @@ -31,6 +31,7 @@ Usage: btree.sh [OPTIONS] -s [num] Run with num keys dyn Run with dynamic root ukey Use integer keys + emb Use embedded value perf Run performance tests direct Use direct string key EOF @@ -39,6 +40,7 @@ EOF PERF="" UINT="" +DYN="" test_conf_pre="" while [ $# -gt 0 ]; do case "$1" in @@ -53,7 +55,7 @@ while [ $# -gt 0 ]; do test_conf_pre="${test_conf_pre} keys=${BAT_NUM}" ;; dyn) - DYN="-t" + DYN="d" shift test_conf_pre="${test_conf_pre} dyn" ;; @@ -107,9 +109,9 @@ run_test() echo "B+tree functional test..." DAOS_DEBUG="$DDEBUG" \ - eval "${VCMD}" "$BTR" --start-test \ - "btree functional ${test_conf_pre} ${test_conf} iterate=${IDIR}" \ - "${DYN}" "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + eval "${VCMD}" "$BTR" \ + --start-test "'btree functional ${test_conf_pre} ${test_conf} iterate=${IDIR}'" \ + -R"${DYN}" -M"${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ -u "$RECORDS" \ @@ -128,8 +130,8 @@ run_test() echo "B+tree batch operations test..." eval "${VCMD}" "$BTR" \ - --start-test "btree batch operations ${test_conf_pre} ${test_conf}" \ - "${DYN}" "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + --start-test "'btree batch operations ${test_conf_pre} ${test_conf}'" \ + -R"${DYN}" -M"${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ -b "$BAT_NUM" \ @@ -137,15 +139,15 @@ run_test() echo "B+tree drain test..." eval "${VCMD}" "$BTR" \ - --start-test "btree drain ${test_conf_pre} ${test_conf}" \ - "${DYN}" "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + --start-test "'btree drain ${test_conf_pre} ${test_conf}'" \ + -R"${DYN}" -M"${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -e -D else echo "B+tree performance test..." eval "${VCMD}" "$BTR" \ - --start-test "btree performance ${test_conf_pre} ${test_conf}" \ - "${DYN}" "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + --start-test "'btree performance ${test_conf_pre} ${test_conf}'" \ + -R"${DYN}" -M"${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -p "$BAT_NUM" \ -D fi @@ -153,7 +155,7 @@ run_test() for IPL in "i," ""; do for IDIR in "f" "b"; do - for PMEM in "-m" ""; do + for PMEM in "p" ""; do run_test done done diff --git a/src/common/tests/btree_direct.c b/src/common/tests/btree_direct.c index 8fb3fa8b6fd..d399bbd1681 100644 --- a/src/common/tests/btree_direct.c +++ b/src/common/tests/btree_direct.c @@ -1,12 +1,12 @@ /** * (C) Copyright 2018-2022 Intel Corporation. + * (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 @@ -25,10 +25,6 @@ #include #include "utest_common.h" -static char **test_group_args; -static int test_group_start; -static int test_group_stop; - enum sk_btr_opc { BTR_OPC_UPDATE, BTR_OPC_LOOKUP, @@ -53,6 +49,11 @@ struct sk_rec { char sr_key[0]; }; +struct btr_test_state { + int argc; + char **argv; +}; + #define SK_TREE_CLASS 100 #define POOL_NAME "/mnt/daos/btree-direct-test" #define POOL_SIZE ((1024 * 1024 * 1024ULL)) @@ -285,15 +286,15 @@ sk_rec_stat(struct btr_instance *tins, struct btr_record *rec, } static btr_ops_t sk_ops = { - .to_key_cmp = sk_key_cmp, - .to_key_encode = sk_key_encode, - .to_key_decode = sk_key_decode, - .to_rec_alloc = sk_rec_alloc, - .to_rec_free = sk_rec_free, - .to_rec_fetch = sk_rec_fetch, - .to_rec_update = sk_rec_update, - .to_rec_string = sk_rec_string, - .to_rec_stat = sk_rec_stat, + .to_key_encode = sk_key_encode, + .to_key_decode = sk_key_decode, + .to_key_cmp = sk_key_cmp, + .to_rec_alloc = sk_rec_alloc, + .to_rec_free = sk_rec_free, + .to_rec_fetch = sk_rec_fetch, + .to_rec_update = sk_rec_update, + .to_rec_string = sk_rec_string, + .to_rec_stat = sk_rec_stat, }; #define SK_SEP ',' @@ -1026,37 +1027,87 @@ sk_btr_perf(void **state) D_FREE(kv); } +static void +sk_btr_memory_register(char *pmem_flag) +{ + int rc = 0; + if (pmem_flag && *pmem_flag != 'p') { + fail_msg("Invalid value of -M parameter: %c\n", *pmem_flag); + } + if (pmem_flag) { + D_PRINT("Using pmem\n"); + rc = utest_pmem_create(POOL_NAME, POOL_SIZE, sizeof(*sk_root), NULL, &sk_utx); + if (rc) { + fail_msg("Cannot setup pmem: %d\n", rc); + } + } else { + D_PRINT("Using vmem\n"); + rc = utest_vmem_create(sizeof(*sk_root), &sk_utx); + if (rc) { + fail_msg("Cannot setup vmem: %d\n", rc); + } + } + + sk_root = utest_utx2root(sk_utx); + sk_uma = utest_utx2uma(sk_utx); +} +static void +sk_btr_class_register() +{ + D_PRINT("Using dynamic tree order\n"); + int rc = dbtree_class_register(SK_TREE_CLASS, BTR_FEAT_EMBED_FIRST | BTR_FEAT_DIRECT_KEY, + &sk_ops); + if (rc) { + fail_msg("Cannot register memory class: %d\n", rc); + } +} + static struct option btr_ops[] = { - { "create", required_argument, NULL, 'C' }, - { "destroy", no_argument, NULL, 'D' }, - { "open", no_argument, NULL, 'o' }, - { "close", no_argument, NULL, 'c' }, - { "update", required_argument, NULL, 'u' }, - { "find", required_argument, NULL, 'f' }, - { "delete", required_argument, NULL, 'd' }, - { "del_retain", required_argument, NULL, 'r' }, - { "query", no_argument, NULL, 'q' }, - { "iterate", required_argument, NULL, 'i' }, - { "batch", required_argument, NULL, 'b' }, - { "perf", required_argument, NULL, 'p' }, - { NULL, 0, NULL, 0 }, + {"start-test", required_argument, NULL, 'S'}, + {"reg-class", no_argument, NULL, 'R'}, + {"reg-memory", optional_argument, NULL, 'M'}, + {"create", required_argument, NULL, 'C'}, + {"destroy", no_argument, NULL, 'D'}, + {"drain", no_argument, NULL, 'e'}, + {"open", no_argument, NULL, 'o'}, + {"close", no_argument, NULL, 'c'}, + {"update", required_argument, NULL, 'u'}, + {"find", required_argument, NULL, 'f'}, + {"delete", required_argument, NULL, 'd'}, + {"del_retain", required_argument, NULL, 'r'}, + {"query", no_argument, NULL, 'q'}, + {"iterate", required_argument, NULL, 'i'}, + {"batch", required_argument, NULL, 'b'}, + {"perf", required_argument, NULL, 'p'}, + {NULL, 0, NULL, 0}, }; +#define BTR_SHORTOPTS "+S:RM::C:Deocqu:f:d:r:qi:b:p:" + static void ts_group(void **state) { - + struct btr_test_state *test_state = (struct btr_test_state *)*state; int opt = 0; void **st = NULL; D_PRINT("--------------------------------------\n"); - while ((opt = getopt_long(test_group_stop-test_group_start+1, - test_group_args+test_group_start, - "mC:Docqu:d:r:f:i:b:p:", - btr_ops, + while ((opt = getopt_long(test_state->argc, test_state->argv, BTR_SHORTOPTS, btr_ops, NULL)) != -1) { tst_fn_val.optval = optarg; tst_fn_val.input = true; + switch (opt) { + case 'S': + /* not part of the test sequence */ + break; + case 'R': + sk_btr_class_register(); + break; + + case 'M': + sk_btr_memory_register(tst_fn_val.optval); + break; + case 'C': sk_btr_open_create(st); break; @@ -1072,6 +1123,10 @@ ts_group(void **state) { tst_fn_val.input = false; sk_btr_close_destroy(st); break; + case 'e': + /* not supported by btree_direct, + but keep here for compatibility with btree.c */ + break; case 'q': sk_btr_query(st); break; @@ -1101,104 +1156,79 @@ ts_group(void **state) { sk_btr_perf(st); break; default: - D_PRINT("Unsupported command %c\n", opt); - case 'm': - /* already handled */ - break; + fail_msg("Unsupported command %c\n", opt); } D_PRINT("--------------------------------------\n"); } } static int -run_cmd_line_test(char *test_name, char **args, int start_idx, int stop_idx) +run_cmd_line_test(char *test_name, struct btr_test_state *initial_state) { const struct CMUnitTest btree_test[] = { - {test_name, ts_group, NULL, NULL}, + {test_name, ts_group, NULL, NULL, initial_state}, }; - test_group_args = args; - test_group_start = start_idx; - test_group_stop = stop_idx; - - return cmocka_run_group_tests_name(test_name, - btree_test, - NULL, - NULL); - + return cmocka_run_group_tests_name(test_name, btree_test, NULL, NULL); } int main(int argc, char **argv) { struct timeval tv; + int rc = 0; int opt; - int rc; - int start_idx; - char *test_name; - int stop_idx; + char *test_name = NULL; + struct btr_test_state initial_state = {.argc = argc, .argv = argv}; d_register_alt_assert(mock_assert); - gettimeofday(&tv, NULL); - srand(tv.tv_usec); - - sk_toh = DAOS_HDL_INVAL; - sk_root_off = UMOFF_NULL; - - rc = daos_debug_init(DAOS_LOG_DEFAULT); - if (rc != 0) - return rc; + if (argc == 1) { + print_message("No parameters provided.\n"); + return -1; + } - rc = dbtree_class_register(SK_TREE_CLASS, BTR_FEAT_EMBED_FIRST | BTR_FEAT_DIRECT_KEY, - &sk_ops); - D_ASSERT(rc == 0); - - stop_idx = argc-1; - if (strcmp(argv[1], "--start-test") == 0) { - start_idx = 2; - test_name = argv[2]; - if (strcmp(argv[3], "-m") == 0) { - D_PRINT("Using pmem\n"); - rc = utest_pmem_create(POOL_NAME, POOL_SIZE, - sizeof(*sk_root), NULL, &sk_utx); - D_ASSERT(rc == 0); - } - } else { - start_idx = 0; - test_name = "Btree testing tool"; - optind = 0; - /* Check for -m option first */ - while ((opt = getopt_long(argc, argv, "mC:Docqu:d:r:f:i:b:p:", - btr_ops, NULL)) != -1) { - if (opt == 'm') { - D_PRINT("Using pmem\n"); - rc = utest_pmem_create(POOL_NAME, POOL_SIZE, - sizeof(*sk_root), NULL, - &sk_utx); - D_ASSERT(rc == 0); - break; - } + /* Check for --start-test parameter and verify that all parameters are in place */ + while ((opt = getopt_long(argc, argv, BTR_SHORTOPTS, btr_ops, NULL)) != -1) { + if (opt == 'S') { + test_name = optarg; + } else if (opt == '?') { + break; } } + if (opt == '?') { + /* invalid option - error message printed on stderr already */ + return -1; + } else if (argc != optind) { + fail_msg("Cannot interpret parameter: \"%s\" at optind: %d.\n", argv[optind], + optind); + } - if (sk_utx == NULL) { - D_PRINT("Using vmem\n"); - rc = utest_vmem_create(sizeof(*sk_root), &sk_utx); - D_ASSERT(rc == 0); + /* getopt_long start over */ + optind = 1; + + if (test_name == NULL) { + test_name = "Btree testing tool"; } - sk_root = utest_utx2root(sk_utx); - sk_uma = utest_utx2uma(sk_utx); + gettimeofday(&tv, NULL); + srand(tv.tv_usec); - /* start over */ - optind = 0; - rc = run_cmd_line_test(test_name, argv, start_idx, stop_idx); + sk_toh = DAOS_HDL_INVAL; + sk_root_off = UMOFF_NULL; + rc = daos_debug_init(DAOS_LOG_DEFAULT); + if (rc != 0) { + fail_msg("daos_debug_init() failed: %d\n", rc); + } + rc = run_cmd_line_test(test_name, &initial_state); daos_debug_fini(); - rc += utest_utx_destroy(sk_utx); - if (rc != 0) - printf("Error: %d\n", rc); + if (sk_utx) { + rc += utest_utx_destroy(sk_utx); + } + if (rc != 0) { + fail_msg("Error: %d\n", rc); + } - return rc; + return 0; }