fix(test): New self-testing of kernel units has been added.

This commit is contained in:
MacRsh
2025-08-13 23:46:50 +08:00
parent 1d811d8c8c
commit 47a9f061f6
8 changed files with 331 additions and 10 deletions

View File

@@ -76,14 +76,14 @@ static void irq_defer_hook_suspend(void *priv) {
MR_UNUSED(priv);
/* Clear soft irq */
SysTick->CTLR &= ~(1 << 31);
SysTick->CTLR &= ~(1U << 31);
}
static void irq_defer_hook_wakeup(void *priv) {
MR_UNUSED(priv);
/* Trigger soft irq */
SysTick->CTLR |= (1 << 31);
SysTick->CTLR |= (1U << 31);
}
void SW_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

View File

@@ -14,7 +14,7 @@ extern "C" {
#endif /* __cplusplus */
/**
* @addtogroup Port-IRQ
* @addtogroup Port-irq
* @{
*/

View File

@@ -26,11 +26,11 @@ mr_uint32_t mr_fifo_init(mr_fifo_t *fifo, void *buf, mr_uint32_t size,
size = FIFO_ALIGN_POW2_DOWN(size / elemsz);
/* Init fifo */
fifo->buf = buf;
fifo->mask = size - 1;
mr_atomic_init(&fifo->ridx, 0);
mr_atomic_init(&fifo->widx, 0);
fifo->elemsz = elemsz;
fifo->mask = size - 1;
fifo->buf = buf;
return size;
}

View File

@@ -254,6 +254,7 @@ static mr_irq_action_t *irq_action_alloc(mr_uint32_t irq, mr_irq_entry_t *entry,
action->defer_entry = defer_entry;
#else
MR_UNUSED(defer_entry);
MR_UNUSED(ret);
#endif /* MR_USE_IRQ_DEFER */
/* Init irq action */

View File

@@ -43,7 +43,6 @@ static void irq_unmask(mr_uint32_t irq, void *priv) {
static void irq_disable(mr_uint32_t irq, void *priv) {
MR_UNUSED(priv);
last_irq = (mr_int32_t)irq;
}
@@ -65,7 +64,6 @@ static mr_irq_ops_t mock_irq_ops = {
static mr_irq_return_t test_irq_handler(mr_uint32_t irq, void *owner) {
MR_UNUSED(irq);
MR_UNUSED(owner);
handle_count++;
return MR_IRQ_HANDLED;
}

View File

@@ -19,7 +19,6 @@ static void test_waiter_cb(mr_waiter_t *waiter, void *param,
mr_uint32_t event) {
MR_UNUSED(waiter);
MR_UNUSED(param);
trig_status++;
last_event = event;
last_param = param;
@@ -225,7 +224,6 @@ static mr_uint32_t test_check_race(mr_waitable_t *w, void *p) {
static mr_uint32_t gen = 0;
MR_UNUSED(p);
if ((gen++) == 0)
{
mr_waitable_complete(w);

324
test/kernel/workqueue.c Normal file
View File

@@ -0,0 +1,324 @@
/**
* @copyright (c) 2024-2025, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2024-09-06 MacRsh First version
*/
#include <test/mr_test.h>
#if defined(MR_USE_TEST)
#if defined(MR_USE_WORKQUEUE)
#include <mr-X/mr_workqueue.h>
static void *last_param = MR_NULL;
static int work_run_count = 0;
static void test_work_entry(struct mr_work *work, void *param) {
MR_UNUSED(work);
work_run_count++;
last_param = param;
}
/* -------------------------------------------------------------------------- */
/* Test: Workqueue init / del */
static void test_workqueue_init_del(void) {
mr_workqueue_t queue;
mr_err_t ret;
ret = mr_workqueue_init(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&queue), MR_TRUE);
ret = mr_workqueue_del(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&queue), MR_FALSE);
}
MR_TEST_EXPORT(workqueue, init_del, test_workqueue_init_del);
/* -------------------------------------------------------------------------- */
/* Test: Workqueue create / del */
static void test_workqueue_create_del(void) {
mr_workqueue_t *queue;
mr_err_t ret;
queue = mr_workqueue_create();
MR_TEST_ASSERT_NE_PTR(queue, MR_NULL);
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(queue), MR_TRUE);
ret = mr_workqueue_del(queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
}
MR_TEST_EXPORT(workqueue, create_del, test_workqueue_create_del);
/* -------------------------------------------------------------------------- */
/* Test: Work init / del */
static void test_work_init_del(void) {
mr_work_t work;
mr_err_t ret;
ret = mr_work_init(&work, test_work_entry, (void *)0x1234);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&work), MR_TRUE);
ret = mr_work_del(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&work), MR_FALSE);
}
MR_TEST_EXPORT(workqueue, work_init_del, test_work_init_del);
/* -------------------------------------------------------------------------- */
/* Test: Work create / del */
static void test_work_create_del(void) {
mr_work_t *work;
mr_err_t ret;
work = mr_work_create(test_work_entry, (void *)0x5678);
MR_TEST_ASSERT_NE_PTR(work, MR_NULL);
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(work), MR_TRUE);
ret = mr_work_del(work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
}
MR_TEST_EXPORT(workqueue, work_create_del, test_work_create_del);
/* -------------------------------------------------------------------------- */
/* Test: Work bind / schedule / execute */
static void test_work_schedule_execute(void) {
mr_workqueue_t queue;
mr_work_t work;
mr_err_t ret;
ret = mr_workqueue_init(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_init(&work, test_work_entry, (void *)0xABCD);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_schedule(&work);
MR_TEST_ASSERT_EQ_INT(ret, -MR_ENOENT);
ret = mr_work_bind(&work, &queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_schedule(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
work_run_count = 0;
ret = mr_workqueue_execute(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(work_run_count, 1);
MR_TEST_ASSERT_EQ_PTR(last_param, (void *)0xABCD);
ret = mr_work_del(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_workqueue_del(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
}
MR_TEST_EXPORT(workqueue, schedule_execute, test_work_schedule_execute);
/* -------------------------------------------------------------------------- */
/* Test: Work delayed schedule */
static void test_work_delayed_schedule(void) {
mr_work_t work, work1;
mr_workqueue_t queue;
mr_err_t ret;
ret = mr_workqueue_init(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_init(&work, test_work_entry, (void *)0xDEAD);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_delayed_schedule(&work, 10);
MR_TEST_ASSERT_EQ_INT(ret, -MR_ENOENT);
ret = mr_work_bind(&work, &queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_init(&work1, test_work_entry, (void *)0xDEAD);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_bind(&work1, &queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_delayed_schedule(&work, 10);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_delayed_schedule(&work, 10);
MR_TEST_ASSERT_EQ_INT(ret, -MR_EBUSY);
ret = mr_work_delayed_schedule(&work1, 20);
MR_TEST_ASSERT_EQ_INT(ret, 0);
mr_clock_increase(10);
work_run_count = 0;
ret = mr_workqueue_execute(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(work_run_count, 1);
MR_TEST_ASSERT_EQ_PTR(last_param, (void *)0xDEAD);
ret = mr_work_delayed_schedule(&work, 0);
MR_TEST_ASSERT_EQ_INT(ret, 0);
mr_clock_increase(10);
mr_work_cancel(&work1);
ret = mr_work_delayed_schedule(&work1, 10);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_workqueue_del(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_del(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_del(&work1);
MR_TEST_ASSERT_EQ_INT(ret, 0);
}
MR_TEST_EXPORT(workqueue, delayed_schedule, test_work_delayed_schedule);
/* -------------------------------------------------------------------------- */
/* Test: Work cancel */
static void test_work_cancel(void) {
mr_workqueue_t queue;
mr_work_t work;
mr_err_t ret;
ret = mr_workqueue_init(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_init(&work, test_work_entry, MR_NULL);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_bind(&work, &queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_schedule(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_cancel(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
work_run_count = 0;
ret = mr_workqueue_execute(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(work_run_count, 0);
ret = mr_work_del(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_workqueue_del(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
}
MR_TEST_EXPORT(workqueue, work_cancel, test_work_cancel);
/* -------------------------------------------------------------------------- */
/* Test: Work is running */
static void test_work_is_running(void) {
mr_workqueue_t queue;
mr_work_t work;
mr_err_t ret;
ret = mr_workqueue_init(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_init(&work, test_work_entry, MR_NULL);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_bind(&work, &queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(MR_WORK_IS_RUNNING(&work), MR_FALSE);
ret = mr_work_schedule(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(MR_WORK_IS_RUNNING(&work), MR_TRUE);
ret = mr_work_schedule(&work);
MR_TEST_ASSERT_NE_INT(ret, 0);
ret = mr_work_cancel(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(MR_WORK_IS_RUNNING(&work), MR_FALSE);
ret = mr_work_del(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_workqueue_del(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
}
MR_TEST_EXPORT(workqueue, work_is_running, test_work_is_running);
#if defined(MR_USE_WORKQUEUE_HOOK)
static int hook_suspend_called = 0;
static int hook_wakeup_called = 0;
static void test_hook_suspend(struct mr_workqueue *queue, void *param) {
MR_UNUSED(queue);
MR_UNUSED(param);
hook_suspend_called = 1;
}
static void test_hook_wakeup(struct mr_workqueue *queue, void *param) {
MR_UNUSED(queue);
MR_UNUSED(param);
hook_wakeup_called = 1;
}
static void test_workqueue_hook(void) {
mr_workqueue_hook_t hook = {.suspend = test_hook_suspend,
.wakeup = test_hook_wakeup,
.param = MR_NULL};
mr_work_t work, work1;
mr_workqueue_t queue;
mr_err_t ret;
ret = mr_workqueue_init(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
mr_workqueue_hook_set(&queue, &hook);
ret = mr_work_init(&work, test_work_entry, MR_NULL);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_bind(&work, &queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_init(&work1, test_work_entry, MR_NULL);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_bind(&work1, &queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
hook_wakeup_called = 0;
ret = mr_work_schedule(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(hook_wakeup_called, 1);
ret = mr_work_schedule(&work1);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(hook_wakeup_called, 1);
hook_suspend_called = 0;
ret = mr_workqueue_execute(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
MR_TEST_ASSERT_EQ_INT(hook_suspend_called, 1);
ret = mr_work_del(&work);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_work_del(&work1);
MR_TEST_ASSERT_EQ_INT(ret, 0);
ret = mr_workqueue_del(&queue);
MR_TEST_ASSERT_EQ_INT(ret, 0);
}
MR_TEST_EXPORT(workqueue, hook, test_workqueue_hook);
#endif /* defined(MR_USE_WORKQUEUE_HOOK) */
#endif /* defined(MR_USE_WORKQUEUE) */
#endif /* defined(MR_USE_TEST) */

View File

@@ -55,7 +55,7 @@ static void test_malloc_free_basic(void) {
usable = mr_malloc_usable_size(MR_NULL);
MR_TEST_ASSERT_EQ_UINT(usable, 0);
usable = mr_malloc_usable_size(p + 32);
usable = mr_malloc_usable_size((mr_uint8_t *)p + 32);
MR_TEST_ASSERT_EQ_UINT(usable, 0);
#else
usable = 128;