summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormazhiyuan <[email protected]>2021-10-11 13:47:26 +0800
committermazhiyuan <[email protected]>2021-10-11 13:47:26 +0800
commitc3465dfab7de0fec94a5b76a88e0f7eb69801de1 (patch)
tree5aa144035d897b75b8d2e0898fd38f91c87e4c0e
parent634e5341a6ee73001988216962cda398a42b1ce4 (diff)
add thread testcase
-rw-r--r--.github/workflows/action_utest.yml1
-rw-r--r--examples/utest/configs/kernel/thread.conf4
-rw-r--r--examples/utest/testcases/kernel/Kconfig6
-rw-r--r--examples/utest/testcases/kernel/SConscript3
-rw-r--r--examples/utest/testcases/kernel/thread_tc.c641
5 files changed, 655 insertions, 0 deletions
diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml
index 197537a9b4..06d8ec15ff 100644
--- a/.github/workflows/action_utest.yml
+++ b/.github/workflows/action_utest.yml
@@ -15,6 +15,7 @@ jobs:
- {UTEST: "kernel/ipc", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/ipc.conf", SD_FILE: "sd.bin"}
- {UTEST: "kernel/irq", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/irq.conf", SD_FILE: "sd.bin"}
- {UTEST: "kernel/timer", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/timer.conf", SD_FILE: "sd.bin"}
+ - {UTEST: "kernel/thread", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "kernel/thread.conf", SD_FILE: "sd.bin"}
- {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", CONFIG_FILE: "utest_self/self.conf", SD_FILE: "sd.bin"}
- {UTEST: "kernel/mem/riscv64", RTT_BSP: "bsp/qemu-riscv-virt64", QEMU_ARCH: "riscv64", QEMU_MACHINE: "virt", CONFIG_FILE: "kernel/mem.conf", SD_FILE: "None"}
env:
diff --git a/examples/utest/configs/kernel/thread.conf b/examples/utest/configs/kernel/thread.conf
new file mode 100644
index 0000000000..9b3234f0d7
--- /dev/null
+++ b/examples/utest/configs/kernel/thread.conf
@@ -0,0 +1,4 @@
+CONFIG_UTEST_THREAD_TC=y
+# dependencies
+CONFIG_RT_USING_TIMER_SOFT=y
+CONFIG_RT_USING_THREAD=y
diff --git a/examples/utest/testcases/kernel/Kconfig b/examples/utest/testcases/kernel/Kconfig
index fba3b8c511..08c3022b77 100644
--- a/examples/utest/testcases/kernel/Kconfig
+++ b/examples/utest/testcases/kernel/Kconfig
@@ -39,4 +39,10 @@ config UTEST_MAILBOX_TC
bool "mailbox test"
default n
+config UTEST_THREAD_TC
+ bool "thread test"
+ default n
+ select RT_USING_TIMER_SOFT
+ select RT_USING_THREAD
+
endmenu
diff --git a/examples/utest/testcases/kernel/SConscript b/examples/utest/testcases/kernel/SConscript
index 484f1fbf3b..0d2645427b 100644
--- a/examples/utest/testcases/kernel/SConscript
+++ b/examples/utest/testcases/kernel/SConscript
@@ -32,6 +32,9 @@ if GetDepend(['UTEST_MUTEX_TC']):
if GetDepend(['UTEST_MAILBOX_TC']):
src += ['mailbox_tc.c']
+if GetDepend(['UTEST_THREAD_TC']):
+ src += ['thread_tc.c']
+
CPPPATH = [cwd]
group = DefineGroup('utestcases', src, depend = [], CPPPATH = CPPPATH)
diff --git a/examples/utest/testcases/kernel/thread_tc.c b/examples/utest/testcases/kernel/thread_tc.c
new file mode 100644
index 0000000000..ea350cb46a
--- /dev/null
+++ b/examples/utest/testcases/kernel/thread_tc.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-09.01 yangjie the firet version
+ * 2021-10.11 mazhiyuan add idle, yield, suspend, control, priority, delay_until
+ */
+
+#include <rtthread.h>
+#include <stdlib.h>
+#include "utest.h"
+
+#define THREAD_STACK_SIZE 512
+#define THREAD_TIMESLICE 10
+
+ALIGN(RT_ALIGN_SIZE)
+static char thread2_stack[1024];
+static struct rt_thread thread2;
+#ifdef RT_USING_HEAP
+static rt_thread_t tid1 = RT_NULL;
+static rt_thread_t tid3 = RT_NULL;
+static rt_thread_t tid4 = RT_NULL;
+static rt_thread_t tid5 = RT_NULL;
+static rt_thread_t tid6 = RT_NULL;
+static rt_thread_t tid7 = RT_NULL;
+#endif /* RT_USING_HEAP */
+
+static rt_uint32_t tid3_delay_pass_flag = 0;
+static rt_uint32_t tid3_finish_flag = 0;
+static rt_uint32_t tid4_finish_flag = 0;
+static rt_uint32_t tid6_finish_flag = 0;
+static rt_uint32_t thread5_source = 0;
+
+#ifndef RT_USING_SMP
+static rt_uint32_t thread_yield_flag = 0;
+#endif
+static rt_uint32_t entry_idle_hook_times = 0;
+static rt_thread_t __current_thread;
+static rt_uint8_t change_priority;
+static rt_uint32_t count = 0;
+
+void thread1_entry(void* param)
+{
+ while(1);
+}
+
+static void test_dynamic_thread(void)
+{
+ rt_err_t ret_startup = -RT_ERROR;
+ rt_err_t ret_delete = -RT_ERROR;
+
+ tid1 = rt_thread_create("thread1",
+ thread1_entry,
+ (void*)1,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority + 1,
+ THREAD_TIMESLICE - 5);
+ if (tid1 == RT_NULL)
+ {
+ uassert_false(tid1 == RT_NULL);
+ goto __exit;
+ }
+
+ ret_startup = rt_thread_startup(tid1);
+ if(ret_startup != RT_EOK)
+ {
+ uassert_false(ret_startup != RT_EOK);
+ goto __exit;
+ }
+
+ ret_delete = rt_thread_delete(tid1);
+ if (ret_delete != RT_EOK)
+ {
+ uassert_false(ret_delete != RT_EOK);
+ goto __exit;
+ }
+
+ uassert_true(tid1 != RT_NULL && ret_startup == RT_EOK && ret_delete == RT_EOK);
+
+__exit:
+ if (tid1 != RT_NULL && ret_delete != RT_EOK)
+ {
+ rt_thread_delete(tid1);
+ }
+ return;
+}
+
+void thread2_entry(void* param)
+{
+ while(1);
+}
+
+static void test_static_thread(void)
+{
+ rt_err_t ret_init = -RT_ERROR;
+ rt_err_t ret_startup = -RT_ERROR;
+ rt_err_t ret_detach = - RT_ERROR;
+
+ ret_init = rt_thread_init(&thread2,
+ "thread2",
+ thread2_entry,
+ (void*)2,
+ &thread2_stack[0],
+ sizeof(thread2_stack),
+ __current_thread->current_priority + 1,
+ THREAD_TIMESLICE);
+ if (ret_init != RT_EOK)
+ {
+ uassert_false(ret_init != RT_EOK);
+ goto __exit;
+ }
+
+ ret_startup = rt_thread_startup(&thread2);
+ if (ret_startup != RT_EOK)
+ {
+ uassert_false(ret_startup != RT_EOK);
+ goto __exit;
+ }
+
+ ret_detach = rt_thread_detach(&thread2);
+ if (ret_detach != RT_EOK)
+ {
+ uassert_false(ret_detach != RT_EOK);
+ goto __exit;
+ }
+
+ uassert_true(ret_init == RT_EOK && ret_startup == RT_EOK && ret_detach == RT_EOK);
+
+__exit:
+ if (ret_init == RT_EOK && ret_detach != RT_EOK)
+ {
+ rt_thread_detach(&thread2);
+ }
+ return;
+}
+
+static void thread3_entry(void *parameter)
+{
+ rt_tick_t tick;
+ tick = rt_tick_get();
+ rt_thread_delay(15);
+ if (rt_tick_get() - tick > 16)
+ {
+ tid3_finish_flag = 1;
+ tid3_delay_pass_flag = 0;
+ return;
+ }
+ tid3_delay_pass_flag = 1;
+ tid3_finish_flag = 1;
+}
+
+static void test_thread_delay(void)
+{
+ rt_err_t ret_startup = -RT_ERROR;
+
+ tid3 = rt_thread_create("thread3",
+ thread3_entry,
+ RT_NULL,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority - 1,
+ THREAD_TIMESLICE);
+ if (tid3 == RT_NULL)
+ {
+ LOG_E("rt_thread_create failed!");
+ uassert_false(tid3 == RT_NULL);
+ goto __exit;
+ }
+
+ ret_startup = rt_thread_startup(tid3);
+ if (ret_startup != RT_EOK)
+ {
+ LOG_E("rt_thread_startup failed!");
+ uassert_false(1);
+ goto __exit;
+ }
+
+ while (tid3_finish_flag != 1);
+ uassert_true(tid3_delay_pass_flag == 1);
+
+__exit:
+ return;
+}
+
+static void idle_hook(void)
+{
+ entry_idle_hook_times ++;
+}
+
+static void thread4_entry(void *parameter)
+{
+ rt_uint32_t delay_times = 5;
+ while (delay_times --)
+ {
+ rt_thread_mdelay(300);
+ }
+ rt_thread_idle_delhook(idle_hook);
+ tid4_finish_flag = 1;
+}
+
+static void test_idle_hook(void)
+{
+ rt_err_t ret_startup = -RT_ERROR;
+
+ rt_thread_idle_sethook(idle_hook);
+
+ tid4 = rt_thread_create("thread4",
+ thread4_entry,
+ RT_NULL,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority - 1,
+ THREAD_TIMESLICE);
+ if (tid4 == RT_NULL)
+ {
+ LOG_E("rt_thread_create failed!");
+ uassert_false(tid4 == RT_NULL);
+ goto __exit;
+ }
+
+ ret_startup = rt_thread_startup(tid4);
+ if (ret_startup != RT_EOK)
+ {
+ LOG_E("rt_thread_startup failed!");
+ uassert_false(1);
+ goto __exit;
+ }
+
+ while (tid4_finish_flag != 1)
+ {
+ rt_thread_mdelay(200);
+ }
+ uassert_true(entry_idle_hook_times > 0);
+
+__exit:
+ return;
+}
+
+static void thread5_entry(void *parameter)
+{
+ while (1)
+ {
+ thread5_source ++;
+ rt_thread_delay(5);
+ if (thread5_source == 5)
+ {
+ rt_thread_yield();
+ }
+ }
+}
+
+static void thread6_entry(void *parameter)
+{
+ while (++ thread5_source <= 9);
+ tid6_finish_flag = 1;
+}
+
+static void test_thread_yield(void)
+{
+ rt_err_t ret_startup = -RT_ERROR;
+ tid5 = rt_thread_create("thread5",
+ thread5_entry,
+ RT_NULL,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority - 1,
+ THREAD_TIMESLICE);
+ if (tid5 == RT_NULL)
+ {
+ LOG_E("rt_thread_create failed!");
+ uassert_false(tid5 == RT_NULL);
+ goto __exit;
+ }
+ ret_startup = rt_thread_startup(tid5);
+ if (ret_startup != RT_EOK)
+ {
+ LOG_E("rt_thread_startup failed!");
+ uassert_false(1);
+ goto __exit;
+ }
+ tid6 = rt_thread_create("thread6",
+ thread6_entry,
+ RT_NULL,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority - 1,
+ THREAD_TIMESLICE);
+ if (tid6 == RT_NULL)
+ {
+ LOG_E("rt_thread_create failed!");
+ uassert_false(tid6 == RT_NULL);
+ goto __exit;
+ }
+ ret_startup = rt_thread_startup(tid6);
+ if (ret_startup != RT_EOK)
+ {
+ LOG_E("rt_thread_startup failed!");
+ uassert_false(1);
+ goto __exit;
+ }
+
+ while (tid6_finish_flag != 1);
+ uassert_true(thread5_source == 10);
+
+__exit:
+ if (tid5 != RT_NULL)
+ {
+ rt_thread_delete(tid5);
+ }
+ return;
+}
+
+static void thread7_entry(void *parameter)
+{
+ while (1);
+}
+
+static void test_thread_control(void)
+{
+ rt_err_t ret_control = -RT_ERROR;
+ rt_err_t rst_delete = -RT_ERROR;
+
+ tid7 = rt_thread_create("thread7",
+ thread7_entry,
+ RT_NULL,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority + 1,
+ THREAD_TIMESLICE);
+ if (tid7 == RT_NULL)
+ {
+ LOG_E("rt_thread_create failed!");
+ uassert_false(tid7 == RT_NULL);
+ goto __exit;
+ }
+
+ ret_control = rt_thread_control(tid7, RT_THREAD_CTRL_STARTUP, RT_NULL);
+ if (ret_control != RT_EOK)
+ {
+ LOG_E("rt_thread_control failed!");
+ uassert_false(1);
+ goto __exit;
+ }
+ rt_thread_mdelay(200);
+ rt_thread_control(tid7, RT_THREAD_CTRL_CHANGE_PRIORITY, &change_priority);
+ if (tid7->current_priority != change_priority)
+ {
+ LOG_E("rt_thread_control failed!");
+ uassert_false(1);
+ goto __exit;
+ }
+ rst_delete = rt_thread_control(tid7, RT_THREAD_CTRL_CLOSE, RT_NULL);
+ if (rst_delete != RT_EOK)
+ {
+ LOG_E("rt_thread_control failed!");
+ uassert_false(rst_delete != RT_EOK);
+ goto __exit;
+ }
+
+ uassert_true(1);
+
+__exit:
+ if (tid7 != RT_NULL && rst_delete != RT_EOK)
+ {
+ rt_thread_delete(tid7);
+ }
+ return;
+}
+
+static void thread8_entry(void *parameter)
+{
+ for (; count < 10; count ++);
+}
+
+static void test_thread_priority(void)
+{
+ rt_err_t ret_startup = -RT_ERROR;
+ rt_thread_t tid8 = RT_NULL;
+
+ tid8 = rt_thread_create("thread8",
+ thread8_entry,
+ RT_NULL,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority - 1,
+ THREAD_TIMESLICE);
+ if (tid8 == RT_NULL)
+ {
+ LOG_E("rt_thread_create failed!");
+ uassert_false(tid8 == RT_NULL);
+ return;
+ }
+ count = 0;
+ ret_startup = rt_thread_startup(tid8);
+ if(ret_startup != RT_EOK)
+ {
+ uassert_false(ret_startup != RT_EOK);
+ return ;
+ }
+ uassert_true(count == 10);
+
+ return;
+}
+
+static void test_delay_until(void)
+{
+ rt_tick_t tick;
+ rt_tick_t check_tick = 0;
+ rt_tick_t delta = 0;
+
+ tick = rt_tick_get();
+
+ check_tick = tick;
+ rt_thread_delay_until(&tick, 100);
+ delta = rt_tick_get() - check_tick;
+ rt_kprintf("delta[100] -> %d\n", delta);
+ uassert_int_equal(delta, 100);
+
+ check_tick = tick;
+ rt_thread_delay(2);
+ rt_thread_delay_until(&tick, 200);
+ delta = rt_tick_get() - check_tick;
+ rt_kprintf("delta[200] -> %d\n", delta);
+ uassert_int_equal(delta, 200);
+
+ check_tick = tick;
+ rt_thread_delay(2);
+ rt_thread_delay_until(&tick, 300);
+ delta = rt_tick_get() - check_tick;
+ rt_kprintf("delta[300] -> %d\n", delta);
+ uassert_int_equal(delta, 300);
+
+ check_tick = tick;
+ rt_thread_delay(2);
+ rt_thread_delay_until(&tick, 100);
+ delta = rt_tick_get() - check_tick;
+ uassert_int_equal(delta, 100);
+
+ check_tick = tick;
+ rt_thread_delay(2);
+ rt_thread_delay_until(&tick, 50);
+ delta = rt_tick_get() - check_tick;
+ rt_kprintf("delta[50] -> %d\n", delta);
+ uassert_int_equal(delta, 50);
+
+ check_tick = tick;
+ rt_thread_delay(2);
+ rt_thread_delay_until(&tick, 20);
+ delta = rt_tick_get() - check_tick;
+ rt_kprintf("delta[20] -> %d\n", delta);
+ uassert_int_equal(delta, 20);
+
+ check_tick = tick;
+ rt_thread_delay(2);
+ rt_thread_delay_until(&tick, 10);
+ delta = rt_tick_get() - check_tick;
+ rt_kprintf("delta[10] -> %d\n", delta);
+ uassert_int_equal(delta, 10);
+}
+
+#ifndef RT_USING_SMP
+static volatile rt_uint32_t yield_count;
+
+static void test_thread_yield_inc_entry(void* parameter)
+{
+ rt_uint32_t loop = 0;
+
+ while (1)
+ {
+ if (loop++ > 10001)
+ break;
+ yield_count++;
+ rt_thread_yield();
+ }
+}
+
+static void test_thread_yield_entry(void* parameter)
+{
+ rt_err_t ret_startup = -RT_ERROR;
+
+ rt_thread_t tid;
+ rt_uint32_t loop = 0;
+ rt_uint32_t count_before;
+
+ tid = rt_thread_create("inc", test_thread_yield_inc_entry, RT_NULL,
+ 2048, 1, 10);
+ if (!tid)
+ {
+ LOG_E("rt_thread_create failed!");
+ return;
+ }
+
+ ret_startup = rt_thread_startup(tid);
+ if (ret_startup != RT_EOK)
+ {
+ LOG_E("rt_thread_startup failed!");
+ uassert_false(1);
+ return ;
+ }
+
+ while (1)
+ {
+ if (loop++ > 10000)
+ break;
+
+ count_before = yield_count;
+ rt_thread_yield();
+ if (yield_count == count_before)
+ {
+ LOG_E("yield error!");
+ return;
+ }
+ }
+ thread_yield_flag = 1;
+}
+
+void test_thread_yield_nosmp(void)
+{
+ rt_err_t ret_startup = -RT_ERROR;
+
+ rt_thread_t tid;
+
+ yield_count = 0;
+
+ tid = rt_thread_create("chkcnt", test_thread_yield_entry, RT_NULL,
+ 2048, 1, 10);
+ if (!tid)
+ {
+ LOG_E("rt_thread_create failed!");
+ return;
+ }
+
+ ret_startup = rt_thread_startup(tid);
+ if (ret_startup != RT_EOK)
+ {
+ LOG_E("rt_thread_startup failed!");
+ uassert_false(1);
+ return ;
+ }
+
+ uassert_true(thread_yield_flag == 1);
+}
+
+static rt_uint32_t thread9_count = 0;
+static void thread9_entry(void *parameter)
+{
+ while(1)
+ {
+ thread9_count ++;
+ }
+
+}
+static void test_thread_suspend(void){
+ static rt_thread_t tid;
+ rt_err_t ret_startup = -RT_ERROR;
+ uint32_t count_before_suspend, count_before_resume, count_after_resume;
+ tid = rt_thread_create("thread9",
+ thread9_entry,
+ RT_NULL,
+ THREAD_STACK_SIZE,
+ __current_thread->current_priority + 1,
+ THREAD_TIMESLICE);
+ if (tid == RT_NULL)
+ {
+ LOG_E("rt_thread_create failed!");
+ uassert_false(tid4 == RT_NULL);
+ goto __exit;
+ }
+
+ ret_startup = rt_thread_startup(tid);
+ if (ret_startup != RT_EOK)
+ {
+ LOG_E("rt_thread_startup failed!");
+ uassert_false(1);
+ goto __exit;
+ }
+ rt_thread_delay(5);
+ rt_thread_suspend(tid);
+ count_before_suspend = thread9_count;
+ uassert_true(count_before_suspend != 0);
+ rt_thread_delay(5);
+ count_before_resume = thread9_count;
+ uassert_true(count_before_suspend == count_before_resume);
+ rt_thread_resume(tid);
+ rt_thread_delay(5);
+ count_after_resume = thread9_count;
+ uassert_true(count_after_resume != count_before_resume);
+
+__exit:
+ if (tid != RT_NULL)
+ {
+ rt_thread_delete(tid);
+ }
+ return;
+}
+#endif
+
+static rt_err_t utest_tc_init(void)
+{
+ __current_thread = rt_thread_self();
+ change_priority = __current_thread->current_priority + 5;
+ tid3_delay_pass_flag = 0;
+ tid3_finish_flag = 0;
+ tid4_finish_flag = 0;
+ tid6_finish_flag = 0;
+ entry_idle_hook_times = 0;
+ count = 0;
+ return RT_EOK;
+}
+
+static rt_err_t utest_tc_cleanup(void)
+{
+ return RT_EOK;
+}
+
+static void testcase(void)
+{
+ /* init, detach */
+ UTEST_UNIT_RUN(test_static_thread);
+ /* create, delete */
+ UTEST_UNIT_RUN(test_dynamic_thread);
+ /* delay */
+ UTEST_UNIT_RUN(test_thread_delay);
+ /* idle_sethook, idle_delhook */
+ UTEST_UNIT_RUN(test_idle_hook);
+ /* yield */
+ UTEST_UNIT_RUN(test_thread_yield);
+#ifndef RT_USING_SMP
+ /* yield_nosmp */
+ UTEST_UNIT_RUN(test_thread_yield_nosmp);
+ /* suspend, resume */
+ UTEST_UNIT_RUN(test_thread_suspend);
+#endif
+ /* control */
+ UTEST_UNIT_RUN(test_thread_control);
+ UTEST_UNIT_RUN(test_thread_priority);
+ /* delay_until */
+ UTEST_UNIT_RUN(test_delay_until);
+}
+
+
+UTEST_TC_EXPORT(testcase, "testcases.kernel.thread_tc", utest_tc_init, utest_tc_cleanup, 1000);
+
+/********************* end of file ************************/