diff options
| author | CYFS <[email protected]> | 2026-06-11 14:41:40 +0800 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2026-06-12 14:22:53 +0800 |
| commit | 103d4c1d92f3844dfcf4473957593af3449bec06 (patch) | |
| tree | fce4bd78b90e2eddb7f34958f18a134ee3637fb4 /components | |
| parent | 23187dedaa0994960dc03e08c38a70fa4ca4d0d4 (diff) | |
utest: move lwp testcases to components/lwp
Signed-off-by: CYFS <[email protected]>
Diffstat (limited to 'components')
| -rw-r--r-- | components/lwp/SConscript | 1 | ||||
| -rw-r--r-- | components/lwp/utest/Kconfig | 8 | ||||
| -rw-r--r-- | components/lwp/utest/SConscript | 13 | ||||
| -rw-r--r-- | components/lwp/utest/condvar_broadcast_tc.c | 190 | ||||
| -rw-r--r-- | components/lwp/utest/condvar_signal_tc.c | 156 | ||||
| -rw-r--r-- | components/lwp/utest/condvar_timedwait_tc.c | 108 |
6 files changed, 476 insertions, 0 deletions
diff --git a/components/lwp/SConscript b/components/lwp/SConscript index 56279cb998..1c97444e51 100644 --- a/components/lwp/SConscript +++ b/components/lwp/SConscript @@ -57,4 +57,5 @@ if not GetDepend(['LWP_USING_RUNTIME']): group = DefineGroup('lwProcess', src, depend = ['RT_USING_SMART'], CPPPATH = CPPPATH) group = group + SConscript(os.path.join('vdso', 'SConscript')) +group = group + SConscript(os.path.join('utest', 'SConscript')) Return('group') diff --git a/components/lwp/utest/Kconfig b/components/lwp/utest/Kconfig new file mode 100644 index 0000000000..ac2900d93a --- /dev/null +++ b/components/lwp/utest/Kconfig @@ -0,0 +1,8 @@ +menu "LWP Testcase" + +config RT_UTEST_LWP + bool "Enable LWP condvar test" + depends on RT_USING_SMART + default n + +endmenu diff --git a/components/lwp/utest/SConscript b/components/lwp/utest/SConscript new file mode 100644 index 0000000000..c7890d6be7 --- /dev/null +++ b/components/lwp/utest/SConscript @@ -0,0 +1,13 @@ +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = [] +CPPPATH = [cwd] + +if GetDepend(['RT_UTEST_LWP', 'RT_USING_SMART']): + src += ['condvar_timedwait_tc.c', 'condvar_broadcast_tc.c', 'condvar_signal_tc.c'] + +group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/lwp/utest/condvar_broadcast_tc.c b/components/lwp/utest/condvar_broadcast_tc.c new file mode 100644 index 0000000000..234ae697a1 --- /dev/null +++ b/components/lwp/utest/condvar_broadcast_tc.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-11-20 Shell add test suites + * 2026-03-19 cl2t Add standardized utest documentation block + */ + +/** + * Test Case Name: Condition Variable Broadcast Test + * + * Test Objectives: + * - Verify that rt_condvar_broadcast() correctly wakes up all threads + * waiting on a condition variable. + * - Test core APIs: rt_condvar_broadcast(), rt_condvar_timedwait(), + * rt_mutex_take(), rt_mutex_release(), rt_mutex_get_owner(). + * + * Test Scenarios: + * - Creates 8 worker threads, each acquiring a mutex and then waiting on + * a condition variable via rt_condvar_timedwait(). + * - The main thread calls rt_condvar_broadcast() to wake all waiters. + * - Each woken thread verifies it re-acquired the mutex, increments a + * counter, and releases the mutex. + * - The main thread verifies all 8 threads were successfully woken. + * + * Verification Metrics: + * - All waiting threads must be woken after broadcast (waken_num == THREAD_NUM). + * - Each woken thread must hold the mutex (verified via rt_mutex_get_owner()). + * - rt_condvar_timedwait() must return 0 on successful wake. + * - Mutex release must succeed for each woken thread. + * + * Dependencies: + * - Software configuration: RT_USING_SMART must be enabled. + * - Environmental assumptions: The platform must support multi-threading + * with at least 8 concurrent threads. + * + * Expected Results: + * - Final output: "[ PASSED ] [ result ] testcase (testcases.ipc.condvar.broadcast)" + * - No assertion failures during test execution. + */ + +#include "common.h" +#include "rtconfig.h" +#include "utest_assert.h" + +#include <rtdevice.h> +#include <rtdef.h> + +static struct rt_mutex _local_mtx; +static struct rt_condvar _local_cv; +#define THREAD_NUM 8 +#define STACK_SIZE (0x2000) + +static volatile int start_num; +static volatile int waken_num; + +static void thr_func(void *arg) +{ + int rc; + rt_mutex_t mutex = &_local_mtx; + rt_condvar_t cond = &_local_cv; + rt_mutex_take(mutex, RT_WAITING_FOREVER); + + start_num++; + rc = rt_condvar_timedwait(cond, mutex, RT_KILLABLE, RT_WAITING_FOREVER); + if (rc != 0) + { + LOG_E("cond_wait returned %d\n", rc); + uassert_false(1); + return; + } + + if (rt_mutex_get_owner(mutex) != rt_thread_self()) + { + LOG_E("Should not be able to lock the mutex again"); + uassert_false(1); + return; + } + else + { + uassert_true(1); + } + LOG_I("Thread was wakened and acquired the mutex again"); + waken_num++; + + if (rt_mutex_release(mutex) != 0) + { + LOG_E("Failed to release the mutex"); + uassert_false(1); + return; + } + else + { + uassert_true(1); + } + + return ; +} + +static void *stack_addr[THREAD_NUM]; + +static void condvar_broadcast_tc(void) +{ + rt_mutex_t mutex = &_local_mtx; + rt_condvar_t cond = &_local_cv; + struct rt_thread thread[THREAD_NUM]; + + for (size_t i = 0; i < THREAD_NUM; i++) + { + if (rt_thread_init(&thread[i], "utest", thr_func, RT_NULL, + stack_addr[i], STACK_SIZE, 25, 100) != 0) + { + LOG_E("Fail to create thread[%d]\n", i); + return; + } + rt_thread_startup(&thread[i]); + } + + while (start_num < THREAD_NUM) + rt_thread_mdelay(1); + + rt_mutex_take(mutex, RT_WAITING_FOREVER); + if (rt_condvar_broadcast(cond)) + { + uassert_false(1); + return ; + } + rt_mutex_release(mutex); + + rt_thread_mdelay(1); + + if (waken_num < THREAD_NUM) + { + LOG_E("[Main thread] Not all waiters were wakened\n"); + uassert_false(1); + return ; + } + else + { + utest_int_equal(waken_num, THREAD_NUM); + } + LOG_I("[Main thread] all waiters were wakened\n"); + + return; +} + +static rt_err_t utest_tc_init(void) +{ + start_num = 0; + waken_num = 0; + if (rt_mutex_init(&_local_mtx, "utest", RT_IPC_FLAG_PRIO) != 0) + { + perror("pthread_mutex_init() error"); + uassert_false(1); + return -1; + } + + rt_condvar_init(&_local_cv, NULL); + + for (size_t i = 0; i < THREAD_NUM; i++) + { + stack_addr[i] = + rt_pages_alloc_ext(rt_page_bits(STACK_SIZE), PAGE_ANY_AVAILABLE); + utest_int_not_equal(stack_addr[i], RT_NULL); + } + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + rt_mutex_detach(&_local_mtx); + rt_condvar_detach(&_local_cv); + + for (size_t i = 0; i < THREAD_NUM; i++) + { + rt_pages_free(stack_addr[i], rt_page_bits(STACK_SIZE)); + stack_addr[i] = 0; + } + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(condvar_broadcast_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.ipc.condvar.broadcast", utest_tc_init, + utest_tc_cleanup, 10); diff --git a/components/lwp/utest/condvar_signal_tc.c b/components/lwp/utest/condvar_signal_tc.c new file mode 100644 index 0000000000..82129560eb --- /dev/null +++ b/components/lwp/utest/condvar_signal_tc.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-11-20 Shell add test suites + * 2026-03-19 cl2t Add standardized utest documentation block + */ + +/** + * Test Case Name: Condition Variable Signal Test + * + * Test Objectives: + * - Verify that rt_condvar_signal() correctly wakes up a single thread + * waiting on a condition variable. + * - Test core APIs: rt_condvar_signal(), rt_condvar_timedwait(), + * rt_mutex_take(), rt_mutex_release(), rt_thread_create(). + * + * Test Scenarios: + * - The main thread acquires a mutex, creates a waker thread, then waits + * on a condition variable with a 100-tick timeout. + * - The waker thread acquires the mutex and calls rt_condvar_signal() to + * wake the main thread. + * - The main thread verifies it was woken successfully and releases the + * mutex. + * + * Verification Metrics: + * - rt_condvar_signal() must return 0 on success. + * - rt_condvar_timedwait() must return 0 when signaled before timeout. + * - Timeout (-ETIMEDOUT) or interrupt (-EINTR) are acceptable non-fatal + * outcomes. + * - Mutex acquire and release must succeed without errors. + * + * Dependencies: + * - Software configuration: RT_USING_SMART must be enabled. + * - Environmental assumptions: The platform must support multi-threading. + * + * Expected Results: + * - Final output: "[ PASSED ] [ result ] testcase (testcases.ipc.condvar.signal)" + * - No assertion failures during test execution. + */ + +#include "common.h" +#include "utest_assert.h" + +#include <rtdevice.h> +#include <rtdef.h> +#define STACK_SIZE (0x2000) + +static struct rt_mutex _local_mtx; +static struct rt_condvar _local_cv; + +static void waker_thr(void *param) +{ + int err; + rt_mutex_t mutex = &_local_mtx; + rt_condvar_t cond = &_local_cv; + rt_mutex_take(mutex, RT_WAITING_FOREVER); + err = rt_condvar_signal(cond); + + if (err != 0) + { + LOG_E("errno=%d, ret=%d\n", errno, err); + LOG_E("rt_condvar_signal() error"); + uassert_false(1); + } + else + { + uassert_false(0); + } + rt_mutex_release(mutex); + + return; +} + +static void condvar_signal_tc(void) +{ + rt_thread_t waker; + rt_mutex_t mutex = &_local_mtx; + rt_condvar_t cond = &_local_cv; + int err; + + waker = rt_thread_create("waker", waker_thr, 0, STACK_SIZE, 25, 50); + uassert_not_null(waker); + + if (rt_mutex_take(mutex, RT_WAITING_FOREVER) != 0) + { + LOG_E("pthread_mutex_lock() error"); + uassert_false(1); + return; + } + else + { + uassert_false(0); + } + + rt_thread_startup(waker); + + err = rt_condvar_timedwait(cond, mutex, RT_KILLABLE, 100); + if (err != 0) + { + if (err == -EINTR || err == -ETIMEDOUT) + { + puts("wait timed out"); + uassert_false(0); + } + else + { + LOG_E("errno=%d, ret=%d\n", errno, err); + LOG_E("pthread_cond_timedwait() error"); + uassert_false(1); + } + } + + err = rt_mutex_release(mutex); + if (err != 0) + { + LOG_E("errno=%d, ret=%d\n", errno, err); + LOG_E("rt_mutex_release() error"); + uassert_false(1); + } + else + { + uassert_false(0); + } + + return ; +} + +static rt_err_t utest_tc_init(void) +{ + if (rt_mutex_init(&_local_mtx, "utest", RT_IPC_FLAG_PRIO) != 0) + { + perror("pthread_mutex_init() error"); + uassert_false(1); + return -1; + } + + rt_condvar_init(&_local_cv, NULL); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + rt_mutex_detach(&_local_mtx); + rt_condvar_detach(&_local_cv); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(condvar_signal_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.ipc.condvar.signal", utest_tc_init, utest_tc_cleanup, 10); diff --git a/components/lwp/utest/condvar_timedwait_tc.c b/components/lwp/utest/condvar_timedwait_tc.c new file mode 100644 index 0000000000..43cfceb695 --- /dev/null +++ b/components/lwp/utest/condvar_timedwait_tc.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-11-20 Shell add test suites + * 2026-03-19 cl2t Add standardized utest documentation block + */ + +/** + * Test Case Name: Condition Variable Timed Wait Test + * + * Test Objectives: + * - Verify that rt_condvar_timedwait() correctly times out when no signal + * is received within the specified timeout period. + * - Test core APIs: rt_condvar_timedwait(), rt_mutex_take(), + * rt_mutex_init(), rt_condvar_init(). + * + * Test Scenarios: + * - The main thread acquires a mutex and calls rt_condvar_timedwait() + * with a 100-tick timeout. + * - Since no other thread signals the condition variable, the call is + * expected to time out with -ETIMEDOUT or be interrupted with -EINTR. + * + * Verification Metrics: + * - rt_condvar_timedwait() must return -ETIMEDOUT or -EINTR when no + * signal is received. + * - Any other non-zero return value indicates a test failure. + * - Mutex initialization and acquisition must succeed. + * + * Dependencies: + * - Software configuration: RT_USING_SMART must be enabled. + * - Environmental assumptions: The platform must support condition + * variables and mutexes. + * + * Expected Results: + * - Final output: "[ PASSED ] [ result ] testcase (testcases.ipc.condvar.timedwait)" + * - No assertion failures during test execution. + */ + +#include "common.h" +#include "utest_assert.h" + +#include <rtdevice.h> +#include <rtdef.h> + +static struct rt_mutex _local_mtx; +static struct rt_condvar _local_cv; + +static void condvar_timedwait_tc(void) +{ + rt_mutex_t mutex = &_local_mtx; + rt_condvar_t cond = &_local_cv; + int err; + + if (rt_mutex_take(mutex, RT_WAITING_FOREVER) != 0) + { + LOG_E("pthread_mutex_lock() error"); + uassert_false(1); + return; + } + + err = rt_condvar_timedwait(cond, mutex, RT_KILLABLE, 100); + if (err != 0) + { + if (err == -EINTR || err == -ETIMEDOUT) + { + puts("wait timed out"); + uassert_false(0); + } + else + { + LOG_E("errno=%d, ret=%d\n", errno, err); + LOG_E("pthread_cond_timedwait() error"); + uassert_false(1); + } + } + + return ; +} + +static rt_err_t utest_tc_init(void) +{ + if (rt_mutex_init(&_local_mtx, "utest", RT_IPC_FLAG_PRIO) != 0) + { + perror("pthread_mutex_init() error"); + uassert_false(1); + return -1; + } + + rt_condvar_init(&_local_cv, NULL); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + rt_mutex_detach(&_local_mtx); + rt_condvar_detach(&_local_cv); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(condvar_timedwait_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.ipc.condvar.timedwait", utest_tc_init, utest_tc_cleanup, 10); |
