From a39219a0874a1cf90894430414e82a44ba2e798c Mon Sep 17 00:00:00 2001 From: Tomasz Gromadzki Date: Mon, 3 Feb 2025 13:14:57 +0100 Subject: [PATCH 1/4] DAOS-16953 tests: fix btree parameter parsing In btree.sh the -m and -t parameters were not applied correctly because of the preceding positional argument containing spaces but not wrapped in quotes In btree.c an invalid parameter sequence was not detected due to of the partially manual parsing process. btr_test_state introduced to provide global parameters to test (argc/argv) and avoid static variables for that purpose. Co-authored-by: Jan Michalski Co-authored-by: Tomasz Gromadzki Signed-off-by: Tomasz Gromadzki --- src/common/tests/btree.c | 222 +++++++++++++++++++------------------- src/common/tests/btree.sh | 11 +- 2 files changed, 116 insertions(+), 117 deletions(-) diff --git a/src/common/tests/btree.c b/src/common/tests/btree.c index 69a595d6109..19e5422c260 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,53 +885,89 @@ 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 void +ik_btr_init_mem(bool pmem, int dynamic_flag) +{ + int rc = 0; + if (pmem) { + 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); + } + } + rc = dbtree_class_register( + IK_TREE_CLASS, dynamic_flag | BTR_FEAT_EMBED_FIRST | BTR_FEAT_UINT_KEY, &ik_ops); + if (rc) { + fail_msg("Cannot register memory class: %d\n", rc); + } -static int -use_pmem() { + ik_root = utest_utx2root(ik_utx); + ik_uma = utest_utx2uma(ik_utx); +} - int rc; +static struct option btr_ops[] = { + {"start-test", required_argument, NULL, 'S'}, + {"dyn_tree", no_argument, NULL, 't'}, + {"pmem", no_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}, +}; - 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; -} +#define BTR_SHORTOPTS "+S:tmC:Deocqu:f:d:r:qi:b:p:" +/** + * Execute test based on the given sequence of steps. + * -S/--start-test parameter is ignored + * -t parameter shall be provided as the first parameter in the sequence, + * otherwise it will be ignored + * -m parameter shall be provided before any other short parameters, + * otherwise it will be ignored + */ static void ts_group(void **state) { + struct btr_test_state *test_state = (struct btr_test_state *)*state; + int opt = 0; + void **st = NULL; + int dynamic_flag = 0; - 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 't': + D_PRINT("Using dynamic tree order\n"); + dynamic_flag = BTR_FEAT_DYNAMIC_ROOT; + break; + case 'm': + ik_btr_init_mem(true, dynamic_flag); + break; case 'C': + if (ik_utx == NULL) + ik_btr_init_mem(false, dynamic_flag); ik_btr_open_create(st); break; case 'D': @@ -978,27 +1015,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 +1039,52 @@ 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; } } + if (argc != optind) { + print_message("Unknown parameter: %s\n", argv[optind]); + return -1; + } + /* getopt_long start over */ + optind = 1; - rc = dbtree_class_register( - IK_TREE_CLASS, dynamic_flag | BTR_FEAT_EMBED_FIRST | BTR_FEAT_UINT_KEY, &ik_ops); - D_ASSERT(rc == 0); - - 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) { + print_message("daos_debug_init() failed: %d\n", rc); + return 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) { + print_message("Error: %d\n", rc); + } return rc; } diff --git a/src/common/tests/btree.sh b/src/common/tests/btree.sh index 03a35d47f9e..bc50d4f472d 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 @@ -107,8 +108,8 @@ run_test() echo "B+tree functional test..." DAOS_DEBUG="$DDEBUG" \ - eval "${VCMD}" "$BTR" --start-test \ - "btree functional ${test_conf_pre} ${test_conf} iterate=${IDIR}" \ + eval "${VCMD}" "$BTR" \ + --start-test "'btree functional ${test_conf_pre} ${test_conf} iterate=${IDIR}'" \ "${DYN}" "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ @@ -128,7 +129,7 @@ run_test() echo "B+tree batch operations test..." eval "${VCMD}" "$BTR" \ - --start-test "btree batch operations ${test_conf_pre} ${test_conf}" \ + --start-test "'btree batch operations ${test_conf_pre} ${test_conf}'" \ "${DYN}" "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ @@ -137,14 +138,14 @@ run_test() echo "B+tree drain test..." eval "${VCMD}" "$BTR" \ - --start-test "btree drain ${test_conf_pre} ${test_conf}" \ + --start-test "'btree drain ${test_conf_pre} ${test_conf}'" \ "${DYN}" "${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}" \ + --start-test "'btree performance ${test_conf_pre} ${test_conf}'" \ "${DYN}" "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -p "$BAT_NUM" \ -D From 1b938010c24f1b2028a9a58b63935d1121e5b079 Mon Sep 17 00:00:00 2001 From: Tomasz Gromadzki Date: Wed, 5 Feb 2025 14:10:50 +0100 Subject: [PATCH 2/4] Introduce new parameters for memory and class reg. Introduce new parameters for explicity class and memory registration. Both parameters must be provided before `-C` parameter. Syntax is as follow: * -M[p] for memory registration. The `p` value inidcates the usage of persisten memory * -R[d] for class registration. The `d` value indicates the usage of `BTR_FEAT_DIRECT_KEY` flag - root is dynamically sized up to tree order. Parameters `-t` and `-d` are no longer valid. Signed-off-by: Tomasz Gromadzki --- src/common/tests/btree.c | 78 +++++++++++++++++++++++---------------- src/common/tests/btree.sh | 13 ++++--- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/common/tests/btree.c b/src/common/tests/btree.c index 19e5422c260..729feca479f 100644 --- a/src/common/tests/btree.c +++ b/src/common/tests/btree.c @@ -886,10 +886,13 @@ ik_btr_drain(void **state) } static void -ik_btr_init_mem(bool pmem, int dynamic_flag) +ik_btr_memory_register(char *pmem_flag) { int rc = 0; - if (pmem) { + 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) { @@ -902,20 +905,33 @@ ik_btr_init_mem(bool pmem, int dynamic_flag) fail_msg("Cannot setup vmem: %d\n", rc); } } - rc = dbtree_class_register( - IK_TREE_CLASS, dynamic_flag | BTR_FEAT_EMBED_FIRST | BTR_FEAT_UINT_KEY, &ik_ops); - if (rc) { - fail_msg("Cannot register memory class: %d\n", rc); - } ik_root = utest_utx2root(ik_utx); ik_uma = utest_utx2uma(ik_utx); } +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'}, - {"dyn_tree", no_argument, NULL, 't'}, - {"pmem", no_argument, NULL, 'm'}, + {"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'}, @@ -932,42 +948,41 @@ static struct option btr_ops[] = { {NULL, 0, NULL, 0}, }; -#define BTR_SHORTOPTS "+S:tmC:Deocqu:f:d:r:qi:b:p:" +#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 parameter is ignored - * -t parameter shall be provided as the first parameter in the sequence, - * otherwise it will be ignored - * -m parameter shall be provided before any other short parameters, - * otherwise it will be ignored + * -R and -M parameters must be provided before -C parameter. */ static void ts_group(void **state) { - struct btr_test_state *test_state = (struct btr_test_state *)*state; - int opt = 0; - void **st = NULL; - int dynamic_flag = 0; + struct btr_test_state *test_state = (struct btr_test_state *)*state; + int opt = 0; + void **st = NULL; 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; + // trim trailing space + while (tst_fn_val.optval && *tst_fn_val.optval != '\0' && + isspace((unsigned char)*tst_fn_val.optval)) { + tst_fn_val.optval++; + } + switch (opt) { case 'S': /* not part of the test sequence */ break; - case 't': - D_PRINT("Using dynamic tree order\n"); - dynamic_flag = BTR_FEAT_DYNAMIC_ROOT; + case 'R': + ik_btr_class_register(tst_fn_val.optval); break; - case 'm': - ik_btr_init_mem(true, dynamic_flag); + case 'M': + ik_btr_memory_register(tst_fn_val.optval); break; case 'C': - if (ik_utx == NULL) - ik_btr_init_mem(false, dynamic_flag); ik_btr_open_create(st); break; case 'D': @@ -1053,11 +1068,13 @@ main(int argc, char **argv) while ((opt = getopt_long(argc, argv, BTR_SHORTOPTS, btr_ops, NULL)) != -1) { if (opt == 'S') { test_name = optarg; + } else if (opt == '?') { + /* unknown parameter */ + break; } } if (argc != optind) { - print_message("Unknown parameter: %s\n", argv[optind]); - return -1; + fail_msg("Unknown parameter: %s\n", argv[optind]); } /* getopt_long start over */ optind = 1; @@ -1074,8 +1091,7 @@ main(int argc, char **argv) rc = daos_debug_init(DAOS_LOG_DEFAULT); if (rc != 0) { - print_message("daos_debug_init() failed: %d\n", rc); - return rc; + fail_msg("daos_debug_init() failed: %d\n", rc); } rc = run_cmd_line_test(test_name, &initial_state); daos_debug_fini(); @@ -1083,8 +1099,8 @@ main(int argc, char **argv) rc += utest_utx_destroy(ik_utx); } if (rc != 0) { - print_message("Error: %d\n", rc); + 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 bc50d4f472d..94014654ddb 100755 --- a/src/common/tests/btree.sh +++ b/src/common/tests/btree.sh @@ -40,6 +40,7 @@ EOF PERF="" UINT="" +DYN="" test_conf_pre="" while [ $# -gt 0 ]; do case "$1" in @@ -54,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" ;; @@ -110,7 +111,7 @@ run_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" \ + -R "${DYN}" -M "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ -u "$RECORDS" \ @@ -130,7 +131,7 @@ 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" \ + -R "${DYN}" -M "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ -b "$BAT_NUM" \ @@ -139,14 +140,14 @@ 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" \ + -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" \ + -R "${DYN}" -M "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -p "$BAT_NUM" \ -D fi @@ -154,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 From 6fdda49de273676e8ea0f8a72f196350d54faa83 Mon Sep 17 00:00:00 2001 From: Tomasz Gromadzki Date: Thu, 6 Feb 2025 09:49:15 +0100 Subject: [PATCH 3/4] No space before optional option's argument -R and -M options have optional argument. The optional argument must be specified on the command line without space. Otherwise, the argument is incorectly interpreted as the next option (invalid one). From getopt() documentation: about option with mandatory argument: "optstring is a string containing the legitimate option characters. If such a character is followed by a colon, the option requires an argument, so getopt() places a pointer to the following text in the same argv-element, or the text of the following argv-element, in optarg." about option with optional argument: "Two colons mean an option takes an optional arg; if there is text in the current argv-element (i.e., in the same word as the option name itself, for example, "-oarg"), then it is returned in optarg, otherwise optarg is set to zero." Signed-off-by: Tomasz Gromadzki --- src/common/tests/btree.c | 21 ++++++++++----------- src/common/tests/btree.sh | 8 ++++---- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/common/tests/btree.c b/src/common/tests/btree.c index 729feca479f..c60c0bdebc8 100644 --- a/src/common/tests/btree.c +++ b/src/common/tests/btree.c @@ -952,8 +952,9 @@ static struct option btr_ops[] = { /** * Execute test based on the given sequence of steps. - * -S/--start-test parameter is ignored - * -R and -M parameters must be provided before -C parameter. + * -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) { @@ -966,12 +967,6 @@ ts_group(void **state) { tst_fn_val.optval = optarg; tst_fn_val.input = true; - // trim trailing space - while (tst_fn_val.optval && *tst_fn_val.optval != '\0' && - isspace((unsigned char)*tst_fn_val.optval)) { - tst_fn_val.optval++; - } - switch (opt) { case 'S': /* not part of the test sequence */ @@ -1069,13 +1064,17 @@ main(int argc, char **argv) if (opt == 'S') { test_name = optarg; } else if (opt == '?') { - /* unknown parameter */ break; } } - if (argc != optind) { - fail_msg("Unknown parameter: %s\n", argv[optind]); + 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); } + /* getopt_long start over */ optind = 1; diff --git a/src/common/tests/btree.sh b/src/common/tests/btree.sh index 94014654ddb..1bc85b21ccb 100755 --- a/src/common/tests/btree.sh +++ b/src/common/tests/btree.sh @@ -111,7 +111,7 @@ run_test() DAOS_DEBUG="$DDEBUG" \ eval "${VCMD}" "$BTR" \ --start-test "'btree functional ${test_conf_pre} ${test_conf} iterate=${IDIR}'" \ - -R "${DYN}" -M "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + -R"${DYN}" -M"${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ -u "$RECORDS" \ @@ -131,7 +131,7 @@ run_test() echo "B+tree batch operations test..." eval "${VCMD}" "$BTR" \ --start-test "'btree batch operations ${test_conf_pre} ${test_conf}'" \ - -R "${DYN}" -M "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + -R"${DYN}" -M"${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -c \ -o \ -b "$BAT_NUM" \ @@ -140,14 +140,14 @@ run_test() echo "B+tree drain test..." eval "${VCMD}" "$BTR" \ --start-test "'btree drain ${test_conf_pre} ${test_conf}'" \ - -R "${DYN}" -M "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + -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}'" \ - -R "${DYN}" -M "${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ + -R"${DYN}" -M"${PMEM}" -C "${UINT}${IPL}o:$ORDER" \ -p "$BAT_NUM" \ -D fi From c08476113bfc6050d1348ce5a9b8f3c1f0104c42 Mon Sep 17 00:00:00 2001 From: Tomasz Gromadzki Date: Mon, 10 Feb 2025 08:34:26 +0100 Subject: [PATCH 4/4] Adapt btree_direct.c to follow btree.c btree_direct.c and btree.c must follow the same parameters except dyenamic registration and drain. Unify test execution implementation. Limit validation scope: Skip-func-hw-test: true Skip-func-test: true Signed-off-by: Tomasz Gromadzki --- src/common/tests/btree_direct.c | 234 ++++++++++++++++++-------------- 1 file changed, 132 insertions(+), 102 deletions(-) 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; }