improve xkvmgr and testsuite for scheduler

This commit is contained in:
Rongsong Shen 2026-02-26 14:39:12 +08:00
parent 2ee87d4ee6
commit 598d381379
10 changed files with 327 additions and 64 deletions

8
src/flake.lock generated
View file

@ -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"
},

7
src/include/attrs.h Normal file
View file

@ -0,0 +1,7 @@
#if !defined(_ATTRS_H_)
#define _ATTRS_H_ 1
#define ATTR_ID ((void *)(long)0)
#endif

View file

@ -78,4 +78,6 @@ typedef struct {
destroy_fn_t datakiller;
} kvmgr_params_t;
extern typeinfo_t xkvmgr_type;
#endif

View file

@ -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,

View file

@ -1,76 +1,129 @@
#include <rtti.h>
#include <stdio.h>
#include <stdlib.h>
#include <unity/unity.h>
#include "kv.h"
#include "kvmgr.h"
#include <unity.h>
#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, &params);
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, &params);
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, &params);
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);
}

View file

@ -471,6 +471,7 @@ static int xzarray_store(meta_obj_t* obj, void* data)
a->count++;
rc = idx;
break;
}
idx++;

View file

@ -3,6 +3,7 @@
#define _SCHEDULER_H_ 1
#include <pthread.h>
#include <rtti.h>
#include <stdint.h>
#include <time.h>

View file

@ -31,3 +31,5 @@ scheduler = executable('xce_scheduler',
dependencies: scheduler_deps,
link_args: wrap_link_args,
install: true)
subdir('testsuite')

View file

@ -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)

View file

@ -0,0 +1,82 @@
#include <argp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unity/unity.h>
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();
}