From 598d381379c644b1c573627a5437a92d14b6ecf4 Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Thu, 26 Feb 2026 14:39:12 +0800 Subject: [PATCH] improve xkvmgr and testsuite for scheduler --- src/flake.lock | 8 +- src/include/attrs.h | 7 ++ src/include/kvmgr.h | 2 + src/lib/kvmgr.c | 114 ++++++++++++++++++-- src/lib/testsuite/test_kvmgr.c | 161 ++++++++++++++++++---------- src/lib/zarray.c | 1 + src/scheduler/include/scheduler.h | 1 + src/scheduler/meson.build | 2 + src/scheduler/testsuite/meson.build | 13 +++ src/scheduler/testsuite/test.c | 82 ++++++++++++++ 10 files changed, 327 insertions(+), 64 deletions(-) create mode 100644 src/include/attrs.h create mode 100644 src/scheduler/testsuite/meson.build create mode 100644 src/scheduler/testsuite/test.c diff --git a/src/flake.lock b/src/flake.lock index e0ed8bcf..baeb7be1 100644 --- a/src/flake.lock +++ b/src/flake.lock @@ -117,11 +117,11 @@ "xbuild": "xbuild" }, "locked": { - "lastModified": 1771560785, - "narHash": "sha256-0iyZt6UrIyYS3gCGNuUma2l7O92LS48XAm9HPd4bEN0=", + "lastModified": 1772074796, + "narHash": "sha256-zcEQs+slX7r7C1u9VFvWXTU8BIRt7RmaDu6/mNHHrLc=", "ref": "master", - "rev": "724c740909879b6b5d8851809f2aead7362bc78f", - "revCount": 17, + "rev": "f66de934830db47db651e83f6c8e466cca19dd54", + "revCount": 18, "type": "git", "url": "ssh://forgejo@gitea.shenrs.eu/rshen/librtti" }, diff --git a/src/include/attrs.h b/src/include/attrs.h new file mode 100644 index 00000000..646c70a8 --- /dev/null +++ b/src/include/attrs.h @@ -0,0 +1,7 @@ +#if !defined(_ATTRS_H_) + +#define _ATTRS_H_ 1 + +#define ATTR_ID ((void *)(long)0) + +#endif diff --git a/src/include/kvmgr.h b/src/include/kvmgr.h index 29805d82..1d8569c4 100644 --- a/src/include/kvmgr.h +++ b/src/include/kvmgr.h @@ -78,4 +78,6 @@ typedef struct { destroy_fn_t datakiller; } kvmgr_params_t; +extern typeinfo_t xkvmgr_type; + #endif diff --git a/src/lib/kvmgr.c b/src/lib/kvmgr.c index dd171d2b..816980b0 100644 --- a/src/lib/kvmgr.c +++ b/src/lib/kvmgr.c @@ -430,7 +430,7 @@ static int xkvmgr_init(meta_obj_t* obj, va_list ap) } kv_params.nslots = params->nslots; - kv_params.datakiller = params->datakiller; + kv_params.datakiller = NULL; switch (params->key_type) { case KVMGR_KEY_INT: @@ -496,12 +496,25 @@ static int xkvmgr_add(meta_obj_t* obj, void* key, void* value) xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj); int rc; xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj); + int idx; if (kvm->dynamic) { my_rwlock_wlock(&(priv->lock)); } - rc = key_add(kvm->kvtab, key, value); + rc = vstore(kvm->data, value); + + if (rc >= 0) { + idx = rc; + + rc = key_add(kvm->kvtab, key, (void*)(long)idx); + + if (rc >= 0) { + rc = idx; + } else { + vclear(kvm->data, idx); + } + } if (kvm->dynamic) { my_rwlock_unlock(&(priv->lock)); @@ -515,12 +528,23 @@ static int xkvmgr_find(meta_obj_t* obj, void* key, void** value) xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj); int rc; xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj); + void* data; + + *value = NULL; if (kvm->dynamic) { my_rwlock_rlock(&(priv->lock)); } - rc = key_find(kvm->kvtab, key, value); + rc = key_find(kvm->kvtab, key, &data); + if (rc >= 0) { + int idx = (int)(long)data; + + rc = vget(kvm->data, idx, &data); + if (rc >= 0) { + *value = data; + } + } if (kvm->dynamic) { my_rwlock_unlock(&(priv->lock)); @@ -587,6 +611,78 @@ static void xkvmgr_iter_destroy(iterator_t* iter) return; } +static int xkvmgr_get_vec(meta_obj_t* obj, int count, int* idxs, void** data) +{ + xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj); + xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj); + int rc = 0; + + if (kvm->dynamic) { + my_rwlock_rlock(&(priv->lock)); + } + rc = vget_vec(kvm->data, count, idxs, data); + + if (kvm->dynamic) { + my_rwlock_unlock(&(priv->lock)); + } + + return rc; +} + +static int xkvmgr_get(meta_obj_t* obj, int idx, void** data) +{ + xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj); + xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj); + int rc = 0; + + if (kvm->dynamic) { + my_rwlock_rlock(&(priv->lock)); + } + rc = vget(kvm->data, idx, data); + + if (kvm->dynamic) { + my_rwlock_unlock(&(priv->lock)); + } + + return rc; +} + +static int xkvmgr_put_vec(meta_obj_t* obj, int count, int* idxs, void** data) +{ + xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj); + xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj); + int rc = 0; + + if (kvm->dynamic) { + my_rwlock_wlock(&(priv->lock)); + } + rc = vput_vec(kvm->data, count, idxs, data); + + if (kvm->dynamic) { + my_rwlock_unlock(&(priv->lock)); + } + + return rc; +} + +static int xkvmgr_put(meta_obj_t* obj, int idx, void* data) +{ + xkvmgr_t* kvm = RTTI_OBJ_TO_DATA(xkvmgr_t, obj); + xkvmgr_private_t* priv = RTTI_OBJ_TO_PRIV(obj); + int rc = 0; + + if (kvm->dynamic) { + my_rwlock_wlock(&(priv->lock)); + } + rc = vput(kvm->data, idx, data); + + if (kvm->dynamic) { + my_rwlock_unlock(&(priv->lock)); + } + + return rc; +} + typeinfo_t xkvmgr_type = { .name = "xkvmgr", .privateSize = sizeof(xkvmgr_private_t), @@ -594,9 +690,15 @@ typeinfo_t xkvmgr_type = { .init = (obj_init_fn_t)xkvmgr_init, .destroy = (obj_destroy_fn_t)xkvmgr_destroy, .interfaces - = { .kv = &(intf_kv_t) { .add_key = (key_add_fn_t)xkvmgr_add, - .del_key = (key_del_fn_t)NULL, - .find_key = (key_find_fn_t)xkvmgr_find }, + = { .kv = &(intf_kv_t) { .add_key = (key_add_fn_t)xkvmgr_add, + .del_key = (key_del_fn_t)NULL, + .find_key = (key_find_fn_t)xkvmgr_find }, + .varray = &(intf_varray_t) { .vstore = (vstore_fn_t)NULL, + .vget = (vget_fn_t)xkvmgr_get, + .vget_vec = (vget_vec_fn_t)xkvmgr_get_vec, + .vput = (vput_fn_t)xkvmgr_put, + .vput_vec = (vput_vec_fn_t)xkvmgr_put_vec, + .vclear = (vclear_fn_t)NULL }, .iter = &(intf_iterator_t) { .make = (iter_make_fn_t)xkvmgr_make_iter, .next = (iter_next_fn_t)xkvmgr_iter_next, diff --git a/src/lib/testsuite/test_kvmgr.c b/src/lib/testsuite/test_kvmgr.c index 4fe1d9a3..292cae9f 100644 --- a/src/lib/testsuite/test_kvmgr.c +++ b/src/lib/testsuite/test_kvmgr.c @@ -1,76 +1,129 @@ +#include #include #include +#include +#include "kv.h" #include "kvmgr.h" -#include -#include "objmgr.h" +#include "utils.h" typedef struct { char* key; int data; } kv_data_t; -static void test_kvadd(void) +static void test_kvmgr_create(void) { - kvmgr_t mgr; - char *key = "key1"; - kv_data_t data = { .key = key, .data = 100 }; - kv_data_t* p = NULL; + kvmgr_params_t params = { .key_type = KVMGR_KEY_STRING, + .dynamic = 0, + .nslots = 4, + .delta = 4, + .datakiller = NULL }; + var kvmgr = makeInstance(&xkvmgr_type, ¶ms); - kvmgr_init(&mgr, string_hash_key, 4, 4, NULL); - kvmgr_add(&mgr, key, &data); - p = kvmgr_lock(&mgr, key, OBJREF_NOP); - TEST_ASSERT_TRUE(p != NULL); - TEST_ASSERT_TRUE(p == &data); - kvmgr_fini(&mgr); + TEST_ASSERT_TRUE(kvmgr != NULL); + + destroy(kvmgr); } -static void test_kvput(void) -{ - kvmgr_t mgr; - char *key = "key1"; - kv_data_t data = { .key = key, .data = 100 }; - kv_data_t* p = NULL; - int idx = 10; +typedef struct { + char* name; + uint16_t age; +} user_t; - kvmgr_init(&mgr, string_hash_key, 4, 4, NULL); - kvmgr_put(&mgr, key, idx, &data); - p = kvmgr_lock(&mgr, key, OBJREF_NOP); - TEST_ASSERT_TRUE(p != NULL); - TEST_ASSERT_TRUE(p == &data); - p = kvmgr_lock_byid(&mgr, idx, OBJREF_NOP); - TEST_ASSERT_TRUE(p != NULL); - TEST_ASSERT_TRUE(p == &data); +static void my_user_killer(void* data) +{ + user_t* u = (user_t*)data; + + if (u == NULL) { + return; + } + + FREEUP(u->name); + FREEUP(u); +} + +static void test_kvmgr_add(void) +{ + kvmgr_params_t params = { .key_type = KVMGR_KEY_STRING, + .dynamic = 0, + .nslots = 4, + .delta = 4, + .datakiller = my_user_killer }; + var kvmgr = makeInstance(&xkvmgr_type, ¶ms); + user_t* u = NULL; + int rc = 0; + void* data = NULL; + + TEST_ASSERT_TRUE(kvmgr != NULL); + + u = calloc(1, sizeof(*u)); + TEST_ASSERT_TRUE(u != NULL); + + u->name = strdup("tester1"); + TEST_ASSERT_TRUE(u->name != NULL); + + u->age = 32; + + rc = key_add(kvmgr, (void*)u->name, (void*)u); + TEST_ASSERT_TRUE(rc >= 0); + + rc = key_find(kvmgr, (void*)u->name, &data); + TEST_ASSERT_TRUE(rc >= 0); + + TEST_ASSERT_TRUE(data == u); + + destroy(kvmgr); +} + +static void test_kvmgr_iter(void) +{ + kvmgr_params_t params = { .key_type = KVMGR_KEY_INT, + .dynamic = 0, + .nslots = 4, + .delta = 4, + .datakiller = NULL }; + var kvmgr = makeInstance(&xkvmgr_type, ¶ms); + int rc = 0; + int i; + iterator_t it; + + TEST_ASSERT_TRUE(kvmgr != NULL); + + for (i = 0; i < 10; i++) { + rc = key_add(kvmgr, (void*)(long)i, (void*)(long)(i * i)); + TEST_ASSERT_TRUE(rc >= 0); + } + + rc = iter_make(&it, kvmgr); + TEST_ASSERT_TRUE(rc >= 0); + + i = 0; + for (;;) { + void* data; + + rc = iter_next(&it, &data); + TEST_ASSERT_TRUE(rc >= 0); + + if (rc == RTTI_ITER_NO_DATA) { + break; + } + + TEST_ASSERT_TRUE((int)(long)data == i * i); + i++; + } + + TEST_ASSERT_TRUE(i == 10); + + iter_destroy(&it); - kvmgr_fini(&mgr); + destroy(kvmgr); } -static void test_kvdel(void) -{ - kvmgr_t mgr; - char *key = "key1"; - kv_data_t data = { .key = key, .data = 100 }; - kv_data_t* p = NULL; - - kvmgr_init(&mgr, string_hash_key, 4, 4, NULL); - kvmgr_add(&mgr, key, &data); - p = kvmgr_lock(&mgr, key, OBJREF_NOP); - TEST_ASSERT_TRUE(p != NULL); - TEST_ASSERT_TRUE(p == &data); - - kvmgr_del(&mgr, key); - p = kvmgr_lock(&mgr, key, OBJREF_NOP); - - TEST_ASSERT_TRUE( p == NULL); - - kvmgr_fini(&mgr); -} - - void test_kvmgr(void) { printf("\n>> kvmgr test\n"); - RUN_TEST(test_kvadd); - RUN_TEST(test_kvput); - RUN_TEST(test_kvdel); + RUN_TEST(test_kvmgr_create); + RUN_TEST(test_kvmgr_add); + RUN_TEST(test_kvmgr_iter); } diff --git a/src/lib/zarray.c b/src/lib/zarray.c index 64d4dcce..c6a136e8 100644 --- a/src/lib/zarray.c +++ b/src/lib/zarray.c @@ -471,6 +471,7 @@ static int xzarray_store(meta_obj_t* obj, void* data) a->count++; rc = idx; + break; } idx++; diff --git a/src/scheduler/include/scheduler.h b/src/scheduler/include/scheduler.h index 7035646d..629d8e02 100644 --- a/src/scheduler/include/scheduler.h +++ b/src/scheduler/include/scheduler.h @@ -3,6 +3,7 @@ #define _SCHEDULER_H_ 1 #include +#include #include #include diff --git a/src/scheduler/meson.build b/src/scheduler/meson.build index 0053cb8d..ccc3e8b2 100644 --- a/src/scheduler/meson.build +++ b/src/scheduler/meson.build @@ -31,3 +31,5 @@ scheduler = executable('xce_scheduler', dependencies: scheduler_deps, link_args: wrap_link_args, install: true) + +subdir('testsuite') diff --git a/src/scheduler/testsuite/meson.build b/src/scheduler/testsuite/meson.build new file mode 100644 index 00000000..c1fa551f --- /dev/null +++ b/src/scheduler/testsuite/meson.build @@ -0,0 +1,13 @@ +scheduler_test_src = [ + 'test.c' +] + +scheduler_test_deps = [libxce_deps, librtti_dep, unity_dep] + +incdir = include_directories('../include', '../../include', '.') + +scheduler_test = executable('sched_test', + scheduler_test_src, + include_directories:[incdir], + dependencies: [scheduler_test_deps], + install: false) diff --git a/src/scheduler/testsuite/test.c b/src/scheduler/testsuite/test.c new file mode 100644 index 00000000..4e4dc2d4 --- /dev/null +++ b/src/scheduler/testsuite/test.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include + +void setUp() { return; } + +void tearDown(void) +{ + printf("\n-----------------------------------------------------\n"); + return; +} + +static char doc[] = "sched_test"; +static char args_doc[] = ""; + +#define MAX_TESTS (256) + +struct arguments { + int ntests; + char* tests[MAX_TESTS]; +}; + +static struct argp_option options[] = { + { "run", 't', "STR", 0, "run test" }, + { 0 } +}; + +static error_t parse_opt(int key, char* arg, struct argp_state* state) +{ + struct arguments* arguments = state->input; + + switch (key) { + case 't': + if (arguments->ntests >= MAX_TESTS) { + fprintf(stderr, "Too many tests\n"); + exit(-1); + } + arguments->tests[arguments->ntests] = arg; + arguments->ntests++; + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; +struct arguments arguments; + +static int check_test(struct arguments* args, char* x) +{ + int i; + + if (args->ntests == 0) { + return 1; + } + for (i = 0; i < args->ntests; i++) { + if (strcmp(x, args->tests[i]) == 0) { + return 1; + } + } + return 0; +} + +#define TEST(x) \ + do { \ + if (check_test(&arguments, #x)) { \ + x(); \ + } \ + } while (0) + +int main(int argc, char* argv[]) +{ + argp_parse(&argp, argc, argv, 0, 0, &arguments); + + UNITY_BEGIN(); + + return UNITY_END(); +}