Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/utils/ddb/tests/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ def scons():
# Required for dtx_act_discard_invalid tests.
# This function is validated by its respective unit tests.
tenv.AppendUnique(LINKFLAGS=['-Wl,--wrap=vos_dtx_discard_invalid'])
# Required for DDB_CAN_PROCEED tests (vmd_wa_can_proceed failure path).
tenv.AppendUnique(LINKFLAGS=['-Wl,--wrap=vmd_wa_can_proceed'])

libs = [
'uuid', 'daos_common_pmem', 'gurt', 'vea', 'abt', 'bio', 'cmocka', 'pthread', 'pmemobj',
'json-c',
]
src = ['ddb_ut.c', 'ddb_vos_ut.c']
src = ['ddb_ut.c', 'ddb_vos_ut.c', 'ddb_commands_ut.c']
# vos and mock object files to wrap vos symbols
vos_obj = tenv.Object(Glob('../../../vos/*.c'))
mock_obj = tenv.Object(Glob('../../../dtx/tests/*_mock.c'))
Expand Down
36 changes: 36 additions & 0 deletions src/utils/ddb/tests/ddb_commands_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,41 @@ dtx_get_cmt_time(char *buf)
return cmt_time;
}

static void
open_cmd_tests(void **state)
{
struct dt_vos_pool_ctx *tctx = *state;
struct ddb_ctx ctx = {0};
struct open_options opt = {0};

ctx.dc_io_ft.ddb_print_message = dvt_fake_print;
ctx.dc_io_ft.ddb_print_error = dvt_fake_print;

/* Non-existent path: must return DER_INVAL */
opt.path = "/non/existent/vos-0";
assert_invalid(ddb_run_open(&ctx, &opt));

/* Read-only open: pool handle must be valid, dc_write_mode must be false */
opt.path = tctx->dvt_pmem_file;
opt.write_mode = false;
assert_success(ddb_run_open(&ctx, &opt));
assert_true(daos_handle_is_valid(ctx.dc_poh));
assert_false(ctx.dc_write_mode);
assert_success(ddb_run_close(&ctx));

/* Write-mode open: dc_write_mode must be propagated to the context */
opt.write_mode = true;
assert_success(ddb_run_open(&ctx, &opt));
assert_true(daos_handle_is_valid(ctx.dc_poh));
assert_true(ctx.dc_write_mode);

/* Pool already open: must return DER_BUSY with an error message */
dvt_fake_print_reset();
assert_rc_equal(-DER_BUSY, ddb_run_open(&ctx, &opt));
assert_printed_contains("Cannot operate on an opened pool. Close it first.");
assert_success(ddb_run_close(&ctx));
}

static void
dtx_aggr_tests(void **state)
{
Expand Down Expand Up @@ -621,6 +656,7 @@ ddb_commands_tests_run()
TEST(dtx_act_discard_invalid_tests),
TEST(dtx_abort_entry_tests),
TEST(feature_cmd_tests),
TEST(open_cmd_tests),
TEST(dtx_aggr_tests),
};

Expand Down
133 changes: 133 additions & 0 deletions src/utils/ddb/tests/ddb_commands_ut.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* (C) Copyright 2026 Hewlett Packard Enterprise Development LP.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/

#include <stddef.h>
#include <stdarg.h>
#include <setjmp.h>
#include <cmocka.h>
#include <string.h>

#include <daos_errno.h>
#include "ddb.h"
#include "ddb_common.h"

/* ----------------------------------------------------------------
* Wrapped vmd_wa_can_proceed
* ----------------------------------------------------------------
* The real function lives in ddb_vmd_wa.c but is intercepted by the linker's
* --wrap mechanism. __real_vmd_wa_can_proceed is the original symbol.
*/
bool
__real_vmd_wa_can_proceed(struct ddb_ctx *ctx, const char *db_path);

bool
__wrap_vmd_wa_can_proceed(struct ddb_ctx *ctx, const char *db_path)
{
return mock_type(bool);
}

/* ----------------------------------------------------------------
* Fake print helpers (minimal, just for capturing output in these tests)
* ---------------------------------------------------------------- */
#define PRINT_BUF_SIZE 4096
static char g_print_buf[PRINT_BUF_SIZE];

static int
fake_print(const char *fmt, ...)
{
va_list ap;
size_t offset = strlen(g_print_buf);
size_t left = PRINT_BUF_SIZE - offset;

va_start(ap, fmt);
vsnprintf(g_print_buf + offset, left, fmt, ap);
va_end(ap);

return 0;
}

static void
fake_print_reset(void)
{
memset(g_print_buf, 0, sizeof(g_print_buf));
}

/* ----------------------------------------------------------------
* Tests
* ---------------------------------------------------------------- */

/**
* ddb_run_open must return -DER_NO_SERVICE when vmd_wa_can_proceed returns
* false (i.e. DDB_CAN_PROCEED macro fires).
*/
static void
open_can_proceed_failure_test(void **state)
{
struct ddb_ctx ctx = {0};
struct open_options opt = {0};
int rc;

ctx.dc_io_ft.ddb_print_message = fake_print;
ctx.dc_io_ft.ddb_print_error = fake_print;

opt.path = "/some/path/vos-0";

/* Make vmd_wa_can_proceed return false */
will_return(__wrap_vmd_wa_can_proceed, false);

rc = ddb_run_open(&ctx, &opt);
assert_int_equal(rc, -DER_NO_SERVICE);
}

/**
* ddb_run_version must print a version string and return 0.
*/
static void
version_test(void **state)
{
struct ddb_ctx ctx = {0};
int rc;

ctx.dc_io_ft.ddb_print_message = fake_print;
fake_print_reset();

rc = ddb_run_version(&ctx);
assert_int_equal(rc, 0);
assert_non_null(strstr(g_print_buf, "ddb version"));
}

/**
* ddb_run_close must return 0 when no pool is open (handle is invalid).
*/
static void
close_not_open_test(void **state)
{
struct ddb_ctx ctx = {0};
int rc;

ctx.dc_poh = DAOS_HDL_INVAL;

rc = ddb_run_close(&ctx);
assert_int_equal(rc, 0);
}

/* ----------------------------------------------------------------
* Suite registration
* ---------------------------------------------------------------- */
#define TEST(x) {#x, x##_test, NULL, NULL}

static const struct CMUnitTest ddb_commands_ut_cases[] = {
TEST(open_can_proceed_failure),
TEST(version),
TEST(close_not_open),
};

int
ddb_commands_ut_run(void)
{
return cmocka_run_group_tests_name("DDB Commands Unit Tests", ddb_commands_ut_cases, NULL,
NULL);
}
4 changes: 4 additions & 0 deletions src/utils/ddb/tests/ddb_ut.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
int
ddb_vos_ut_run(void);

int
ddb_commands_ut_run(void);

static int
ddb_test_driver_arguments_parse(uint32_t argc, char **argv)
{
Expand Down Expand Up @@ -88,6 +91,7 @@ main(int argc, char *argv[])
/* filtering suites and tests */
char test_suites[] = "";
RUN_TEST_SUIT('a', ddb_vos_ut_run);
RUN_TEST_SUIT('b', ddb_commands_ut_run);

ddb_fini();
if (rc > 0)
Expand Down
Loading