From f7bd66ea2abcde01a5a66aecd2dcab2eb4fe0f31 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Thu, 31 Jul 2025 14:34:50 +0200 Subject: [PATCH 01/10] add unit tests to dlck_vector Signed-off-by: Oksana Salyk --- src/include/daos_srv/d_vector.h | 7 +- src/utils/dlck/tests/dlck_d_vector_ut.c | 105 +++++++++++++++++++++++- 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/src/include/daos_srv/d_vector.h b/src/include/daos_srv/d_vector.h index 4fdad1c9072..a2bf8ff0f22 100644 --- a/src/include/daos_srv/d_vector.h +++ b/src/include/daos_srv/d_vector.h @@ -86,6 +86,9 @@ d_vector_segment_append(d_vector_segment_t *dvs, void *entry) static inline int d_vector_append(d_vector_t *dst, void *src) { + if (dst == NULL || src == NULL) + return DER_INVAL; + d_vector_segment_t *dvs; bool new_segment = false; @@ -190,8 +193,10 @@ _d_vector_foreach_next(void **entry, d_vector_segment_t **segment, uint32_t *idx } } - if (load_entry) { + if (load_entry && *idx < (*segment)->dvs_len) { *entry = d_vector_segment_entry(*segment, *idx); + } else { + *entry = NULL; } } diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index f97853c27b2..c52c11bdfa6 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -28,9 +28,11 @@ struct element { struct state { struct element *array; - d_vector_t vec; + d_vector_t vec; }; +#define ENTRY_SIZE sizeof(struct element) + static int setup(void **state_ptr) { @@ -76,8 +78,107 @@ empty_vector(void **state_ptr) } } +static void +append_null_vector_test(void **state_ptr) +{ + struct state *state = *state_ptr; + int rc = d_vector_append(NULL, &state->array[0]); + assert_int_equal(rc, DER_INVAL); +} + +static void +append_null_entry_test(void **state_ptr) +{ + struct state *state = *state_ptr; + int rc = d_vector_append(&state->vec, NULL); + assert_int_equal(rc, DER_INVAL); +} + +static void +move_empty_vector_test(void **state_ptr) +{ + struct state *state = *state_ptr; + d_vector_t empty; + + d_vector_init(sizeof(struct element), &empty); + d_vector_move(&state->vec, &empty); + + assert_true(d_list_empty(&empty.dv_list)); + assert_true(d_list_empty(&state->vec.dv_list)); +} + +static void +double_free_test(void **state_ptr) +{ + struct state *state = *state_ptr; + + for (int i = 0; i < ARRAY_MAX; ++i) + d_vector_append(&state->vec, &state->array[i]); + + d_vector_free(&state->vec); + d_vector_free(&state->vec); + + assert_true(d_list_empty(&state->vec.dv_list)); +} + +static void +append_segment_overflow_test(void **state_ptr) +{ + struct state *state = *state_ptr; + + int capacity = D_VECTOR_SEGMENT_RAW_CAPACITY / ENTRY_SIZE; + + // Fill the segment completely + for (int i = 0; i < capacity; i++) { + int rc = d_vector_append(&state->vec, &state->array[i]); + assert_int_equal(rc, DER_SUCCESS); + } + + // Add one more item - exceeding capacity + int rc = d_vector_append(&state->vec, &state->array[capacity]); + assert_int_equal(rc, DER_SUCCESS); + + // Check that we have 2 segments + uint32_t segment_count = 0; + d_vector_segment_t *seg; + d_list_for_each_entry(seg, &state->vec.dv_list, dvs_link) { + segment_count += 1; + } + assert_int_equal(segment_count, 2); + + d_vector_free(&state->vec); +} + +static void +append_and_iterate_success(void **state_ptr) +{ + struct state *state = *state_ptr; + struct element *entry; + d_vector_segment_t *segment; + uint32_t idx; + + d_vector_init(sizeof(struct element), &state->vec); + + for (int i = 0; i < ARRAY_MAX; ++i) { + int rc = d_vector_append(&state->vec, &state->array[i]); + assert_int_equal(rc, DER_SUCCESS); + } + + d_vector_for_each_entry(entry, segment, idx, &state->vec.dv_list) + + assert_int_equal(d_vector_size(&state->vec), ARRAY_MAX); + + d_vector_free(&state->vec); +} + static const struct CMUnitTest tests_all[] = { - {"DVEC100: empty", empty_vector, setup, teardown}, + {"DVEC100: empty", empty_vector, setup, teardown}, + {"DVEC101: null_vector", append_null_vector_test, setup, teardown}, + {"DVEC102: null_entry", append_null_entry_test, setup, teardown}, + {"DVEC103: empty_vector", move_empty_vector_test, setup, teardown}, + {"DVEC104: double_free", double_free_test, setup, teardown}, + {"DVEC105: segment_overflow", append_segment_overflow_test, setup, teardown}, + {"DVEC106: happy_day_scenario", append_and_iterate_success, setup, teardown}, }; int From 2595b662ae8bdc5e18c3ee903959d40c3f80c5d2 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Fri, 1 Aug 2025 11:23:57 +0200 Subject: [PATCH 02/10] add corrections after the review Signed-off-by: Oksana Salyk --- src/include/daos_srv/d_vector.h | 20 +++---- src/utils/dlck/tests/dlck_d_vector_ut.c | 72 ++++++++++++++++--------- 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/include/daos_srv/d_vector.h b/src/include/daos_srv/d_vector.h index a2bf8ff0f22..5fca35dcc6f 100644 --- a/src/include/daos_srv/d_vector.h +++ b/src/include/daos_srv/d_vector.h @@ -23,8 +23,8 @@ struct d_vector { #define D_VECTOR_SEGMENT_SIZE 4096 -#define D_VECTOR_SEGMENT_HEADER \ - struct { \ +#define D_VECTOR_SEGMENT_HEADER \ + struct { \ d_list_t dvs_link; \ uint32_t dvs_len; \ uint32_t dvs_capacity; \ @@ -86,8 +86,9 @@ d_vector_segment_append(d_vector_segment_t *dvs, void *entry) static inline int d_vector_append(d_vector_t *dst, void *src) { - if (dst == NULL || src == NULL) - return DER_INVAL; + if (dst == NULL || src == NULL) { + return -DER_INVAL; + } d_vector_segment_t *dvs; bool new_segment = false; @@ -188,7 +189,7 @@ _d_vector_foreach_next(void **entry, d_vector_segment_t **segment, uint32_t *idx prefetch((*segment)->dvs_link.next); *idx = 0; } else { - *idx += 1; + *segment = NULL; load_entry = false; } } @@ -200,10 +201,11 @@ _d_vector_foreach_next(void **entry, d_vector_segment_t **segment, uint32_t *idx } } -#define d_vector_for_each_entry(entry, segment, idx, head) \ - for (_d_vector_foreach_init((void **)&entry, &segment, &idx, head); \ - segment != NULL && (segment->dvs_link.next != (head) || idx < segment->dvs_len); \ - _d_vector_foreach_next((void **)&entry, &segment, &idx, head)) +#define d_vector_for_each_entry(entry, segment, idx, head) \ + for (_d_vector_foreach_init((void **)&entry, &segment, &idx, head); \ + segment != NULL; \ + _d_vector_foreach_next((void **)&entry, &segment, &idx, head)) \ + if (idx < segment->dvs_len) /** * @} diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index c52c11bdfa6..4c6f204c43d 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -28,11 +28,9 @@ struct element { struct state { struct element *array; - d_vector_t vec; + d_vector_t vec; }; -#define ENTRY_SIZE sizeof(struct element) - static int setup(void **state_ptr) { @@ -83,7 +81,7 @@ append_null_vector_test(void **state_ptr) { struct state *state = *state_ptr; int rc = d_vector_append(NULL, &state->array[0]); - assert_int_equal(rc, DER_INVAL); + assert_int_equal(rc, -DER_INVAL); } static void @@ -91,7 +89,7 @@ append_null_entry_test(void **state_ptr) { struct state *state = *state_ptr; int rc = d_vector_append(&state->vec, NULL); - assert_int_equal(rc, DER_INVAL); + assert_int_equal(rc, -DER_INVAL); } static void @@ -103,7 +101,7 @@ move_empty_vector_test(void **state_ptr) d_vector_init(sizeof(struct element), &empty); d_vector_move(&state->vec, &empty); - assert_true(d_list_empty(&empty.dv_list)); + assert_int_equal(d_vector_size(&empty), 0); assert_true(d_list_empty(&state->vec.dv_list)); } @@ -112,10 +110,12 @@ double_free_test(void **state_ptr) { struct state *state = *state_ptr; - for (int i = 0; i < ARRAY_MAX; ++i) + for (int i = 0; i < ARRAY_MAX; ++i) { d_vector_append(&state->vec, &state->array[i]); + } d_vector_free(&state->vec); + assert_true(d_list_empty(&state->vec.dv_list)); d_vector_free(&state->vec); assert_true(d_list_empty(&state->vec.dv_list)); @@ -126,49 +126,69 @@ append_segment_overflow_test(void **state_ptr) { struct state *state = *state_ptr; - int capacity = D_VECTOR_SEGMENT_RAW_CAPACITY / ENTRY_SIZE; + d_vector_t *vec = &state->vec; + int capacity = (int)vec->dv_segment_capacity; + + assert_true(capacity + 1 < ARRAY_MAX); - // Fill the segment completely - for (int i = 0; i < capacity; i++) { - int rc = d_vector_append(&state->vec, &state->array[i]); + int index = 0; + int expected_count = capacity + 1; + struct element *entry; + d_vector_segment_t *seg; + uint32_t idx; + + /** Fill the segment completely + one more item - exceeding capacity. */ + for (int i = 0; i <= capacity; i++) { + int rc = d_vector_append(vec, &state->array[i]); assert_int_equal(rc, DER_SUCCESS); } - // Add one more item - exceeding capacity - int rc = d_vector_append(&state->vec, &state->array[capacity]); - assert_int_equal(rc, DER_SUCCESS); - - // Check that we have 2 segments - uint32_t segment_count = 0; - d_vector_segment_t *seg; - d_list_for_each_entry(seg, &state->vec.dv_list, dvs_link) { + /** Check that we have 2 segments */ + int segment_count = 0; + d_list_for_each_entry(seg, &vec->dv_list, dvs_link) { segment_count += 1; } assert_int_equal(segment_count, 2); - d_vector_free(&state->vec); + /** Verify the contents */ + d_vector_for_each_entry(entry, seg, idx, &vec->dv_list) { + assert_memory_equal(entry, &state->array[index], vec->dv_entry_size); + index++; + } + assert_int_equal(index, expected_count); + + d_vector_free(vec); + + /** Check if d_vector_free works properly */ + assert_ptr_equal(vec->dv_list.next, &vec->dv_list); + assert_ptr_equal(vec->dv_list.prev, &vec->dv_list); } static void append_and_iterate_success(void **state_ptr) { struct state *state = *state_ptr; + d_vector_t *vec = &state->vec; struct element *entry; - d_vector_segment_t *segment; + d_vector_segment_t *seg; uint32_t idx; + int index = 0; - d_vector_init(sizeof(struct element), &state->vec); + assert_int_equal(d_vector_size(vec), 0); for (int i = 0; i < ARRAY_MAX; ++i) { - int rc = d_vector_append(&state->vec, &state->array[i]); + int rc = d_vector_append(vec, &state->array[i]); assert_int_equal(rc, DER_SUCCESS); } - d_vector_for_each_entry(entry, segment, idx, &state->vec.dv_list) - - assert_int_equal(d_vector_size(&state->vec), ARRAY_MAX); + d_vector_for_each_entry(entry, seg, idx, &vec->dv_list) { + assert_memory_equal(entry, &state->array[index], vec->dv_entry_size); + assert_int_equal(d_vector_size(&state->vec), ARRAY_MAX); + index++; + } d_vector_free(&state->vec); + assert_int_equal(d_vector_size(&state->vec), 0); } static const struct CMUnitTest tests_all[] = { From 9ca14b69dbf938526f1b33d0435300b899c27ff6 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Mon, 4 Aug 2025 13:47:29 +0200 Subject: [PATCH 03/10] update after code review Signed-off-by: Oksana Salyk --- src/include/daos_srv/d_vector.h | 25 ++++----- src/utils/dlck/tests/dlck_d_vector_ut.c | 73 ++++++++++++++----------- 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/src/include/daos_srv/d_vector.h b/src/include/daos_srv/d_vector.h index 5fca35dcc6f..eb9c9bafa2b 100644 --- a/src/include/daos_srv/d_vector.h +++ b/src/include/daos_srv/d_vector.h @@ -178,34 +178,29 @@ _d_vector_foreach_init(void **entry, d_vector_segment_t **segment, uint32_t *idx static inline void _d_vector_foreach_next(void **entry, d_vector_segment_t **segment, uint32_t *idx, d_list_t *head) { - bool load_entry = true; - - if (*idx < (*segment)->dvs_len) { + if (*idx + 1 < (*segment)->dvs_len) { /** there is another entry in the current segment */ *idx += 1; - } else { + } else { /** look for the next segment */ d_list_t *next = (*segment)->dvs_link.next; - if (next != head) { + if (next != head) { /** the next segment exists */ (*segment) = d_list_entry(next, __typeof__(**segment), dvs_link); prefetch((*segment)->dvs_link.next); *idx = 0; - } else { + } else { /** there are no more segments */ *segment = NULL; - load_entry = false; + *idx = 0; + *entry = NULL; } } - if (load_entry && *idx < (*segment)->dvs_len) { + if (*segment != NULL) { *entry = d_vector_segment_entry(*segment, *idx); - } else { - *entry = NULL; } } -#define d_vector_for_each_entry(entry, segment, idx, head) \ - for (_d_vector_foreach_init((void **)&entry, &segment, &idx, head); \ - segment != NULL; \ - _d_vector_foreach_next((void **)&entry, &segment, &idx, head)) \ - if (idx < segment->dvs_len) +#define d_vector_for_each_entry(entry, segment, idx, head) \ + for (_d_vector_foreach_init((void **)&entry, &segment, &idx, head); segment != NULL; \ + _d_vector_foreach_next((void **)&entry, &segment, &idx, head)) /** * @} diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index 4c6f204c43d..d654a9ffba1 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -102,7 +102,16 @@ move_empty_vector_test(void **state_ptr) d_vector_move(&state->vec, &empty); assert_int_equal(d_vector_size(&empty), 0); - assert_true(d_list_empty(&state->vec.dv_list)); + assert_int_equal(d_vector_size(&state->vec), 0); +} + +static void +big_entry_size_test(void **state_ptr) +{ + d_vector_t vec; + size_t entry_size = D_VECTOR_SEGMENT_RAW_CAPACITY + 8; + d_vector_init(entry_size, &vec); + assert_true(d_vector_size(&vec) == 0); } static void @@ -110,33 +119,31 @@ double_free_test(void **state_ptr) { struct state *state = *state_ptr; + assert_true(ARRAY_MAX > state->vec.dv_segment_capacity); + for (int i = 0; i < ARRAY_MAX; ++i) { d_vector_append(&state->vec, &state->array[i]); } d_vector_free(&state->vec); - assert_true(d_list_empty(&state->vec.dv_list)); - d_vector_free(&state->vec); + assert_false(d_vector_size(&state->vec)); - assert_true(d_list_empty(&state->vec.dv_list)); + d_vector_free(&state->vec); + assert_false(d_vector_size(&state->vec)); } static void append_segment_overflow_test(void **state_ptr) { - struct state *state = *state_ptr; - + struct state *state = *state_ptr; d_vector_t *vec = &state->vec; - int capacity = (int)vec->dv_segment_capacity; - - assert_true(capacity + 1 < ARRAY_MAX); - - int index = 0; - int expected_count = capacity + 1; + int capacity = (int)vec->dv_segment_capacity; struct element *entry; d_vector_segment_t *seg; uint32_t idx; + assert_true(capacity + 1 < ARRAY_MAX); + /** Fill the segment completely + one more item - exceeding capacity. */ for (int i = 0; i <= capacity; i++) { int rc = d_vector_append(vec, &state->array[i]); @@ -151,17 +158,17 @@ append_segment_overflow_test(void **state_ptr) assert_int_equal(segment_count, 2); /** Verify the contents */ + int entry_count = 0; d_vector_for_each_entry(entry, seg, idx, &vec->dv_list) { - assert_memory_equal(entry, &state->array[index], vec->dv_entry_size); - index++; + assert_memory_equal(entry, &state->array[entry_count], vec->dv_entry_size); + entry_count += 1; } - assert_int_equal(index, expected_count); + assert_int_equal(entry_count, capacity + 1); d_vector_free(vec); /** Check if d_vector_free works properly */ - assert_ptr_equal(vec->dv_list.next, &vec->dv_list); - assert_ptr_equal(vec->dv_list.prev, &vec->dv_list); + assert_true(d_list_empty(&state->vec.dv_list)); } static void @@ -169,36 +176,40 @@ append_and_iterate_success(void **state_ptr) { struct state *state = *state_ptr; d_vector_t *vec = &state->vec; + int capacity = (int)vec->dv_segment_capacity; struct element *entry; d_vector_segment_t *seg; - uint32_t idx; - int index = 0; + uint32_t idx; - assert_int_equal(d_vector_size(vec), 0); + assert_true(capacity + 1 < ARRAY_MAX); for (int i = 0; i < ARRAY_MAX; ++i) { int rc = d_vector_append(vec, &state->array[i]); assert_int_equal(rc, DER_SUCCESS); } + int entry_count = 0; d_vector_for_each_entry(entry, seg, idx, &vec->dv_list) { - assert_memory_equal(entry, &state->array[index], vec->dv_entry_size); - assert_int_equal(d_vector_size(&state->vec), ARRAY_MAX); - index++; + assert_memory_equal(entry, &state->array[entry_count], vec->dv_entry_size); + entry_count += 1; } + assert_int_equal(entry_count, ARRAY_MAX); d_vector_free(&state->vec); - assert_int_equal(d_vector_size(&state->vec), 0); + + /** Check if d_vector_free works properly */ + assert_true(d_list_empty(&state->vec.dv_list)); } static const struct CMUnitTest tests_all[] = { - {"DVEC100: empty", empty_vector, setup, teardown}, - {"DVEC101: null_vector", append_null_vector_test, setup, teardown}, - {"DVEC102: null_entry", append_null_entry_test, setup, teardown}, - {"DVEC103: empty_vector", move_empty_vector_test, setup, teardown}, - {"DVEC104: double_free", double_free_test, setup, teardown}, - {"DVEC105: segment_overflow", append_segment_overflow_test, setup, teardown}, - {"DVEC106: happy_day_scenario", append_and_iterate_success, setup, teardown}, + {"DVEC100: empty", empty_vector, setup, teardown}, + {"DVEC101: null_vector", append_null_vector_test, setup, teardown}, + {"DVEC102: null_entry", append_null_entry_test, setup, teardown}, + {"DVEC103: empty_vector", move_empty_vector_test, setup, teardown}, + {"DVEC104: big_entry_size", big_entry_size_test, setup, teardown}, + {"DVEC105: double_free", double_free_test, setup, teardown}, + {"DVEC106: segment_overflow", append_segment_overflow_test, setup, teardown}, + {"DVEC107: happy_day_scenario", append_and_iterate_success, setup, teardown}, }; int From efd5adf2d0e13b2d328271f46645199963a73487 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Mon, 4 Aug 2025 14:01:57 +0200 Subject: [PATCH 04/10] run clang-format Signed-off-by: Oksana Salyk --- src/include/daos_srv/d_vector.h | 4 ++-- src/utils/dlck/tests/dlck_d_vector_ut.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/daos_srv/d_vector.h b/src/include/daos_srv/d_vector.h index eb9c9bafa2b..54c6cd2b8ac 100644 --- a/src/include/daos_srv/d_vector.h +++ b/src/include/daos_srv/d_vector.h @@ -23,8 +23,8 @@ struct d_vector { #define D_VECTOR_SEGMENT_SIZE 4096 -#define D_VECTOR_SEGMENT_HEADER \ - struct { \ +#define D_VECTOR_SEGMENT_HEADER \ + struct { \ d_list_t dvs_link; \ uint32_t dvs_len; \ uint32_t dvs_capacity; \ diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index d654a9ffba1..39a0066612b 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -144,7 +144,7 @@ append_segment_overflow_test(void **state_ptr) assert_true(capacity + 1 < ARRAY_MAX); - /** Fill the segment completely + one more item - exceeding capacity. */ + /** Fill the segment completely + one more item - exceeding capacity */ for (int i = 0; i <= capacity; i++) { int rc = d_vector_append(vec, &state->array[i]); assert_int_equal(rc, DER_SUCCESS); From b57776b4eef90e2bb64d2cade09e6e78a8ac58d7 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Mon, 4 Aug 2025 16:13:32 +0200 Subject: [PATCH 05/10] run clang-format Signed-off-by: Oksana Salyk --- src/include/daos_srv/d_vector.h | 2 +- src/utils/dlck/tests/dlck_d_vector_ut.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/daos_srv/d_vector.h b/src/include/daos_srv/d_vector.h index 54c6cd2b8ac..009540d9b34 100644 --- a/src/include/daos_srv/d_vector.h +++ b/src/include/daos_srv/d_vector.h @@ -84,7 +84,7 @@ d_vector_segment_append(d_vector_segment_t *dvs, void *entry) * \param[in] src Address of the element to append. */ static inline int -d_vector_append(d_vector_t *dst, void *src) +d_vector_append( d_vector_t *dst, void *src ) { if (dst == NULL || src == NULL) { return -DER_INVAL; diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index 39a0066612b..c355d09dad7 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -32,7 +32,7 @@ struct state { }; static int -setup(void **state_ptr) +setup( void **state_ptr ) { static struct state state; From 03b8495d1cc998c642423d1fb70049d1508a3cd4 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Mon, 4 Aug 2025 16:14:32 +0200 Subject: [PATCH 06/10] run clang-format Signed-off-by: Oksana Salyk --- src/include/daos_srv/d_vector.h | 2 +- src/utils/dlck/tests/dlck_d_vector_ut.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/daos_srv/d_vector.h b/src/include/daos_srv/d_vector.h index 009540d9b34..54c6cd2b8ac 100644 --- a/src/include/daos_srv/d_vector.h +++ b/src/include/daos_srv/d_vector.h @@ -84,7 +84,7 @@ d_vector_segment_append(d_vector_segment_t *dvs, void *entry) * \param[in] src Address of the element to append. */ static inline int -d_vector_append( d_vector_t *dst, void *src ) +d_vector_append(d_vector_t *dst, void *src) { if (dst == NULL || src == NULL) { return -DER_INVAL; diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index c355d09dad7..39a0066612b 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -32,7 +32,7 @@ struct state { }; static int -setup( void **state_ptr ) +setup(void **state_ptr) { static struct state state; From 3009f13a3c908c6f7d089f78af4055804ef7c6da Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Mon, 4 Aug 2025 16:22:02 +0200 Subject: [PATCH 07/10] fix clang-format Signed-off-by: Oksana Salyk --- src/utils/dlck/tests/dlck_d_vector_ut.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index 39a0066612b..c2ac4882115 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -80,7 +80,7 @@ static void append_null_vector_test(void **state_ptr) { struct state *state = *state_ptr; - int rc = d_vector_append(NULL, &state->array[0]); + int rc = d_vector_append(NULL, &state->array[0]); assert_int_equal(rc, -DER_INVAL); } @@ -88,7 +88,7 @@ static void append_null_entry_test(void **state_ptr) { struct state *state = *state_ptr; - int rc = d_vector_append(&state->vec, NULL); + int rc = d_vector_append(&state->vec, NULL); assert_int_equal(rc, -DER_INVAL); } @@ -96,7 +96,7 @@ static void move_empty_vector_test(void **state_ptr) { struct state *state = *state_ptr; - d_vector_t empty; + d_vector_t empty; d_vector_init(sizeof(struct element), &empty); d_vector_move(&state->vec, &empty); @@ -136,7 +136,7 @@ static void append_segment_overflow_test(void **state_ptr) { struct state *state = *state_ptr; - d_vector_t *vec = &state->vec; + d_vector_t *vec = &state->vec; int capacity = (int)vec->dv_segment_capacity; struct element *entry; d_vector_segment_t *seg; @@ -174,10 +174,10 @@ append_segment_overflow_test(void **state_ptr) static void append_and_iterate_success(void **state_ptr) { - struct state *state = *state_ptr; - d_vector_t *vec = &state->vec; + struct state *state = *state_ptr; + d_vector_t *vec = &state->vec; int capacity = (int)vec->dv_segment_capacity; - struct element *entry; + struct element *entry; d_vector_segment_t *seg; uint32_t idx; From 1b213dda309b11c72680477a218a858535aa5d71 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Tue, 5 Aug 2025 10:25:00 +0200 Subject: [PATCH 08/10] add new test cases Signed-off-by: Oksana Salyk --- src/utils/dlck/tests/dlck_d_vector_ut.c | 77 ++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index c2ac4882115..8d5fef99ba1 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -92,6 +92,26 @@ append_null_entry_test(void **state_ptr) assert_int_equal(rc, -DER_INVAL); } +static void +init_large_entry_size_test(void **state_ptr) +{ + /** entry_size larger than segment raw capacity */ + d_vector_t vec_large; + size_t large_size = D_VECTOR_SEGMENT_RAW_CAPACITY + 1; + d_vector_init(large_size, &vec_large); + assert_true(d_list_empty(&vec_large.dv_list)); +} + +static void +init_misaligned_entry_size_test(void **state_ptr) +{ + /** entry_size not perfectly divisible into segment raw capacity */ + d_vector_t vec_misaligned; + size_t misaligned_size = D_VECTOR_SEGMENT_RAW_CAPACITY / 3; + d_vector_init(misaligned_size, &vec_misaligned); + assert_true(d_list_empty(&vec_misaligned.dv_list)); +} + static void move_empty_vector_test(void **state_ptr) { @@ -105,6 +125,46 @@ move_empty_vector_test(void **state_ptr) assert_int_equal(d_vector_size(&state->vec), 0); } +static void +move_populated_vector_test(void **state_ptr) +{ + struct state *state = *state_ptr; + d_vector_t target; + + d_vector_init(sizeof(struct element), &target); + + /** Plan to overload one segmentation */ + int total_entries = (int)(state->vec.dv_segment_capacity * 2 + 1); + assert_true(total_entries < ARRAY_MAX); + + for (int i = 0; i < total_entries; i++) { + int rc = d_vector_append(&state->vec, &state->array[i]); + assert_int_equal(rc, DER_SUCCESS); + } + + /** Move data to terget */ + d_vector_move(&target, &state->vec); + + /** The original vector should be empty */ + assert_int_equal(d_vector_size(&state->vec), 0); + assert_true(d_list_empty(&state->vec.dv_list)); + + /** Target should include data */ + struct element *entry; + d_vector_segment_t *seg; + uint32_t idx; + int count = 0; + + d_vector_for_each_entry(entry, seg, idx, &target.dv_list) { + assert_memory_equal(entry, &state->array[count], target.dv_entry_size); + count += 1; + } + + assert_int_equal(count, total_entries); + + d_vector_free(&target); +} + static void big_entry_size_test(void **state_ptr) { @@ -126,10 +186,10 @@ double_free_test(void **state_ptr) } d_vector_free(&state->vec); - assert_false(d_vector_size(&state->vec)); + assert_int_equal(d_vector_size(&state->vec), 0); d_vector_free(&state->vec); - assert_false(d_vector_size(&state->vec)); + assert_int_equal(d_vector_size(&state->vec), 0); } static void @@ -205,11 +265,14 @@ static const struct CMUnitTest tests_all[] = { {"DVEC100: empty", empty_vector, setup, teardown}, {"DVEC101: null_vector", append_null_vector_test, setup, teardown}, {"DVEC102: null_entry", append_null_entry_test, setup, teardown}, - {"DVEC103: empty_vector", move_empty_vector_test, setup, teardown}, - {"DVEC104: big_entry_size", big_entry_size_test, setup, teardown}, - {"DVEC105: double_free", double_free_test, setup, teardown}, - {"DVEC106: segment_overflow", append_segment_overflow_test, setup, teardown}, - {"DVEC107: happy_day_scenario", append_and_iterate_success, setup, teardown}, + {"DVEC103: large_entry_size", init_large_entry_size_test, setup, teardown}, + {"DVEC104: misaligned_entry_size", init_misaligned_entry_size_test, setup, teardown}, + {"DVEC105: empty_vector", move_empty_vector_test, setup, teardown}, + {"DVEC106: move_populated_vector", move_populated_vector_test, setup, teardown}, + {"DVEC107: big_entry_size", big_entry_size_test, setup, teardown}, + {"DVEC108: double_free", double_free_test, setup, teardown}, + {"DVEC109: segment_overflow", append_segment_overflow_test, setup, teardown}, + {"DVEC110: happy_day_scenario", append_and_iterate_success, setup, teardown}, }; int From 7867ea760e735f994bd259603bf296912c1bb38c Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Wed, 6 Aug 2025 22:25:44 +0200 Subject: [PATCH 09/10] Fixes after code review Signed-off-by: Oksana Salyk --- src/include/daos_srv/d_vector.h | 1 + src/utils/dlck/tests/dlck_d_vector_ut.c | 42 +++++++------------------ 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/src/include/daos_srv/d_vector.h b/src/include/daos_srv/d_vector.h index 54c6cd2b8ac..4cc06887258 100644 --- a/src/include/daos_srv/d_vector.h +++ b/src/include/daos_srv/d_vector.h @@ -122,6 +122,7 @@ d_vector_init(size_t entry_size, d_vector_t *dv) { memset(dv, 0, sizeof(d_vector_t)); dv->dv_entry_size = entry_size; + D_ASSERT(entry_size <= D_VECTOR_SEGMENT_RAW_CAPACITY); dv->dv_segment_capacity = D_VECTOR_SEGMENT_RAW_CAPACITY / entry_size; D_INIT_LIST_HEAD(&dv->dv_list); } diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index 8d5fef99ba1..4f6d8580d4e 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -93,23 +93,12 @@ append_null_entry_test(void **state_ptr) } static void -init_large_entry_size_test(void **state_ptr) +init_too_big_entry_size_test(void **state_ptr) { /** entry_size larger than segment raw capacity */ d_vector_t vec_large; size_t large_size = D_VECTOR_SEGMENT_RAW_CAPACITY + 1; - d_vector_init(large_size, &vec_large); - assert_true(d_list_empty(&vec_large.dv_list)); -} - -static void -init_misaligned_entry_size_test(void **state_ptr) -{ - /** entry_size not perfectly divisible into segment raw capacity */ - d_vector_t vec_misaligned; - size_t misaligned_size = D_VECTOR_SEGMENT_RAW_CAPACITY / 3; - d_vector_init(misaligned_size, &vec_misaligned); - assert_true(d_list_empty(&vec_misaligned.dv_list)); + expect_assert_failure(d_vector_init(large_size, &vec_large)) } static void @@ -149,7 +138,7 @@ move_populated_vector_test(void **state_ptr) assert_int_equal(d_vector_size(&state->vec), 0); assert_true(d_list_empty(&state->vec.dv_list)); - /** Target should include data */ + /** Target should contain data */ struct element *entry; d_vector_segment_t *seg; uint32_t idx; @@ -165,15 +154,6 @@ move_populated_vector_test(void **state_ptr) d_vector_free(&target); } -static void -big_entry_size_test(void **state_ptr) -{ - d_vector_t vec; - size_t entry_size = D_VECTOR_SEGMENT_RAW_CAPACITY + 8; - d_vector_init(entry_size, &vec); - assert_true(d_vector_size(&vec) == 0); -} - static void double_free_test(void **state_ptr) { @@ -265,14 +245,12 @@ static const struct CMUnitTest tests_all[] = { {"DVEC100: empty", empty_vector, setup, teardown}, {"DVEC101: null_vector", append_null_vector_test, setup, teardown}, {"DVEC102: null_entry", append_null_entry_test, setup, teardown}, - {"DVEC103: large_entry_size", init_large_entry_size_test, setup, teardown}, - {"DVEC104: misaligned_entry_size", init_misaligned_entry_size_test, setup, teardown}, - {"DVEC105: empty_vector", move_empty_vector_test, setup, teardown}, - {"DVEC106: move_populated_vector", move_populated_vector_test, setup, teardown}, - {"DVEC107: big_entry_size", big_entry_size_test, setup, teardown}, - {"DVEC108: double_free", double_free_test, setup, teardown}, - {"DVEC109: segment_overflow", append_segment_overflow_test, setup, teardown}, - {"DVEC110: happy_day_scenario", append_and_iterate_success, setup, teardown}, + {"DVEC103: too_big_entry_size", init_too_big_entry_size_test, NULL, NULL}, + {"DVEC104: empty_vector", move_empty_vector_test, setup, teardown}, + {"DVEC105: move_populated_vector", move_populated_vector_test, setup, teardown}, + {"DVEC106: double_free", double_free_test, setup, teardown}, + {"DVEC107: segment_overflow", append_segment_overflow_test, setup, teardown}, + {"DVEC108: happy_day_scenario", append_and_iterate_success, setup, teardown}, }; int @@ -280,5 +258,7 @@ main(int argc, char **argv) { const char *test_name = "d_vector_t tests"; + d_register_alt_assert(mock_assert); + return cmocka_run_group_tests_name(test_name, tests_all, NULL, NULL); } From 121db23269f3a1efbf5dd3d4c0cfe14ea9eae142 Mon Sep 17 00:00:00 2001 From: Oksana Salyk Date: Fri, 8 Aug 2025 06:59:54 +0200 Subject: [PATCH 10/10] comment update Signed-off-by: Oksana Salyk --- src/utils/dlck/tests/dlck_d_vector_ut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/dlck/tests/dlck_d_vector_ut.c b/src/utils/dlck/tests/dlck_d_vector_ut.c index 4f6d8580d4e..5779aff839a 100644 --- a/src/utils/dlck/tests/dlck_d_vector_ut.c +++ b/src/utils/dlck/tests/dlck_d_vector_ut.c @@ -122,7 +122,7 @@ move_populated_vector_test(void **state_ptr) d_vector_init(sizeof(struct element), &target); - /** Plan to overload one segmentation */ + /** Overload two segment. Three segments in total. */ int total_entries = (int)(state->vec.dv_segment_capacity * 2 + 1); assert_true(total_entries < ARRAY_MAX);