import RT-Thread@9217865c without bsp, libcpu and components/net
This commit is contained in:
commit
e2376a3709
1414 changed files with 390370 additions and 0 deletions
19
examples/utest/testcases/Kconfig
Normal file
19
examples/utest/testcases/Kconfig
Normal file
|
@ -0,0 +1,19 @@
|
|||
menu "RT-Thread Utestcases"
|
||||
|
||||
config RT_USING_UTESTCASES
|
||||
bool "RT-Thread Utestcases"
|
||||
default n
|
||||
select RT_USING_UTEST
|
||||
|
||||
if RT_USING_UTESTCASES
|
||||
|
||||
source "$RTT_DIR/examples/utest/testcases/utest/Kconfig"
|
||||
source "$RTT_DIR/examples/utest/testcases/kernel/Kconfig"
|
||||
source "$RTT_DIR/examples/utest/testcases/cpp11/Kconfig"
|
||||
source "$RTT_DIR/examples/utest/testcases/drivers/serial_v2/Kconfig"
|
||||
source "$RTT_DIR/examples/utest/testcases/posix/Kconfig"
|
||||
source "$RTT_DIR/examples/utest/testcases/mm/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
15
examples/utest/testcases/SConscript
Normal file
15
examples/utest/testcases/SConscript
Normal file
|
@ -0,0 +1,15 @@
|
|||
# RT-Thread building script for bridge
|
||||
|
||||
import os
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
Return('objs')
|
9
examples/utest/testcases/cpp11/Kconfig
Normal file
9
examples/utest/testcases/cpp11/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menu "CPP11 Testcase"
|
||||
|
||||
config UTEST_CPP11_THREAD_TC
|
||||
bool "Cpp11 thread test"
|
||||
select RT_USING_CPLUSPLUS
|
||||
select RT_USING_CPLUSPLUS11
|
||||
default n
|
||||
|
||||
endmenu
|
13
examples/utest/testcases/cpp11/SConscript
Normal file
13
examples/utest/testcases/cpp11/SConscript
Normal file
|
@ -0,0 +1,13 @@
|
|||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Split('''
|
||||
thread_tc.cpp
|
||||
''')
|
||||
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('utestcases', src, depend = ['UTEST_CPP11_THREAD_TC'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
59
examples/utest/testcases/cpp11/thread_tc.cpp
Normal file
59
examples/utest/testcases/cpp11/thread_tc.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-03 liukang the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <thread>
|
||||
|
||||
static void test_thread(void)
|
||||
{
|
||||
int count = 0;
|
||||
auto func = [&]() mutable
|
||||
{
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
};
|
||||
|
||||
std::thread t1(func);
|
||||
t1.join();
|
||||
|
||||
if (count != 100)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
std::thread t2(func);
|
||||
t2.join();
|
||||
|
||||
if (count != 200)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_thread);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.cpp11.thread_tc", utest_tc_init, utest_tc_cleanup, 10);
|
15
examples/utest/testcases/drivers/SConscript
Normal file
15
examples/utest/testcases/drivers/SConscript
Normal file
|
@ -0,0 +1,15 @@
|
|||
# RT-Thread building script for bridge
|
||||
|
||||
import os
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
Return('objs')
|
7
examples/utest/testcases/drivers/serial_v2/Kconfig
Normal file
7
examples/utest/testcases/drivers/serial_v2/Kconfig
Normal file
|
@ -0,0 +1,7 @@
|
|||
menu "Utest Serial Testcase"
|
||||
|
||||
config UTEST_SERIAL_TC
|
||||
bool "Serial testcase"
|
||||
default n
|
||||
|
||||
endmenu
|
120
examples/utest/testcases/drivers/serial_v2/README.md
Normal file
120
examples/utest/testcases/drivers/serial_v2/README.md
Normal file
|
@ -0,0 +1,120 @@
|
|||
## 1、介绍
|
||||
|
||||
该目录下 c 文件是新版本串口的测试用例,在 `examples/utest/testcases/drivers/serial_v2` 目录结构里,该测试用例用来测试串口的各个操作模式是否正常工作。
|
||||
|
||||
## 2、 文件说明
|
||||
|
||||
| 文件 | 描述 |
|
||||
| ---------------- | ----------------------------------------- |
|
||||
| uart_rxb_txb.c | 串口接收阻塞和发送阻塞模式 的测试用例 |
|
||||
| uart_rxb_txnb.c | 串口接收阻塞和发送非阻塞模式 的测试用例 |
|
||||
| uart_rxnb_txb.c | 串口接收非阻塞和发送阻塞模式 的测试用例 |
|
||||
| uart_rxnb_txnb.c | 串口接收非阻塞和发送非阻塞模式 的测试用例 |
|
||||
|
||||
## 3、软硬件环境
|
||||
|
||||
硬件上需要支持 RT-Thread 的完整版操作系统,版本为4.0.4及以上,且硬件有串口硬件外设,软件上需要支持 内核接口、IPC 、Device 框架。
|
||||
|
||||
## 4、测试项
|
||||
|
||||
### 4.1 测试说明
|
||||
|
||||
上文所提及的模式是指串口使用时的操作模式,不涉及硬件的工作模式的配置情况(硬件工作模式一般有轮询POLL、中断INT、DMA),因此使用时需要结合具体的硬件工作模式去配置使用。例如 发送阻塞和接收非阻塞模式 ,这个测试有很多种硬件配置,配置情况例如:DMA发送阻塞和DMA接收非阻塞,INT发送阻塞和DMA接收非阻塞,POLL发送阻塞和DMA接收非阻塞等等。因此通过排列组合后的测试场景有4*9=36种,有意义的组合方式为20种。如下表:
|
||||
|
||||
|
||||
| 接收非阻塞 | 发送阻塞 | 组合 | 有意义的组合方式 |
|
||||
| ---------- | -------- | ----------------- | ---------------- |
|
||||
| POLL | POLL | RX_POLL + TX_POLL | |
|
||||
| | INT | RX_POLL + TX_INT | |
|
||||
| | DMA | RX_POLL + TX_DMA | |
|
||||
| INT | POLL | RX_INT + TX_POLL | ✔ |
|
||||
| | INT | RX_INT + TX_INT | ✔ |
|
||||
| | DMA | RX_INT + TX_DMA | ✔ |
|
||||
| DMA | POLL | RX_DMA + TX_POLL | ✔ |
|
||||
| | INT | RX_DMA + TX_INT | ✔ |
|
||||
| | DMA | RX_DMA + TX_DMA | ✔ |
|
||||
|
||||
| 接收非阻塞 | 发送非阻塞 | 组合 | 有意义的组合方式 |
|
||||
| ---------- | ---------- | ----------------- | ---------------- |
|
||||
| POLL | POLL | RX_POLL + TX_POLL | |
|
||||
| | INT | RX_POLL + TX_INT | |
|
||||
| | DMA | RX_POLL + TX_DMA | |
|
||||
| INT | POLL | RX_INT + TX_POLL | |
|
||||
| | INT | RX_INT + TX_INT | ✔ |
|
||||
| | DMA | RX_INT + TX_DMA | ✔ |
|
||||
| DMA | POLL | RX_DMA + TX_POLL | |
|
||||
| | INT | RX_DMA + TX_INT | ✔ |
|
||||
| | DMA | RX_DMA + TX_DMA | ✔ |
|
||||
|
||||
| 接收阻塞 | 发送阻塞 | 组合 | 有意义的组合方式 |
|
||||
| -------- | -------- | ----------------- | ---------------- |
|
||||
| POLL | POLL | RX_POLL + TX_POLL | |
|
||||
| | INT | RX_POLL + TX_INT | |
|
||||
| | DMA | RX_POLL + TX_DMA | |
|
||||
| INT | POLL | RX_INT + TX_POLL | ✔ |
|
||||
| | INT | RX_INT + TX_INT | ✔ |
|
||||
| | DMA | RX_INT + TX_DMA | ✔ |
|
||||
| DMA | POLL | RX_DMA + TX_POLL | ✔ |
|
||||
| | INT | RX_DMA + TX_INT | ✔ |
|
||||
| | DMA | RX_DMA + TX_DMA | ✔ |
|
||||
|
||||
| 接收阻塞 | 发送非阻塞 | 组合 | 有意义的组合方式 |
|
||||
| -------- | ---------- | ----------------- | ---------------- |
|
||||
| POLL | POLL | RX_POLL + TX_POLL | |
|
||||
| | INT | RX_POLL + TX_INT | |
|
||||
| | DMA | RX_POLL + TX_DMA | |
|
||||
| INT | POLL | RX_INT + TX_POLL | |
|
||||
| | INT | RX_INT + TX_INT | ✔ |
|
||||
| | DMA | RX_INT + TX_DMA | ✔ |
|
||||
| DMA | POLL | RX_DMA + TX_POLL | |
|
||||
| | INT | RX_DMA + TX_INT | ✔ |
|
||||
| | DMA | RX_DMA + TX_DMA | ✔ |
|
||||
|
||||
需要解释的是,为什么会存在无意义的组合模式,举个例子,非阻塞模式下,肯定是不会出现POLL(轮询)方式的,因为POLL方式已经表明是阻塞方式了。
|
||||
该测试用例在测试多种组合时,需要通过更改`rtconfig.h`文件对硬件模式进行静态配置。
|
||||
|
||||
### 4.2 测试思路
|
||||
|
||||
这四个测试用例的测试思路基本一致。
|
||||
|
||||
硬件上:**短接串口的发送TX引脚和接收RX引脚,完成自发自收的回路**。
|
||||
|
||||
软件上:创建两个线程A和B,A为接收线程,B为发送线程,设置A线程优先级比B线程优先级高。发送线程发送随机长度(长度范围是 0 到 1000)的数据,接收线程接收到数据进行校验,数据正确则测试通过,默认测试100次。
|
||||
|
||||
## 5、配置
|
||||
|
||||
使用该测试用例需要在 `env` 工具的 `menuconfig` 中做相关配置,配置如下所示(使用 RT-Thread-Studio 的配置路径一致 ):
|
||||
|
||||
```
|
||||
RT-Thread Utestcases --->
|
||||
[*] RT-Thread Utestcases --->
|
||||
Utest Serial Testcase --->
|
||||
[*] Serial testcase
|
||||
```
|
||||
|
||||
## 6、使用
|
||||
|
||||
\- 编译下载。
|
||||
|
||||
\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。
|
||||
|
||||
\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。
|
||||
|
||||
\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。
|
||||
|
||||
\- 在 MSH 中输入 `utest_run testcases.drivers.uart_rxb_txb` 运行串口接收阻塞和发送阻塞测试用例。
|
||||
|
||||
如果仅仅配置了 `Serial testcase` 相关的测试用例,则直接输入 `utest_run` 运行即可将上述测试用例按序测试。
|
||||
|
||||
## 7、注意事项
|
||||
|
||||
\- 需配置正确的测试用例。
|
||||
|
||||
\- 如有需要,可开启 ULOG 查看测试用例日志信息。
|
||||
|
||||
\- 需在 MSH 中输入正确的命令行。
|
||||
|
||||
\- 测试用例默认的测试数据长度范围最大为1000字节,如果接收端的缓冲区大小配置为小于1000字节时,那么在测试接收阻塞模式时,将会由于获取不了1000字节长度导致线程持续阻塞(因为测试用例是按 `recv_len` 长度去接收的,而不是按照单字节去接收的),因此建议接收端的缓冲区大小 (对应宏例如为 `BSP_UART2_RX_BUFSIZE`)设置为1024即可;当然也可按需减小测试的最大数据长度。
|
||||
|
||||
\- 该测试用例需要结合硬件具体的工作模式(POLL 、INT、DMA)进行测试,而硬件工作模式只能选择一种,因此需要在 `rtconfig.h` 中对串口相应的宏进行配置,来选择不同的工作模式去进行测试。
|
||||
|
16
examples/utest/testcases/drivers/serial_v2/SConscript
Normal file
16
examples/utest/testcases/drivers/serial_v2/SConscript
Normal file
|
@ -0,0 +1,16 @@
|
|||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Split('''
|
||||
uart_rxb_txnb.c
|
||||
uart_rxb_txb.c
|
||||
uart_rxnb_txb.c
|
||||
uart_rxnb_txnb.c
|
||||
''')
|
||||
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('utestcases', src, depend = ['UTEST_SERIAL_TC'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
230
examples/utest/testcases/drivers/serial_v2/uart_rxb_txb.c
Normal file
230
examples/utest/testcases/drivers/serial_v2/uart_rxb_txb.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-06-16 KyleChan the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <rtdevice.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TC_UART_DEVICE_NAME "uart2"
|
||||
#define TC_UART_SEND_TIMES 100
|
||||
|
||||
|
||||
#ifdef UTEST_SERIAL_TC
|
||||
|
||||
#define TEST_UART_NAME TC_UART_DEVICE_NAME
|
||||
|
||||
static struct rt_serial_device *serial;
|
||||
static rt_uint8_t uart_over_flag;
|
||||
static rt_bool_t uart_result = RT_TRUE;
|
||||
|
||||
static rt_err_t uart_find(void)
|
||||
{
|
||||
serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME);
|
||||
|
||||
if (serial == RT_NULL)
|
||||
{
|
||||
LOG_E("find %s device failed!\n", TEST_UART_NAME);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void uart_send_entry(void *parameter)
|
||||
{
|
||||
rt_uint8_t *uart_write_buffer;
|
||||
rt_uint16_t send_len;
|
||||
|
||||
rt_uint32_t i = 0;
|
||||
send_len = *(rt_uint16_t *)parameter;
|
||||
/* assign send buffer */
|
||||
uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len);
|
||||
if (uart_write_buffer == RT_NULL)
|
||||
{
|
||||
LOG_E("Without spare memory for uart dma!");
|
||||
uart_result = RT_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
rt_memset(uart_write_buffer, 0, send_len);
|
||||
|
||||
for (i = 0; i < send_len; i++)
|
||||
{
|
||||
uart_write_buffer[i] = (rt_uint8_t)i;
|
||||
}
|
||||
/* send buffer */
|
||||
if (rt_device_write(&serial->parent, 0, uart_write_buffer, send_len) != send_len)
|
||||
{
|
||||
LOG_E("device write failed\r\n");
|
||||
}
|
||||
rt_free(uart_write_buffer);
|
||||
|
||||
}
|
||||
|
||||
static void uart_rec_entry(void *parameter)
|
||||
{
|
||||
rt_uint16_t rev_len;
|
||||
|
||||
rev_len = *(rt_uint16_t *)parameter;
|
||||
rt_uint8_t *ch;
|
||||
ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1));
|
||||
rt_int32_t cnt, i;
|
||||
rt_uint8_t last_old_data;
|
||||
rt_bool_t fisrt_flag = RT_TRUE;
|
||||
rt_uint32_t all_receive_length = 0;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len);
|
||||
if (cnt == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fisrt_flag != RT_TRUE)
|
||||
{
|
||||
if ((rt_uint8_t)(last_old_data + 1) != ch[0])
|
||||
{
|
||||
LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]);
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fisrt_flag = RT_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt - 1; i++)
|
||||
{
|
||||
if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1])
|
||||
{
|
||||
LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]);
|
||||
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
all_receive_length += cnt;
|
||||
if (all_receive_length >= rev_len)
|
||||
break;
|
||||
else
|
||||
last_old_data = ch[cnt - 1];
|
||||
}
|
||||
rt_free(ch);
|
||||
uart_over_flag = RT_TRUE;
|
||||
}
|
||||
|
||||
static rt_err_t uart_api(rt_uint16_t length)
|
||||
{
|
||||
rt_thread_t thread_send = RT_NULL;
|
||||
rt_thread_t thread_recv = RT_NULL;
|
||||
rt_err_t result = RT_EOK;
|
||||
uart_over_flag = RT_FALSE;
|
||||
|
||||
result = uart_find();
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* Reinitialize */
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
config.baud_rate = BAUD_RATE_115200;
|
||||
config.rx_bufsz = BSP_UART2_RX_BUFSIZE;
|
||||
config.tx_bufsz = BSP_UART2_TX_BUFSIZE;
|
||||
rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
|
||||
result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
|
||||
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("Open uart device failed.");
|
||||
uart_result = RT_FALSE;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
thread_send = rt_thread_create("uart_send", uart_send_entry, &length, 1024, RT_THREAD_PRIORITY_MAX - 4, 10);
|
||||
thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &length, 1024, RT_THREAD_PRIORITY_MAX - 5, 10);
|
||||
if ((thread_send != RT_NULL) && (thread_recv != RT_NULL))
|
||||
{
|
||||
rt_thread_startup(thread_send);
|
||||
rt_thread_startup(thread_recv);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (uart_result != RT_TRUE)
|
||||
{
|
||||
LOG_E("The test for uart dma is failure.");
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
if (uart_over_flag == RT_TRUE)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
/* waiting for test over */
|
||||
rt_thread_mdelay(5);
|
||||
}
|
||||
__exit:
|
||||
rt_device_close(&serial->parent);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void tc_uart_api(void)
|
||||
{
|
||||
rt_uint32_t times = 0;
|
||||
rt_uint16_t num = 0;
|
||||
while (TC_UART_SEND_TIMES - times)
|
||||
{
|
||||
num = (rand() % 1000) + 1;
|
||||
if(uart_api(num) == RT_EOK)
|
||||
LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times);
|
||||
else
|
||||
{
|
||||
LOG_E("uart test error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
uassert_true(uart_over_flag == RT_TRUE);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
uart_result = RT_TRUE;
|
||||
uart_over_flag = RT_FALSE;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(tc_uart_api);
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxb_txb", utest_tc_init, utest_tc_cleanup, 30);
|
||||
|
||||
#endif /* TC_UART_USING_TC */
|
263
examples/utest/testcases/drivers/serial_v2/uart_rxb_txnb.c
Normal file
263
examples/utest/testcases/drivers/serial_v2/uart_rxb_txnb.c
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-06-16 KyleChan the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <rtdevice.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TC_UART_DEVICE_NAME "uart2"
|
||||
#define TC_UART_SEND_TIMES 100
|
||||
|
||||
|
||||
#ifdef UTEST_SERIAL_TC
|
||||
|
||||
#define TEST_UART_NAME TC_UART_DEVICE_NAME
|
||||
|
||||
static struct rt_serial_device *serial;
|
||||
static rt_sem_t tx_sem;
|
||||
static rt_uint8_t uart_over_flag;
|
||||
static rt_bool_t uart_result = RT_TRUE;
|
||||
|
||||
static rt_err_t uart_find(void)
|
||||
{
|
||||
serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME);
|
||||
|
||||
if (serial == RT_NULL)
|
||||
{
|
||||
LOG_E("find %s device failed!\n", TEST_UART_NAME);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t uart_tx_completion(rt_device_t device, void *buffer)
|
||||
{
|
||||
rt_sem_release(tx_sem);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void uart_send_entry(void *parameter)
|
||||
{
|
||||
rt_uint8_t *uart_write_buffer;
|
||||
rt_uint16_t send_len, len = 0;
|
||||
rt_err_t result;
|
||||
|
||||
rt_uint32_t i = 0;
|
||||
send_len = *(rt_uint16_t *)parameter;
|
||||
/* assign send buffer */
|
||||
uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len);
|
||||
if (uart_write_buffer == RT_NULL)
|
||||
{
|
||||
LOG_E("Without spare memory for uart dma!");
|
||||
uart_result = RT_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
rt_memset(uart_write_buffer, 0, send_len);
|
||||
|
||||
for (i = 0; i < send_len; i++)
|
||||
{
|
||||
uart_write_buffer[i] = (rt_uint8_t)i;
|
||||
}
|
||||
/* send buffer */
|
||||
while (send_len - len)
|
||||
{
|
||||
len += rt_device_write(&serial->parent, 0, uart_write_buffer + len, send_len - len);
|
||||
result = rt_sem_take(tx_sem, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("take sem err in send.");
|
||||
}
|
||||
}
|
||||
rt_free(uart_write_buffer);
|
||||
|
||||
}
|
||||
|
||||
static void uart_rec_entry(void *parameter)
|
||||
{
|
||||
rt_uint16_t rev_len;
|
||||
|
||||
rev_len = *(rt_uint16_t *)parameter;
|
||||
rt_uint8_t *ch;
|
||||
ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1));
|
||||
rt_int32_t cnt, i;
|
||||
rt_uint8_t last_old_data;
|
||||
rt_bool_t fisrt_flag = RT_TRUE;
|
||||
rt_uint32_t all_receive_length = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len);
|
||||
if (cnt != rev_len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fisrt_flag != RT_TRUE)
|
||||
{
|
||||
if ((rt_uint8_t)(last_old_data + 1) != ch[0])
|
||||
{
|
||||
LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]);
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fisrt_flag = RT_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt - 1; i++)
|
||||
{
|
||||
if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1])
|
||||
{
|
||||
LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]);
|
||||
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
all_receive_length += cnt;
|
||||
if (all_receive_length >= rev_len)
|
||||
break;
|
||||
else
|
||||
last_old_data = ch[cnt - 1];
|
||||
}
|
||||
rt_free(ch);
|
||||
uart_over_flag = RT_TRUE;
|
||||
}
|
||||
|
||||
static rt_err_t uart_api(rt_uint16_t test_buf)
|
||||
{
|
||||
rt_thread_t thread_send = RT_NULL;
|
||||
rt_thread_t thread_recv = RT_NULL;
|
||||
rt_err_t result = RT_EOK;
|
||||
uart_over_flag = RT_FALSE;
|
||||
|
||||
result = uart_find();
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
tx_sem = rt_sem_create("tx_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (tx_sem == RT_NULL)
|
||||
{
|
||||
LOG_E("Init sem failed.");
|
||||
uart_result = RT_FALSE;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* Reinitialize */
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
config.baud_rate = BAUD_RATE_115200;
|
||||
config.rx_bufsz = BSP_UART2_RX_BUFSIZE;
|
||||
config.tx_bufsz = BSP_UART2_TX_BUFSIZE;
|
||||
rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
|
||||
result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING);
|
||||
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("Open uart device failed.");
|
||||
uart_result = RT_FALSE;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* set receive callback function */
|
||||
result = rt_device_set_tx_complete(&serial->parent, uart_tx_completion);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 5, 10);
|
||||
thread_send = rt_thread_create("uart_send", uart_send_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 4, 10);
|
||||
|
||||
if (thread_send != RT_NULL && thread_recv != RT_NULL)
|
||||
{
|
||||
rt_thread_startup(thread_recv);
|
||||
rt_thread_startup(thread_send);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (uart_result != RT_TRUE)
|
||||
{
|
||||
LOG_E("The test for uart dma is failure.");
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
if (uart_over_flag == RT_TRUE)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
/* waiting for test over */
|
||||
rt_thread_mdelay(5);
|
||||
}
|
||||
__exit:
|
||||
if (tx_sem)
|
||||
rt_sem_delete(tx_sem);
|
||||
|
||||
rt_device_close(&serial->parent);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void tc_uart_api(void)
|
||||
{
|
||||
rt_uint32_t times = 0;
|
||||
rt_uint16_t num = 0;
|
||||
while (TC_UART_SEND_TIMES - times)
|
||||
{
|
||||
num = (rand() % 1000) + 1;
|
||||
if(uart_api(num) == RT_EOK)
|
||||
LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times);
|
||||
else
|
||||
{
|
||||
LOG_E("uart test error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
uassert_true(uart_over_flag == RT_TRUE);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
tx_sem = RT_NULL;
|
||||
uart_result = RT_TRUE;
|
||||
uart_over_flag = RT_FALSE;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(tc_uart_api);
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxb_txnb", utest_tc_init, utest_tc_cleanup, 30);
|
||||
|
||||
#endif
|
266
examples/utest/testcases/drivers/serial_v2/uart_rxnb_txb.c
Normal file
266
examples/utest/testcases/drivers/serial_v2/uart_rxnb_txb.c
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-06-16 KyleChan the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <rtdevice.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TC_UART_DEVICE_NAME "uart2"
|
||||
#define TC_UART_SEND_TIMES 100
|
||||
|
||||
|
||||
#ifdef UTEST_SERIAL_TC
|
||||
|
||||
#define TEST_UART_NAME TC_UART_DEVICE_NAME
|
||||
|
||||
static struct rt_serial_device *serial;
|
||||
static rt_sem_t rx_sem;
|
||||
static rt_uint8_t uart_over_flag;
|
||||
static rt_bool_t uart_result = RT_TRUE;
|
||||
|
||||
static rt_err_t uart_find(void)
|
||||
{
|
||||
serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME);
|
||||
|
||||
if (serial == RT_NULL)
|
||||
{
|
||||
LOG_E("find %s device failed!\n", TEST_UART_NAME);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t uart_rx_indicate(rt_device_t device, rt_size_t size)
|
||||
{
|
||||
rt_sem_release(rx_sem);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void uart_send_entry(void *parameter)
|
||||
{
|
||||
rt_uint8_t *uart_write_buffer;
|
||||
rt_uint16_t send_len;
|
||||
|
||||
rt_uint32_t i = 0;
|
||||
send_len = *(rt_uint16_t *)parameter;
|
||||
|
||||
/* assign send buffer */
|
||||
uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len);
|
||||
if (uart_write_buffer == RT_NULL)
|
||||
{
|
||||
LOG_E("Without spare memory for uart dma!");
|
||||
uart_result = RT_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
rt_memset(uart_write_buffer, 0, send_len);
|
||||
|
||||
for (i = 0; i < send_len; i++)
|
||||
{
|
||||
uart_write_buffer[i] = (rt_uint8_t)i;
|
||||
}
|
||||
|
||||
/* send buffer */
|
||||
if (rt_device_write(&serial->parent, 0, uart_write_buffer, send_len) != send_len)
|
||||
{
|
||||
LOG_E("device write failed\r\n");
|
||||
}
|
||||
rt_free(uart_write_buffer);
|
||||
}
|
||||
|
||||
static void uart_rec_entry(void *parameter)
|
||||
{
|
||||
rt_uint16_t rev_len;
|
||||
|
||||
rev_len = *(rt_uint16_t *)parameter;
|
||||
rt_uint8_t *ch;
|
||||
ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1));
|
||||
rt_int32_t cnt, i;
|
||||
rt_uint8_t last_old_data;
|
||||
rt_bool_t fisrt_flag = RT_TRUE;
|
||||
rt_uint32_t all_receive_length = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_sem_take(rx_sem, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("take sem err in recv.");
|
||||
}
|
||||
|
||||
cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len);
|
||||
if (cnt == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fisrt_flag != RT_TRUE)
|
||||
{
|
||||
if ((rt_uint8_t)(last_old_data + 1) != ch[0])
|
||||
{
|
||||
LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]);
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fisrt_flag = RT_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt - 1; i++)
|
||||
{
|
||||
if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1])
|
||||
{
|
||||
LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]);
|
||||
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
all_receive_length += cnt;
|
||||
if (all_receive_length >= rev_len)
|
||||
break;
|
||||
else
|
||||
last_old_data = ch[cnt - 1];
|
||||
}
|
||||
rt_free(ch);
|
||||
uart_over_flag = RT_TRUE;
|
||||
}
|
||||
|
||||
static rt_err_t uart_api(rt_uint16_t test_buf)
|
||||
{
|
||||
rt_thread_t thread_send = RT_NULL;
|
||||
rt_thread_t thread_recv = RT_NULL;
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = uart_find();
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rx_sem = rt_sem_create("rx_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (rx_sem == RT_NULL)
|
||||
{
|
||||
LOG_E("Init sem failed.");
|
||||
uart_result = RT_FALSE;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* reinitialize */
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
config.baud_rate = BAUD_RATE_115200;
|
||||
config.rx_bufsz = BSP_UART2_RX_BUFSIZE;
|
||||
config.tx_bufsz = BSP_UART2_TX_BUFSIZE;
|
||||
rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
|
||||
result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
|
||||
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("Open uart device failed.");
|
||||
uart_result = RT_FALSE;
|
||||
rt_sem_delete(rx_sem);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* set receive callback function */
|
||||
result = rt_device_set_rx_indicate(&serial->parent, uart_rx_indicate);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 5, 10);
|
||||
thread_send = rt_thread_create("uart_send", uart_send_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 4, 10);
|
||||
|
||||
if (thread_send != RT_NULL && thread_recv != RT_NULL)
|
||||
{
|
||||
rt_thread_startup(thread_recv);
|
||||
rt_thread_startup(thread_send);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (uart_result != RT_TRUE)
|
||||
{
|
||||
LOG_E("The test for uart dma is failure.");
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
if (uart_over_flag == RT_TRUE)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
/* waiting for test over */
|
||||
rt_thread_mdelay(5);
|
||||
}
|
||||
__exit:
|
||||
if (rx_sem)
|
||||
rt_sem_delete(rx_sem);
|
||||
rt_device_close(&serial->parent);
|
||||
uart_over_flag = RT_FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void tc_uart_api(void)
|
||||
{
|
||||
rt_uint32_t times = 0;
|
||||
rt_uint16_t num = 0;
|
||||
while (TC_UART_SEND_TIMES - times)
|
||||
{
|
||||
num = (rand() % 1000) + 1;
|
||||
if(uart_api(num) == RT_EOK)
|
||||
LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times);
|
||||
else
|
||||
{
|
||||
LOG_E("uart test error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
uassert_true(uart_result == RT_TRUE);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
rx_sem = RT_NULL;
|
||||
uart_result = RT_TRUE;
|
||||
uart_over_flag = RT_FALSE;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(tc_uart_api);
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxnb_txb", utest_tc_init, utest_tc_cleanup, 30);
|
||||
|
||||
#endif /* TC_UART_USING_TC */
|
294
examples/utest/testcases/drivers/serial_v2/uart_rxnb_txnb.c
Normal file
294
examples/utest/testcases/drivers/serial_v2/uart_rxnb_txnb.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-06-16 KyleChan the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <rtdevice.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TC_UART_DEVICE_NAME "uart2"
|
||||
#define TC_UART_SEND_TIMES 100
|
||||
|
||||
|
||||
#ifdef UTEST_SERIAL_TC
|
||||
|
||||
#define TEST_UART_NAME TC_UART_DEVICE_NAME
|
||||
|
||||
static struct rt_serial_device *serial;
|
||||
static rt_sem_t tx_sem;
|
||||
static rt_sem_t rx_sem;
|
||||
static rt_uint8_t uart_over_flag;
|
||||
static rt_bool_t uart_result = RT_TRUE;
|
||||
|
||||
static rt_err_t uart_find(void)
|
||||
{
|
||||
serial = (struct rt_serial_device *)rt_device_find(TEST_UART_NAME);
|
||||
|
||||
if (serial == RT_NULL)
|
||||
{
|
||||
LOG_E("find %s device failed!\n", TEST_UART_NAME);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t uart_tx_completion(rt_device_t device, void *buffer)
|
||||
{
|
||||
rt_sem_release(tx_sem);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t uart_rx_indicate(rt_device_t device, rt_size_t size)
|
||||
{
|
||||
rt_sem_release(rx_sem);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void uart_send_entry(void *parameter)
|
||||
{
|
||||
rt_uint8_t *uart_write_buffer;
|
||||
rt_uint16_t send_len, len = 0;
|
||||
rt_err_t result;
|
||||
|
||||
rt_uint32_t i = 0;
|
||||
send_len = *(rt_uint16_t *)parameter;
|
||||
/* assign send buffer */
|
||||
uart_write_buffer = (rt_uint8_t *)rt_malloc(send_len);
|
||||
if (uart_write_buffer == RT_NULL)
|
||||
{
|
||||
LOG_E("Without spare memory for uart dma!");
|
||||
uart_result = RT_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
rt_memset(uart_write_buffer, 0, send_len);
|
||||
|
||||
for (i = 0; i < send_len; i++)
|
||||
{
|
||||
uart_write_buffer[i] = (rt_uint8_t)i;
|
||||
}
|
||||
/* send buffer */
|
||||
while (send_len - len)
|
||||
{
|
||||
len += rt_device_write(&serial->parent, 0, uart_write_buffer + len, send_len - len);
|
||||
result = rt_sem_take(tx_sem, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("take sem err in send.");
|
||||
}
|
||||
}
|
||||
rt_free(uart_write_buffer);
|
||||
|
||||
}
|
||||
|
||||
static void uart_rec_entry(void *parameter)
|
||||
{
|
||||
rt_uint16_t rev_len;
|
||||
|
||||
rev_len = *(rt_uint16_t *)parameter;
|
||||
rt_uint8_t *ch;
|
||||
ch = (rt_uint8_t *)rt_calloc(1, sizeof(rt_uint8_t) * (rev_len + 1));
|
||||
rt_int32_t cnt, i;
|
||||
rt_uint8_t last_old_data;
|
||||
rt_bool_t fisrt_flag = RT_TRUE;
|
||||
rt_uint32_t all_receive_length = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_sem_take(rx_sem, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("take sem err in recv.");
|
||||
}
|
||||
|
||||
cnt = rt_device_read(&serial->parent, 0, (void *)ch, rev_len);
|
||||
if (cnt == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fisrt_flag != RT_TRUE)
|
||||
{
|
||||
if ((rt_uint8_t)(last_old_data + 1) != ch[0])
|
||||
{
|
||||
LOG_E("_Read Different data -> former data: %x, current data: %x.", last_old_data, ch[0]);
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fisrt_flag = RT_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt - 1; i++)
|
||||
{
|
||||
if ((rt_uint8_t)(ch[i] + 1) != ch[i + 1])
|
||||
{
|
||||
LOG_E("Read Different data -> former data: %x, current data: %x.", ch[i], ch[i + 1]);
|
||||
|
||||
uart_result = RT_FALSE;
|
||||
rt_free(ch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
all_receive_length += cnt;
|
||||
if (all_receive_length >= rev_len)
|
||||
break;
|
||||
else
|
||||
last_old_data = ch[cnt - 1];
|
||||
}
|
||||
rt_free(ch);
|
||||
uart_over_flag = RT_TRUE;
|
||||
}
|
||||
|
||||
static rt_err_t uart_api(rt_uint16_t test_buf)
|
||||
{
|
||||
rt_thread_t thread_send = RT_NULL;
|
||||
rt_thread_t thread_recv = RT_NULL;
|
||||
rt_err_t result = RT_EOK;
|
||||
uart_over_flag = RT_FALSE;
|
||||
|
||||
result = uart_find();
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
rx_sem = rt_sem_create("rx_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (rx_sem == RT_NULL)
|
||||
{
|
||||
LOG_E("Init rx_sem failed.");
|
||||
uart_result = RT_FALSE;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
tx_sem = rt_sem_create("tx_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (tx_sem == RT_NULL)
|
||||
{
|
||||
LOG_E("Init tx_sem failed.");
|
||||
uart_result = RT_FALSE;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* reinitialize */
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
config.baud_rate = BAUD_RATE_115200;
|
||||
config.rx_bufsz = BSP_UART2_RX_BUFSIZE;
|
||||
config.tx_bufsz = BSP_UART2_TX_BUFSIZE;
|
||||
rt_device_control(&serial->parent, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
|
||||
result = rt_device_open(&serial->parent, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING);
|
||||
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
LOG_E("Open uart device failed.");
|
||||
uart_result = RT_FALSE;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* set receive callback function */
|
||||
result = rt_device_set_tx_complete(&serial->parent, uart_tx_completion);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
result = rt_device_set_rx_indicate(&serial->parent, uart_rx_indicate);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
thread_recv = rt_thread_create("uart_recv", uart_rec_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 5, 10);
|
||||
thread_send = rt_thread_create("uart_send", uart_send_entry, &test_buf, 1024, RT_THREAD_PRIORITY_MAX - 4, 10);
|
||||
|
||||
if (thread_send != RT_NULL && thread_recv != RT_NULL)
|
||||
{
|
||||
rt_thread_startup(thread_recv);
|
||||
rt_thread_startup(thread_send);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (uart_result != RT_TRUE)
|
||||
{
|
||||
LOG_E("The test for uart dma is failure.");
|
||||
result = -RT_ERROR;
|
||||
goto __exit;
|
||||
}
|
||||
if (uart_over_flag == RT_TRUE)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
/* waiting for test over */
|
||||
rt_thread_mdelay(5);
|
||||
}
|
||||
__exit:
|
||||
if (tx_sem)
|
||||
rt_sem_delete(tx_sem);
|
||||
|
||||
if (rx_sem)
|
||||
rt_sem_delete(rx_sem);
|
||||
|
||||
rt_device_close(&serial->parent);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void tc_uart_api(void)
|
||||
{
|
||||
rt_uint32_t times = 0;
|
||||
rt_uint16_t num = 0;
|
||||
while (TC_UART_SEND_TIMES - times)
|
||||
{
|
||||
num = (rand() % 1000) + 1;
|
||||
if(uart_api(num) == RT_EOK)
|
||||
LOG_I("data_lens [%3d], it is correct to read and write data. [%d] times testing.", num, ++times);
|
||||
else
|
||||
{
|
||||
LOG_E("uart test error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
uassert_true(uart_over_flag == RT_TRUE);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
LOG_I("UART TEST: Please connect Tx and Rx directly for self testing.");
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
tx_sem = RT_NULL;
|
||||
uart_result = RT_TRUE;
|
||||
uart_over_flag = RT_FALSE;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(tc_uart_api);
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "testcases.drivers.uart_rxnb_txnb", utest_tc_init, utest_tc_cleanup, 30);
|
||||
|
||||
#endif
|
62
examples/utest/testcases/kernel/Kconfig
Normal file
62
examples/utest/testcases/kernel/Kconfig
Normal file
|
@ -0,0 +1,62 @@
|
|||
menu "Kernel Testcase"
|
||||
|
||||
config UTEST_MEMHEAP_TC
|
||||
bool "memheap stability test"
|
||||
default y
|
||||
depends on RT_USING_MEMHEAP
|
||||
|
||||
config UTEST_SMALL_MEM_TC
|
||||
bool "mem test"
|
||||
default y
|
||||
depends on RT_USING_SMALL_MEM
|
||||
|
||||
config UTEST_SLAB_TC
|
||||
bool "slab test"
|
||||
default n
|
||||
depends on RT_USING_SLAB
|
||||
|
||||
config UTEST_IRQ_TC
|
||||
bool "IRQ test"
|
||||
default n
|
||||
|
||||
config UTEST_SEMAPHORE_TC
|
||||
bool "semaphore test"
|
||||
default n
|
||||
depends on RT_USING_SEMAPHORE
|
||||
|
||||
config UTEST_EVENT_TC
|
||||
bool "event test"
|
||||
default n
|
||||
depends on RT_USING_EVENT
|
||||
|
||||
config UTEST_TIMER_TC
|
||||
bool "timer test"
|
||||
default n
|
||||
|
||||
config UTEST_MESSAGEQUEUE_TC
|
||||
bool "message queue test"
|
||||
default n
|
||||
|
||||
config UTEST_SIGNAL_TC
|
||||
bool "signal test"
|
||||
default n
|
||||
|
||||
config UTEST_MUTEX_TC
|
||||
bool "mutex test"
|
||||
default n
|
||||
|
||||
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
|
||||
|
||||
config UTEST_ATOMIC_TC
|
||||
bool "atomic test"
|
||||
default n
|
||||
|
||||
endmenu
|
49
examples/utest/testcases/kernel/SConscript
Normal file
49
examples/utest/testcases/kernel/SConscript
Normal file
|
@ -0,0 +1,49 @@
|
|||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = []
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if GetDepend(['UTEST_MEMHEAP_TC']):
|
||||
src += ['memheap_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SMALL_MEM_TC']):
|
||||
src += ['mem_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SLAB_TC']):
|
||||
src += ['slab_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_IRQ_TC']):
|
||||
src += ['irq_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SEMAPHORE_TC']):
|
||||
src += ['semaphore_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_EVENT_TC']):
|
||||
src += ['event_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_TIMER_TC']):
|
||||
src += ['timer_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_MESSAGEQUEUE_TC']):
|
||||
src += ['messagequeue_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_SIGNAL_TC']):
|
||||
src += ['signal_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_MUTEX_TC']):
|
||||
src += ['mutex_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_MAILBOX_TC']):
|
||||
src += ['mailbox_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_THREAD_TC']):
|
||||
src += ['thread_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_ATOMIC_TC']):
|
||||
src += ['atomic_tc.c']
|
||||
|
||||
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
170
examples/utest/testcases/kernel/atomic_tc.c
Normal file
170
examples/utest/testcases/kernel/atomic_tc.c
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-07-27 flybreak the first version
|
||||
* 2023-03-21 WangShun add atomic test
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include "rtatomic.h"
|
||||
#include <rthw.h>
|
||||
|
||||
#define THREAD_PRIORITY 25
|
||||
#define THREAD_TIMESLICE 1
|
||||
#define THREAD_STACKSIZE 1024
|
||||
|
||||
/* convenience macro - return either 64-bit or 32-bit value */
|
||||
#define ATOMIC_WORD(val_if_64, val_if_32) \
|
||||
((rt_atomic_t)((sizeof(void *) == sizeof(uint64_t)) ? (val_if_64) : (val_if_32)))
|
||||
|
||||
static rt_atomic_t count = 0;
|
||||
static rt_sem_t sem_t;
|
||||
|
||||
static void test_atomic_api(void)
|
||||
{
|
||||
rt_atomic_t base;
|
||||
rt_atomic_t oldval;
|
||||
rt_atomic_t result;
|
||||
|
||||
/* rt_atomic_t */
|
||||
uassert_true(sizeof(rt_atomic_t) == ATOMIC_WORD(sizeof(uint64_t), sizeof(uint32_t)));
|
||||
|
||||
/* rt_atomic_add */
|
||||
base = 0;
|
||||
result = rt_atomic_add(&base, 10);
|
||||
uassert_true(base == 10);
|
||||
uassert_true(result == 0);
|
||||
/* rt_atomic_add negative */
|
||||
base = 2;
|
||||
result = rt_atomic_add(&base, -4);
|
||||
uassert_true(base == -2);
|
||||
uassert_true(result == 2);
|
||||
|
||||
/* rt_atomic_sub */
|
||||
base = 11;
|
||||
result = rt_atomic_sub(&base, 10);
|
||||
uassert_true(base == 1);
|
||||
uassert_true(result == 11);
|
||||
/* rt_atomic_sub negative */
|
||||
base = 2;
|
||||
result = rt_atomic_sub(&base, -5);
|
||||
uassert_true(base == 7);
|
||||
uassert_true(result == 2);
|
||||
|
||||
/* rt_atomic_or */
|
||||
base = 0xFF00;
|
||||
result = rt_atomic_or(&base, 0x0F0F);
|
||||
uassert_true(base == 0xFF0F);
|
||||
uassert_true(result == 0xFF00);
|
||||
|
||||
/* rt_atomic_xor */
|
||||
base = 0xFF00;
|
||||
result = rt_atomic_xor(&base, 0x0F0F);
|
||||
uassert_true(base == 0xF00F);
|
||||
uassert_true(result == 0xFF00);
|
||||
|
||||
/* rt_atomic_and */
|
||||
base = 0xFF00;
|
||||
result = rt_atomic_and(&base, 0x0F0F);
|
||||
uassert_true(base == 0x0F00);
|
||||
uassert_true(result == 0xFF00);
|
||||
|
||||
/* rt_atomic_exchange */
|
||||
base = 0xFF00;
|
||||
result = rt_atomic_exchange(&base, 0x0F0F);
|
||||
uassert_true(base == 0x0F0F);
|
||||
uassert_true(result == 0xFF00);
|
||||
|
||||
/* rt_atomic_flag_test_and_set (Flag 0) */
|
||||
base = 0x0;
|
||||
result = rt_atomic_flag_test_and_set(&base);
|
||||
uassert_true(base == 0x1);
|
||||
uassert_true(result == 0x0);
|
||||
/* rt_atomic_flag_test_and_set (Flag 1) */
|
||||
base = 0x1;
|
||||
result = rt_atomic_flag_test_and_set(&base);
|
||||
uassert_true(base == 0x1);
|
||||
uassert_true(result == 0x1);
|
||||
|
||||
/* rt_atomic_flag_clear */
|
||||
base = 0x1;
|
||||
rt_atomic_flag_clear(&base);
|
||||
uassert_true(base == 0x0);
|
||||
|
||||
/* rt_atomic_load */
|
||||
base = 0xFF00;
|
||||
result = rt_atomic_load(&base);
|
||||
uassert_true(base == 0xFF00);
|
||||
uassert_true(result == 0xFF00);
|
||||
|
||||
/* rt_atomic_store */
|
||||
base = 0xFF00;
|
||||
rt_atomic_store(&base, 0x0F0F);
|
||||
uassert_true(base == 0x0F0F);
|
||||
|
||||
/* rt_atomic_compare_exchange_strong (equal) */
|
||||
base = 10;
|
||||
oldval = 10;
|
||||
result = rt_atomic_compare_exchange_strong(&base, &oldval, 11);
|
||||
uassert_true(base == 11);
|
||||
uassert_true(result == 0x1);
|
||||
/* rt_atomic_compare_exchange_strong (not equal) */
|
||||
base = 10;
|
||||
oldval = 5;
|
||||
result = rt_atomic_compare_exchange_strong(&base, &oldval, 11);
|
||||
uassert_true(base == 10);
|
||||
uassert_true(result == 0x0);
|
||||
}
|
||||
|
||||
static void ture_entry(void *parameter)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 1000000; i++)
|
||||
{
|
||||
rt_atomic_add(&count, 1);
|
||||
}
|
||||
rt_sem_release(sem_t);
|
||||
}
|
||||
|
||||
static void test_atomic_add(void)
|
||||
{
|
||||
rt_thread_t thread;
|
||||
int i;
|
||||
sem_t = rt_sem_create("atomic_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
|
||||
count = 0;
|
||||
thread = rt_thread_create("t1", ture_entry, RT_NULL, THREAD_STACKSIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
|
||||
rt_thread_startup(thread);
|
||||
thread = rt_thread_create("t2", ture_entry, RT_NULL, THREAD_STACKSIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
|
||||
rt_thread_startup(thread);
|
||||
thread = rt_thread_create("t3", ture_entry, RT_NULL, THREAD_STACKSIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
|
||||
rt_thread_startup(thread);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
rt_sem_take(sem_t, RT_WAITING_FOREVER);
|
||||
}
|
||||
uassert_true(count == 3000000);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_atomic_api);
|
||||
UTEST_UNIT_RUN(test_atomic_add);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.atomic_tc", utest_tc_init, utest_tc_cleanup, 10);
|
344
examples/utest/testcases/kernel/event_tc.c
Normal file
344
examples/utest/testcases/kernel/event_tc.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-08-15 liukang the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define EVENT_FLAG3 (1 << 3)
|
||||
#define EVENT_FLAG5 (1 << 5)
|
||||
|
||||
static struct rt_event static_event = {0};
|
||||
#ifdef RT_USING_HEAP
|
||||
static rt_event_t dynamic_event = RT_NULL;
|
||||
static rt_uint32_t dynamic_event_recv_thread_finish = 0, dynamic_event_send_thread_finish = 0;
|
||||
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
static char thread3_stack[1024];
|
||||
static struct rt_thread thread3;
|
||||
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
static char thread4_stack[1024];
|
||||
static struct rt_thread thread4;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
static rt_uint32_t recv_event_times1 = 0, recv_event_times2 = 0;
|
||||
static rt_uint32_t static_event_recv_thread_finish = 0, static_event_send_thread_finish = 0;
|
||||
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
static char thread1_stack[1024];
|
||||
static struct rt_thread thread1;
|
||||
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
static char thread2_stack[1024];
|
||||
static struct rt_thread thread2;
|
||||
|
||||
#define THREAD_PRIORITY 9
|
||||
#define THREAD_TIMESLICE 5
|
||||
|
||||
static void test_event_init(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_event_init(&static_event, "event", RT_IPC_FLAG_PRIO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_event_detach(&static_event);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_event_init(&static_event, "event", RT_IPC_FLAG_FIFO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_event_detach(&static_event);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void test_event_detach(void)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_event_init(&static_event, "event", RT_IPC_FLAG_PRIO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_event_detach(&static_event);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void thread1_recv_static_event(void *param)
|
||||
{
|
||||
rt_uint32_t e;
|
||||
|
||||
if (rt_event_recv(&static_event, (EVENT_FLAG3 | EVENT_FLAG5),
|
||||
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
|
||||
RT_WAITING_FOREVER, &e) != RT_EOK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
recv_event_times1 = e;
|
||||
|
||||
rt_thread_mdelay(50);
|
||||
|
||||
if (rt_event_recv(&static_event, (EVENT_FLAG3 | EVENT_FLAG5),
|
||||
RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
|
||||
RT_WAITING_FOREVER, &e) != RT_EOK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
recv_event_times2 = e;
|
||||
|
||||
static_event_recv_thread_finish = 1;
|
||||
}
|
||||
|
||||
static void thread2_send_static_event(void *param)
|
||||
{
|
||||
rt_event_send(&static_event, EVENT_FLAG3);
|
||||
rt_thread_mdelay(10);
|
||||
|
||||
rt_event_send(&static_event, EVENT_FLAG5);
|
||||
rt_thread_mdelay(10);
|
||||
|
||||
rt_event_send(&static_event, EVENT_FLAG3);
|
||||
|
||||
static_event_send_thread_finish = 1;
|
||||
}
|
||||
|
||||
|
||||
static void test_static_event_send_recv(void)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_event_init(&static_event, "event", RT_IPC_FLAG_PRIO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
rt_thread_init(&thread1,
|
||||
"thread1",
|
||||
thread1_recv_static_event,
|
||||
RT_NULL,
|
||||
&thread1_stack[0],
|
||||
sizeof(thread1_stack),
|
||||
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
|
||||
rt_thread_startup(&thread1);
|
||||
|
||||
rt_thread_init(&thread2,
|
||||
"thread2",
|
||||
thread2_send_static_event,
|
||||
RT_NULL,
|
||||
&thread2_stack[0],
|
||||
sizeof(thread2_stack),
|
||||
THREAD_PRIORITY, THREAD_TIMESLICE);
|
||||
rt_thread_startup(&thread2);
|
||||
|
||||
while (static_event_recv_thread_finish != 1 || static_event_send_thread_finish != 1)
|
||||
{
|
||||
rt_thread_delay(1);
|
||||
}
|
||||
|
||||
if (recv_event_times1 == EVENT_FLAG3 && recv_event_times2 == (EVENT_FLAG3 | EVENT_FLAG5))
|
||||
{
|
||||
if (rt_event_detach(&static_event) != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
uassert_true(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rt_event_detach(&static_event) != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
static void test_event_create(void)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
dynamic_event = rt_event_create("dynamic_event", RT_IPC_FLAG_FIFO);
|
||||
if (dynamic_event == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_event_delete(dynamic_event);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void test_event_delete(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
dynamic_event = rt_event_create("dynamic_event", RT_IPC_FLAG_FIFO);
|
||||
if (dynamic_event == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_event_delete(dynamic_event);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void thread3_recv_dynamic_event(void *param)
|
||||
{
|
||||
rt_uint32_t e;
|
||||
|
||||
if (rt_event_recv(dynamic_event, (EVENT_FLAG3 | EVENT_FLAG5),
|
||||
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
|
||||
RT_WAITING_FOREVER, &e) != RT_EOK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
recv_event_times1 = e;
|
||||
|
||||
rt_thread_mdelay(50);
|
||||
|
||||
if (rt_event_recv(dynamic_event, (EVENT_FLAG3 | EVENT_FLAG5),
|
||||
RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
|
||||
RT_WAITING_FOREVER, &e) != RT_EOK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
recv_event_times2 = e;
|
||||
|
||||
dynamic_event_recv_thread_finish = 1;
|
||||
}
|
||||
|
||||
static void thread4_send_dynamic_event(void *param)
|
||||
{
|
||||
rt_event_send(dynamic_event, EVENT_FLAG3);
|
||||
rt_thread_mdelay(10);
|
||||
|
||||
rt_event_send(dynamic_event, EVENT_FLAG5);
|
||||
rt_thread_mdelay(10);
|
||||
|
||||
rt_event_send(dynamic_event, EVENT_FLAG3);
|
||||
|
||||
dynamic_event_send_thread_finish = 1;
|
||||
}
|
||||
|
||||
static void test_dynamic_event_send_recv(void)
|
||||
{
|
||||
dynamic_event = rt_event_create("dynamic_event", RT_IPC_FLAG_PRIO);
|
||||
if (dynamic_event == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
rt_thread_init(&thread3,
|
||||
"thread3",
|
||||
thread3_recv_dynamic_event,
|
||||
RT_NULL,
|
||||
&thread3_stack[0],
|
||||
sizeof(thread3_stack),
|
||||
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
|
||||
rt_thread_startup(&thread3);
|
||||
|
||||
rt_thread_init(&thread4,
|
||||
"thread4",
|
||||
thread4_send_dynamic_event,
|
||||
RT_NULL,
|
||||
&thread4_stack[0],
|
||||
sizeof(thread4_stack),
|
||||
THREAD_PRIORITY, THREAD_TIMESLICE);
|
||||
rt_thread_startup(&thread4);
|
||||
|
||||
while (dynamic_event_recv_thread_finish != 1 || dynamic_event_send_thread_finish != 1)
|
||||
{
|
||||
rt_thread_delay(1);
|
||||
}
|
||||
|
||||
if (recv_event_times1 == EVENT_FLAG3 && recv_event_times2 == (EVENT_FLAG3 | EVENT_FLAG5))
|
||||
{
|
||||
if (rt_event_delete(dynamic_event) != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
uassert_true(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rt_event_delete(dynamic_event) != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
static_event_recv_thread_finish = 0;
|
||||
static_event_send_thread_finish = 0;
|
||||
#ifdef RT_USING_HEAP
|
||||
dynamic_event_recv_thread_finish = 0;
|
||||
dynamic_event_send_thread_finish = 0;
|
||||
#endif
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_event_init);
|
||||
UTEST_UNIT_RUN(test_event_detach);
|
||||
UTEST_UNIT_RUN(test_static_event_send_recv);
|
||||
#ifdef RT_USING_HEAP
|
||||
UTEST_UNIT_RUN(test_event_create);
|
||||
UTEST_UNIT_RUN(test_event_delete);
|
||||
UTEST_UNIT_RUN(test_dynamic_event_send_recv);
|
||||
#endif
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "src.ipc.event_tc", utest_tc_init, utest_tc_cleanup, 60);
|
78
examples/utest/testcases/kernel/irq_tc.c
Normal file
78
examples/utest/testcases/kernel/irq_tc.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-08-15 supperthomas add irq_test
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include "rthw.h"
|
||||
|
||||
#define UTEST_NAME "irq_tc"
|
||||
static uint32_t irq_count = 0;
|
||||
static uint32_t max_get_nest_count = 0;
|
||||
|
||||
static void irq_callback()
|
||||
{
|
||||
if(rt_interrupt_get_nest() > max_get_nest_count)
|
||||
{
|
||||
max_get_nest_count = rt_interrupt_get_nest();
|
||||
}
|
||||
irq_count ++;
|
||||
}
|
||||
|
||||
static void irq_test(void)
|
||||
{
|
||||
irq_count = 0;
|
||||
rt_interrupt_enter_sethook(irq_callback);
|
||||
rt_interrupt_leave_sethook(irq_callback);
|
||||
rt_thread_mdelay(2);
|
||||
LOG_D("%s test irq_test! irq_count %d max_get_nest_count %d\n", UTEST_NAME, irq_count, max_get_nest_count);
|
||||
uassert_int_not_equal(0, irq_count);
|
||||
uassert_int_not_equal(0, max_get_nest_count);
|
||||
rt_interrupt_enter_sethook(RT_NULL);
|
||||
rt_interrupt_leave_sethook(RT_NULL);
|
||||
LOG_D("irq_test OK!\n");
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
irq_count = 0;
|
||||
max_get_nest_count = 0;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void interrupt_test(void)
|
||||
{
|
||||
rt_base_t level;
|
||||
uint32_t i = 1000;
|
||||
|
||||
rt_interrupt_enter_sethook(irq_callback);
|
||||
rt_interrupt_leave_sethook(irq_callback);
|
||||
irq_count = 0;
|
||||
level = rt_hw_interrupt_disable();
|
||||
while(i)
|
||||
{
|
||||
i --;
|
||||
}
|
||||
uassert_int_equal(0, irq_count);
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_interrupt_enter_sethook(RT_NULL);
|
||||
rt_interrupt_leave_sethook(RT_NULL);
|
||||
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(irq_test);
|
||||
UTEST_UNIT_RUN(interrupt_test);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.irq_tc", utest_tc_init, utest_tc_cleanup, 10);
|
371
examples/utest/testcases/kernel/mailbox_tc.c
Normal file
371
examples/utest/testcases/kernel/mailbox_tc.c
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-08 liukang the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static struct rt_mailbox test_static_mb;
|
||||
static char mb_pool[128];
|
||||
|
||||
static rt_mailbox_t test_dynamic_mb;
|
||||
|
||||
static uint8_t static_mb_recv_thread_finish, static_mb_send_thread_finish;
|
||||
static uint8_t dynamic_mb_recv_thread_finish, dynamic_mb_send_thread_finish;
|
||||
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
static char thread1_stack[1024];
|
||||
static struct rt_thread thread1;
|
||||
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
static char thread2_stack[1024];
|
||||
static struct rt_thread thread2;
|
||||
|
||||
#define THREAD_PRIORITY 9
|
||||
#define THREAD_TIMESLICE 5
|
||||
|
||||
static rt_thread_t mb_send = RT_NULL;
|
||||
static rt_thread_t mb_recv = RT_NULL;
|
||||
|
||||
static rt_uint8_t mb_send_str1[] = "this is first mail!";
|
||||
static rt_uint8_t mb_send_str2[] = "this is second mail!";
|
||||
static rt_uint8_t mb_send_str3[] = "this is thirdy mail!";
|
||||
|
||||
static rt_uint8_t *mb_recv_str1;
|
||||
static rt_uint8_t *mb_recv_str2;
|
||||
static rt_uint8_t *mb_recv_str3;
|
||||
|
||||
static void test_mailbox_init(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_mb_init(&test_static_mb, "mbt", &mb_pool[0], sizeof(mb_pool) / 4, RT_IPC_FLAG_FIFO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_mb_detach(&test_static_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_mb_init(&test_static_mb, "mbt", &mb_pool[0], sizeof(mb_pool) / 4, RT_IPC_FLAG_PRIO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_mb_detach(&test_static_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void test_mailbox_deatch(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_mb_init(&test_static_mb, "mbt", &mb_pool[0], sizeof(mb_pool) / 4, RT_IPC_FLAG_FIFO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_mb_detach(&test_static_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_mb_init(&test_static_mb, "mbt", &mb_pool[0], sizeof(mb_pool) / 4, RT_IPC_FLAG_PRIO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_mb_detach(&test_static_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void test_mailbox_create(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
test_dynamic_mb = rt_mb_create("test_dynamic_mb", sizeof(mb_pool) / 4, RT_IPC_FLAG_FIFO);
|
||||
if (test_dynamic_mb == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_mb_delete(test_dynamic_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
test_dynamic_mb = rt_mb_create("test_dynamic_mb", sizeof(mb_pool) / 4, RT_IPC_FLAG_PRIO);
|
||||
if (test_dynamic_mb == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_mb_delete(test_dynamic_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void test_mailbox_delete(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
test_dynamic_mb = rt_mb_create("test_dynamic_mb", sizeof(mb_pool) / 4, RT_IPC_FLAG_FIFO);
|
||||
if (test_dynamic_mb == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_mb_delete(test_dynamic_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
test_dynamic_mb = rt_mb_create("test_dynamic_mb", sizeof(mb_pool) / 4, RT_IPC_FLAG_PRIO);
|
||||
if (test_dynamic_mb == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
result = rt_mb_delete(test_dynamic_mb);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void thread2_send_static_mb(void *arg)
|
||||
{
|
||||
rt_err_t res = RT_EOK;
|
||||
|
||||
res = rt_mb_send(&test_static_mb, (rt_ubase_t)&mb_send_str1);
|
||||
if (res != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
rt_thread_mdelay(100);
|
||||
|
||||
res = rt_mb_send_wait(&test_static_mb, (rt_ubase_t)&mb_send_str2, 10);
|
||||
if (res != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
rt_thread_mdelay(100);
|
||||
|
||||
res = rt_mb_urgent(&test_static_mb, (rt_ubase_t)&mb_send_str3);
|
||||
if (res != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
static_mb_send_thread_finish = 1;
|
||||
}
|
||||
|
||||
static void thread1_recv_static_mb(void *arg)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_mb_recv(&test_static_mb, (rt_ubase_t *)&mb_recv_str1, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK || rt_strcmp((const char *)mb_recv_str1, (const char *)mb_send_str1) != 0)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_mb_recv(&test_static_mb, (rt_ubase_t *)&mb_recv_str2, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK || rt_strcmp((const char *)mb_recv_str2, (const char *)mb_send_str2) != 0)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_mb_recv(&test_static_mb, (rt_ubase_t *)&mb_recv_str3, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK || rt_strcmp((const char *)mb_recv_str3, (const char *)mb_send_str3) != 0)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
static_mb_recv_thread_finish = 1;
|
||||
}
|
||||
|
||||
static void test_static_mailbox_send_recv(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_mb_init(&test_static_mb, "mbt", &mb_pool[0], sizeof(mb_pool) / 4, RT_IPC_FLAG_FIFO);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
rt_thread_init(&thread1,
|
||||
"thread1",
|
||||
thread1_recv_static_mb,
|
||||
RT_NULL,
|
||||
&thread1_stack[0],
|
||||
sizeof(thread1_stack),
|
||||
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
|
||||
rt_thread_startup(&thread1);
|
||||
|
||||
rt_thread_init(&thread2,
|
||||
"thread2",
|
||||
thread2_send_static_mb,
|
||||
RT_NULL,
|
||||
&thread2_stack[0],
|
||||
sizeof(thread2_stack),
|
||||
THREAD_PRIORITY, THREAD_TIMESLICE);
|
||||
rt_thread_startup(&thread2);
|
||||
|
||||
while (static_mb_recv_thread_finish != 1 || static_mb_send_thread_finish != 1)
|
||||
{
|
||||
rt_thread_delay(1);
|
||||
}
|
||||
|
||||
if (rt_mb_detach(&test_static_mb) != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static void thread4_send_dynamic_mb(void *arg)
|
||||
{
|
||||
rt_err_t res = RT_EOK;
|
||||
|
||||
res = rt_mb_send(test_dynamic_mb, (rt_ubase_t)&mb_send_str1);
|
||||
if (res != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
rt_thread_mdelay(100);
|
||||
|
||||
res = rt_mb_send_wait(test_dynamic_mb, (rt_ubase_t)&mb_send_str2, 10);
|
||||
if (res != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
rt_thread_mdelay(100);
|
||||
|
||||
res = rt_mb_urgent(test_dynamic_mb, (rt_ubase_t)&mb_send_str3);
|
||||
if (res != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
dynamic_mb_send_thread_finish = 1;
|
||||
}
|
||||
|
||||
static void thread3_recv_dynamic_mb(void *arg)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
result = rt_mb_recv(test_dynamic_mb, (rt_ubase_t *)&mb_recv_str1, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK || rt_strcmp((const char *)mb_recv_str1, (const char *)mb_send_str1) != 0)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_mb_recv(test_dynamic_mb, (rt_ubase_t *)&mb_recv_str2, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK || rt_strcmp((const char *)mb_recv_str2, (const char *)mb_send_str2) != 0)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
result = rt_mb_recv(test_dynamic_mb, (rt_ubase_t *)&mb_recv_str3, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK || rt_strcmp((const char *)mb_recv_str3, (const char *)mb_send_str3) != 0)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
dynamic_mb_recv_thread_finish = 1;
|
||||
}
|
||||
|
||||
static void test_dynamic_mailbox_send_recv(void)
|
||||
{
|
||||
test_dynamic_mb = rt_mb_create("mbt", sizeof(mb_pool) / 4, RT_IPC_FLAG_FIFO);
|
||||
if (test_dynamic_mb == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
mb_recv = rt_thread_create("mb_recv_thread",
|
||||
thread3_recv_dynamic_mb,
|
||||
RT_NULL,
|
||||
1024,
|
||||
THREAD_PRIORITY - 1,
|
||||
THREAD_TIMESLICE);
|
||||
if (mb_recv == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
rt_thread_startup(mb_recv);
|
||||
|
||||
mb_send = rt_thread_create("mb_send_thread",
|
||||
thread4_send_dynamic_mb,
|
||||
RT_NULL,
|
||||
1024,
|
||||
THREAD_PRIORITY - 1,
|
||||
THREAD_TIMESLICE);
|
||||
if (mb_send == RT_NULL)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
rt_thread_startup(mb_send);
|
||||
|
||||
while (dynamic_mb_recv_thread_finish != 1 || dynamic_mb_send_thread_finish != 1)
|
||||
{
|
||||
rt_thread_delay(1);
|
||||
}
|
||||
|
||||
if (rt_mb_delete(test_dynamic_mb) != RT_EOK)
|
||||
{
|
||||
uassert_false(1);
|
||||
}
|
||||
|
||||
uassert_true(1);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_mailbox_init);
|
||||
UTEST_UNIT_RUN(test_mailbox_deatch);
|
||||
UTEST_UNIT_RUN(test_mailbox_create);
|
||||
UTEST_UNIT_RUN(test_mailbox_delete);
|
||||
UTEST_UNIT_RUN(test_static_mailbox_send_recv);
|
||||
UTEST_UNIT_RUN(test_dynamic_mailbox_send_recv);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "src.ipc.mailbox_tc", utest_tc_init, utest_tc_cleanup, 60);
|
588
examples/utest/testcases/kernel/mem_tc.c
Normal file
588
examples/utest/testcases/kernel/mem_tc.c
Normal file
|
@ -0,0 +1,588 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-10-14 tyx the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "utest.h"
|
||||
|
||||
struct rt_small_mem_item
|
||||
{
|
||||
rt_ubase_t pool_ptr; /**< small memory object addr */
|
||||
#ifdef ARCH_CPU_64BIT
|
||||
rt_uint32_t resv;
|
||||
#endif /* ARCH_CPU_64BIT */
|
||||
rt_size_t next; /**< next free item */
|
||||
rt_size_t prev; /**< prev free item */
|
||||
#ifdef RT_USING_MEMTRACE
|
||||
#ifdef ARCH_CPU_64BIT
|
||||
rt_uint8_t thread[8]; /**< thread name */
|
||||
#else
|
||||
rt_uint8_t thread[4]; /**< thread name */
|
||||
#endif /* ARCH_CPU_64BIT */
|
||||
#endif /* RT_USING_MEMTRACE */
|
||||
};
|
||||
|
||||
struct rt_small_mem
|
||||
{
|
||||
struct rt_memory parent; /**< inherit from rt_memory */
|
||||
rt_uint8_t *heap_ptr; /**< pointer to the heap */
|
||||
struct rt_small_mem_item *heap_end;
|
||||
struct rt_small_mem_item *lfree;
|
||||
rt_size_t mem_size_aligned; /**< aligned memory size */
|
||||
};
|
||||
|
||||
#define MEM_SIZE(_heap, _mem) \
|
||||
(((struct rt_small_mem_item *)(_mem))->next - ((rt_ubase_t)(_mem) - \
|
||||
(rt_ubase_t)((_heap)->heap_ptr)) - RT_ALIGN(sizeof(struct rt_small_mem_item), RT_ALIGN_SIZE))
|
||||
|
||||
#define TEST_MEM_SIZE 1024
|
||||
|
||||
static rt_size_t max_block(struct rt_small_mem *heap)
|
||||
{
|
||||
struct rt_small_mem_item *mem;
|
||||
rt_size_t max = 0, size;
|
||||
|
||||
for (mem = (struct rt_small_mem_item *)heap->heap_ptr;
|
||||
mem != heap->heap_end;
|
||||
mem = (struct rt_small_mem_item *)&heap->heap_ptr[mem->next])
|
||||
{
|
||||
if (((rt_ubase_t)mem->pool_ptr & 0x1) == 0)
|
||||
{
|
||||
size = MEM_SIZE(heap, mem);
|
||||
if (size > max)
|
||||
{
|
||||
max = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
static int _mem_cmp(void *ptr, rt_uint8_t v, rt_size_t size)
|
||||
{
|
||||
while (size-- != 0)
|
||||
{
|
||||
if (*(rt_uint8_t *)ptr != v)
|
||||
return *(rt_uint8_t *)ptr - v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mem_test_context
|
||||
{
|
||||
void *ptr;
|
||||
rt_size_t size;
|
||||
rt_uint8_t magic;
|
||||
};
|
||||
|
||||
static void mem_functional_test(void)
|
||||
{
|
||||
rt_size_t total_size;
|
||||
rt_uint8_t *buf;
|
||||
struct rt_small_mem *heap;
|
||||
rt_uint8_t magic = __LINE__;
|
||||
|
||||
/* Prepare test memory */
|
||||
buf = rt_malloc(TEST_MEM_SIZE);
|
||||
uassert_not_null(buf);
|
||||
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||||
rt_memset(buf, 0xAA, TEST_MEM_SIZE);
|
||||
/* small heap init */
|
||||
heap = (struct rt_small_mem *)rt_smem_init("mem_tc", buf, TEST_MEM_SIZE);
|
||||
/* get total size */
|
||||
total_size = max_block(heap);
|
||||
uassert_int_not_equal(total_size, 0);
|
||||
/*
|
||||
* Allocate all memory at a time and test whether
|
||||
* the memory allocation release function is effective
|
||||
*/
|
||||
{
|
||||
struct mem_test_context ctx;
|
||||
ctx.magic = magic++;
|
||||
ctx.size = max_block(heap);
|
||||
ctx.ptr = rt_smem_alloc(&heap->parent, ctx.size);
|
||||
uassert_not_null(ctx.ptr);
|
||||
rt_memset(ctx.ptr, ctx.magic, ctx.size);
|
||||
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||||
rt_smem_free(ctx.ptr);
|
||||
uassert_int_equal(max_block(heap), total_size);
|
||||
}
|
||||
/*
|
||||
* Apply for memory release sequentially and
|
||||
* test whether memory block merging is effective
|
||||
*/
|
||||
{
|
||||
rt_size_t i, max_free = 0;
|
||||
struct mem_test_context ctx[3];
|
||||
/* alloc mem */
|
||||
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||||
{
|
||||
ctx[i].magic = magic++;
|
||||
ctx[i].size = max_block(heap) / (sizeof(ctx) / sizeof(ctx[0]) - i);
|
||||
ctx[i].ptr = rt_smem_alloc(&heap->parent, ctx[i].size);
|
||||
uassert_not_null(ctx[i].ptr);
|
||||
rt_memset(ctx[i].ptr, ctx[i].magic, ctx[i].size);
|
||||
}
|
||||
/* All memory has been applied. The remaining memory should be 0 */
|
||||
uassert_int_equal(max_block(heap), 0);
|
||||
/* Verify that the memory data is correct */
|
||||
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||||
{
|
||||
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||||
}
|
||||
/* Sequential memory release */
|
||||
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||||
{
|
||||
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||||
rt_smem_free(ctx[i].ptr);
|
||||
max_free += ctx[i].size;
|
||||
uassert_true(max_block(heap) >= max_free);
|
||||
}
|
||||
/* Check whether the memory is fully merged */
|
||||
uassert_int_equal(max_block(heap), total_size);
|
||||
}
|
||||
/*
|
||||
* Apply for memory release at an interval to
|
||||
* test whether memory block merging is effective
|
||||
*/
|
||||
{
|
||||
rt_size_t i, max_free = 0;
|
||||
struct mem_test_context ctx[3];
|
||||
/* alloc mem */
|
||||
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||||
{
|
||||
ctx[i].magic = magic++;
|
||||
ctx[i].size = max_block(heap) / (sizeof(ctx) / sizeof(ctx[0]) - i);
|
||||
ctx[i].ptr = rt_smem_alloc(&heap->parent, ctx[i].size);
|
||||
uassert_not_null(ctx[i].ptr);
|
||||
rt_memset(ctx[i].ptr, ctx[i].magic, ctx[i].size);
|
||||
}
|
||||
/* All memory has been applied. The remaining memory should be 0 */
|
||||
uassert_int_equal(max_block(heap), 0);
|
||||
/* Verify that the memory data is correct */
|
||||
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||||
{
|
||||
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||||
}
|
||||
/* Release even address */
|
||||
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||||
rt_smem_free(ctx[i].ptr);
|
||||
uassert_true(max_block(heap) >= ctx[0].size);
|
||||
}
|
||||
}
|
||||
/* Release odd addresses and merge memory blocks */
|
||||
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||||
{
|
||||
if (i % 2 != 0)
|
||||
{
|
||||
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||||
rt_smem_free(ctx[i].ptr);
|
||||
max_free += ctx[i - 1].size + ctx[i + 1].size;
|
||||
uassert_true(max_block(heap) >= max_free);
|
||||
}
|
||||
}
|
||||
/* Check whether the memory is fully merged */
|
||||
uassert_int_equal(max_block(heap), total_size);
|
||||
}
|
||||
/* mem realloc test,Small - > Large */
|
||||
{
|
||||
/* Request a piece of memory for subsequent reallocation operations */
|
||||
struct mem_test_context ctx[3];
|
||||
ctx[0].magic = magic++;
|
||||
ctx[0].size = max_block(heap) / 3;
|
||||
ctx[0].ptr = rt_smem_alloc(&heap->parent, ctx[0].size);
|
||||
uassert_not_null(ctx[0].ptr);
|
||||
rt_memset(ctx[0].ptr, ctx[0].magic, ctx[0].size);
|
||||
/* Apply for a small piece of memory and split the continuous memory */
|
||||
ctx[1].magic = magic++;
|
||||
ctx[1].size = RT_ALIGN_SIZE;
|
||||
ctx[1].ptr = rt_smem_alloc(&heap->parent, ctx[1].size);
|
||||
uassert_not_null(ctx[1].ptr);
|
||||
rt_memset(ctx[1].ptr, ctx[1].magic, ctx[1].size);
|
||||
/* Check whether the maximum memory block is larger than the first piece of memory */
|
||||
uassert_true(max_block(heap) > ctx[0].size);
|
||||
/* Reallocate the first piece of memory */
|
||||
ctx[2].magic = magic++;
|
||||
ctx[2].size = max_block(heap);
|
||||
ctx[2].ptr = rt_smem_realloc(&heap->parent, ctx[0].ptr, ctx[2].size);
|
||||
uassert_not_null(ctx[2].ptr);
|
||||
uassert_int_not_equal(ctx[0].ptr, ctx[2].ptr);
|
||||
uassert_int_equal(_mem_cmp(ctx[2].ptr, ctx[0].magic, ctx[0].size), 0);
|
||||
rt_memset(ctx[2].ptr, ctx[2].magic, ctx[2].size);
|
||||
/* Free the second piece of memory */
|
||||
uassert_int_equal(_mem_cmp(ctx[1].ptr, ctx[1].magic, ctx[1].size), 0);
|
||||
rt_smem_free(ctx[1].ptr);
|
||||
/* Free reallocated memory */
|
||||
uassert_int_equal(_mem_cmp(ctx[2].ptr, ctx[2].magic, ctx[2].size), 0);
|
||||
rt_smem_free(ctx[2].ptr);
|
||||
/* Check memory integrity */
|
||||
uassert_int_equal(max_block(heap), total_size);
|
||||
}
|
||||
/* mem realloc test,Large - > Small */
|
||||
{
|
||||
rt_size_t max_free;
|
||||
struct mem_test_context ctx;
|
||||
/* alloc a piece of memory */
|
||||
ctx.magic = magic++;
|
||||
ctx.size = max_block(heap) / 2;
|
||||
ctx.ptr = rt_smem_alloc(&heap->parent, ctx.size);
|
||||
uassert_not_null(ctx.ptr);
|
||||
rt_memset(ctx.ptr, ctx.magic, ctx.size);
|
||||
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||||
/* Get remaining memory */
|
||||
max_free = max_block(heap);
|
||||
/* Change memory size */
|
||||
ctx.size = ctx.size / 2;
|
||||
uassert_int_equal((rt_ubase_t)rt_smem_realloc(&heap->parent, ctx.ptr, ctx.size), (rt_ubase_t)ctx.ptr);
|
||||
/* Get remaining size */
|
||||
uassert_true(max_block(heap) > max_free);
|
||||
/* Free memory */
|
||||
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||||
rt_smem_free(ctx.ptr);
|
||||
/* Check memory integrity */
|
||||
uassert_int_equal(max_block(heap), total_size);
|
||||
}
|
||||
/* mem realloc test,equal */
|
||||
{
|
||||
rt_size_t max_free;
|
||||
struct mem_test_context ctx;
|
||||
/* alloc a piece of memory */
|
||||
ctx.magic = magic++;
|
||||
ctx.size = max_block(heap) / 2;
|
||||
ctx.ptr = rt_smem_alloc(&heap->parent, ctx.size);
|
||||
uassert_not_null(ctx.ptr);
|
||||
rt_memset(ctx.ptr, ctx.magic, ctx.size);
|
||||
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||||
/* Get remaining memory */
|
||||
max_free = max_block(heap);
|
||||
/* Do not change memory size */
|
||||
uassert_int_equal((rt_ubase_t)rt_smem_realloc(&heap->parent, ctx.ptr, ctx.size), (rt_ubase_t)ctx.ptr);
|
||||
/* Get remaining size */
|
||||
uassert_true(max_block(heap) == max_free);
|
||||
/* Free memory */
|
||||
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||||
rt_smem_free(ctx.ptr);
|
||||
/* Check memory integrity */
|
||||
uassert_int_equal(max_block(heap), total_size);
|
||||
}
|
||||
/* small heap deinit */
|
||||
rt_smem_detach(&heap->parent);
|
||||
/* release test resources */
|
||||
rt_free(buf);
|
||||
}
|
||||
|
||||
struct mem_alloc_context
|
||||
{
|
||||
rt_list_t node;
|
||||
rt_size_t size;
|
||||
rt_uint8_t magic;
|
||||
};
|
||||
|
||||
struct mem_alloc_head
|
||||
{
|
||||
rt_list_t list;
|
||||
rt_size_t count;
|
||||
rt_tick_t start;
|
||||
rt_tick_t end;
|
||||
rt_tick_t interval;
|
||||
};
|
||||
|
||||
#define MEM_RANG_ALLOC_BLK_MIN 2
|
||||
#define MEM_RANG_ALLOC_BLK_MAX 5
|
||||
#define MEM_RANG_ALLOC_TEST_TIME 5
|
||||
|
||||
static void mem_alloc_test(void)
|
||||
{
|
||||
struct mem_alloc_head head;
|
||||
rt_uint8_t *buf;
|
||||
struct rt_small_mem *heap;
|
||||
rt_size_t total_size, size;
|
||||
struct mem_alloc_context *ctx;
|
||||
|
||||
/* init */
|
||||
rt_list_init(&head.list);
|
||||
head.count = 0;
|
||||
head.start = rt_tick_get();
|
||||
head.end = rt_tick_get() + rt_tick_from_millisecond(MEM_RANG_ALLOC_TEST_TIME * 1000);
|
||||
head.interval = (head.end - head.start) / 20;
|
||||
buf = rt_malloc(TEST_MEM_SIZE);
|
||||
uassert_not_null(buf);
|
||||
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||||
rt_memset(buf, 0xAA, TEST_MEM_SIZE);
|
||||
heap = (struct rt_small_mem *)rt_smem_init("mem_tc", buf, TEST_MEM_SIZE);
|
||||
total_size = max_block(heap);
|
||||
uassert_int_not_equal(total_size, 0);
|
||||
/* test run */
|
||||
while (head.end - head.start < RT_TICK_MAX / 2)
|
||||
{
|
||||
if (rt_tick_get() - head.start >= head.interval)
|
||||
{
|
||||
head.start = rt_tick_get();
|
||||
rt_kprintf("#");
|
||||
}
|
||||
/* %60 probability to perform alloc operation */
|
||||
if (rand() % 10 >= 4)
|
||||
{
|
||||
size = rand() % MEM_RANG_ALLOC_BLK_MAX + MEM_RANG_ALLOC_BLK_MIN;
|
||||
size *= sizeof(struct mem_alloc_context);
|
||||
ctx = rt_smem_alloc(&heap->parent, size);
|
||||
if (ctx == RT_NULL)
|
||||
{
|
||||
if (head.count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
size = head.count / 2;
|
||||
while (size != head.count)
|
||||
{
|
||||
ctx = rt_list_first_entry(&head.list, struct mem_alloc_context, node);
|
||||
rt_list_remove(&ctx->node);
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||||
{
|
||||
uassert_true(0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_smem_free(ctx);
|
||||
head.count --;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (RT_ALIGN((rt_ubase_t)ctx, RT_ALIGN_SIZE) != (rt_ubase_t)ctx)
|
||||
{
|
||||
uassert_int_equal(RT_ALIGN((rt_ubase_t)ctx, RT_ALIGN_SIZE), (rt_ubase_t)ctx);
|
||||
}
|
||||
rt_memset(ctx, 0, size);
|
||||
rt_list_init(&ctx->node);
|
||||
ctx->size = size;
|
||||
ctx->magic = rand() & 0xff;
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
rt_memset(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
}
|
||||
rt_list_insert_after(&head.list, &ctx->node);
|
||||
head.count += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rt_list_isempty(&head.list))
|
||||
{
|
||||
ctx = rt_list_first_entry(&head.list, struct mem_alloc_context, node);
|
||||
rt_list_remove(&ctx->node);
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||||
{
|
||||
uassert_true(0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_smem_free(ctx);
|
||||
head.count --;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!rt_list_isempty(&head.list))
|
||||
{
|
||||
ctx = rt_list_first_entry(&head.list, struct mem_alloc_context, node);
|
||||
rt_list_remove(&ctx->node);
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||||
{
|
||||
uassert_true(0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_smem_free(ctx);
|
||||
head.count --;
|
||||
}
|
||||
uassert_int_equal(head.count, 0);
|
||||
uassert_int_equal(max_block(heap), total_size);
|
||||
/* small heap deinit */
|
||||
rt_smem_detach(&heap->parent);
|
||||
/* release test resources */
|
||||
rt_free(buf);
|
||||
}
|
||||
|
||||
#define MEM_RANG_REALLOC_BLK_MIN 0
|
||||
#define MEM_RANG_REALLOC_BLK_MAX 5
|
||||
#define MEM_RANG_REALLOC_TEST_TIME 5
|
||||
|
||||
struct mem_realloc_context
|
||||
{
|
||||
rt_size_t size;
|
||||
rt_uint8_t magic;
|
||||
};
|
||||
|
||||
struct mem_realloc_head
|
||||
{
|
||||
struct mem_realloc_context **ctx_tab;
|
||||
rt_size_t count;
|
||||
rt_tick_t start;
|
||||
rt_tick_t end;
|
||||
rt_tick_t interval;
|
||||
};
|
||||
|
||||
static void mem_realloc_test(void)
|
||||
{
|
||||
struct mem_realloc_head head;
|
||||
rt_uint8_t *buf;
|
||||
struct rt_small_mem *heap;
|
||||
rt_size_t total_size, size, idx;
|
||||
struct mem_realloc_context *ctx;
|
||||
int res;
|
||||
|
||||
size = RT_ALIGN(sizeof(struct mem_realloc_context), RT_ALIGN_SIZE) + RT_ALIGN_SIZE;
|
||||
size = TEST_MEM_SIZE / size;
|
||||
/* init */
|
||||
head.ctx_tab = RT_NULL;
|
||||
head.count = size;
|
||||
head.start = rt_tick_get();
|
||||
head.end = rt_tick_get() + rt_tick_from_millisecond(MEM_RANG_ALLOC_TEST_TIME * 1000);
|
||||
head.interval = (head.end - head.start) / 20;
|
||||
buf = rt_malloc(TEST_MEM_SIZE);
|
||||
uassert_not_null(buf);
|
||||
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||||
rt_memset(buf, 0xAA, TEST_MEM_SIZE);
|
||||
heap = (struct rt_small_mem *)rt_smem_init("mem_tc", buf, TEST_MEM_SIZE);
|
||||
total_size = max_block(heap);
|
||||
uassert_int_not_equal(total_size, 0);
|
||||
/* init ctx tab */
|
||||
size = head.count * sizeof(struct mem_realloc_context *);
|
||||
head.ctx_tab = rt_smem_alloc(&heap->parent, size);
|
||||
uassert_not_null(head.ctx_tab);
|
||||
rt_memset(head.ctx_tab, 0, size);
|
||||
/* test run */
|
||||
while (head.end - head.start < RT_TICK_MAX / 2)
|
||||
{
|
||||
if (rt_tick_get() - head.start >= head.interval)
|
||||
{
|
||||
head.start = rt_tick_get();
|
||||
rt_kprintf("#");
|
||||
}
|
||||
size = rand() % MEM_RANG_ALLOC_BLK_MAX + MEM_RANG_ALLOC_BLK_MIN;
|
||||
size *= sizeof(struct mem_realloc_context);
|
||||
idx = rand() % head.count;
|
||||
ctx = rt_smem_realloc(&heap->parent, head.ctx_tab[idx], size);
|
||||
if (ctx == RT_NULL)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
if (head.ctx_tab[idx])
|
||||
{
|
||||
head.ctx_tab[idx] = RT_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (idx = 0; idx < head.count; idx++)
|
||||
{
|
||||
ctx = head.ctx_tab[idx];
|
||||
if (rand() % 2 && ctx)
|
||||
{
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
if (res != 0)
|
||||
{
|
||||
uassert_int_equal(res, 0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_smem_realloc(&heap->parent, ctx, 0);
|
||||
head.ctx_tab[idx] = RT_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* check mem */
|
||||
if (head.ctx_tab[idx] != RT_NULL)
|
||||
{
|
||||
res = 0;
|
||||
if (ctx->size < size)
|
||||
{
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, size - sizeof(*ctx));
|
||||
}
|
||||
}
|
||||
if (res != 0)
|
||||
{
|
||||
uassert_int_equal(res, 0);
|
||||
}
|
||||
}
|
||||
/* init mem */
|
||||
ctx->magic = rand() & 0xff;
|
||||
ctx->size = size;
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
rt_memset(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
}
|
||||
head.ctx_tab[idx] = ctx;
|
||||
}
|
||||
/* free all mem */
|
||||
for (idx = 0; idx < head.count; idx++)
|
||||
{
|
||||
ctx = head.ctx_tab[idx];
|
||||
if (ctx == RT_NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
if (res != 0)
|
||||
{
|
||||
uassert_int_equal(res, 0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_smem_realloc(&heap->parent, ctx, 0);
|
||||
head.ctx_tab[idx] = RT_NULL;
|
||||
}
|
||||
uassert_int_not_equal(max_block(heap), total_size);
|
||||
/* small heap deinit */
|
||||
rt_smem_detach(&heap->parent);
|
||||
/* release test resources */
|
||||
rt_free(buf);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(mem_functional_test);
|
||||
UTEST_UNIT_RUN(mem_alloc_test);
|
||||
UTEST_UNIT_RUN(mem_realloc_test);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.mem_tc", utest_tc_init, utest_tc_cleanup, 20);
|
97
examples/utest/testcases/kernel/memheap_tc.c
Normal file
97
examples/utest/testcases/kernel/memheap_tc.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-01-16 flybreak the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "utest.h"
|
||||
|
||||
#define HEAP_SIZE (64 * 1024)
|
||||
#define HEAP_ALIGN (4)
|
||||
#define SLICE_NUM (40)
|
||||
#define TEST_TIMES (100000)
|
||||
#define HEAP_NAME "heap1"
|
||||
#define SLICE_SIZE_MAX (HEAP_SIZE/SLICE_NUM)
|
||||
|
||||
static void memheap_test(void)
|
||||
{
|
||||
struct rt_memheap heap1;
|
||||
void * ptr_start;
|
||||
void *ptr[SLICE_NUM];
|
||||
int i, cnt = 0;
|
||||
|
||||
/* init heap */
|
||||
ptr_start = rt_malloc_align(HEAP_SIZE, HEAP_ALIGN);
|
||||
if (ptr_start == RT_NULL)
|
||||
{
|
||||
rt_kprintf("totle size too big,can not malloc memory!");
|
||||
return;
|
||||
}
|
||||
|
||||
rt_memheap_init(&heap1, HEAP_NAME, ptr_start, HEAP_SIZE);
|
||||
|
||||
/* test start */
|
||||
for (i = 0; i < SLICE_NUM; i++)
|
||||
{
|
||||
ptr[i] = 0;
|
||||
}
|
||||
/* test alloc */
|
||||
for (i = 0; i < SLICE_NUM; i++)
|
||||
{
|
||||
rt_uint32_t slice_size = rand() % SLICE_SIZE_MAX;
|
||||
ptr[i] = rt_memheap_alloc(&heap1, slice_size);
|
||||
}
|
||||
/* test realloc */
|
||||
while (cnt < TEST_TIMES)
|
||||
{
|
||||
rt_uint32_t slice_size = rand() % SLICE_SIZE_MAX;
|
||||
rt_uint32_t ptr_index = rand() % SLICE_NUM;
|
||||
rt_uint32_t operation = rand() % 2;
|
||||
|
||||
if (ptr[ptr_index])
|
||||
{
|
||||
if (operation == 0) /* free and malloc */
|
||||
{
|
||||
rt_memheap_free(ptr[ptr_index]);
|
||||
ptr[ptr_index] = rt_memheap_alloc(&heap1, slice_size);
|
||||
}
|
||||
else /* realloc */
|
||||
{
|
||||
ptr[ptr_index] = rt_memheap_realloc(&heap1, ptr[ptr_index], slice_size);
|
||||
}
|
||||
}
|
||||
cnt ++;
|
||||
if (cnt % (TEST_TIMES / 10) == 0)
|
||||
{
|
||||
rt_kprintf(">");
|
||||
}
|
||||
}
|
||||
|
||||
rt_kprintf("test OK!\n");
|
||||
|
||||
/* test end */
|
||||
rt_memheap_detach(&heap1);
|
||||
rt_free_align((void *)ptr_start);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(memheap_test);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.memheap_tc", utest_tc_init, utest_tc_cleanup, 10);
|
192
examples/utest/testcases/kernel/messagequeue_tc.c
Normal file
192
examples/utest/testcases/kernel/messagequeue_tc.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-08-28 Sherman the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
|
||||
#define MSG_SIZE 4
|
||||
#define MAX_MSGS 5
|
||||
|
||||
static struct rt_messagequeue static_mq;
|
||||
static rt_uint8_t mq_buf[(MSG_SIZE + (rt_uint8_t)sizeof(rt_ubase_t)) * MAX_MSGS];
|
||||
|
||||
static struct rt_thread mq_send_thread;
|
||||
static struct rt_thread mq_recv_thread;
|
||||
static rt_uint8_t mq_send_stack[1024];
|
||||
static rt_uint8_t mq_recv_stack[1024];
|
||||
|
||||
static struct rt_event finish_e;
|
||||
#define MQSEND_FINISH 0x01
|
||||
#define MQRECV_FINIHS 0x02
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
static rt_mq_t dynamic_mq;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
static void test_mq_init(void)
|
||||
{
|
||||
rt_err_t ret;
|
||||
ret = rt_mq_init(&static_mq,"testmq1", mq_buf, MSG_SIZE, sizeof(mq_buf), RT_IPC_FLAG_FIFO);
|
||||
uassert_true(ret == RT_EOK);
|
||||
}
|
||||
|
||||
static void test_mq_create(void)
|
||||
{
|
||||
#ifdef RT_USING_HEAP
|
||||
dynamic_mq = rt_mq_create("testmq2", MSG_SIZE, MAX_MSGS, RT_IPC_FLAG_FIFO);
|
||||
uassert_true(dynamic_mq != RT_NULL);
|
||||
#endif /* RT_USING_HEAP */
|
||||
}
|
||||
|
||||
static void mq_send_case(rt_mq_t testmq)
|
||||
{
|
||||
rt_uint32_t send_buf[MAX_MSGS+1] = {0};
|
||||
rt_err_t ret = RT_EOK;
|
||||
|
||||
for (int var = 0; var < MAX_MSGS; ++var)
|
||||
{
|
||||
send_buf[var] = var + 1;
|
||||
ret = rt_mq_send_wait(testmq, &send_buf[var], sizeof(send_buf[0]), RT_WAITING_FOREVER);
|
||||
uassert_true(ret == RT_EOK);
|
||||
}
|
||||
send_buf[MAX_MSGS] = MAX_MSGS + 1;
|
||||
ret = rt_mq_send(testmq, &send_buf[MAX_MSGS], sizeof(send_buf[0]));
|
||||
uassert_true(ret == -RT_EFULL);
|
||||
|
||||
ret = rt_mq_send_wait(testmq, &send_buf[MAX_MSGS], sizeof(send_buf[0]), RT_WAITING_FOREVER);
|
||||
uassert_true(ret == RT_EOK);
|
||||
|
||||
while (testmq->entry != 0)
|
||||
{
|
||||
rt_thread_delay(100);
|
||||
}
|
||||
|
||||
ret = rt_mq_send(testmq, &send_buf[1], sizeof(send_buf[0]));
|
||||
uassert_true(ret == RT_EOK);
|
||||
|
||||
ret = rt_mq_send(testmq, &send_buf[2], sizeof(send_buf[0]));
|
||||
uassert_true(ret == RT_EOK);
|
||||
|
||||
ret = rt_mq_urgent(testmq, &send_buf[0], sizeof(send_buf[0]));
|
||||
uassert_true(ret == RT_EOK);
|
||||
|
||||
while (testmq->entry != 0)
|
||||
{
|
||||
rt_thread_delay(100);
|
||||
}
|
||||
|
||||
ret = rt_mq_send(testmq, &send_buf[1], sizeof(send_buf[0]));
|
||||
uassert_true(ret == RT_EOK);
|
||||
ret = rt_mq_control(testmq, RT_IPC_CMD_RESET, RT_NULL);
|
||||
uassert_true(ret == RT_EOK);
|
||||
uassert_true(testmq->entry == 0);
|
||||
}
|
||||
|
||||
static void mq_send_entry(void *param)
|
||||
{
|
||||
mq_send_case(&static_mq);
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
if(dynamic_mq != RT_NULL)
|
||||
{
|
||||
mq_send_case(dynamic_mq);
|
||||
}
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
rt_event_send(&finish_e, MQSEND_FINISH);
|
||||
}
|
||||
|
||||
static void mq_recv_case(rt_mq_t testmq)
|
||||
{
|
||||
rt_uint32_t recv_buf[MAX_MSGS+1] = {0};
|
||||
rt_err_t ret = RT_EOK;
|
||||
|
||||
for (int var = 0; var < MAX_MSGS + 1; ++var)
|
||||
{
|
||||
ret = rt_mq_recv(testmq, &recv_buf[var], sizeof(recv_buf[0]), RT_WAITING_FOREVER);
|
||||
uassert_true(ret == RT_EOK);
|
||||
uassert_true(recv_buf[var] == (var + 1));
|
||||
}
|
||||
|
||||
for (int var = 0; var < 3; ++var)
|
||||
{
|
||||
ret = rt_mq_recv(testmq, &recv_buf[var], sizeof(recv_buf[0]), RT_WAITING_FOREVER);
|
||||
uassert_true(ret == RT_EOK);
|
||||
uassert_true(recv_buf[var] == (var + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void mq_recv_entry(void *param)
|
||||
{
|
||||
mq_recv_case(&static_mq);
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
if(dynamic_mq != RT_NULL)
|
||||
{
|
||||
mq_recv_case(dynamic_mq);
|
||||
}
|
||||
#endif /* RT_USING_HEAP */
|
||||
rt_event_send(&finish_e, MQRECV_FINIHS);
|
||||
}
|
||||
|
||||
static void test_mq_testcase(void)
|
||||
{
|
||||
rt_thread_startup(&mq_send_thread);
|
||||
rt_thread_startup(&mq_recv_thread);
|
||||
|
||||
rt_event_recv(&finish_e, MQSEND_FINISH | MQRECV_FINIHS, RT_EVENT_FLAG_AND, RT_WAITING_FOREVER, RT_NULL);
|
||||
}
|
||||
|
||||
static void test_mq_detach(void)
|
||||
{
|
||||
rt_err_t ret = rt_mq_detach(&static_mq);
|
||||
uassert_true(ret == RT_EOK);
|
||||
}
|
||||
|
||||
static void test_mq_delete(void)
|
||||
{
|
||||
#ifdef RT_USING_HEAP
|
||||
rt_err_t ret = rt_mq_delete(dynamic_mq);
|
||||
uassert_true(ret == RT_EOK);
|
||||
#endif /* RT_USING_HEAP */
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
rt_err_t ret ;
|
||||
ret = rt_thread_init(&mq_send_thread, "mq_send", mq_send_entry, RT_NULL, mq_send_stack, sizeof(mq_send_stack), 22, 20);
|
||||
if(ret != RT_EOK)
|
||||
return -RT_ERROR;
|
||||
|
||||
ret = rt_thread_init(&mq_recv_thread, "mq_recv", mq_recv_entry, RT_NULL, mq_recv_stack, sizeof(mq_recv_stack), 23, 20);
|
||||
if(ret != RT_EOK)
|
||||
return -RT_ERROR;
|
||||
|
||||
ret = rt_event_init(&finish_e, "finish", RT_IPC_FLAG_FIFO);
|
||||
if(ret != RT_EOK)
|
||||
return -RT_ERROR;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_mq_init);
|
||||
UTEST_UNIT_RUN(test_mq_create);
|
||||
UTEST_UNIT_RUN(test_mq_testcase);
|
||||
UTEST_UNIT_RUN(test_mq_detach);
|
||||
UTEST_UNIT_RUN(test_mq_delete);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.messagequeue_tc", utest_tc_init, utest_tc_cleanup, 1000);
|
676
examples/utest/testcases/kernel/mutex_tc.c
Normal file
676
examples/utest/testcases/kernel/mutex_tc.c
Normal file
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09.01 luckyzjq the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "utest.h"
|
||||
|
||||
static struct rt_mutex static_mutex;
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
static rt_mutex_t dynamic_mutex;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
/* init test */
|
||||
static void test_static_mutex_init(void)
|
||||
{
|
||||
rt_err_t result = -RT_ERROR;
|
||||
|
||||
result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
result = rt_mutex_detach(&static_mutex);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
result = rt_mutex_detach(&static_mutex);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* static take test */
|
||||
static void static_mutex_take_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex;
|
||||
|
||||
int rand_num = rand() % 0x1000;
|
||||
mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_take(mutex, rand_num);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
static void test_static_mutex_take(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* take mutex and not release */
|
||||
result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
rt_thread_t tid = rt_thread_create("mutex_th",
|
||||
static_mutex_take_entry,
|
||||
&static_mutex,
|
||||
2048,
|
||||
10,
|
||||
10);
|
||||
if (RT_NULL == tid)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* startup thread take second */
|
||||
rt_thread_startup(tid);
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(5);
|
||||
|
||||
result = rt_mutex_detach(&static_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* static release test */
|
||||
static void static_mutex_release_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex;
|
||||
|
||||
int rand_num = rand() % 0x1000;
|
||||
mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_take(mutex, rand_num);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
static void test_static_mutex_release(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* take mutex */
|
||||
result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
/* release mutex */
|
||||
result = rt_mutex_release(&static_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
rt_thread_t tid = rt_thread_create("mutex_th",
|
||||
static_mutex_release_entry,
|
||||
&static_mutex,
|
||||
2048,
|
||||
10,
|
||||
10);
|
||||
if (RT_NULL == tid)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* startup thread and take mutex second */
|
||||
rt_thread_startup(tid);
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(5);
|
||||
|
||||
result = rt_mutex_detach(&static_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* static trytake test */
|
||||
static void static_mutex_trytake_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex;
|
||||
|
||||
mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_trytake(mutex);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
static void test_static_mutex_trytake(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* take mutex and not release */
|
||||
result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
rt_thread_t tid = rt_thread_create("mutex_th",
|
||||
static_mutex_trytake_entry,
|
||||
&static_mutex,
|
||||
2048,
|
||||
10,
|
||||
10);
|
||||
if (RT_NULL == tid)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* startup thread and trytake mutex second */
|
||||
rt_thread_startup(tid);
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(5);
|
||||
|
||||
result = rt_mutex_detach(&static_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static rt_thread_t tid1 = RT_NULL;
|
||||
static rt_thread_t tid2 = RT_NULL;
|
||||
static rt_thread_t tid3 = RT_NULL;
|
||||
|
||||
/* static mutex priority reverse test */
|
||||
static void static_thread1_entry(void *param)
|
||||
{
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(100);
|
||||
|
||||
/* thread3 hode mutex thread2 take mutex */
|
||||
/* check thread2 and thread3 priority */
|
||||
if (tid2->current_priority != tid3->current_priority)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void static_thread2_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex = (rt_mutex_t)param;
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(50);
|
||||
|
||||
result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
|
||||
if (result == RT_EOK)
|
||||
{
|
||||
rt_mutex_release(mutex);
|
||||
}
|
||||
}
|
||||
static void static_thread3_entry(void *param)
|
||||
{
|
||||
rt_tick_t tick;
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
tick = rt_tick_get();
|
||||
while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2));
|
||||
|
||||
rt_mutex_release(mutex);
|
||||
}
|
||||
|
||||
static void test_static_pri_reverse(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
tid1 = RT_NULL;
|
||||
tid2 = RT_NULL;
|
||||
tid3 = RT_NULL;
|
||||
|
||||
result = rt_mutex_init(&static_mutex, "static_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* thread1 */
|
||||
tid1 = rt_thread_create("thread1",
|
||||
static_thread1_entry,
|
||||
&static_mutex,
|
||||
1024,
|
||||
10 - 1,
|
||||
10);
|
||||
if (tid1 != RT_NULL)
|
||||
rt_thread_startup(tid1);
|
||||
|
||||
/* thread2 */
|
||||
tid2 = rt_thread_create("thread2",
|
||||
static_thread2_entry,
|
||||
&static_mutex,
|
||||
1024,
|
||||
10,
|
||||
10);
|
||||
if (tid2 != RT_NULL)
|
||||
rt_thread_startup(tid2);
|
||||
|
||||
/* thread3 */
|
||||
tid3 = rt_thread_create("thread3",
|
||||
static_thread3_entry,
|
||||
&static_mutex,
|
||||
1024,
|
||||
10 + 1,
|
||||
10);
|
||||
if (tid3 != RT_NULL)
|
||||
rt_thread_startup(tid3);
|
||||
|
||||
rt_thread_mdelay(1000);
|
||||
|
||||
result = rt_mutex_detach(&static_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* create test */
|
||||
static void test_dynamic_mutex_create(void)
|
||||
{
|
||||
rt_err_t result = -RT_ERROR;
|
||||
|
||||
/* PRIO mode */
|
||||
dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_mutex)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
result = rt_mutex_delete(dynamic_mutex);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* FIFO mode */
|
||||
dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_mutex)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
result = rt_mutex_delete(dynamic_mutex);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* dynamic take test */
|
||||
static void dynamic_mutex_take_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex;
|
||||
|
||||
int rand_num = rand() % 0x1000;
|
||||
mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_take(mutex, rand_num);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
static void test_dynamic_mutex_take(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_mutex)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* take mutex and not release */
|
||||
result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
rt_thread_t tid = rt_thread_create("mutex_th",
|
||||
dynamic_mutex_take_entry,
|
||||
dynamic_mutex,
|
||||
2048,
|
||||
10,
|
||||
10);
|
||||
if (RT_NULL == tid)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* startup thread take second */
|
||||
rt_thread_startup(tid);
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(5);
|
||||
|
||||
result = rt_mutex_delete(dynamic_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* dynamic release test */
|
||||
static void dynamic_mutex_release_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex;
|
||||
|
||||
int rand_num = rand() % 0x1000;
|
||||
mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_take(mutex, rand_num);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
static void test_dynamic_mutex_release(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_mutex)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* take mutex */
|
||||
result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
/* release mutex */
|
||||
result = rt_mutex_release(dynamic_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
rt_thread_t tid = rt_thread_create("mutex_th",
|
||||
dynamic_mutex_release_entry,
|
||||
dynamic_mutex,
|
||||
2048,
|
||||
10,
|
||||
10);
|
||||
if (RT_NULL == tid)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* startup thread and take mutex second */
|
||||
rt_thread_startup(tid);
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(5);
|
||||
|
||||
result = rt_mutex_delete(dynamic_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* dynamic trytake test */
|
||||
static void dynamic_mutex_trytake_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex;
|
||||
|
||||
mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_trytake(mutex);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
static void test_dynamic_mutex_trytake(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_mutex)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* take mutex and not release */
|
||||
result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
rt_thread_t tid = rt_thread_create("mutex_th",
|
||||
dynamic_mutex_trytake_entry,
|
||||
dynamic_mutex,
|
||||
2048,
|
||||
10,
|
||||
10);
|
||||
if (RT_NULL == tid)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* startup thread and trytake mutex second */
|
||||
rt_thread_startup(tid);
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(5);
|
||||
|
||||
result = rt_mutex_delete(dynamic_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
/* dynamic mutex priority reverse test */
|
||||
static void dynamic_thread1_entry(void *param)
|
||||
{
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(100);
|
||||
|
||||
/* thread3 hode mutex thread2 take mutex */
|
||||
/* check thread2 and thread3 priority */
|
||||
if (tid2->current_priority != tid3->current_priority)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void dynamic_thread2_entry(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex = (rt_mutex_t)param;
|
||||
|
||||
/* let system schedule */
|
||||
rt_thread_mdelay(50);
|
||||
|
||||
result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
|
||||
if (result == RT_EOK)
|
||||
{
|
||||
rt_mutex_release(mutex);
|
||||
}
|
||||
}
|
||||
static void dynamic_thread3_entry(void *param)
|
||||
{
|
||||
rt_tick_t tick;
|
||||
rt_err_t result;
|
||||
rt_mutex_t mutex = (rt_mutex_t)param;
|
||||
|
||||
result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
tick = rt_tick_get();
|
||||
while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2));
|
||||
|
||||
rt_mutex_release(mutex);
|
||||
}
|
||||
|
||||
static void test_dynamic_pri_reverse(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
tid1 = RT_NULL;
|
||||
tid2 = RT_NULL;
|
||||
tid3 = RT_NULL;
|
||||
|
||||
dynamic_mutex = rt_mutex_create("dynamic_mutex", RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_mutex)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* thread1 */
|
||||
tid1 = rt_thread_create("thread1",
|
||||
dynamic_thread1_entry,
|
||||
dynamic_mutex,
|
||||
1024,
|
||||
10 - 1,
|
||||
10);
|
||||
if (tid1 != RT_NULL)
|
||||
rt_thread_startup(tid1);
|
||||
|
||||
/* thread2 */
|
||||
tid2 = rt_thread_create("thread2",
|
||||
dynamic_thread2_entry,
|
||||
dynamic_mutex,
|
||||
1024,
|
||||
10,
|
||||
10);
|
||||
if (tid2 != RT_NULL)
|
||||
rt_thread_startup(tid2);
|
||||
|
||||
/* thread3 */
|
||||
tid3 = rt_thread_create("thread3",
|
||||
dynamic_thread3_entry,
|
||||
dynamic_mutex,
|
||||
1024,
|
||||
10 + 1,
|
||||
10);
|
||||
if (tid3 != RT_NULL)
|
||||
rt_thread_startup(tid3);
|
||||
|
||||
rt_thread_mdelay(1000);
|
||||
|
||||
result = rt_mutex_delete(dynamic_mutex);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
#ifdef RT_USING_HEAP
|
||||
dynamic_mutex = RT_NULL;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
#ifdef RT_USING_HEAP
|
||||
dynamic_mutex = RT_NULL;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_static_mutex_init);
|
||||
UTEST_UNIT_RUN(test_static_mutex_take);
|
||||
UTEST_UNIT_RUN(test_static_mutex_release);
|
||||
UTEST_UNIT_RUN(test_static_mutex_trytake);
|
||||
UTEST_UNIT_RUN(test_static_pri_reverse);
|
||||
#ifdef RT_USING_HEAP
|
||||
UTEST_UNIT_RUN(test_dynamic_mutex_create);
|
||||
UTEST_UNIT_RUN(test_dynamic_mutex_take);
|
||||
UTEST_UNIT_RUN(test_dynamic_mutex_release);
|
||||
UTEST_UNIT_RUN(test_dynamic_mutex_trytake);
|
||||
UTEST_UNIT_RUN(test_dynamic_pri_reverse);
|
||||
#endif
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.mutex_tc", utest_tc_init, utest_tc_cleanup, 1000);
|
||||
|
||||
/********************* end of file ************************/
|
558
examples/utest/testcases/kernel/semaphore_tc.c
Normal file
558
examples/utest/testcases/kernel/semaphore_tc.c
Normal file
|
@ -0,0 +1,558 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-08-12 luckyzjq the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "utest.h"
|
||||
|
||||
static struct rt_semaphore static_semaphore;
|
||||
#ifdef RT_USING_HEAP
|
||||
static rt_sem_t dynamic_semaphore;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
static void test_static_semaphore_init(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int rand_num = rand() % 0x10000;
|
||||
|
||||
for (int i = 0; i < rand_num; i++)
|
||||
{
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
rt_sem_detach(&static_semaphore);
|
||||
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_FIFO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
rt_sem_detach(&static_semaphore);
|
||||
}
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static void test_static_semaphore_detach(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int rand_num = rand() % 0x10000;
|
||||
|
||||
for (int i = 0; i < rand_num; i++)
|
||||
{
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = rt_sem_detach(&static_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_FIFO);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
result = rt_sem_detach(&static_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static void test_static_semaphore_take(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", 1, RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
/* first take */
|
||||
result = rt_sem_take(&static_semaphore, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
/* second take */
|
||||
result = rt_sem_take(&static_semaphore, 100);
|
||||
if (-RT_ETIMEOUT != result)
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_detach(&static_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_static_semaphore_trytake(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", 1, RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
/* first take */
|
||||
result = rt_sem_trytake(&static_semaphore);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
/* second take */
|
||||
result = rt_sem_trytake(&static_semaphore);
|
||||
if (-RT_ETIMEOUT != result)
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_detach(&static_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_static_semaphore_release(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
/* first take */
|
||||
result = rt_sem_take(&static_semaphore, 100);
|
||||
if (-RT_ETIMEOUT != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
/* release */
|
||||
result = rt_sem_release(&static_semaphore);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
/* second take */
|
||||
result = rt_sem_take(&static_semaphore, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_detach(&static_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_static_semaphore_control(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int value = 0;
|
||||
|
||||
value = rand() % 100;
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", 1, RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
result = rt_sem_control(&static_semaphore, RT_IPC_CMD_RESET, &value);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < value; i++)
|
||||
{
|
||||
result = rt_sem_take(&static_semaphore, 10);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
rt_sem_detach(&static_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static void static_release_isr_hardware_callback(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_sem_release(&static_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void static_release_isr_software_callback(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_sem_release(&static_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_static_semaphore_release_isr(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_timer_t hardware_timer;
|
||||
rt_timer_t software_timer;
|
||||
|
||||
/* create timer */
|
||||
hardware_timer = rt_timer_create("release_isr",
|
||||
static_release_isr_hardware_callback,
|
||||
RT_NULL,
|
||||
100,
|
||||
RT_TIMER_FLAG_HARD_TIMER | RT_TIMER_FLAG_ONE_SHOT);
|
||||
software_timer = rt_timer_create("release_isr",
|
||||
static_release_isr_software_callback,
|
||||
RT_NULL,
|
||||
100,
|
||||
RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT);
|
||||
/* start tiemr */
|
||||
if (hardware_timer)
|
||||
rt_timer_start(hardware_timer);
|
||||
if (software_timer)
|
||||
rt_timer_start(software_timer);
|
||||
|
||||
result = rt_sem_init(&static_semaphore, "static_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (RT_EOK == result)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
result = rt_sem_take(&static_semaphore, 1000);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_detach(&static_semaphore);
|
||||
rt_timer_delete(hardware_timer);
|
||||
rt_timer_delete(software_timer);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
static void test_dynamic_semaphore_create(void)
|
||||
{
|
||||
int rand_num = rand() % 0x10000;
|
||||
|
||||
for (int i = 0; i < rand_num; i++)
|
||||
{
|
||||
dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_semaphore)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
rt_sem_delete(dynamic_semaphore);
|
||||
|
||||
dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_FIFO);
|
||||
if (RT_NULL == dynamic_semaphore)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
rt_sem_delete(dynamic_semaphore);
|
||||
}
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static void test_dynamic_semaphore_delete(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int rand_num = rand() % 0x10000;
|
||||
|
||||
for (int i = 0; i < rand_num; i++)
|
||||
{
|
||||
dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL == dynamic_semaphore)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = rt_sem_delete(dynamic_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_FIFO);
|
||||
if (RT_NULL == dynamic_semaphore)
|
||||
{
|
||||
break;
|
||||
}
|
||||
result = rt_sem_delete(dynamic_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static void test_dynamic_semaphore_take(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
dynamic_semaphore = rt_sem_create("static_sem", 1, RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL != dynamic_semaphore)
|
||||
{
|
||||
/* first take */
|
||||
result = rt_sem_take(dynamic_semaphore, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
/* second take */
|
||||
result = rt_sem_take(dynamic_semaphore, 100);
|
||||
if (-RT_ETIMEOUT != result)
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_delete(dynamic_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_dynamic_semaphore_trytake(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
dynamic_semaphore = rt_sem_create("static_sem", 1, RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL != dynamic_semaphore)
|
||||
{
|
||||
/* first take */
|
||||
result = rt_sem_trytake(dynamic_semaphore);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
/* second take */
|
||||
result = rt_sem_trytake(dynamic_semaphore);
|
||||
if (-RT_ETIMEOUT != result)
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_delete(dynamic_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_dynamic_semaphore_release(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
dynamic_semaphore = rt_sem_create("static_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL != dynamic_semaphore)
|
||||
{
|
||||
/* first take */
|
||||
result = rt_sem_take(dynamic_semaphore, 100);
|
||||
if (-RT_ETIMEOUT != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
/* release */
|
||||
result = rt_sem_release(dynamic_semaphore);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
|
||||
/* second take */
|
||||
result = rt_sem_take(dynamic_semaphore, RT_WAITING_FOREVER);
|
||||
if (RT_EOK != result)
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_delete(dynamic_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_dynamic_semaphore_control(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int value = 0;
|
||||
|
||||
value = rand() % 100;
|
||||
dynamic_semaphore = rt_sem_create("static_sem", 1, RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL != dynamic_semaphore)
|
||||
{
|
||||
result = rt_sem_control(dynamic_semaphore, RT_IPC_CMD_RESET, &value);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < value; i++)
|
||||
{
|
||||
result = rt_sem_take(dynamic_semaphore, 10);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
rt_sem_delete(dynamic_semaphore);
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
static void dynamic_release_isr_hardware_callback(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_sem_release(dynamic_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void dynamic_release_isr_software_callback(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
result = rt_sem_release(dynamic_semaphore);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_dynamic_semaphore_release_isr(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_timer_t hardware_timer;
|
||||
rt_timer_t software_timer;
|
||||
|
||||
/* create timer */
|
||||
hardware_timer = rt_timer_create("release_isr",
|
||||
dynamic_release_isr_hardware_callback,
|
||||
RT_NULL,
|
||||
100,
|
||||
RT_TIMER_FLAG_HARD_TIMER | RT_TIMER_FLAG_ONE_SHOT);
|
||||
software_timer = rt_timer_create("release_isr",
|
||||
dynamic_release_isr_software_callback,
|
||||
RT_NULL,
|
||||
100,
|
||||
RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT);
|
||||
/* start tiemr */
|
||||
if (hardware_timer)
|
||||
rt_timer_start(hardware_timer);
|
||||
if (software_timer)
|
||||
rt_timer_start(software_timer);
|
||||
|
||||
dynamic_semaphore = rt_sem_create("static_sem", 0, RT_IPC_FLAG_PRIO);
|
||||
if (RT_NULL != dynamic_semaphore)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
result = rt_sem_take(dynamic_semaphore, 1000);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt_sem_delete(dynamic_semaphore);
|
||||
rt_timer_delete(hardware_timer);
|
||||
rt_timer_delete(software_timer);
|
||||
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
#ifdef RT_USING_HEAP
|
||||
dynamic_semaphore = RT_NULL;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
#ifdef RT_USING_HEAP
|
||||
dynamic_semaphore = RT_NULL;
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_static_semaphore_init);
|
||||
UTEST_UNIT_RUN(test_static_semaphore_take);
|
||||
UTEST_UNIT_RUN(test_static_semaphore_release);
|
||||
UTEST_UNIT_RUN(test_static_semaphore_detach);
|
||||
UTEST_UNIT_RUN(test_static_semaphore_trytake);
|
||||
UTEST_UNIT_RUN(test_static_semaphore_control);
|
||||
UTEST_UNIT_RUN(test_static_semaphore_release_isr);
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
UTEST_UNIT_RUN(test_dynamic_semaphore_create);
|
||||
UTEST_UNIT_RUN(test_dynamic_semaphore_take);
|
||||
UTEST_UNIT_RUN(test_dynamic_semaphore_release);
|
||||
UTEST_UNIT_RUN(test_dynamic_semaphore_delete);
|
||||
UTEST_UNIT_RUN(test_dynamic_semaphore_trytake);
|
||||
UTEST_UNIT_RUN(test_dynamic_semaphore_control);
|
||||
UTEST_UNIT_RUN(test_dynamic_semaphore_release_isr);
|
||||
#endif /* RT_USING_HEAP */
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.semaphore_tc", utest_tc_init, utest_tc_cleanup, 1000);
|
199
examples/utest/testcases/kernel/signal_tc.c
Normal file
199
examples/utest/testcases/kernel/signal_tc.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-08-12 flybreak the first version
|
||||
*
|
||||
* case 1:rt_signal_install, install all available signal
|
||||
* case 2:rt_signal_install, install illegal signal
|
||||
* case 3:rt_signal_mask/unmask, one thread self, install and unmask, then kill, should received.
|
||||
* case 4:rt_signal_mask/unmask, one thread self, install and unmask and mask, then kill, should can't received.
|
||||
* case 5:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: kill, should received.
|
||||
* case 6:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: sleep 2s then kill, should can't received.
|
||||
* case 7:rt_signal_kill, kill legal thread, return 0;
|
||||
* case 8:rt_signal_kill, kill illegal thread, return failed (unused);
|
||||
* case 9:rt_signal_kill, kill illegal signo, return -RT_EINVAL;
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "utest.h"
|
||||
|
||||
int recive_sig = 0;
|
||||
|
||||
void sig_handle_default(int signo)
|
||||
{
|
||||
recive_sig = signo;
|
||||
}
|
||||
|
||||
static void rt_signal_install_test(void)
|
||||
{
|
||||
int signo;
|
||||
rt_sighandler_t result;
|
||||
|
||||
/* case 1:rt_signal_install, install all available signal. */
|
||||
for (signo = 0; signo < RT_SIG_MAX; signo++)
|
||||
{
|
||||
result = rt_signal_install(signo, sig_handle_default);
|
||||
uassert_true(result != SIG_ERR);
|
||||
}
|
||||
/* case 2:rt_signal_install, install illegal signal. */
|
||||
result = rt_signal_install(signo, sig_handle_default);
|
||||
uassert_true(result == SIG_ERR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void rt_signal_mask_test(void)
|
||||
{
|
||||
int signo;
|
||||
rt_sighandler_t result;
|
||||
|
||||
/* case 3:rt_signal_mask/unmask, one thread self, install and unmask, then kill, should received. */
|
||||
for (signo = 0; signo < RT_SIG_MAX; signo++)
|
||||
{
|
||||
recive_sig = -1;
|
||||
result = rt_signal_install(signo, sig_handle_default);
|
||||
uassert_true(result != SIG_ERR);
|
||||
rt_signal_unmask(signo);
|
||||
uassert_int_equal(rt_thread_kill(rt_thread_self(), signo), RT_EOK);
|
||||
rt_thread_mdelay(1);
|
||||
uassert_int_equal(recive_sig, signo);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void rt_signal_unmask_test(void)
|
||||
{
|
||||
int signo;
|
||||
rt_sighandler_t result;
|
||||
|
||||
/* case 4:rt_signal_mask/unmask, one thread self, install and unmask and mask, then kill, should can't received. */
|
||||
for (signo = 0; signo < RT_SIG_MAX; signo++)
|
||||
{
|
||||
recive_sig = -1;
|
||||
result = rt_signal_install(signo, sig_handle_default);
|
||||
uassert_true(result != SIG_ERR);
|
||||
rt_signal_unmask(signo);
|
||||
rt_signal_mask(signo);
|
||||
uassert_int_equal(rt_thread_kill(rt_thread_self(), signo), RT_EOK);
|
||||
rt_thread_mdelay(1);
|
||||
uassert_int_not_equal(recive_sig, signo);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void rt_signal_kill_test(void)
|
||||
{
|
||||
int signo;
|
||||
rt_sighandler_t result;
|
||||
|
||||
/* case 7:rt_signal_kill, kill legal thread, return 0; */
|
||||
for (signo = 0; signo < RT_SIG_MAX; signo++)
|
||||
{
|
||||
recive_sig = -1;
|
||||
result = rt_signal_install(signo, sig_handle_default);
|
||||
uassert_true(result != SIG_ERR);
|
||||
rt_signal_unmask(signo);
|
||||
uassert_int_equal(rt_thread_kill(rt_thread_self(), signo), RT_EOK);
|
||||
rt_thread_mdelay(1);
|
||||
uassert_int_equal(recive_sig, signo);
|
||||
}
|
||||
/* case 8:rt_signal_kill, kill illegal thread, return failed; */
|
||||
// uassert_true(rt_thread_kill((rt_thread_t)-1, signo) == -RT_ERROR);
|
||||
|
||||
/* case 9:rt_signal_kill, kill illegal signo, return -RT_EINVAL; */
|
||||
uassert_true(rt_thread_kill(rt_thread_self(), -1) == -RT_EINVAL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void rt_signal_wait_thread(void *parm)
|
||||
{
|
||||
sigset_t selectset;
|
||||
siginfo_t recive_si;
|
||||
|
||||
rt_signal_install(SIGUSR1, sig_handle_default);
|
||||
rt_signal_unmask(SIGUSR1);
|
||||
|
||||
(void)sigemptyset(&selectset);
|
||||
(void)sigaddset(&selectset, SIGUSR1);
|
||||
|
||||
/* case 5:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: kill, should received. */
|
||||
if (rt_signal_wait(&selectset, &recive_si, RT_TICK_PER_SECOND) != RT_EOK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
recive_sig = recive_si.si_signo;
|
||||
}
|
||||
|
||||
static void rt_signal_wait_test(void)
|
||||
{
|
||||
rt_thread_t t1;
|
||||
|
||||
recive_sig = -1;
|
||||
t1 = rt_thread_create("sig_t1", rt_signal_wait_thread, 0, 4096, 14, 10);
|
||||
if (t1)
|
||||
{
|
||||
rt_thread_startup(t1);
|
||||
}
|
||||
|
||||
rt_thread_mdelay(1);
|
||||
/* case 5:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: kill, should received. */
|
||||
uassert_int_equal(rt_thread_kill(t1, SIGUSR1), RT_EOK);
|
||||
rt_thread_mdelay(1);
|
||||
uassert_int_equal(recive_sig, SIGUSR1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void rt_signal_wait_test2(void)
|
||||
{
|
||||
rt_thread_t t1;
|
||||
|
||||
recive_sig = -1;
|
||||
t1 = rt_thread_create("sig_t1", rt_signal_wait_thread, 0, 4096, 14, 10);
|
||||
if (t1)
|
||||
{
|
||||
rt_thread_startup(t1);
|
||||
}
|
||||
|
||||
/* case 6:rt_signal_wait, two thread, thread1: install and unmask, then wait 1s; thread2: sleep 2s then kill, should can't received. */
|
||||
rt_thread_mdelay(2000);
|
||||
uassert_int_equal(rt_thread_kill(t1, SIGUSR1), RT_EOK);
|
||||
rt_thread_mdelay(1);
|
||||
uassert_int_not_equal(recive_sig, SIGUSR1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
#ifdef RT_USING_HEAP
|
||||
UTEST_UNIT_RUN(rt_signal_install_test);
|
||||
UTEST_UNIT_RUN(rt_signal_mask_test);
|
||||
UTEST_UNIT_RUN(rt_signal_unmask_test);
|
||||
UTEST_UNIT_RUN(rt_signal_kill_test);
|
||||
UTEST_UNIT_RUN(rt_signal_wait_test);
|
||||
UTEST_UNIT_RUN(rt_signal_wait_test2);
|
||||
#endif /* RT_USING_HEAP */
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.signal_tc", utest_tc_init, utest_tc_cleanup, 1000);
|
||||
|
||||
/*********************** end of file ****************************/
|
323
examples/utest/testcases/kernel/slab_tc.c
Normal file
323
examples/utest/testcases/kernel/slab_tc.c
Normal file
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-10-14 tyx the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "utest.h"
|
||||
|
||||
#define TEST_SLAB_SIZE 1024 * 1024
|
||||
|
||||
static int _mem_cmp(void *ptr, rt_uint8_t v, rt_size_t size)
|
||||
{
|
||||
while (size-- != 0)
|
||||
{
|
||||
if (*(rt_uint8_t *)ptr != v)
|
||||
return *(rt_uint8_t *)ptr - v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct slab_alloc_context
|
||||
{
|
||||
rt_list_t node;
|
||||
rt_size_t size;
|
||||
rt_uint8_t magic;
|
||||
};
|
||||
|
||||
struct slab_alloc_head
|
||||
{
|
||||
rt_list_t list;
|
||||
rt_size_t count;
|
||||
rt_tick_t start;
|
||||
rt_tick_t end;
|
||||
rt_tick_t interval;
|
||||
};
|
||||
|
||||
#define SLAB_RANG_ALLOC_BLK_MIN 2
|
||||
#define SLAB_RANG_ALLOC_BLK_MAX 5
|
||||
#define SLAB_RANG_ALLOC_TEST_TIME 5
|
||||
|
||||
static void slab_alloc_test(void)
|
||||
{
|
||||
struct slab_alloc_head head;
|
||||
rt_uint8_t *buf;
|
||||
rt_slab_t heap;
|
||||
rt_size_t size;
|
||||
struct slab_alloc_context *ctx;
|
||||
|
||||
/* init */
|
||||
rt_list_init(&head.list);
|
||||
head.count = 0;
|
||||
head.start = rt_tick_get();
|
||||
head.end = rt_tick_get() + rt_tick_from_millisecond(SLAB_RANG_ALLOC_TEST_TIME * 1000);
|
||||
head.interval = (head.end - head.start) / 20;
|
||||
buf = rt_malloc(TEST_SLAB_SIZE);
|
||||
uassert_not_null(buf);
|
||||
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||||
rt_memset(buf, 0xAA, TEST_SLAB_SIZE);
|
||||
heap = rt_slab_init("slab_tc", buf, TEST_SLAB_SIZE);
|
||||
// test run
|
||||
while (head.end - head.start < RT_TICK_MAX / 2)
|
||||
{
|
||||
if (rt_tick_get() - head.start >= head.interval)
|
||||
{
|
||||
head.start = rt_tick_get();
|
||||
rt_kprintf("#");
|
||||
}
|
||||
// %60 probability to perform alloc operation
|
||||
if (rand() % 10 >= 4)
|
||||
{
|
||||
size = rand() % SLAB_RANG_ALLOC_BLK_MAX + SLAB_RANG_ALLOC_BLK_MIN;
|
||||
size *= sizeof(struct slab_alloc_context);
|
||||
ctx = rt_slab_alloc(heap, size);
|
||||
if (ctx == RT_NULL)
|
||||
{
|
||||
if (head.count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
size = head.count / 2;
|
||||
while (size != head.count)
|
||||
{
|
||||
ctx = rt_list_first_entry(&head.list, struct slab_alloc_context, node);
|
||||
rt_list_remove(&ctx->node);
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||||
{
|
||||
uassert_true(0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_slab_free(heap, ctx);
|
||||
head.count --;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//if (RT_ALIGN((rt_ubase_t)ctx, RT_ALIGN_SIZE) != (rt_ubase_t)ctx)
|
||||
//{
|
||||
// uassert_int_equal(RT_ALIGN((rt_ubase_t)ctx, RT_ALIGN_SIZE), (rt_ubase_t)ctx);
|
||||
//}
|
||||
rt_memset(ctx, 0, size);
|
||||
rt_list_init(&ctx->node);
|
||||
ctx->size = size;
|
||||
ctx->magic = rand() & 0xff;
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
rt_memset(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
}
|
||||
rt_list_insert_after(&head.list, &ctx->node);
|
||||
head.count += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rt_list_isempty(&head.list))
|
||||
{
|
||||
ctx = rt_list_first_entry(&head.list, struct slab_alloc_context, node);
|
||||
rt_list_remove(&ctx->node);
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||||
{
|
||||
uassert_true(0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_slab_free(heap, ctx);
|
||||
head.count --;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!rt_list_isempty(&head.list))
|
||||
{
|
||||
ctx = rt_list_first_entry(&head.list, struct slab_alloc_context, node);
|
||||
rt_list_remove(&ctx->node);
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||||
{
|
||||
uassert_true(0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_slab_free(heap, ctx);
|
||||
head.count --;
|
||||
}
|
||||
uassert_int_equal(head.count, 0);
|
||||
// slab heap deinit
|
||||
rt_slab_detach(heap);
|
||||
/* release test resources */
|
||||
rt_free(buf);
|
||||
}
|
||||
|
||||
#define SLAB_RANG_REALLOC_BLK_MIN 0
|
||||
#define SLAB_RANG_REALLOC_BLK_MAX 5
|
||||
#define SLAB_RANG_REALLOC_TEST_TIME 5
|
||||
|
||||
struct slab_realloc_context
|
||||
{
|
||||
rt_size_t size;
|
||||
rt_uint8_t magic;
|
||||
};
|
||||
|
||||
struct slab_realloc_head
|
||||
{
|
||||
struct slab_realloc_context **ctx_tab;
|
||||
rt_size_t count;
|
||||
rt_tick_t start;
|
||||
rt_tick_t end;
|
||||
rt_tick_t interval;
|
||||
};
|
||||
|
||||
static void slab_realloc_test(void)
|
||||
{
|
||||
struct slab_realloc_head head;
|
||||
rt_uint8_t *buf;
|
||||
rt_slab_t heap;
|
||||
rt_size_t size, idx;
|
||||
struct slab_realloc_context *ctx;
|
||||
int res;
|
||||
|
||||
size = RT_ALIGN(sizeof(struct slab_realloc_context), RT_ALIGN_SIZE) + RT_ALIGN_SIZE;
|
||||
size = TEST_SLAB_SIZE / size;
|
||||
/* init */
|
||||
head.ctx_tab = RT_NULL;
|
||||
head.count = size;
|
||||
head.start = rt_tick_get();
|
||||
head.end = rt_tick_get() + rt_tick_from_millisecond(SLAB_RANG_ALLOC_TEST_TIME * 1000);
|
||||
head.interval = (head.end - head.start) / 20;
|
||||
buf = rt_malloc(TEST_SLAB_SIZE);
|
||||
uassert_not_null(buf);
|
||||
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||||
rt_memset(buf, 0xAA, TEST_SLAB_SIZE);
|
||||
heap = rt_slab_init("slab_tc", buf, TEST_SLAB_SIZE);
|
||||
/* init ctx tab */
|
||||
size = head.count * sizeof(struct slab_realloc_context *);
|
||||
head.ctx_tab = rt_slab_alloc(heap, size);
|
||||
uassert_not_null(head.ctx_tab);
|
||||
rt_memset(head.ctx_tab, 0, size);
|
||||
// test run
|
||||
while (head.end - head.start < RT_TICK_MAX / 2)
|
||||
{
|
||||
if (rt_tick_get() - head.start >= head.interval)
|
||||
{
|
||||
head.start = rt_tick_get();
|
||||
rt_kprintf("#");
|
||||
}
|
||||
size = rand() % SLAB_RANG_ALLOC_BLK_MAX + SLAB_RANG_ALLOC_BLK_MIN;
|
||||
size *= sizeof(struct slab_realloc_context);
|
||||
idx = rand() % head.count;
|
||||
ctx = rt_slab_realloc(heap, head.ctx_tab[idx], size);
|
||||
if (ctx == RT_NULL)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
if (head.ctx_tab[idx])
|
||||
{
|
||||
head.ctx_tab[idx] = RT_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (idx = 0; idx < head.count; idx++)
|
||||
{
|
||||
ctx = head.ctx_tab[idx];
|
||||
if (rand() % 2 && ctx)
|
||||
{
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
if (res != 0)
|
||||
{
|
||||
uassert_int_equal(res, 0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_slab_realloc(heap, ctx, 0);
|
||||
head.ctx_tab[idx] = RT_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* check slab */
|
||||
if (head.ctx_tab[idx] != RT_NULL)
|
||||
{
|
||||
res = 0;
|
||||
if (ctx->size < size)
|
||||
{
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, size - sizeof(*ctx));
|
||||
}
|
||||
}
|
||||
if (res != 0)
|
||||
{
|
||||
uassert_int_equal(res, 0);
|
||||
}
|
||||
}
|
||||
/* init slab */
|
||||
ctx->magic = rand() & 0xff;
|
||||
ctx->size = size;
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
rt_memset(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
}
|
||||
head.ctx_tab[idx] = ctx;
|
||||
}
|
||||
// free all slab
|
||||
for (idx = 0; idx < head.count; idx++)
|
||||
{
|
||||
ctx = head.ctx_tab[idx];
|
||||
if (ctx == RT_NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (ctx->size > sizeof(*ctx))
|
||||
{
|
||||
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||||
if (res != 0)
|
||||
{
|
||||
uassert_int_equal(res, 0);
|
||||
}
|
||||
}
|
||||
rt_memset(ctx, 0xAA, ctx->size);
|
||||
rt_slab_realloc(heap, ctx, 0);
|
||||
head.ctx_tab[idx] = RT_NULL;
|
||||
}
|
||||
// slab heap deinit
|
||||
rt_slab_detach(heap);
|
||||
/* release test resources */
|
||||
rt_free(buf);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(slab_alloc_test);
|
||||
UTEST_UNIT_RUN(slab_realloc_test);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.slab_tc", utest_tc_init, utest_tc_cleanup, 20);
|
743
examples/utest/testcases/kernel/thread_tc.c
Normal file
743
examples/utest/testcases/kernel/thread_tc.c
Normal file
|
@ -0,0 +1,743 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
rt_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 volatile rt_uint32_t tid3_delay_pass_flag = 0;
|
||||
static volatile rt_uint32_t tid3_finish_flag = 0;
|
||||
static volatile rt_uint32_t tid4_finish_flag = 0;
|
||||
static volatile 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;
|
||||
thread5_source = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
static rt_thread_t tidA, tidB1, tidB2;
|
||||
static uint32_t timeslice_cntA, timeslice_cntB1, timeslice_cntB2;
|
||||
|
||||
static void test_timeslice_threadA_entry(void *parameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
rt_thread_delay(2);
|
||||
timeslice_cntA++;
|
||||
if (timeslice_cntA > 10) return;
|
||||
}
|
||||
}
|
||||
static void test_timeslice_threadB1_entry(void *parameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
timeslice_cntB1++;
|
||||
if (timeslice_cntA > 10) return;
|
||||
}
|
||||
}
|
||||
static void test_timeslice_threadB2_entry(void *parameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
timeslice_cntB2++;
|
||||
if (timeslice_cntA > 10) return;
|
||||
}
|
||||
}
|
||||
|
||||
void test_timeslice(void)
|
||||
{
|
||||
rt_err_t ret_startup = -RT_ERROR;
|
||||
uint32_t diff;
|
||||
|
||||
timeslice_cntA = 0;
|
||||
timeslice_cntB1 = 0;
|
||||
timeslice_cntB2 = 0;
|
||||
|
||||
tidA = rt_thread_create("timeslice", test_timeslice_threadA_entry, RT_NULL,
|
||||
2048, __current_thread->current_priority + 1, 10);
|
||||
if (!tidA)
|
||||
{
|
||||
LOG_E("rt_thread_create failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
rt_thread_control(tidA, RT_THREAD_CTRL_BIND_CPU, (void *)1);
|
||||
ret_startup = rt_thread_startup(tidA);
|
||||
if (ret_startup != RT_EOK)
|
||||
{
|
||||
LOG_E("rt_thread_startup failed!");
|
||||
uassert_false(1);
|
||||
return ;
|
||||
}
|
||||
|
||||
tidB1 = rt_thread_create("timeslice", test_timeslice_threadB1_entry, RT_NULL,
|
||||
2048, __current_thread->current_priority + 2, 2);
|
||||
if (!tidB1)
|
||||
{
|
||||
LOG_E("rt_thread_create failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
rt_thread_control(tidB1, RT_THREAD_CTRL_BIND_CPU, (void *)1);
|
||||
ret_startup = rt_thread_startup(tidB1);
|
||||
if (ret_startup != RT_EOK)
|
||||
{
|
||||
LOG_E("rt_thread_startup failed!");
|
||||
uassert_false(1);
|
||||
return ;
|
||||
}
|
||||
|
||||
tidB2 = rt_thread_create("timeslice", test_timeslice_threadB2_entry, RT_NULL,
|
||||
2048, __current_thread->current_priority + 2, 2);
|
||||
if (!tidB2)
|
||||
{
|
||||
LOG_E("rt_thread_create failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
rt_thread_control(tidB2, RT_THREAD_CTRL_BIND_CPU, (void *)1);
|
||||
ret_startup = rt_thread_startup(tidB2);
|
||||
if (ret_startup != RT_EOK)
|
||||
{
|
||||
LOG_E("rt_thread_startup failed!");
|
||||
uassert_false(1);
|
||||
return ;
|
||||
}
|
||||
do{
|
||||
rt_thread_delay(2 * 20);
|
||||
}while(timeslice_cntA <= 10);
|
||||
|
||||
rt_kprintf("A:%d,B1:%d,B2:%d\n", timeslice_cntA, timeslice_cntB1, timeslice_cntB2);
|
||||
diff = abs(timeslice_cntB1 - timeslice_cntB2);
|
||||
uassert_true(diff * 100 / timeslice_cntB1 < 30);
|
||||
uassert_true(timeslice_cntA == 11);
|
||||
}
|
||||
|
||||
#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);
|
||||
/* timeslice */
|
||||
// UTEST_UNIT_RUN(test_timeslice); /* Can not running in Github Action QEMU */
|
||||
}
|
||||
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.thread_tc", utest_tc_init, utest_tc_cleanup, 1000);
|
||||
|
||||
/********************* end of file ************************/
|
520
examples/utest/testcases/kernel/timer_tc.c
Normal file
520
examples/utest/testcases/kernel/timer_tc.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2019, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-08-12 luckyzjq the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "utest.h"
|
||||
|
||||
static rt_uint8_t timer_flag_oneshot[] = {
|
||||
RT_TIMER_FLAG_ONE_SHOT,
|
||||
RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_HARD_TIMER,
|
||||
RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER,
|
||||
};
|
||||
|
||||
static rt_uint8_t timer_flag_periodic[] = {
|
||||
RT_TIMER_FLAG_PERIODIC,
|
||||
RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_HARD_TIMER,
|
||||
RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER,
|
||||
};
|
||||
|
||||
typedef struct test_timer_struct
|
||||
{
|
||||
struct rt_timer static_timer; /* static timer handler */
|
||||
rt_timer_t dynamic_timer; /* dynamic timer pointer */
|
||||
rt_tick_t expect_tick; /* expect tick */
|
||||
rt_uint8_t test_flag; /* timer callback done flag */
|
||||
} timer_struct;
|
||||
static timer_struct timer;
|
||||
|
||||
#define test_static_timer_start test_static_timer_init
|
||||
#define test_static_timer_stop test_static_timer_init
|
||||
#define test_static_timer_detach test_static_timer_init
|
||||
|
||||
static void static_timer_oneshot(void *param)
|
||||
{
|
||||
timer_struct *timer_call;
|
||||
timer_call = (timer_struct *)param;
|
||||
timer_call->test_flag = RT_TRUE;
|
||||
|
||||
/* check expect tick */
|
||||
if (rt_tick_get() - timer_call->expect_tick > 1)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
static void static_timer_periodic(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
timer_struct *timer_call;
|
||||
timer_call = (timer_struct *)param;
|
||||
timer_call->test_flag = RT_TRUE;
|
||||
|
||||
/* check expect tick */
|
||||
if (rt_tick_get() - timer_call->expect_tick > 1)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* periodic timer can stop */
|
||||
result = rt_timer_stop(&timer_call->static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_static_timer_init(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int rand_num = rand() % 10;
|
||||
|
||||
/* one shot timer test */
|
||||
for (int time_out = 0; time_out < rand_num; time_out++)
|
||||
{
|
||||
for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
|
||||
{
|
||||
rt_timer_init(&timer.static_timer,
|
||||
"static_timer",
|
||||
static_timer_oneshot,
|
||||
&timer,
|
||||
time_out,
|
||||
timer_flag_oneshot[i]);
|
||||
|
||||
/* calc expect tick */
|
||||
timer.expect_tick = rt_tick_get() + time_out;
|
||||
|
||||
/* start timer */
|
||||
result = rt_timer_start(&timer.static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait for timerout */
|
||||
rt_thread_delay(time_out + 1);
|
||||
|
||||
/* detach timer */
|
||||
result = rt_timer_detach(&timer.static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer.test_flag != RT_TRUE)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* periodic timer test */
|
||||
for (int time_out = 0; time_out < rand_num; time_out++)
|
||||
{
|
||||
for (int i = 0; i < sizeof(timer_flag_periodic); i++)
|
||||
{
|
||||
rt_timer_init(&timer.static_timer,
|
||||
"static_timer",
|
||||
static_timer_periodic,
|
||||
&timer,
|
||||
time_out,
|
||||
timer_flag_periodic[i]);
|
||||
|
||||
/* calc expect tick */
|
||||
timer.expect_tick = rt_tick_get() + time_out;
|
||||
|
||||
/* start timer */
|
||||
result = rt_timer_start(&timer.static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait for timerout */
|
||||
rt_thread_delay(time_out + 1);
|
||||
|
||||
/* detach timer */
|
||||
result = rt_timer_detach(&timer.static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer.test_flag != RT_TRUE)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timer.test_flag = RT_FALSE;
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void static_timer_control(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
timer_struct *timer_call;
|
||||
timer_call = (timer_struct *)param;
|
||||
timer_call->test_flag = RT_TRUE;
|
||||
|
||||
/* check expect tick */
|
||||
if (rt_tick_get() - timer_call->expect_tick > 1)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* periodic timer can stop */
|
||||
result = rt_timer_stop(&timer_call->static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_static_timer_control(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int rand_num = rand() % 10;
|
||||
int set_data;
|
||||
int get_data;
|
||||
|
||||
rt_timer_init(&timer.static_timer,
|
||||
"static_timer",
|
||||
static_timer_control,
|
||||
&timer,
|
||||
5,
|
||||
RT_TIMER_FLAG_PERIODIC);
|
||||
|
||||
/* test set data */
|
||||
set_data = rand_num;
|
||||
result = rt_timer_control(&timer.static_timer, RT_TIMER_CTRL_SET_TIME, &set_data);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* test get data */
|
||||
result = rt_timer_control(&timer.static_timer, RT_TIMER_CTRL_GET_TIME, &get_data);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* a set of test */
|
||||
if (set_data != get_data)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* calc expect tick */
|
||||
timer.expect_tick = rt_tick_get() + set_data;
|
||||
|
||||
/* start timer */
|
||||
result = rt_timer_start(&timer.static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
rt_thread_delay(set_data + 1);
|
||||
|
||||
/* detach timer */
|
||||
result = rt_timer_detach(&timer.static_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer.test_flag != RT_TRUE)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
timer.test_flag = RT_FALSE;
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
|
||||
#define test_dynamic_timer_start test_dynamic_timer_create
|
||||
#define test_dynamic_timer_stop test_dynamic_timer_create
|
||||
#define test_dynamic_timer_delete test_dynamic_timer_create
|
||||
|
||||
static void dynamic_timer_oneshot(void *param)
|
||||
{
|
||||
timer_struct *timer_call;
|
||||
timer_call = (timer_struct *)param;
|
||||
timer_call->test_flag = RT_TRUE;
|
||||
|
||||
/* check expect tick */
|
||||
if (rt_tick_get() - timer_call->expect_tick > 1)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
static void dynamic_timer_periodic(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
timer_struct *timer_call;
|
||||
timer_call = (timer_struct *)param;
|
||||
timer_call->test_flag = RT_TRUE;
|
||||
|
||||
/* check expect tick */
|
||||
if (rt_tick_get() - timer_call->expect_tick > 1)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* periodic timer can stop */
|
||||
result = rt_timer_stop(timer_call->dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_dynamic_timer_create(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int rand_num = rand() % 10;
|
||||
|
||||
/* one shot timer test */
|
||||
for (int time_out = 0; time_out < rand_num; time_out++)
|
||||
{
|
||||
for (int i = 0; i < sizeof(timer_flag_oneshot); i++)
|
||||
{
|
||||
timer.dynamic_timer = rt_timer_create("dynamic_timer",
|
||||
dynamic_timer_oneshot,
|
||||
&timer,
|
||||
time_out,
|
||||
timer_flag_oneshot[i]);
|
||||
|
||||
/* calc expect tick */
|
||||
timer.expect_tick = rt_tick_get() + time_out;
|
||||
|
||||
/* start timer */
|
||||
result = rt_timer_start(timer.dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait for timerout */
|
||||
rt_thread_delay(time_out + 1);
|
||||
|
||||
/* detach timer */
|
||||
result = rt_timer_delete(timer.dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer.test_flag != RT_TRUE)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* periodic timer test */
|
||||
for (int time_out = 0; time_out < rand_num; time_out++)
|
||||
{
|
||||
for (int i = 0; i < sizeof(timer_flag_periodic); i++)
|
||||
{
|
||||
timer.dynamic_timer = rt_timer_create("dynamic_timer",
|
||||
dynamic_timer_periodic,
|
||||
&timer,
|
||||
time_out,
|
||||
timer_flag_periodic[i]);
|
||||
|
||||
/* calc expect tick */
|
||||
timer.expect_tick = rt_tick_get() + time_out;
|
||||
|
||||
/* start timer */
|
||||
result = rt_timer_start(timer.dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait for timerout */
|
||||
rt_thread_delay(time_out + 1);
|
||||
|
||||
/* detach timer */
|
||||
result = rt_timer_delete(timer.dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer.test_flag != RT_TRUE)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timer.test_flag = RT_FALSE;
|
||||
uassert_true(RT_TRUE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void dynamic_timer_control(void *param)
|
||||
{
|
||||
rt_err_t result;
|
||||
timer_struct *timer_call;
|
||||
timer_call = (timer_struct *)param;
|
||||
timer_call->test_flag = RT_TRUE;
|
||||
|
||||
/* check expect tick */
|
||||
if (rt_tick_get() - timer_call->expect_tick > 1)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* periodic timer can stop */
|
||||
result = rt_timer_stop(timer_call->dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_dynamic_timer_control(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
int rand_num = rand() % 10;
|
||||
int set_data;
|
||||
int get_data;
|
||||
|
||||
timer.dynamic_timer = rt_timer_create("dynamic_timer",
|
||||
dynamic_timer_control,
|
||||
&timer,
|
||||
5,
|
||||
RT_TIMER_FLAG_PERIODIC);
|
||||
|
||||
/* test set data */
|
||||
set_data = rand_num;
|
||||
result = rt_timer_control(timer.dynamic_timer, RT_TIMER_CTRL_SET_TIME, &set_data);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* test get data */
|
||||
result = rt_timer_control(timer.dynamic_timer, RT_TIMER_CTRL_GET_TIME, &get_data);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* a set of test */
|
||||
if (set_data != get_data)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
}
|
||||
|
||||
/* calc expect tick */
|
||||
timer.expect_tick = rt_tick_get() + set_data;
|
||||
|
||||
/* start timer */
|
||||
result = rt_timer_start(timer.dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
rt_thread_delay(set_data + 1);
|
||||
|
||||
/* detach timer */
|
||||
result = rt_timer_delete(timer.dynamic_timer);
|
||||
if (RT_EOK != result)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer.test_flag != RT_TRUE)
|
||||
{
|
||||
uassert_true(RT_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
timer.test_flag = RT_FALSE;
|
||||
uassert_true(RT_TRUE);
|
||||
}
|
||||
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
timer.dynamic_timer = RT_NULL;
|
||||
timer.test_flag = RT_FALSE;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
timer.dynamic_timer = RT_NULL;
|
||||
timer.test_flag = RT_FALSE;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_static_timer_init);
|
||||
UTEST_UNIT_RUN(test_static_timer_start);
|
||||
UTEST_UNIT_RUN(test_static_timer_stop);
|
||||
UTEST_UNIT_RUN(test_static_timer_detach);
|
||||
UTEST_UNIT_RUN(test_static_timer_control);
|
||||
#ifdef RT_USING_HEAP
|
||||
UTEST_UNIT_RUN(test_dynamic_timer_create);
|
||||
UTEST_UNIT_RUN(test_dynamic_timer_start);
|
||||
UTEST_UNIT_RUN(test_dynamic_timer_stop);
|
||||
UTEST_UNIT_RUN(test_dynamic_timer_delete);
|
||||
UTEST_UNIT_RUN(test_dynamic_timer_control);
|
||||
#endif /* RT_USING_HEAP */
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.kernel.timer_tc", utest_tc_init, utest_tc_cleanup, 1000);
|
||||
|
||||
/*********************** end of file ****************************/
|
17
examples/utest/testcases/mm/Kconfig
Normal file
17
examples/utest/testcases/mm/Kconfig
Normal file
|
@ -0,0 +1,17 @@
|
|||
menu "Memory Management Subsytem Testcase"
|
||||
|
||||
config UTEST_MM_API_TC
|
||||
bool "Enable Utest for MM API"
|
||||
default n
|
||||
help
|
||||
The test covers the Memory Management APIs under the
|
||||
`components/mm` and `libcpu/[mmu.*|tlb.*|cache.*]`
|
||||
|
||||
config UTEST_MM_LWP_TC
|
||||
bool "Enable Utest for MM API in lwp"
|
||||
default n
|
||||
help
|
||||
The test covers the Memory Management APIs under the
|
||||
`components/lwp`.
|
||||
|
||||
endmenu
|
16
examples/utest/testcases/mm/SConscript
Normal file
16
examples/utest/testcases/mm/SConscript
Normal file
|
@ -0,0 +1,16 @@
|
|||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = []
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if GetDepend(['UTEST_MM_API_TC']):
|
||||
src += ['mm_api_tc.c', 'mm_libcpu_tc.c']
|
||||
|
||||
if GetDepend(['UTEST_MM_LWP_TC']):
|
||||
src += ['mm_lwp_tc.c']
|
||||
|
||||
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
65
examples/utest/testcases/mm/common.h
Normal file
65
examples/utest/testcases/mm/common.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-20 WangXiaoyao Complete testcase for mm_aspace.c
|
||||
*/
|
||||
#ifndef __TEST_MM_COMMON_H__
|
||||
#define __TEST_MM_COMMON_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <utest.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <lwp_arch.h>
|
||||
#include <mmu.h>
|
||||
#include <tlb.h>
|
||||
|
||||
#include <ioremap.h>
|
||||
#include <mm_aspace.h>
|
||||
#include <mm_flag.h>
|
||||
#include <mm_page.h>
|
||||
#include <mm_private.h>
|
||||
|
||||
extern rt_base_t rt_heap_lock(void);
|
||||
extern void rt_heap_unlock(rt_base_t level);
|
||||
|
||||
/**
|
||||
* @brief During the operations, is heap still the same;
|
||||
*/
|
||||
#define CONSIST_HEAP(statement) do { \
|
||||
rt_size_t total, used, max_used; \
|
||||
rt_size_t totala, useda, max_useda; \
|
||||
rt_ubase_t level = rt_heap_lock(); \
|
||||
rt_memory_info(&total, &used, &max_used); \
|
||||
statement; \
|
||||
rt_memory_info(&totala, &useda, &max_useda); \
|
||||
rt_heap_unlock(level); \
|
||||
uassert_true(total == totala); \
|
||||
uassert_true(used == useda); \
|
||||
uassert_true(max_used == max_useda); \
|
||||
} while (0)
|
||||
|
||||
rt_inline int memtest(volatile char *buf, int value, size_t buf_sz)
|
||||
{
|
||||
int ret = 0;
|
||||
for (size_t i = 0; i < buf_sz; i++)
|
||||
{
|
||||
if (buf[i] != value)
|
||||
{
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __TEST_MM_COMMON_H__ */
|
113
examples/utest/testcases/mm/mm_api_tc.c
Normal file
113
examples/utest/testcases/mm/mm_api_tc.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-12-14 WangXiaoyao the first version
|
||||
* 2023-03-20 WangXiaoyao Format & add more testcases for API under mm_aspace.h
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* @brief Testing all APIs under components/mm
|
||||
*/
|
||||
|
||||
void ioremap_tc(void);
|
||||
void flag_tc(void);
|
||||
|
||||
#ifdef STANDALONE_TC
|
||||
#define TC_ASSERT(expr) \
|
||||
((expr) \
|
||||
? 0 \
|
||||
: rt_kprintf("AssertFault(%d): %s\n", __LINE__, RT_STRINGIFY(expr)))
|
||||
#else
|
||||
#define TC_ASSERT(expr) uassert_true(expr)
|
||||
#endif
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#include "test_aspace_api.h"
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(aspace_tc);
|
||||
UTEST_UNIT_RUN(ioremap_tc);
|
||||
UTEST_UNIT_RUN(flag_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.mm.api_tc", utest_tc_init, utest_tc_cleanup, 20);
|
||||
|
||||
void ioremap_tc(void)
|
||||
{
|
||||
const size_t bufsz = 0x1000;
|
||||
void *paddr = (void *)rt_pages_alloc(rt_page_bits(bufsz)) + PV_OFFSET;
|
||||
int *vaddr;
|
||||
vaddr = rt_ioremap_cached(paddr, bufsz);
|
||||
if (vaddr)
|
||||
{
|
||||
TC_ASSERT(*vaddr == *(int *)(paddr - PV_OFFSET));
|
||||
|
||||
rt_iounmap(vaddr);
|
||||
rt_pages_free(paddr - PV_OFFSET, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void flag_tc(void)
|
||||
{
|
||||
size_t flags;
|
||||
|
||||
flags = MMF_CREATE(MMF_MAP_FIXED, 0x4000);
|
||||
TC_ASSERT(MMF_GET_CNTL(flags) == (MMF_MAP_FIXED | MMF_REQUEST_ALIGN));
|
||||
TC_ASSERT((1 << MMF_GET_ALIGN(flags)) == 0x4000);
|
||||
|
||||
flags = MMF_CREATE(MMF_MAP_FIXED, 0);
|
||||
TC_ASSERT(MMF_GET_CNTL(flags) == MMF_MAP_FIXED);
|
||||
TC_ASSERT(MMF_GET_ALIGN(flags) == 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#define BUF_SIZE (4ul << 20)
|
||||
static char ALIGN(BUF_SIZE) buf[BUF_SIZE];
|
||||
|
||||
void buddy_tc(void)
|
||||
{
|
||||
size_t total, free;
|
||||
rt_page_get_info(&total, &free);
|
||||
|
||||
rt_region_t region = {
|
||||
.start = (size_t)buf,
|
||||
.end = (size_t)buf + BUF_SIZE,
|
||||
};
|
||||
|
||||
size_t new_total, new_free;
|
||||
rt_page_install(region);
|
||||
rt_page_get_info(&new_total, &new_free);
|
||||
TC_ASSERT(new_total - total == (BUF_SIZE >> ARCH_PAGE_SHIFT));
|
||||
TC_ASSERT(new_free > free);
|
||||
}
|
||||
|
||||
void mmu_page_tc()
|
||||
{
|
||||
mm_aspace_t aspace = ASPACE_NEW();
|
||||
size_t total, free;
|
||||
rt_page_get_info(&total, &free);
|
||||
rt_hw_mmu_map(aspace, (void *)0x3fffffffff, 0, ARCH_PAGE_SIZE,
|
||||
MMU_MAP_K_RWCB);
|
||||
rt_hw_mmu_unmap(aspace, (void *)0x3fffffffff, ARCH_PAGE_SIZE);
|
||||
|
||||
size_t new_total, new_free;
|
||||
rt_page_get_info(&new_total, &new_free);
|
||||
TC_ASSERT(new_free == free);
|
||||
mm_aspace_delete(aspace);
|
||||
}
|
||||
#endif
|
16
examples/utest/testcases/mm/mm_libcpu_tc.c
Normal file
16
examples/utest/testcases/mm/mm_libcpu_tc.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-17 WangXiaoyao cache API unit test
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef ARCH_RISCV64
|
||||
#include "test_cache_rv64.h"
|
||||
#elif defined(ARCH_ARMV8)
|
||||
#include "test_cache_aarch64.h"
|
||||
#endif
|
116
examples/utest/testcases/mm/mm_lwp_tc.c
Normal file
116
examples/utest/testcases/mm/mm_lwp_tc.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-27 WangXiaoyao testcase for lwp
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include <lwp.h>
|
||||
#include "lwp_arch.h"
|
||||
#include "lwp_user_mm.h"
|
||||
#include "mm_aspace.h"
|
||||
#include "mmu.h"
|
||||
|
||||
/**
|
||||
* @brief user map API
|
||||
* rt_varea_t lwp_map_user_varea(struct rt_lwp *lwp, void *map_va, size_t map_size);
|
||||
* rt_varea_t lwp_map_user_varea_ext(struct rt_lwp *lwp, void *map_va, size_t map_size, size_t flags);
|
||||
*/
|
||||
#if 1 /* make it clear to identify the block :) */
|
||||
/* for testing on _aspace_traverse */
|
||||
static void *_prev_end;
|
||||
static size_t _count;
|
||||
static int _test_increase(rt_varea_t varea, void *param)
|
||||
{
|
||||
uassert_true(varea->start >= _prev_end);
|
||||
_prev_end = varea->start + varea->size;
|
||||
_count += 1;
|
||||
return 0;
|
||||
}
|
||||
#define TEST_VAREA_INSERT(statement, aspace) do {\
|
||||
size_t _prev_count; \
|
||||
_count = 0; \
|
||||
_prev_end = 0; \
|
||||
rt_aspace_traversal((aspace), _test_increase, NULL);\
|
||||
_prev_count = _count; \
|
||||
statement; \
|
||||
_count = 0; \
|
||||
_prev_end = 0; \
|
||||
rt_aspace_traversal((aspace), _test_increase, NULL);\
|
||||
uassert_true(_prev_count + 1 == _count); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
static void test_user_map_varea(void)
|
||||
{
|
||||
const size_t buf_sz = ARCH_PAGE_SIZE * 4;
|
||||
struct rt_lwp *lwp;
|
||||
rt_varea_t varea;
|
||||
lwp = lwp_new();
|
||||
|
||||
uassert_true(!!lwp);
|
||||
uassert_true(!lwp_user_space_init(lwp, 0));
|
||||
|
||||
TEST_VAREA_INSERT(
|
||||
varea = lwp_map_user_varea(lwp, 0, buf_sz),
|
||||
lwp->aspace);
|
||||
uassert_true(!!varea);
|
||||
uassert_true(varea->attr == (MMU_MAP_U_RWCB));
|
||||
uassert_true(varea->size == buf_sz);
|
||||
uassert_true(varea->aspace == lwp->aspace);
|
||||
uassert_true(varea->flag == 0);
|
||||
uassert_true(varea->start != 0);
|
||||
uassert_true(varea->start >= (void *)USER_VADDR_START && varea->start < (void *)USER_VADDR_TOP);
|
||||
|
||||
uassert_true(!lwp_ref_dec(lwp));
|
||||
}
|
||||
|
||||
static void test_user_map_varea_ext(void)
|
||||
{
|
||||
const size_t buf_sz = ARCH_PAGE_SIZE * 4;
|
||||
struct rt_lwp *lwp;
|
||||
rt_varea_t varea;
|
||||
lwp = lwp_new();
|
||||
|
||||
uassert_true(!!lwp);
|
||||
uassert_true(!lwp_user_space_init(lwp, 0));
|
||||
|
||||
TEST_VAREA_INSERT(
|
||||
varea = lwp_map_user_varea_ext(lwp, 0, buf_sz, LWP_MAP_FLAG_NOCACHE),
|
||||
lwp->aspace);
|
||||
uassert_true(!!varea);
|
||||
uassert_true(varea->attr == (MMU_MAP_U_RW));
|
||||
uassert_true(varea->size == buf_sz);
|
||||
uassert_true(varea->aspace == lwp->aspace);
|
||||
uassert_true(varea->flag == 0);
|
||||
uassert_true(varea->start != 0);
|
||||
uassert_true(varea->start >= (void *)USER_VADDR_START && varea->start < (void *)USER_VADDR_TOP);
|
||||
|
||||
uassert_true(!lwp_ref_dec(lwp));
|
||||
}
|
||||
|
||||
static void user_map_varea_tc(void)
|
||||
{
|
||||
CONSIST_HEAP(test_user_map_varea());
|
||||
CONSIST_HEAP(test_user_map_varea_ext());
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(user_map_varea_tc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "testcases.lwp.mm_tc", utest_tc_init, utest_tc_cleanup, 20);
|
37
examples/utest/testcases/mm/semaphore.h
Normal file
37
examples/utest/testcases/mm/semaphore.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-24 WangXiaoyao Complete testcase for synchronization
|
||||
*/
|
||||
#ifndef __SEMAPHORE_H__
|
||||
#define __SEMAPHORE_H__
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
typedef struct {
|
||||
atomic_int count;
|
||||
} semaphore_t;
|
||||
|
||||
void semaphore_init(semaphore_t *sem, int count)
|
||||
{
|
||||
atomic_init(&sem->count, count);
|
||||
}
|
||||
|
||||
void semaphore_wait(semaphore_t *sem)
|
||||
{
|
||||
int count;
|
||||
do {
|
||||
count = atomic_load(&sem->count);
|
||||
} while (count == 0 || !atomic_compare_exchange_weak(&sem->count, &count, count - 1));
|
||||
}
|
||||
|
||||
void semaphore_signal(semaphore_t *sem)
|
||||
{
|
||||
atomic_fetch_add(&sem->count, 1);
|
||||
}
|
||||
|
||||
#endif /* __SEMAPHORE_H__ */
|
287
examples/utest/testcases/mm/test_aspace_api.h
Normal file
287
examples/utest/testcases/mm/test_aspace_api.h
Normal file
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-20 WangXiaoyao Complete testcase for mm_aspace.c
|
||||
*/
|
||||
#ifndef __TEST_ASPACE_API_H__
|
||||
#define __TEST_ASPACE_API_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "lwp_arch.h"
|
||||
#include "test_aspace_api_internal.h"
|
||||
#include "test_synchronization.h"
|
||||
|
||||
/**
|
||||
* @brief API for aspace create/destroy
|
||||
*
|
||||
* rt_aspace_t rt_aspace_create(void *start, rt_size_t length, void *pgtbl);
|
||||
* rt_aspace_t rt_aspace_init(rt_aspace_t aspace, void *start, rt_size_t length, void *pgtbl);
|
||||
* void rt_aspace_delete(rt_aspace_t aspace);
|
||||
* void rt_aspace_detach(rt_aspace_t aspace);
|
||||
*
|
||||
* the init & detach is covered by create & detach
|
||||
*/
|
||||
|
||||
static void aspace_create_tc(void)
|
||||
{
|
||||
/* test robustness, detect failure and recover status of overall system */
|
||||
rt_aspace_t aspace;
|
||||
|
||||
CONSIST_HEAP(aspace = rt_aspace_create((void *)(0 - 0x1000), 0x1000, NULL));
|
||||
uassert_true(!aspace);
|
||||
}
|
||||
|
||||
#if 1 /* make it clear to identify the block :) */
|
||||
/* for testing on _aspace_traverse */
|
||||
static void *_prev_end;
|
||||
static size_t _count;
|
||||
static int _test_increase(rt_varea_t varea, void *param)
|
||||
{
|
||||
uassert_true(varea->start >= _prev_end);
|
||||
_prev_end = varea->start + varea->size;
|
||||
_count += 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void aspace_delete_tc(void)
|
||||
{
|
||||
/**
|
||||
* @brief Requirements: delete should recycle all types of vareas properly inside
|
||||
* and release the resource allocated for it
|
||||
*/
|
||||
rt_aspace_t aspace;
|
||||
struct rt_mm_va_hint hint = {.flags = 0,
|
||||
.map_size = 0x1000,
|
||||
.prefer = 0};
|
||||
struct rt_varea varea_phy;
|
||||
struct rt_varea varea_mobj;
|
||||
void *pgtbl;
|
||||
void *vaddr;
|
||||
|
||||
/* compatible to armv7a */
|
||||
pgtbl = rt_pages_alloc(2);
|
||||
uassert_true(!!pgtbl); /* page must be usable */
|
||||
rt_memset(pgtbl, 0, ARCH_PAGE_SIZE);
|
||||
|
||||
CONSIST_HEAP({
|
||||
aspace = rt_aspace_create((void *)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, pgtbl);
|
||||
uassert_true(!!aspace);
|
||||
|
||||
/* insert 4 types of vareas into this aspace */
|
||||
hint.limit_start = aspace->start;
|
||||
hint.limit_range_size = aspace->size;
|
||||
uassert_true(!rt_aspace_map_phy(aspace, &hint, MMU_MAP_K_RWCB, 0, &vaddr));
|
||||
uassert_true(!rt_aspace_map_phy_static(aspace, &varea_phy, &hint, MMU_MAP_K_RWCB, 0, &vaddr));
|
||||
uassert_true(!rt_aspace_map(aspace, &vaddr, 0x1000, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(!rt_aspace_map_static(aspace, &varea_mobj, &vaddr, 0x1000, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0));
|
||||
|
||||
/* for testing on _aspace_traverse */
|
||||
_count = 0;
|
||||
_prev_end = 0;
|
||||
uassert_true(!rt_aspace_traversal(aspace, _test_increase, 0));
|
||||
/* ensure the mapping is done */
|
||||
uassert_true(_count == 4);
|
||||
|
||||
rt_aspace_delete(aspace);
|
||||
|
||||
uassert_true(rt_pages_free(pgtbl, 2) == 1); /* page free must success */
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memory Map on Virtual Address Space to Mappable Object
|
||||
* int rt_aspace_map(rt_aspace_t aspace, void **addr, rt_size_t length, rt_size_t attr,
|
||||
* mm_flag_t flags, rt_mem_obj_t mem_obj, rt_size_t offset);
|
||||
* int rt_aspace_map_static(rt_aspace_t aspace, rt_varea_t varea, void **addr,
|
||||
* rt_size_t length, rt_size_t attr, mm_flag_t flags,
|
||||
* rt_mem_obj_t mem_obj, rt_size_t offset);
|
||||
*/
|
||||
static void aspace_map_tc(void)
|
||||
{
|
||||
/**
|
||||
* @brief Requirement:
|
||||
* Robustness, filter out invalid input
|
||||
*/
|
||||
void *vaddr = RT_NULL;
|
||||
uassert_true(rt_aspace_map(0, &vaddr, 0x1000, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(vaddr == RT_NULL);
|
||||
|
||||
vaddr = (void *)USER_VADDR_START;
|
||||
uassert_true(rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(vaddr == RT_NULL);
|
||||
|
||||
uassert_true(rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, -1, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(vaddr == RT_NULL);
|
||||
|
||||
/**
|
||||
* @brief Requirement:
|
||||
* in _rt_aspace_map:_varea_install
|
||||
* not covering an existed varea if a named mapping is mandatory
|
||||
*/
|
||||
vaddr = (void *)((rt_ubase_t)aspace_map_tc & ~ARCH_PAGE_MASK);
|
||||
CONSIST_HEAP(
|
||||
uassert_true(
|
||||
rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_MAP_FIXED, &rt_mm_dummy_mapper, 0)));
|
||||
uassert_true(vaddr == RT_NULL);
|
||||
|
||||
/**
|
||||
* @brief Requirement:
|
||||
* in _rt_aspace_map:_varea_install:_find_free
|
||||
* verify that this routine can choose a free region with specified size
|
||||
* and specified alignment requirement
|
||||
*/
|
||||
#define ALIGN_REQ (0x04000000)
|
||||
CONSIST_HEAP({
|
||||
uassert_true(!rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_CREATE(0, ALIGN_REQ), &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(!((rt_ubase_t)vaddr & (ALIGN_REQ - 1)));
|
||||
rt_aspace_unmap(&rt_kernel_space, vaddr);
|
||||
});
|
||||
|
||||
/* test internal APIs */
|
||||
test_find_free();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Page frames mapping to varea
|
||||
* complete the page table on specified varea, and handle tlb maintenance
|
||||
* There are 2 variants of this API
|
||||
*
|
||||
* int rt_varea_map_page(rt_varea_t varea, void *vaddr, void *page);
|
||||
* int rt_varea_map_range(rt_varea_t varea, void *vaddr, void *paddr, rt_size_t length);
|
||||
*/
|
||||
|
||||
static rt_varea_t _create_varea(const size_t size)
|
||||
{
|
||||
rt_varea_t varea;
|
||||
void *vaddr = rt_ioremap_start;
|
||||
|
||||
varea = rt_malloc(sizeof(*varea));
|
||||
uassert_true(!!varea);
|
||||
uassert_true(!rt_aspace_map_static(&rt_kernel_space, varea, &vaddr, size, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0));
|
||||
varea->flag &= ~MMF_STATIC_ALLOC;
|
||||
uassert_true(!!vaddr);
|
||||
return varea;
|
||||
}
|
||||
|
||||
static void test_varea_map_page(void)
|
||||
{
|
||||
/**
|
||||
* @brief rt_varea_map_page
|
||||
* Requirements: complete the page table entry
|
||||
*/
|
||||
const size_t buf_sz = 4 * ARCH_PAGE_SIZE;
|
||||
rt_varea_t varea = _create_varea(buf_sz);
|
||||
for (size_t i = 0; i < buf_sz; i += ARCH_PAGE_SIZE)
|
||||
{
|
||||
void *page = rt_pages_alloc(0);
|
||||
uassert_true(!!page);
|
||||
uassert_true(!rt_varea_map_page(varea, varea->start + i, page));
|
||||
|
||||
/* let page manager handle the free of page */
|
||||
rt_varea_pgmgr_insert(varea, page);
|
||||
uassert_true(rt_kmem_v2p(varea->start + i) == (page + PV_OFFSET));
|
||||
}
|
||||
|
||||
uassert_true(!rt_aspace_unmap(&rt_kernel_space, varea->start));
|
||||
}
|
||||
|
||||
static void test_varea_map_range(void)
|
||||
{
|
||||
/**
|
||||
* @brief rt_varea_map_range
|
||||
* Requirements: complete the page table entry
|
||||
*/
|
||||
const size_t buf_sz = 4 * ARCH_PAGE_SIZE;
|
||||
rt_varea_t varea = _create_varea(buf_sz);
|
||||
void *page = rt_pages_alloc(rt_page_bits(buf_sz));
|
||||
uassert_true(!!page);
|
||||
uassert_true(!rt_varea_map_range(varea, varea->start, page + PV_OFFSET, buf_sz));
|
||||
for (size_t i = 0; i < buf_sz; i += ARCH_PAGE_SIZE)
|
||||
{
|
||||
uassert_true(rt_kmem_v2p(varea->start + i) == (page + i + PV_OFFSET));
|
||||
}
|
||||
|
||||
uassert_true(rt_pages_free(page, rt_page_bits(buf_sz)));
|
||||
uassert_true(!rt_aspace_unmap(&rt_kernel_space, varea->start));
|
||||
}
|
||||
|
||||
static void varea_map_tc(void)
|
||||
{
|
||||
CONSIST_HEAP(test_varea_map_page());
|
||||
CONSIST_HEAP(test_varea_map_range());
|
||||
}
|
||||
|
||||
static void aspace_traversal_tc(void)
|
||||
{
|
||||
/**
|
||||
* @brief Requirement
|
||||
* Iterate over each varea in the kernel space
|
||||
*/
|
||||
CONSIST_HEAP(aspace_delete_tc());
|
||||
uassert_true(4 == _count);
|
||||
}
|
||||
|
||||
#ifdef ARCH_ARMV8
|
||||
static void aspace_control_tc(void)
|
||||
{
|
||||
/* this case is designed only for one page size */
|
||||
const size_t buf_sz = ARCH_PAGE_SIZE;
|
||||
void *vaddr = RT_NULL;
|
||||
volatile char *remap_nocache;
|
||||
int platform_cache_probe;
|
||||
uassert_true(!rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_PREFETCH, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(!!vaddr);
|
||||
|
||||
/* map non-cacheable region to verify cache */
|
||||
remap_nocache = rt_ioremap(rt_kmem_v2p(vaddr), buf_sz);
|
||||
uassert_true(!!remap_nocache);
|
||||
|
||||
/* pre probing */
|
||||
rt_memset(vaddr, 0xba, buf_sz);
|
||||
/* no need to sync transaction on same core */
|
||||
platform_cache_probe = memtest(remap_nocache, 0xab, buf_sz);
|
||||
|
||||
if (!platform_cache_probe)
|
||||
{
|
||||
LOG_I("Cannot distinguish cache attribution on current platform");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_I("Ready to verify attribution of cached & non-cacheable");
|
||||
}
|
||||
|
||||
/* verify cache */
|
||||
uassert_true(!rt_aspace_control(&rt_kernel_space, vaddr, MMU_CNTL_NONCACHE));
|
||||
rt_memset(vaddr, 0, buf_sz);
|
||||
uassert_true(!memtest(remap_nocache, 0, buf_sz));
|
||||
|
||||
/* another option as MMU_CNTL_CACHE */
|
||||
uassert_true(!rt_aspace_control(&rt_kernel_space, vaddr, MMU_CNTL_CACHE));
|
||||
|
||||
rt_iounmap(remap_nocache);
|
||||
uassert_true(!rt_aspace_unmap(&rt_kernel_space, vaddr));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void aspace_tc(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(aspace_create_tc);
|
||||
UTEST_UNIT_RUN(aspace_delete_tc);
|
||||
UTEST_UNIT_RUN(aspace_map_tc);
|
||||
UTEST_UNIT_RUN(aspace_traversal_tc);
|
||||
#ifdef ARCH_ARMV8
|
||||
UTEST_UNIT_RUN(aspace_control_tc);
|
||||
#endif
|
||||
UTEST_UNIT_RUN(varea_map_tc);
|
||||
|
||||
/* functionality */
|
||||
UTEST_UNIT_RUN(synchronization_tc);
|
||||
return ;
|
||||
}
|
||||
|
||||
#endif /* __TEST_ASPACE_API_H__ */
|
80
examples/utest/testcases/mm/test_aspace_api_internal.h
Normal file
80
examples/utest/testcases/mm/test_aspace_api_internal.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-23 WangXiaoyao Complete testcase for internal APIs
|
||||
*/
|
||||
#ifndef __TEST_ASPACE_API_INTERNAL_H__
|
||||
#define __TEST_ASPACE_API_INTERNAL_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "mmu.h"
|
||||
#include "test_bst_adpt.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @brief 3 cases for find free:
|
||||
* with prefer & MAP_FIXED
|
||||
* with prefer
|
||||
* without prefer
|
||||
*
|
||||
* the requirement of find free:
|
||||
* it will return a subset in address space that is free
|
||||
* the subset contains `length` contiguous elements
|
||||
* the alignment is satisfied
|
||||
*/
|
||||
static void test_find_free(void)
|
||||
{
|
||||
void *top_page = rt_kernel_space.start + rt_kernel_space.size - 0x1000;
|
||||
void *vaddr = top_page;
|
||||
|
||||
CONSIST_HEAP({
|
||||
/* type 1, on success */
|
||||
uassert_true(!rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_MAP_FIXED, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(vaddr == top_page);
|
||||
/* type 1, on failure */
|
||||
uassert_true(rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_MAP_FIXED, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(!vaddr);
|
||||
|
||||
/* type 2, on success */
|
||||
vaddr = top_page;
|
||||
uassert_true(!rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(vaddr < top_page);
|
||||
uassert_true(!!vaddr);
|
||||
rt_aspace_unmap(&rt_kernel_space, vaddr);
|
||||
/* type 2, on failure */
|
||||
vaddr = rt_kernel_space.start;
|
||||
uassert_true(-RT_ENOSPC == rt_aspace_map(&rt_kernel_space, &vaddr, rt_kernel_space.size - 0x08000000, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0));
|
||||
uassert_true(!vaddr);
|
||||
|
||||
/* type 3, on success is covered by ioremap */
|
||||
/* type 3, on failure */
|
||||
size_t map_size = ARCH_PAGE_SIZE;
|
||||
while (1)
|
||||
{
|
||||
void *va = rt_ioremap(0, map_size);
|
||||
if (va)
|
||||
{
|
||||
uassert_true(1);
|
||||
rt_iounmap(va);
|
||||
map_size <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uassert_true(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* free top page */
|
||||
rt_aspace_unmap(&rt_kernel_space, top_page);
|
||||
});
|
||||
|
||||
/* test mm_private.h */
|
||||
CONSIST_HEAP(test_bst_adpt());
|
||||
}
|
||||
|
||||
#endif /* __TEST_ASPACE_API_INTERNAL_H__ */
|
107
examples/utest/testcases/mm/test_bst_adpt.h
Normal file
107
examples/utest/testcases/mm/test_bst_adpt.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-23 WangXiaoyao Complete testcase for internal APIs
|
||||
*/
|
||||
#ifndef __TEST_BST_ADPT_H__
|
||||
#define __TEST_BST_ADPT_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "lwp_arch.h"
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
#include "lwp_user_mm.h"
|
||||
#include "mm_aspace.h"
|
||||
#include "mm_flag.h"
|
||||
#include <mm_private.h>
|
||||
#include <lwp_pid.h>
|
||||
|
||||
void test_bst_adpt(void)
|
||||
{
|
||||
size_t flags = MMF_MAP_FIXED;
|
||||
void *target_va = (void *)USER_VADDR_START + 0x3000;
|
||||
size_t map_size = 0x1000;
|
||||
void *prev_va = target_va - map_size;
|
||||
void *next_va = target_va + map_size + 1;
|
||||
struct rt_lwp *lwp;
|
||||
rt_aspace_t aspace;
|
||||
rt_mem_obj_t mem_obj;
|
||||
|
||||
/* create aspace by lwp */
|
||||
lwp = lwp_new();
|
||||
uassert_true(!!lwp);
|
||||
uassert_true(!lwp_user_space_init(lwp, 0));
|
||||
aspace = lwp->aspace;
|
||||
mem_obj = &lwp->lwp_obj->mem_obj;
|
||||
uassert_true(!!aspace);
|
||||
uassert_true(!!mem_obj);
|
||||
|
||||
/* _aspace_bst_search not cover */
|
||||
uassert_true(!_aspace_bst_search(aspace, target_va)); // ret == NULL
|
||||
|
||||
uassert_true(
|
||||
!rt_aspace_map(aspace, &target_va, map_size, MMU_MAP_K_RWCB, flags, mem_obj, 0));
|
||||
/* 2 wrappers */
|
||||
uassert_true(
|
||||
!rt_aspace_map(aspace, &prev_va, map_size - 1, MMU_MAP_K_RWCB, flags, mem_obj, 0));
|
||||
uassert_true(
|
||||
!rt_aspace_map(aspace, &next_va, map_size - 1, MMU_MAP_K_RWCB, flags, mem_obj, 0));
|
||||
|
||||
/* _aspace_bst_search */
|
||||
uassert_true(!!_aspace_bst_search(aspace, target_va));
|
||||
uassert_true(!_aspace_bst_search(aspace, target_va + map_size));
|
||||
uassert_true(!_aspace_bst_search(aspace, target_va - 1));
|
||||
|
||||
/**
|
||||
* @brief _aspace_bst_search_exceed
|
||||
* for given map [start, end]
|
||||
*/
|
||||
rt_varea_t find;
|
||||
find = _aspace_bst_search_exceed(aspace, target_va);
|
||||
uassert_true(!!find);
|
||||
uassert_true(find->start == target_va);
|
||||
|
||||
rt_varea_t last = ASPACE_VAREA_LAST(aspace);
|
||||
find = _aspace_bst_search_exceed(aspace, last->start + 1);
|
||||
uassert_true(!find);
|
||||
|
||||
/**
|
||||
* @brief _aspace_bst_search_overlap
|
||||
* for given map [start, end], five types of overlapping
|
||||
*/
|
||||
/* 1. all below */
|
||||
struct _mm_range range = {.start = prev_va - 2, .end = prev_va - 1};
|
||||
find = _aspace_bst_search_overlap(aspace, range);
|
||||
uassert_true(!find);
|
||||
/* 2. start below */
|
||||
range.end = prev_va;
|
||||
find = _aspace_bst_search_overlap(aspace, range);
|
||||
uassert_true(!!find);
|
||||
uassert_true(find->start == prev_va);
|
||||
/* 3. all wrapped */
|
||||
range.start = prev_va;
|
||||
range.end = prev_va + 1;
|
||||
find = _aspace_bst_search_overlap(aspace, range);
|
||||
uassert_true(!!find);
|
||||
uassert_true(find->start == prev_va);
|
||||
/* 4. end exceed */
|
||||
range.start = next_va;
|
||||
range.end = next_va + map_size + 1;
|
||||
find = _aspace_bst_search_overlap(aspace, range);
|
||||
uassert_true(!!find);
|
||||
uassert_true(find->start == next_va);
|
||||
/* 5. all exceed */
|
||||
range.start = next_va + map_size;
|
||||
find = _aspace_bst_search_overlap(aspace, range);
|
||||
uassert_true(!find);
|
||||
|
||||
lwp_ref_dec(lwp);
|
||||
}
|
||||
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
#endif /* __TEST_BST_ADPT_H__ */
|
115
examples/utest/testcases/mm/test_cache_aarch64.h
Normal file
115
examples/utest/testcases/mm/test_cache_aarch64.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-17 WangXiaoyao cache API unit test
|
||||
*/
|
||||
#ifndef __TEST_CACHE_AARCH64_H__
|
||||
#define __TEST_CACHE_AARCH64_H__
|
||||
|
||||
#include "common.h"
|
||||
#include <cache.h>
|
||||
|
||||
const char *platform_cache_not_guarantee = "Cannot guarantee cache operation works";
|
||||
|
||||
/**
|
||||
* ==============================================================
|
||||
* TEST FEATURE
|
||||
* API under cache.h
|
||||
*
|
||||
* void rt_hw_icache_invalidate_range(unsigned long start_addr, int size);
|
||||
* void rt_hw_cpu_icache_invalidate(void *addr, rt_size_t size);
|
||||
* void rt_hw_cpu_dcache_clean_and_invalidate(void *addr, rt_size_t size);
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
static int _get1_const(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get1(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get2(void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* hot patching codes and test if the value can be seen by icache */
|
||||
static void _test_icache_invalidate_range(void)
|
||||
{
|
||||
/* reset _get1 */
|
||||
rt_memcpy(_get1, _get1_const, _get2 - _get1);
|
||||
rt_hw_cpu_dcache_clean(_get1, _get2 - _get1);
|
||||
rt_hw_cpu_icache_invalidate(_get1, _get2 - _get1);
|
||||
uassert_true(1 == _get1());
|
||||
|
||||
/* now copy _get2 to _get1 */
|
||||
rt_memcpy(_get1, _get2, _get2 - _get1);
|
||||
if (1 != _get1())
|
||||
LOG_W(platform_cache_not_guarantee);
|
||||
|
||||
rt_hw_cpu_dcache_clean(_get1, _get2 - _get1);
|
||||
rt_hw_cpu_icache_invalidate(_get1, _get2 - _get1);
|
||||
__asm__ volatile("isb");
|
||||
uassert_true(2 == _get1());
|
||||
LOG_I("%s ok", __func__);
|
||||
}
|
||||
|
||||
/* due to hardware feature of cortex-a, we should done this on 2 separated cpu */
|
||||
static void _test_dcache_clean_and_invalidate(void)
|
||||
{
|
||||
const size_t padding = 1024 * 2;
|
||||
const size_t buf_sz = ARCH_PAGE_SIZE * 2;
|
||||
volatile char *remap_nocache;
|
||||
char *page = rt_pages_alloc(rt_page_bits(buf_sz));
|
||||
uassert_true(!!page);
|
||||
|
||||
rt_memset(page, 0xab, buf_sz);
|
||||
rt_hw_cpu_dcache_invalidate(page, buf_sz);
|
||||
|
||||
int _outdate_flag = 0;
|
||||
if (memtest(page, 0xab, buf_sz))
|
||||
_outdate_flag = 1;
|
||||
|
||||
/* after ioremap, we can access system memory to verify outcome */
|
||||
remap_nocache = rt_ioremap(page + PV_OFFSET, buf_sz);
|
||||
|
||||
rt_hw_cpu_dcache_clean(page + padding, ARCH_PAGE_SIZE);
|
||||
memtest(remap_nocache + padding, 0xab, ARCH_PAGE_SIZE);
|
||||
|
||||
if (!_outdate_flag)
|
||||
LOG_W(platform_cache_not_guarantee);
|
||||
else
|
||||
LOG_I("%s ok", __func__);
|
||||
|
||||
rt_pages_free(page, 0);
|
||||
rt_iounmap(remap_nocache);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
/* todo: format API under cache.h first */
|
||||
UTEST_UNIT_RUN(_test_icache_invalidate_range);
|
||||
UTEST_UNIT_RUN(_test_dcache_clean_and_invalidate);
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "testcases.libcpu.cache", utest_tc_init, utest_tc_cleanup, 10);
|
||||
|
||||
#endif /* __TEST_CACHE_AARCH64_H__ */
|
194
examples/utest/testcases/mm/test_cache_rv64.h
Normal file
194
examples/utest/testcases/mm/test_cache_rv64.h
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-17 WangXiaoyao cache API unit test
|
||||
*/
|
||||
|
||||
#ifndef __TEST_CACHE_RV64_H
|
||||
#define __TEST_CACHE_RV64_H
|
||||
|
||||
#ifdef ARCH_RISCV64
|
||||
#include "riscv_mmu.h"
|
||||
#include <utest.h>
|
||||
#include <cache.h>
|
||||
#include <page.h>
|
||||
#include <mmu.h>
|
||||
#include <ioremap.h>
|
||||
|
||||
/**
|
||||
* ==============================================================
|
||||
* TEST FEATURE
|
||||
* API under cache.h
|
||||
* rt_hw_sync_cache_local
|
||||
*
|
||||
* rt_hw_cpu_dcache_clean
|
||||
* rt_hw_cpu_dcache_invalidate
|
||||
* rt_hw_cpu_dcache_clean_invalidate
|
||||
* rt_hw_cpu_dcache_clean_all
|
||||
* rt_hw_cpu_dcache_invalidate_all // meaningless
|
||||
* rt_hw_cpu_dcache_clean_invalidate_all
|
||||
* rt_hw_cpu_icache_invalidate
|
||||
* rt_hw_cpu_icache_invalidate_all
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
/* Ensure the ISA is valid for target ARCHITECTURE */
|
||||
static void _illegal_instr(void)
|
||||
{
|
||||
rt_hw_sync_cache_local(_illegal_instr, 64);
|
||||
rt_hw_cpu_dcache_clean(_illegal_instr, 64);
|
||||
rt_hw_cpu_dcache_invalidate(_illegal_instr, 64);
|
||||
// rt_hw_cpu_dcache_clean_invalidate(_illegal_instr, 64); // C908 ONLY
|
||||
rt_hw_cpu_dcache_clean_all();
|
||||
rt_hw_cpu_dcache_invalidate_all(); // !CAREFUL must be inline
|
||||
// rt_hw_cpu_dcache_clean_invalidate_all(); // C908 ONLY
|
||||
rt_hw_cpu_icache_invalidate(_illegal_instr, 64);
|
||||
rt_hw_cpu_icache_invalidate_all();
|
||||
uassert_true(1);
|
||||
LOG_I("All ok!");
|
||||
}
|
||||
|
||||
static int _get1(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get2(void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* hot patching codes and test if the value can be seen by icache */
|
||||
static void _test_cache_sync(void)
|
||||
{
|
||||
uassert_true(1 == _get1());
|
||||
rt_memcpy(_get1, _get2, _get2 - _get1);
|
||||
uassert_true(1 == _get1());
|
||||
rt_hw_sync_cache_local(_get1, _get2 - _get1);
|
||||
uassert_true(2 == _get1());
|
||||
LOG_I("%s ok", __func__);
|
||||
}
|
||||
|
||||
/* test clean operation should do and only effect the range specified by writing to a page */
|
||||
static void _test_dcache_clean(void)
|
||||
{
|
||||
const size_t padding = 1024 * 3;
|
||||
const size_t buf_sz = ARCH_PAGE_SIZE * 2;
|
||||
|
||||
char *page = rt_pages_alloc(rt_page_bits(buf_sz));
|
||||
uassert_true(!!page);
|
||||
|
||||
/* after ioremap, we can access system memory to verify outcome */
|
||||
volatile char *remap_nocache = rt_ioremap(page + PV_OFFSET, buf_sz);
|
||||
rt_memset(page, 0xab, buf_sz);
|
||||
rt_hw_cpu_sync();
|
||||
|
||||
int _outdate_flag = 0;
|
||||
for (size_t i = padding; i < ARCH_PAGE_SIZE; i++)
|
||||
{
|
||||
if (remap_nocache[i] != 0xab)
|
||||
{
|
||||
_outdate_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
page[padding - 1] = 0xac;
|
||||
page[padding + ARCH_PAGE_SIZE] = 0xac;
|
||||
rt_hw_cpu_dcache_clean(page + padding, ARCH_PAGE_SIZE);
|
||||
|
||||
/* free some space in dcache to avoid padding data being written back */
|
||||
rt_hw_cpu_dcache_invalidate(page + padding, ARCH_PAGE_SIZE);
|
||||
uassert_true(remap_nocache[padding - 1] != 0xac);
|
||||
uassert_true(remap_nocache[padding + ARCH_PAGE_SIZE] != 0xac);
|
||||
|
||||
int _test_ok = 1;
|
||||
for (size_t i = padding; i < ARCH_PAGE_SIZE; i++)
|
||||
{
|
||||
if (remap_nocache[i] != 0xab)
|
||||
{
|
||||
_test_ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
uassert_true(_test_ok);
|
||||
|
||||
if (!_outdate_flag)
|
||||
LOG_W("Cannot guarantee clean works");
|
||||
else
|
||||
LOG_I("%s ok", __func__);
|
||||
|
||||
rt_pages_free(page, 0);
|
||||
rt_iounmap(remap_nocache);
|
||||
}
|
||||
|
||||
/* test clean op should do and only effect the range */
|
||||
static void _test_dcache_invalidate(void)
|
||||
{
|
||||
const size_t padding = 1024 * 3;
|
||||
const size_t buf_sz = ARCH_PAGE_SIZE * 2;
|
||||
|
||||
/* prepare */
|
||||
char *page = rt_pages_alloc(rt_page_bits(buf_sz));
|
||||
uassert_true(!!page);
|
||||
|
||||
volatile char *remap_nocache = rt_ioremap(page + PV_OFFSET, buf_sz);
|
||||
rt_memset(page, 0x0, buf_sz);
|
||||
rt_hw_cpu_sync();
|
||||
|
||||
int _outdate_flag = 0;
|
||||
for (size_t i = padding; i < ARCH_PAGE_SIZE; i++)
|
||||
{
|
||||
remap_nocache[i] = 0xab;
|
||||
rt_hw_cpu_dcache_invalidate((void *)&remap_nocache[i], 1);
|
||||
}
|
||||
|
||||
rt_hw_cpu_dcache_clean_all();
|
||||
|
||||
int _test_ok = 1;
|
||||
for (size_t i = padding; i < ARCH_PAGE_SIZE; i++)
|
||||
{
|
||||
if (remap_nocache[i] == 0xab)
|
||||
{
|
||||
_test_ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
uassert_true(_test_ok);
|
||||
|
||||
LOG_I("%s ok", __func__);
|
||||
|
||||
rt_pages_free(page, 0);
|
||||
rt_iounmap(remap_nocache);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(_illegal_instr);
|
||||
#ifdef BOARD_allwinnerd1s
|
||||
/* thead ISA extension */
|
||||
UTEST_UNIT_RUN(_test_cache_sync);
|
||||
/* part of it is hard to test on simulation machine */
|
||||
UTEST_UNIT_RUN(_test_dcache_clean);
|
||||
UTEST_UNIT_RUN(_test_dcache_invalidate);
|
||||
#endif
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "testcases.libcpu.cache", utest_tc_init, utest_tc_cleanup, 10);
|
||||
|
||||
#endif /* ARCH_RISCV64 */
|
||||
#endif /* __TEST_CACHE_RV64_H */
|
165
examples/utest/testcases/mm/test_synchronization.h
Normal file
165
examples/utest/testcases/mm/test_synchronization.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-24 WangXiaoyao Complete testcase for synchronization
|
||||
*/
|
||||
#ifndef __TEST_SYNCHRONIZATION_H__
|
||||
#define __TEST_SYNCHRONIZATION_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "semaphore.h"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
|
||||
#define THREAD_CNT RT_CPUS_NR
|
||||
#define TEST_TIMES 2000
|
||||
#define PRIO (UTEST_THR_PRIORITY + 1)
|
||||
/* size of mapping buffer */
|
||||
#define BUF_SIZE (64ul << 10)
|
||||
|
||||
/* engage with sibling */
|
||||
struct rt_semaphore done;
|
||||
static semaphore_t sem1[THREAD_CNT / 2];
|
||||
static semaphore_t sem2[THREAD_CNT / 2];
|
||||
|
||||
static void *map(void)
|
||||
{
|
||||
int err;
|
||||
int flags = MMF_PREFETCH;
|
||||
size_t attr = MMU_MAP_K_RWCB;
|
||||
void *vaddr = 0;
|
||||
err =
|
||||
rt_aspace_map(&rt_kernel_space, &vaddr, BUF_SIZE, attr, flags, &rt_mm_dummy_mapper, 0);
|
||||
if (err)
|
||||
uassert_true(0);
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
static void unmap(void *buf)
|
||||
{
|
||||
int err;
|
||||
err =
|
||||
rt_aspace_unmap(&rt_kernel_space, buf);
|
||||
if (err)
|
||||
uassert_true(0);
|
||||
return ;
|
||||
}
|
||||
|
||||
static void group1_entry(void *param)
|
||||
{
|
||||
const size_t id = (size_t)param;
|
||||
size_t test_times = TEST_TIMES;
|
||||
size_t alive = test_times / 10;
|
||||
void *buf;
|
||||
|
||||
while (test_times--)
|
||||
{
|
||||
if (test_times % alive == 0)
|
||||
uassert_true(1);
|
||||
|
||||
buf = map();
|
||||
|
||||
memset(buf, 'A' + id, BUF_SIZE);
|
||||
/* if other core write to our cache, force the changes to be visible to us */
|
||||
rt_hw_dmb();
|
||||
|
||||
if (memtest(buf, 'A' + id, BUF_SIZE))
|
||||
uassert_true(0);
|
||||
|
||||
semaphore_signal(&sem1[id]);
|
||||
semaphore_wait(&sem2[id]);
|
||||
unmap(buf);
|
||||
}
|
||||
|
||||
rt_sem_release(&done);
|
||||
return;
|
||||
}
|
||||
|
||||
static void group2_entry(void *param)
|
||||
{
|
||||
const size_t id = (size_t)param;
|
||||
size_t test_times = TEST_TIMES;
|
||||
size_t alive = test_times / 10;
|
||||
void *buf;
|
||||
|
||||
while (test_times--)
|
||||
{
|
||||
if (test_times % alive == 0)
|
||||
uassert_true(1);
|
||||
|
||||
semaphore_signal(&sem2[id]);
|
||||
semaphore_wait(&sem1[id]);
|
||||
buf = map();
|
||||
|
||||
memset(buf, 'a' + id, BUF_SIZE);
|
||||
/* if other core write to our cache, force the changes to be visible to us */
|
||||
rt_hw_dmb();
|
||||
|
||||
if (memtest(buf, 'a' + id, BUF_SIZE))
|
||||
uassert_true(0);
|
||||
|
||||
unmap(buf);
|
||||
}
|
||||
|
||||
rt_sem_release(&done);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief On a smp system, we create at least 4 threads
|
||||
* 2 doing map, 2 doing unmapping at the same moment
|
||||
*/
|
||||
|
||||
static void synchronization_tc(void)
|
||||
{
|
||||
rt_thread_t group1[THREAD_CNT / 2];
|
||||
rt_thread_t group2[THREAD_CNT / 2];
|
||||
|
||||
rt_sem_init(&done, __func__, 0, RT_IPC_FLAG_FIFO);
|
||||
|
||||
for (size_t i = 0; i < THREAD_CNT / 2; i++)
|
||||
{
|
||||
char name[RT_NAME_MAX];
|
||||
rt_sprintf(name, "grp1_%d", i);
|
||||
group1[i] =
|
||||
rt_thread_create(name, group1_entry, (void *)i, ARCH_PAGE_SIZE, PRIO, 10);
|
||||
uassert_true(!!group1[i]);
|
||||
semaphore_init(&sem1[i], 0);
|
||||
|
||||
uassert_true(!rt_thread_startup(group1[i]));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < THREAD_CNT / 2; i++)
|
||||
{
|
||||
char name[RT_NAME_MAX];
|
||||
rt_sprintf(name, "grp2_%d", i);
|
||||
group2[i] =
|
||||
rt_thread_create(name, group2_entry, (void *)i, ARCH_PAGE_SIZE, PRIO, 10);
|
||||
uassert_true(!!group2[i]);
|
||||
semaphore_init(&sem2[i], 0);
|
||||
|
||||
uassert_true(!rt_thread_startup(group2[i]));
|
||||
}
|
||||
|
||||
/* wait all thread exit */
|
||||
for (size_t i = 0; i < (THREAD_CNT / 2 * 2); i++)
|
||||
{
|
||||
rt_sem_take(&done, RT_WAITING_FOREVER);
|
||||
}
|
||||
LOG_I("all threads exit");
|
||||
rt_sem_detach(&done);
|
||||
}
|
||||
|
||||
#else /* RT_USING_SMP */
|
||||
|
||||
static void synchronization_tc(void)
|
||||
{
|
||||
uassert_true(1);
|
||||
}
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
#endif /* __TEST_SYNCHRONIZATION_H__ */
|
37
examples/utest/testcases/posix/Kconfig
Normal file
37
examples/utest/testcases/posix/Kconfig
Normal file
|
@ -0,0 +1,37 @@
|
|||
menu "RTT Posix Testcase"
|
||||
|
||||
config RTT_POSIX_TESTCASE
|
||||
select RT_USING_UTEST
|
||||
bool "RTT Posix Testcase"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/aio_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/arpa/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/ctype_h/Kconfig" # reserve
|
||||
source "$RTT_DIR/examples/utest/testcases/posix/dirent_h/Kconfig"
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/errno_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/fcntl_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/fenv_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/inttypes_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/libgen_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/locale_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/mqueue_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/net/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/netdb_h/Kconfig" # reserve
|
||||
source "$RTT_DIR/examples/utest/testcases/posix/pthread_h/Kconfig"
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/sched_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/semaphore_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/setjmp_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/signal_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/stdarg_h/Kconfig" # reserve
|
||||
source "$RTT_DIR/examples/utest/testcases/posix/stdio_h/Kconfig"
|
||||
source "$RTT_DIR/examples/utest/testcases/posix/stdlib_h/Kconfig"
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/string_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/stropts_h/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/sys/Kconfig" # reserve
|
||||
# source "$RTT_DIR/examples/utest/testcases/posix/time_h/Kconfig" # reserve
|
||||
source "$RTT_DIR/examples/utest/testcases/posix/unistd_h/Kconfig"
|
||||
endif
|
||||
|
||||
endmenu
|
14
examples/utest/testcases/posix/SConscript
Normal file
14
examples/utest/testcases/posix/SConscript
Normal file
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
Return('objs')
|
39
examples/utest/testcases/posix/aio_h/Kconfig
Normal file
39
examples/utest/testcases/posix/aio_h/Kconfig
Normal file
|
@ -0,0 +1,39 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_AIO_H
|
||||
bool "<aio.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_AIO_H
|
||||
|
||||
config AIO_H_AIO_CANCEL
|
||||
bool "<aio.h -> aio_cancel>"
|
||||
default n
|
||||
|
||||
config AIO_H_AIO_ERROR
|
||||
bool "<aio.h -> aio_error>"
|
||||
default n
|
||||
|
||||
config AIO_H_AIO_FSYNC
|
||||
bool "<aio.h -> aio_fsync>"
|
||||
default n
|
||||
|
||||
config AIO_H_AIO_READ
|
||||
bool "<aio.h -> aio_read>"
|
||||
default n
|
||||
|
||||
config AIO_H_AIO_RETURN
|
||||
bool "<aio.h -> aio_return>"
|
||||
default n
|
||||
|
||||
config AIO_H_AIO_SUSPEND
|
||||
bool "<aio.h -> aio_suspend>"
|
||||
default n
|
||||
|
||||
config AIO_H_AIO_WRITE
|
||||
bool "<aio.h -> aio_write>"
|
||||
default n
|
||||
|
||||
config AIO_H_AIO_LISTIO
|
||||
bool "<aio.h -> lio_listio>"
|
||||
default n
|
||||
|
||||
endif
|
1
examples/utest/testcases/posix/arpa/Kconfig
Normal file
1
examples/utest/testcases/posix/arpa/Kconfig
Normal file
|
@ -0,0 +1 @@
|
|||
source "$RTT_DIR/examples/utest/testcases/posix/arpa/inet_h/Kconfig"
|
11
examples/utest/testcases/posix/arpa/inet_h/Kconfig
Normal file
11
examples/utest/testcases/posix/arpa/inet_h/Kconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_ARPA_INET_H
|
||||
bool "<arpa/inet.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_ARPA_INET_H
|
||||
|
||||
config ARPA_INET_H_INTERFACE
|
||||
bool "<arpa/inet.h> -> htonl, htons, ntohl, ntohs, inet_addr, inet_ntoa, inet_ntop, inet_pton"
|
||||
default n
|
||||
|
||||
endif
|
9
examples/utest/testcases/posix/ctype_h/Kconfig
Normal file
9
examples/utest/testcases/posix/ctype_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_CTYPE_H
|
||||
bool "<ctype.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_CTYPE_H
|
||||
|
||||
# functions, TODO
|
||||
|
||||
endif
|
16
examples/utest/testcases/posix/ctype_h/SConscript
Normal file
16
examples/utest/testcases/posix/ctype_h/SConscript
Normal file
|
@ -0,0 +1,16 @@
|
|||
import rtconfig
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
# get current directory
|
||||
cwd = GetCurrentDir()
|
||||
path = [cwd]
|
||||
src = []
|
||||
|
||||
if GetDepend('RTT_POSIX_TESTCASE_CTYPE_H'):
|
||||
src += Glob('./definitions/*.c')
|
||||
|
||||
group = DefineGroup('rtt_posix_testcase', src, depend = ['RTT_POSIX_TESTCASE_CTYPE_H'], CPPPATH = path)
|
||||
|
||||
|
||||
Return('group')
|
31
examples/utest/testcases/posix/ctype_h/definitions/ctype_h.c
Normal file
31
examples/utest/testcases/posix/ctype_h/definitions/ctype_h.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Bull SA. All rights reserved.
|
||||
* Created by: Laurent.Vivier@bull.net
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
*/
|
||||
|
||||
/* <ctype.h> */
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static char xx;
|
||||
|
||||
static int test_defined()
|
||||
{
|
||||
isalnum(xx);
|
||||
isalpha(xx);
|
||||
isblank(xx);
|
||||
iscntrl(xx);
|
||||
isdigit(xx);
|
||||
isgraph(xx);
|
||||
islower(xx);
|
||||
isprint(xx);
|
||||
ispunct(xx);
|
||||
isspace(xx);
|
||||
isupper(xx);
|
||||
isxdigit(xx);
|
||||
tolower(xx);
|
||||
toupper(xx);
|
||||
}
|
11
examples/utest/testcases/posix/dirent_h/Kconfig
Normal file
11
examples/utest/testcases/posix/dirent_h/Kconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_DIRENT_H
|
||||
bool "<dirent.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_DIRENT_H
|
||||
|
||||
config DIRENT_H_OPENDIR_READDIR_CLOSEDIR
|
||||
bool "<dirent.h> -> opendir, readdir, closedir"
|
||||
default n
|
||||
|
||||
endif
|
19
examples/utest/testcases/posix/dirent_h/SConscript
Normal file
19
examples/utest/testcases/posix/dirent_h/SConscript
Normal file
|
@ -0,0 +1,19 @@
|
|||
import rtconfig
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
# get current directory
|
||||
cwd = GetCurrentDir()
|
||||
path = [cwd]
|
||||
src = []
|
||||
|
||||
if GetDepend('RTT_POSIX_TESTCASE_DIRENT_H'):
|
||||
src += Glob('./definitions/*.c')
|
||||
|
||||
if GetDepend('DIRENT_H_OPENDIR_READDIR_CLOSEDIR'):
|
||||
src += Glob('./functions/open_read_close_dir_tc.c')
|
||||
|
||||
|
||||
group = DefineGroup('rtt_posix_testcase', src, depend = ['RTT_POSIX_TESTCASE_DIRENT_H'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
|
@ -0,0 +1,41 @@
|
|||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIRFD_TEST_NAME "/"
|
||||
|
||||
/* API for: opendir readdir closedir */
|
||||
static int dir_test_entry(void)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *d;
|
||||
|
||||
dirp = opendir(DIRFD_TEST_NAME);
|
||||
if (dirp == RT_NULL)
|
||||
{
|
||||
printf("open directory error!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((d = readdir(dirp)) != RT_NULL)
|
||||
{
|
||||
printf("found %s\n", d->d_name);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_dir(void)
|
||||
{
|
||||
uassert_int_equal(dir_test_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_dir);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.dirent_h.open_read_close_dir_tc.c", RT_NULL, RT_NULL, 10);
|
||||
|
3
examples/utest/testcases/posix/errno_h/Kconfig
Normal file
3
examples/utest/testcases/posix/errno_h/Kconfig
Normal file
|
@ -0,0 +1,3 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_ERRNO_H
|
||||
bool "<errno.h>"
|
||||
default n
|
15
examples/utest/testcases/posix/errno_h/SConscript
Normal file
15
examples/utest/testcases/posix/errno_h/SConscript
Normal file
|
@ -0,0 +1,15 @@
|
|||
import rtconfig
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
# get current directory
|
||||
cwd = GetCurrentDir()
|
||||
path = [cwd]
|
||||
src = []
|
||||
|
||||
if GetDepend('RTT_POSIX_TESTCASE_ERRNO_H'):
|
||||
src += Glob('./definitions/*.c')
|
||||
|
||||
group = DefineGroup('rtt_posix_testcase', src, depend = ['RTT_POSIX_TESTCASE_ERRNO_H'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
104
examples/utest/testcases/posix/errno_h/definitions/errno_h.c
Normal file
104
examples/utest/testcases/posix/errno_h/definitions/errno_h.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* This test tests if error.h is exist and useble
|
||||
*author:ysun@lnxw.com
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
|
||||
static int errno_test;
|
||||
|
||||
__attribute__((unused)) static int dummy1 = E2BIG;
|
||||
__attribute__((unused)) static int dummy2 = EACCES;
|
||||
__attribute__((unused)) static int dummy3 = EADDRINUSE;
|
||||
__attribute__((unused)) static int dummy4 = EADDRNOTAVAIL;
|
||||
__attribute__((unused)) static int dummy5 = EAFNOSUPPORT;
|
||||
__attribute__((unused)) static int dummy6 = EAGAIN;
|
||||
__attribute__((unused)) static int dummy7 = EALREADY;
|
||||
__attribute__((unused)) static int dummy8 = EBADF;
|
||||
#ifdef EBADMSG
|
||||
__attribute__((unused)) static int dummy9 = EBADMSG;
|
||||
#endif
|
||||
__attribute__((unused)) static int dummy10 = EBUSY;
|
||||
__attribute__((unused)) static int dummy11 = ECANCELED;
|
||||
__attribute__((unused)) static int dummy12 = ECHILD;
|
||||
__attribute__((unused)) static int dummy13 = ECONNABORTED;
|
||||
__attribute__((unused)) static int dummy14 = ECONNREFUSED;
|
||||
__attribute__((unused)) static int dummy15 = ECONNRESET;
|
||||
__attribute__((unused)) static int dummy16 = EDEADLK;
|
||||
__attribute__((unused)) static int dummy17 = EDESTADDRREQ;
|
||||
__attribute__((unused)) static int dummy18 = EDOM;
|
||||
__attribute__((unused)) static int dummy19 = EDQUOT;
|
||||
__attribute__((unused)) static int dummy20 = EEXIST;
|
||||
__attribute__((unused)) static int dummy21 = EFAULT;
|
||||
__attribute__((unused)) static int dummy22 = EFBIG;
|
||||
__attribute__((unused)) static int dummy23 = EHOSTUNREACH;
|
||||
__attribute__((unused)) static int dummy24 = EIDRM;
|
||||
__attribute__((unused)) static int dummy25 = EILSEQ;
|
||||
__attribute__((unused)) static int dummy26 = EINPROGRESS;
|
||||
__attribute__((unused)) static int dummy27 = EINTR;
|
||||
__attribute__((unused)) static int dummy28 = EINVAL;
|
||||
__attribute__((unused)) static int dummy29 = EIO;
|
||||
__attribute__((unused)) static int dummy30 = EISCONN;
|
||||
__attribute__((unused)) static int dummy31 = EISDIR;
|
||||
__attribute__((unused)) static int dummy32 = ELOOP;
|
||||
__attribute__((unused)) static int dummy33 = EMFILE;
|
||||
__attribute__((unused)) static int dummy34 = EMLINK;
|
||||
__attribute__((unused)) static int dummy35 = EMSGSIZE;
|
||||
__attribute__((unused)) static int dummy36 = EMULTIHOP;
|
||||
__attribute__((unused)) static int dummy37 = ENAMETOOLONG;
|
||||
__attribute__((unused)) static int dummy38 = ENETDOWN;
|
||||
__attribute__((unused)) static int dummy39 = ENETRESET;
|
||||
__attribute__((unused)) static int dummy40 = ENETUNREACH;
|
||||
__attribute__((unused)) static int dummy41 = ENFILE;
|
||||
__attribute__((unused)) static int dummy42 = ENOBUFS;
|
||||
#ifdef ENODATA
|
||||
__attribute__((unused)) static int dummy43 = ENODATA;
|
||||
#endif
|
||||
__attribute__((unused)) static int dummy44 = ENODEV;
|
||||
__attribute__((unused)) static int dummy45 = ENOENT;
|
||||
__attribute__((unused)) static int dummy46 = ENOEXEC;
|
||||
__attribute__((unused)) static int dummy47 = ENOLCK;
|
||||
__attribute__((unused)) static int dummy48 = ENOLINK;
|
||||
__attribute__((unused)) static int dummy49 = ENOMEM;
|
||||
__attribute__((unused)) static int dummy50 = ENOMSG;
|
||||
__attribute__((unused)) static int dummy51 = ENOPROTOOPT;
|
||||
__attribute__((unused)) static int dummy52 = ENOSPC;
|
||||
#ifdef ENOSR
|
||||
__attribute__((unused)) static int dummy53 = ENOSR;
|
||||
#endif
|
||||
#ifdef ENOSTR
|
||||
__attribute__((unused)) static int dummy54 = ENOSTR;
|
||||
#endif
|
||||
__attribute__((unused)) static int dummy55 = ENOSYS;
|
||||
__attribute__((unused)) static int dummy56 = ENOTCONN;
|
||||
__attribute__((unused)) static int dummy57 = ENOTDIR;
|
||||
__attribute__((unused)) static int dummy58 = ENOTEMPTY;
|
||||
__attribute__((unused)) static int dummy59 = ENOTSOCK;
|
||||
__attribute__((unused)) static int dummy60 = ENOTSUP;
|
||||
__attribute__((unused)) static int dummy61 = ENOTTY;
|
||||
__attribute__((unused)) static int dummy62 = ENXIO;
|
||||
__attribute__((unused)) static int dummy63 = EOPNOTSUPP;
|
||||
__attribute__((unused)) static int dummy64 = EOVERFLOW;
|
||||
__attribute__((unused)) static int dummy65 = EPERM;
|
||||
__attribute__((unused)) static int dummy66 = EPIPE;
|
||||
__attribute__((unused)) static int dummy67 = EPROTO;
|
||||
__attribute__((unused)) static int dummy68 = EPROTONOSUPPORT;
|
||||
__attribute__((unused)) static int dummy69 = EPROTOTYPE;
|
||||
__attribute__((unused)) static int dummy70 = ERANGE;
|
||||
__attribute__((unused)) static int dummy71 = EROFS;
|
||||
__attribute__((unused)) static int dummy72 = ESPIPE;
|
||||
__attribute__((unused)) static int dummy73 = ESRCH;
|
||||
__attribute__((unused)) static int dummy74 = ESTALE;
|
||||
#ifdef ETIME
|
||||
__attribute__((unused)) static int dummy75 = ETIME;
|
||||
#endif
|
||||
__attribute__((unused)) static int dummy76 = ETIMEDOUT;
|
||||
__attribute__((unused)) static int dummy77 = ETXTBSY;
|
||||
__attribute__((unused)) static int dummy78 = EWOULDBLOCK;
|
||||
__attribute__((unused)) static int dummy79 = EXDEV;
|
||||
|
||||
__attribute__((unused))static int dummyfcn(void)
|
||||
{
|
||||
errno_test = errno;
|
||||
return 0;
|
||||
}
|
9
examples/utest/testcases/posix/fcntl_h/Kconfig
Normal file
9
examples/utest/testcases/posix/fcntl_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_FCNTL_H
|
||||
bool "<fcntl.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_FCNTL_H
|
||||
|
||||
# function, TODO
|
||||
|
||||
endif
|
9
examples/utest/testcases/posix/fenv_h/Kconfig
Normal file
9
examples/utest/testcases/posix/fenv_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_FENV_H
|
||||
bool "<fenv.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_FENV_H
|
||||
|
||||
# function, TODO
|
||||
|
||||
endif
|
9
examples/utest/testcases/posix/inttypes_h/Kconfig
Normal file
9
examples/utest/testcases/posix/inttypes_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_INTTYPES_H
|
||||
bool "<inttypes.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_INTTYPES_H
|
||||
|
||||
# function, TODO
|
||||
|
||||
endif
|
15
examples/utest/testcases/posix/libgen_h/Kconfig
Normal file
15
examples/utest/testcases/posix/libgen_h/Kconfig
Normal file
|
@ -0,0 +1,15 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_LIBGEN_H
|
||||
bool "<libgen.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_LIBGEN_H
|
||||
|
||||
config LIBGEN_H_BASENAME
|
||||
bool "<libgen.h> -> basename"
|
||||
default n
|
||||
|
||||
config LIBGEN_H_DIRNAME
|
||||
bool "<libgen.h> -> dirname"
|
||||
default n
|
||||
|
||||
endif
|
15
examples/utest/testcases/posix/locale_h/Kconfig
Normal file
15
examples/utest/testcases/posix/locale_h/Kconfig
Normal file
|
@ -0,0 +1,15 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_LOCALE_H
|
||||
bool "<locale.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_LOCALE_H
|
||||
|
||||
config LOCALE_H_SETLOCALE
|
||||
bool "<locale.h -> setlocale>"
|
||||
default n
|
||||
|
||||
config LIBGEN_H_LOCALECONV
|
||||
bool "<locale.h -> localconv>"
|
||||
default n
|
||||
|
||||
endif
|
9
examples/utest/testcases/posix/mqueue_h/Kconfig
Normal file
9
examples/utest/testcases/posix/mqueue_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_MQUEUE_H
|
||||
bool "<mqueue.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_MQUEUE_H
|
||||
|
||||
# functions, TODO
|
||||
|
||||
endif
|
1
examples/utest/testcases/posix/net/Kconfig
Normal file
1
examples/utest/testcases/posix/net/Kconfig
Normal file
|
@ -0,0 +1 @@
|
|||
source "$RTT_DIR/examples/utest/testcases/posix/net/if_h/Kconfig"
|
11
examples/utest/testcases/posix/net/if_h/Kconfig
Normal file
11
examples/utest/testcases/posix/net/if_h/Kconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_NET_IF_H
|
||||
bool "<net/if.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_NET_IF_H
|
||||
|
||||
config NET_IF_H_NAMEINDEX
|
||||
bool "<net/if.h> -> if_freenameindex, if_indextoname, if_nameindex, if_nametoindex"
|
||||
default n
|
||||
|
||||
endif
|
11
examples/utest/testcases/posix/netdb_h/Kconfig
Normal file
11
examples/utest/testcases/posix/netdb_h/Kconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_NETDB_H
|
||||
bool "<netdb.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_NETDB_H
|
||||
|
||||
config NETDB_H_ADDRINFO
|
||||
bool "<netdb.h> -> getaddrinfo, gai_strerror, getnameinfo, freeaddrinfo"
|
||||
default n
|
||||
|
||||
endif
|
43
examples/utest/testcases/posix/pthread_h/Kconfig
Normal file
43
examples/utest/testcases/posix/pthread_h/Kconfig
Normal file
|
@ -0,0 +1,43 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_PTHREAD_H
|
||||
bool "<pthread.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_PTHREAD_H
|
||||
|
||||
config PTHREAD_H_PTHREAD_CREATE
|
||||
bool "<pthread.h> -> pthread_create"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_JOIN
|
||||
bool "<pthread.h> -> pthread_join"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_EXIT
|
||||
bool "<pthread.h> -> pthread_exit"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_COND_INIT
|
||||
bool "<pthread.h> -> pthread_cond_init"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_COND_DESTROY
|
||||
bool "<pthread.h> -> pthread_cond_destroy"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_COND_BROADCAST
|
||||
bool "<pthread.h> -> pthread_cond_broadcast"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_COND_SIGNAL
|
||||
bool "<pthread.h> -> pthread_cond_signal"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_COND_TIMEWAIT
|
||||
bool "<pthread.h> -> pthread_cond_timedwait"
|
||||
default n
|
||||
|
||||
config PTHREAD_H_PTHREAD_DETACH
|
||||
bool "<pthread.h> -> pthread_detach"
|
||||
default n
|
||||
|
||||
endif
|
47
examples/utest/testcases/posix/pthread_h/SConscript
Normal file
47
examples/utest/testcases/posix/pthread_h/SConscript
Normal file
|
@ -0,0 +1,47 @@
|
|||
import rtconfig
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
# get current directory
|
||||
cwd = GetCurrentDir()
|
||||
path = [cwd + '/functions']
|
||||
src = []
|
||||
|
||||
src += Glob('./definitions/testfrmw/*.c')
|
||||
path += [cwd + '/functions/testfrmw']
|
||||
|
||||
if GetDepend('RTT_POSIX_TESTCASE_PTHREAD_H'):
|
||||
src += Glob('./definitions/*.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_CREATE']):
|
||||
src += Glob('./functions/pthread_create/pthread_create_1-2_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_JOIN']):
|
||||
src += Glob('./functions/pthread_join/pthread_join_1-1_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_EXIT']):
|
||||
src += Glob('./functions/pthread_exit/pthread_exit_1-1_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_COND_INIT']):
|
||||
src += Glob('./functions/pthread_cond_init/pthread_cond_init_1-1_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_COND_DESTROY']):
|
||||
src += Glob('./functions/pthread_cond_destroy/pthread_cond_destroy_1-1_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_COND_BROADCAST']):
|
||||
src += Glob('./functions/pthread_cond_broadcast/pthread_cond_broadcast_1-1_tc.c')
|
||||
src += Glob('./functions/pthread_cond_broadcast/pthread_cond_broadcast_2-1_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_COND_SIGNAL']):
|
||||
src += Glob('./functions/pthread_cond_signal/pthread_cond_signal_2-2_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_COND_TIMEWAIT']):
|
||||
src += Glob('./functions/pthread_cond_timedwait/pthread_cond_timedwait_1-1_tc.c')
|
||||
src += Glob('./functions/pthread_cond_timedwait/pthread_cond_timedwait_2-1_tc.c')
|
||||
|
||||
if GetDepend(['PTHREAD_H_PTHREAD_DETACH']):
|
||||
src += Glob('./functions/pthread_detach/pthread_detach_4-1_tc.c')
|
||||
|
||||
group = DefineGroup('rtt_posix_testcase', src, depend = ['RTT_POSIX_TESTCASE_PTHREAD_H'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
159
examples/utest/testcases/posix/pthread_h/definitions/pthread_h.c
Normal file
159
examples/utest/testcases/posix/pthread_h/definitions/pthread_h.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
Test this function is defined:
|
||||
|
||||
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
int (*test_pthread_atfork)(void (*prepare)(void), void (*parent)(void), void (*child)(void));
|
||||
int (*test_pthread_attr_destroy)(pthread_attr_t *__attr);
|
||||
int (*test_pthread_attr_getdetachstate)(const pthread_attr_t *__attr, int *__detachstate);
|
||||
int (*test_pthread_attr_getguardsize)(const pthread_attr_t *__attr, size_t *__guardsize);
|
||||
int (*test_pthread_attr_getinheritsched)(const pthread_attr_t *__attr, int *__inheritsched);
|
||||
int (*test_pthread_attr_getschedparam)(const pthread_attr_t *__attr, struct sched_param *__param);
|
||||
int (*test_pthread_attr_getschedpolicy)(const pthread_attr_t *__attr, int *__policy);
|
||||
int (*test_pthread_attr_getscope)(const pthread_attr_t *__attr, int *__contentionscope);
|
||||
int (*test_pthread_attr_getstack)(const pthread_attr_t *attr, void **__stackaddr, size_t *__stacksize);
|
||||
int (*test_pthread_attr_getstackaddr)(const pthread_attr_t *__attr, void **__stackaddr);
|
||||
int (*test_pthread_attr_getstacksize)(const pthread_attr_t *__attr, size_t *__stacksize);
|
||||
int (*test_pthread_attr_init)(pthread_attr_t *__attr);
|
||||
int (*test_pthread_attr_setdetachstate)(pthread_attr_t *__attr, int __detachstate);
|
||||
int (*test_pthread_attr_setguardsize)(pthread_attr_t *__attr, size_t __guardsize);
|
||||
int (*test_pthread_attr_setinheritsched)(pthread_attr_t *__attr, int __inheritsched);
|
||||
int (*test_pthread_attr_setschedparam)(pthread_attr_t *__attr, const struct sched_param *__param);
|
||||
int (*test_pthread_attr_setschedpolicy)(pthread_attr_t *__attr, int __policy);
|
||||
int (*test_pthread_attr_setscope)(pthread_attr_t *__attr, int __contentionscope);
|
||||
int (*test_pthread_attr_setstack)(pthread_attr_t *attr, void *__stackaddr, size_t __stacksize);
|
||||
int (*test_pthread_attr_setstackaddr)(pthread_attr_t *__attr, void *__stackaddr);
|
||||
int (*test_pthread_attr_setstacksize)(pthread_attr_t *__attr, size_t __stacksize);
|
||||
int (*test_pthread_cancel)(pthread_t __pthread);
|
||||
void (*test_pthread_cleanup_pop)(int execute);
|
||||
void (*test_pthread_cleanup_push)(void (*routine)(void*), void *arg);
|
||||
int (*test_pthread_cond_broadcast)(pthread_cond_t *__cond);
|
||||
int (*test_pthread_cond_destroy)(pthread_cond_t *__mutex);
|
||||
int (*test_pthread_cond_init)(pthread_cond_t *__cond, const pthread_condattr_t *__attr);
|
||||
int (*test_pthread_cond_signal)(pthread_cond_t *__cond);
|
||||
int (*test_pthread_cond_timedwait)(pthread_cond_t *__cond, pthread_mutex_t *__mutex, const struct timespec *__abstime);
|
||||
int (*test_pthread_cond_wait)(pthread_cond_t *__cond, pthread_mutex_t *__mutex);
|
||||
int (*test_pthread_condattr_destroy)(pthread_condattr_t *__attr);
|
||||
int (*test_pthread_condattr_getclock)(const pthread_condattr_t *__restrict __attr, clockid_t *__restrict __clock_id);
|
||||
int (*test_pthread_condattr_init)(pthread_condattr_t *__attr);
|
||||
int (*test_pthread_condattr_setclock)(pthread_condattr_t *__attr, clockid_t __clock_id);
|
||||
int (*test_pthread_create)(pthread_t *__pthread, const pthread_attr_t *__attr, void *(*__start_routine)(void *), void *__arg);
|
||||
int (*test_pthread_detach)(pthread_t __pthread);
|
||||
int (*test_pthread_equal)(pthread_t __t1, pthread_t __t2);
|
||||
void (*test_pthread_exit)(void *__value_ptr);
|
||||
int (*test_pthread_getcpuclockid)(pthread_t thread, clockid_t *clock_id);
|
||||
int (*test_pthread_getconcurrency)(void);
|
||||
int (*test_pthread_getschedparam)(pthread_t __pthread, int *__policy, struct sched_param *__param);
|
||||
void * (*test_pthread_getspecific)(pthread_key_t __key);
|
||||
int (*test_pthread_join)(pthread_t __pthread, void **__value_ptr);
|
||||
int (*test_pthread_key_create)(pthread_key_t *__key, void (*__destructor)(void *));
|
||||
int (*test_pthread_key_delete)(pthread_key_t __key);
|
||||
int (*test_pthread_mutex_destroy)(pthread_mutex_t *__mutex);
|
||||
int (*test_pthread_mutex_getprioceiling)(const pthread_mutex_t *__restrict __mutex, int *__prioceiling);
|
||||
int (*test_pthread_mutex_init)(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__attr);
|
||||
int (*test_pthread_mutex_lock)(pthread_mutex_t *__mutex);
|
||||
int (*test_pthread_mutex_setprioceiling)(pthread_mutex_t *__mutex, int __prioceiling, int *__old_ceiling);
|
||||
int (*test_pthread_mutex_trylock)(pthread_mutex_t *__mutex);
|
||||
int (*test_pthread_mutex_unlock)(pthread_mutex_t *__mutex);
|
||||
int (*test_pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr);
|
||||
int (*test_pthread_mutexattr_getprioceiling)(const pthread_mutexattr_t *__attr, int *__prioceiling);
|
||||
int (*test_pthread_mutexattr_getprotocol)(const pthread_mutexattr_t *__attr, int *__protocol);
|
||||
int (*test_pthread_mutexattr_gettype)(const pthread_mutexattr_t *__attr, int *__kind);
|
||||
int (*test_pthread_mutexattr_init)(pthread_mutexattr_t *__attr);
|
||||
int (*test_pthread_mutexattr_setprioceiling)(const pthread_mutexattr_t *__attr, int __prioceiling);
|
||||
int (*test_pthread_mutexattr_setprotocol)(const pthread_mutexattr_t *__attr, int __protocol);
|
||||
int (*test_pthread_mutexattr_settype)(pthread_mutexattr_t *__attr, int __kind);
|
||||
int (*test_pthread_once)(pthread_once_t *__once_control, void (*__init_routine)(void));
|
||||
pthread_t (*test_pthread_self)(void);
|
||||
int (*test_pthread_setcancelstate)(int __state, int *__oldstate);
|
||||
int (*test_pthread_setcanceltype)(int __type, int *__oldtype);
|
||||
int (*test_pthread_setconcurrency)(int new_level);
|
||||
int (*test_pthread_setschedparam)(pthread_t __pthread, int __policy, const struct sched_param *__param);
|
||||
int (*test_pthread_setschedprio)(pthread_t thread, int prio);
|
||||
int (*test_pthread_setspecific)(pthread_key_t __key, const void *__value);
|
||||
void (*test_pthread_testcancel)(void);
|
||||
|
||||
|
||||
__attribute__((unused)) static void dummy_func()
|
||||
{
|
||||
test_pthread_atfork = pthread_atfork;
|
||||
test_pthread_attr_destroy = pthread_attr_destroy;
|
||||
test_pthread_attr_getdetachstate = pthread_attr_getdetachstate;
|
||||
test_pthread_attr_getguardsize = pthread_attr_getguardsize;
|
||||
test_pthread_attr_getinheritsched = pthread_attr_getinheritsched;
|
||||
test_pthread_attr_getschedparam = pthread_attr_getschedparam;
|
||||
test_pthread_attr_getschedpolicy = pthread_attr_getschedpolicy;
|
||||
test_pthread_attr_getscope = pthread_attr_getscope;
|
||||
test_pthread_attr_getstack = pthread_attr_getstack;
|
||||
test_pthread_attr_getstackaddr = pthread_attr_getstackaddr;
|
||||
test_pthread_attr_getstacksize = pthread_attr_getstacksize;
|
||||
test_pthread_attr_init = pthread_attr_init;
|
||||
test_pthread_attr_setdetachstate = pthread_attr_setdetachstate;
|
||||
test_pthread_attr_setguardsize = pthread_attr_setguardsize;
|
||||
test_pthread_attr_setinheritsched = pthread_attr_setinheritsched;
|
||||
test_pthread_attr_setschedparam = pthread_attr_setschedparam;
|
||||
test_pthread_attr_setschedpolicy = pthread_attr_setschedpolicy;
|
||||
test_pthread_attr_setscope = pthread_attr_setscope;
|
||||
test_pthread_attr_setstack = pthread_attr_setstack;
|
||||
test_pthread_attr_setstackaddr = pthread_attr_setstackaddr;
|
||||
test_pthread_attr_setstacksize = pthread_attr_setstacksize;
|
||||
test_pthread_cancel = pthread_cancel;
|
||||
test_pthread_cleanup_pop = pthread_cleanup_pop;
|
||||
test_pthread_cleanup_push = pthread_cleanup_push;
|
||||
test_pthread_cond_broadcast = pthread_cond_broadcast;
|
||||
test_pthread_cond_destroy = pthread_cond_destroy;
|
||||
test_pthread_cond_init = pthread_cond_init;
|
||||
test_pthread_cond_signal = pthread_cond_signal;
|
||||
test_pthread_cond_timedwait = pthread_cond_timedwait;
|
||||
test_pthread_cond_wait = pthread_cond_wait;
|
||||
test_pthread_condattr_destroy = pthread_condattr_destroy;
|
||||
test_pthread_condattr_getclock = pthread_condattr_getclock;
|
||||
test_pthread_condattr_init = pthread_condattr_init;
|
||||
test_pthread_condattr_setclock = pthread_condattr_setclock;
|
||||
test_pthread_create = pthread_create;
|
||||
test_pthread_detach = pthread_detach;
|
||||
test_pthread_equal = pthread_equal;
|
||||
test_pthread_exit = pthread_exit;
|
||||
test_pthread_getcpuclockid = pthread_getcpuclockid;
|
||||
test_pthread_getconcurrency = pthread_getconcurrency;
|
||||
test_pthread_getschedparam = pthread_getschedparam;
|
||||
test_pthread_getspecific = pthread_getspecific;
|
||||
test_pthread_join = pthread_join;
|
||||
test_pthread_key_create = pthread_key_create;
|
||||
test_pthread_key_delete = pthread_key_delete;
|
||||
test_pthread_mutex_destroy = pthread_mutex_destroy;
|
||||
test_pthread_mutex_getprioceiling = pthread_mutex_getprioceiling;
|
||||
test_pthread_mutex_init = pthread_mutex_init;
|
||||
test_pthread_mutex_lock = pthread_mutex_lock;
|
||||
test_pthread_mutex_setprioceiling = pthread_mutex_setprioceiling;
|
||||
test_pthread_mutex_trylock = pthread_mutex_trylock;
|
||||
test_pthread_mutex_unlock = pthread_mutex_unlock;
|
||||
test_pthread_mutexattr_destroy = pthread_mutexattr_destroy;
|
||||
test_pthread_mutexattr_getprioceiling = pthread_mutexattr_getprioceiling;
|
||||
test_pthread_mutexattr_getprotocol = pthread_mutexattr_getprotocol;
|
||||
test_pthread_mutexattr_gettype = pthread_mutexattr_gettype;
|
||||
test_pthread_mutexattr_init = pthread_mutexattr_init;
|
||||
test_pthread_mutexattr_setprioceiling = pthread_mutexattr_setprioceiling;
|
||||
test_pthread_mutexattr_setprotocol = pthread_mutexattr_setprotocol;
|
||||
test_pthread_mutexattr_settype = pthread_mutexattr_settype;
|
||||
test_pthread_once = pthread_once;
|
||||
test_pthread_self = pthread_self;
|
||||
test_pthread_setcancelstate = pthread_setcancelstate;
|
||||
test_pthread_setcanceltype = pthread_setcanceltype;
|
||||
test_pthread_setconcurrency = pthread_setconcurrency;
|
||||
test_pthread_setschedparam = pthread_setschedparam;
|
||||
test_pthread_setschedprio = pthread_setschedprio;
|
||||
test_pthread_setspecific = pthread_setspecific;
|
||||
test_pthread_testcancel = pthread_testcancel;
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: julie.n.fleischer REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
*/
|
||||
|
||||
/*
|
||||
* return codes
|
||||
*/
|
||||
|
||||
#define PTS_PASS 0
|
||||
#define PTS_FAIL 1
|
||||
#define PTS_UNRESOLVED 2
|
||||
#define PTS_UNSUPPORTED 4
|
||||
#define PTS_UNTESTED 5
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
#endif
|
||||
|
||||
#define PTS_ATTRIBUTE_NORETURN __attribute__((noreturn))
|
||||
#define PTS_ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
#define PTS_ATTRIBUTE_UNUSED_RESULT __attribute__((warn_unused_result))
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: bing.wei.liu REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_cond_broadcast()
|
||||
* When each thread unblocked as a result of pthread_cond_signal()
|
||||
* returns from its call to pthread_cond_wait(), the thread shall
|
||||
* own the mutex with which it called pthread_cond_wait().
|
||||
*/
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
#define THREAD_NUM 3
|
||||
|
||||
static struct testdata {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
} td;
|
||||
|
||||
static int start_num;
|
||||
static int waken_num;
|
||||
|
||||
static void *thr_func(void *arg PTS_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
int rc;
|
||||
pthread_t self = pthread_self();
|
||||
|
||||
if (pthread_mutex_lock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "[Thread 0x%p] failed to acquire the mutex\n",
|
||||
(void *)self);
|
||||
exit(PTS_UNRESOLVED);
|
||||
}
|
||||
fprintf(stderr, "[Thread 0x%p] started and locked the mutex\n",
|
||||
(void *)self);
|
||||
start_num++;
|
||||
|
||||
fprintf(stderr, "[Thread 0x%p] is waiting for the cond\n",
|
||||
(void *)self);
|
||||
rc = pthread_cond_wait(&td.cond, &td.mutex);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "pthread_cond_wait return %d\n", rc);
|
||||
exit(PTS_UNRESOLVED);
|
||||
}
|
||||
|
||||
if (pthread_mutex_trylock(&td.mutex) == 0) {
|
||||
fprintf(stderr, "[Thread 0x%p] should not be able to lock the "
|
||||
"mutex again\n", (void *)self);
|
||||
printf("Test FAILED\n");
|
||||
exit(PTS_FAIL);
|
||||
}
|
||||
fprintf(stderr, "[Thread 0x%p] was wakened and acquired the "
|
||||
"mutex again\n", (void *)self);
|
||||
waken_num++;
|
||||
|
||||
if (pthread_mutex_unlock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "[Thread 0x%p] failed to release the "
|
||||
"mutex\n", (void *)self);
|
||||
printf("Test FAILED\n");
|
||||
exit(PTS_FAIL);
|
||||
}
|
||||
fprintf(stderr, "[Thread 0x%p] released the mutex\n", (void *)self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
struct timespec completion_wait_ts = {0, 100000};
|
||||
int i, rc;
|
||||
pthread_t thread[THREAD_NUM];
|
||||
|
||||
if (pthread_mutex_init(&td.mutex, NULL) != 0) {
|
||||
fprintf(stderr, "Fail to initialize mutex\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
if (pthread_cond_init(&td.cond, NULL) != 0) {
|
||||
fprintf(stderr, "Fail to initialize cond\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
for (i = 0; i < THREAD_NUM; i++) {
|
||||
if (pthread_create(&thread[i], NULL, thr_func, NULL) != 0) {
|
||||
fprintf(stderr, "Fail to create thread[%d]\n", i);
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
}
|
||||
while (start_num < THREAD_NUM)
|
||||
nanosleep(&completion_wait_ts, NULL);
|
||||
|
||||
/* Acquire the mutex to make sure that all waiters are currently
|
||||
blocked on pthread_cond_wait */
|
||||
if (pthread_mutex_lock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "Main: Fail to acquire mutex\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
if (pthread_mutex_unlock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "Main: Fail to release mutex\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* broadcast the condition to wake up all waiters */
|
||||
fprintf(stderr, "[Main thread] broadcast the condition\n");
|
||||
rc = pthread_cond_broadcast(&td.cond);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "[Main thread] failed to broadcast the "
|
||||
"condition\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
sleep(1);
|
||||
if (waken_num < THREAD_NUM) {
|
||||
fprintf(stderr, "[Main thread] Not all waiters were wakened\n");
|
||||
for (i = 0; i < THREAD_NUM; i++)
|
||||
pthread_cancel(thread[i]);
|
||||
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
fprintf(stderr, "[Main thread] all waiters were wakened\n");
|
||||
|
||||
/* join all secondary threads */
|
||||
for (i = 0; i < THREAD_NUM; i++) {
|
||||
if (pthread_join(thread[i], NULL) != 0) {
|
||||
fprintf(stderr, "Fail to join thread[%d]\n", i);
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
}
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_cond_broadcast.2-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: bing.wei.liu REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_cond_destroy()
|
||||
* shall destroy the condition variable referenced by 'cond';
|
||||
* the condition variable object in effect becomes uninitialized.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
static pthread_cond_t cond1, cond2;
|
||||
static pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_condattr_t condattr;
|
||||
int rc;
|
||||
|
||||
/* Initialize a condition variable attribute object */
|
||||
if ((rc = pthread_condattr_init(&condattr)) != 0) {
|
||||
fprintf(stderr, "Error at pthread_condattr_init(), rc=%d\n",
|
||||
rc);
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
printf("Line-%04d\n", __LINE__);
|
||||
|
||||
/* Initialize cond1 with the default condition variable attribute */
|
||||
if ((rc = pthread_cond_init(&cond1, &condattr)) != 0) {
|
||||
fprintf(stderr, "Fail to initialize cond1, rc=%d\n", rc);
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
printf("Line-%04d\n", __LINE__);
|
||||
/* Initialize cond2 with NULL attributes */
|
||||
if ((rc = pthread_cond_init(&cond2, NULL)) != 0) {
|
||||
fprintf(stderr, "Fail to initialize cond2, rc=%d\n", rc);
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
printf("Line-%04d\n", __LINE__);
|
||||
/* Destroy the condition variable attribute object */
|
||||
if ((rc = pthread_condattr_destroy(&condattr)) != 0) {
|
||||
fprintf(stderr, "Error at pthread_condattr_destroy(), rc=%d\n",
|
||||
rc);
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
printf("Line-%04d\n", __LINE__);
|
||||
/* Destroy cond1 */
|
||||
if ((rc = pthread_cond_destroy(&cond1)) != 0) {
|
||||
fprintf(stderr, "Fail to destroy cond1, rc=%d\n", rc);
|
||||
printf("Test FAILED\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
printf("Line-%04d\n", __LINE__);
|
||||
/* Destroy cond2 */
|
||||
if ((rc = pthread_cond_destroy(&cond2)) != 0) {
|
||||
fprintf(stderr, "Fail to destroy cond2, rc=%d\n", rc);
|
||||
printf("Test FAILED\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
printf("Line-%04d", __LINE__);
|
||||
/* Destroy cond3 */
|
||||
if ((rc = pthread_cond_destroy(&cond3)) != 0) {
|
||||
fprintf(stderr, "Fail to destroy cond3, rc=%d\n", rc);
|
||||
printf("Test FAILED\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
printf("Line-%04d", __LINE__);
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_cond_destroy.1-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: bing.wei.liu REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_cond_init()
|
||||
* shall initialize the condition variable referenced by cond with attributes
|
||||
* referenced by attr. If attr is NULL, the default condition variable
|
||||
* attributes shall be used; the effect is the same as passing the address
|
||||
* of a default condition variable attributes object.
|
||||
|
||||
* NOTE: There is no direct way to judge if two condition variables are equal,
|
||||
* so this test does not cover the statement in the last sentence.
|
||||
*
|
||||
*
|
||||
* Modified - LK coding style 30/05/2011
|
||||
* Peter W. Morreale <pmorreale AT novell DOT com>
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
#define ERR_MSG(f, rc) printf("Failed: func: %s rc: %s (%u)\n", \
|
||||
f, strerror(rc), rc);
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_condattr_t condattr;
|
||||
pthread_cond_t cond1;
|
||||
pthread_cond_t cond2;
|
||||
int rc;
|
||||
char *f;
|
||||
int status = PTS_UNRESOLVED;
|
||||
|
||||
f = "pthread_condattr_init()";
|
||||
rc = pthread_condattr_init(&condattr);
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
status = PTS_FAIL;
|
||||
f = "pthread_cond_init() - condattr";
|
||||
rc = pthread_cond_init(&cond1, &condattr);
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
f = "pthread_cond_init() - NULL";
|
||||
rc = pthread_cond_init(&cond2, NULL);
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
|
||||
done:
|
||||
ERR_MSG(f, rc);
|
||||
return status;
|
||||
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_cond_init.1-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: bing.wei.liu REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_cond_timedwait()
|
||||
* shall be equivalent to pthread_cond_wait(), except that an error is returned
|
||||
* if the absolute time specified by abstime passes before the condition cond is
|
||||
* signaled or broadcasted, or if the absolute time specified by abstime has
|
||||
* already been passed at the time of the call.
|
||||
*
|
||||
* Case 2-1
|
||||
* Upon successful return, the mutex shall have been locked and shall
|
||||
* be owned by the calling thread.
|
||||
*/
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
#define INTERVAL 1
|
||||
#define TIMEOUT 5
|
||||
|
||||
static struct testdata {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
} td;
|
||||
|
||||
static int t1_start = 0;
|
||||
static int signaled = 0;
|
||||
|
||||
static void *t1_func(void *arg)
|
||||
{
|
||||
int rc;
|
||||
struct timespec timeout;
|
||||
struct timeval curtime;
|
||||
|
||||
(void) arg;
|
||||
|
||||
if (pthread_mutex_lock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "Thread1 failed to acquire the mutex\n");
|
||||
exit(PTS_UNRESOLVED);
|
||||
}
|
||||
fprintf(stderr, "Thread1 started\n");
|
||||
t1_start = 1; /* let main thread continue */
|
||||
|
||||
if (gettimeofday(&curtime, NULL) != 0) {
|
||||
fprintf(stderr, "Fail to get current time\n");
|
||||
exit(PTS_UNRESOLVED);
|
||||
}
|
||||
timeout.tv_sec = curtime.tv_sec + TIMEOUT;
|
||||
timeout.tv_nsec = curtime.tv_usec * 1000;
|
||||
|
||||
fprintf(stderr, "Thread1 is waiting for the cond\n");
|
||||
rc = pthread_cond_timedwait(&td.cond, &td.mutex, &timeout);
|
||||
if (rc != 0) {
|
||||
if (rc == ETIMEDOUT) {
|
||||
fprintf(stderr,
|
||||
"Thread1 stops waiting when time is out\n");
|
||||
exit(PTS_UNRESOLVED);
|
||||
} else {
|
||||
fprintf(stderr, "pthread_cond_timedwait return %d\n",
|
||||
rc);
|
||||
exit(PTS_UNRESOLVED);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Thread1 wakened\n");
|
||||
if (signaled == 0) {
|
||||
fprintf(stderr, "Thread1 did not block on the cond at all\n");
|
||||
exit(PTS_UNRESOLVED);
|
||||
}
|
||||
|
||||
if (pthread_mutex_trylock(&td.mutex) == 0) {
|
||||
fprintf(stderr,
|
||||
"Thread1 should not be able to lock the mutex again\n");
|
||||
printf("Test FAILED\n");
|
||||
exit(PTS_FAIL);
|
||||
}
|
||||
fprintf(stderr, "Thread1 failed to trylock the mutex (as expected)\n");
|
||||
|
||||
if (pthread_mutex_unlock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "Thread1 failed to release the mutex\n");
|
||||
printf("Test FAILED\n");
|
||||
exit(PTS_FAIL);
|
||||
}
|
||||
fprintf(stderr, "Thread1 released the mutex\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_t thread1;
|
||||
struct timespec thread_start_ts = {0, 100000};
|
||||
|
||||
if (pthread_mutex_init(&td.mutex, NULL) != 0) {
|
||||
fprintf(stderr, "Fail to initialize mutex\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
if (pthread_cond_init(&td.cond, NULL) != 0) {
|
||||
fprintf(stderr, "Fail to initialize cond\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
if (pthread_create(&thread1, NULL, t1_func, NULL) != 0) {
|
||||
fprintf(stderr, "Fail to create thread 1\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
while (!t1_start) /* wait for thread1 started */
|
||||
nanosleep(&thread_start_ts, NULL);
|
||||
|
||||
/* acquire the mutex released by pthread_cond_wait() within thread 1 */
|
||||
if (pthread_mutex_lock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "Main failed to acquire mutex\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
if (pthread_mutex_unlock(&td.mutex) != 0) {
|
||||
fprintf(stderr, "Main failed to release mutex\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
sleep(INTERVAL);
|
||||
|
||||
fprintf(stderr, "Time to wake up thread1 by signaling a condition\n");
|
||||
signaled = 1;
|
||||
if (pthread_cond_signal(&td.cond) != 0) {
|
||||
fprintf(stderr, "Main failed to signal the condition\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
pthread_join(thread1, NULL);
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_cond_timedwait.2-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_create() creates a new thread with attributes specified
|
||||
* by 'attr', within a process.
|
||||
*
|
||||
* Steps:
|
||||
* 1. Create a thread using pthread_create()
|
||||
* 2. Cancel that thread with pthread_cancel()
|
||||
* 3. If that thread doesn't exist, then it pthread_cancel() will return
|
||||
* an error code. This would mean that pthread_create() did not create
|
||||
* a thread successfully.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
static void *a_thread_func()
|
||||
{
|
||||
sleep(10);
|
||||
|
||||
/* Shouldn't reach here. If we do, then the pthread_cancel()
|
||||
* function did not succeed. */
|
||||
fprintf(stderr, "Could not send cancel request correctly\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_t new_th;
|
||||
int ret;
|
||||
|
||||
ret = pthread_create(&new_th, NULL, a_thread_func, NULL);
|
||||
if (ret) {
|
||||
fprintf(stderr, "pthread_create(): %s\n", strerror(ret));
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Try to cancel the newly created thread. If an error is returned,
|
||||
* then the thread wasn't created successfully. */
|
||||
ret = pthread_cancel(new_th);
|
||||
if (ret) {
|
||||
printf("Test FAILED: A new thread wasn't created: %s\n",
|
||||
strerror(ret));
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_create.1-2.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_detach()
|
||||
*
|
||||
* shall detach a thread. It shall indicate to the implementation that storage
|
||||
* for 'thread' can be reclaimed when that thread terminates.
|
||||
*
|
||||
* STEPS:
|
||||
* 1. Create a joinable thread
|
||||
* 2. Detach that thread with pthread_detach()
|
||||
* 3. Try and join the thread to main() using pthread_join()
|
||||
* 4. An error should return from the pthread_join() function saying that the
|
||||
* thread is detched. The test passes.
|
||||
* 5. Else, if pthread_join is successful, the test fails.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
static void *a_thread_func()
|
||||
{
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
|
||||
/* If the thread wasn't canceled in 10 seconds, time out */
|
||||
sleep(10);
|
||||
|
||||
perror("Thread couldn't be canceled (at cleanup time), timing out\n");
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_attr_t new_attr;
|
||||
pthread_t new_th;
|
||||
int ret;
|
||||
|
||||
/* Initialize attribute */
|
||||
if (pthread_attr_init(&new_attr) != 0) {
|
||||
perror("Cannot initialize attribute object\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Set the attribute object to be joinable */
|
||||
if (pthread_attr_setdetachstate(&new_attr, PTHREAD_CREATE_JOINABLE) !=
|
||||
0) {
|
||||
perror("Error in pthread_attr_setdetachstate()\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Create the thread */
|
||||
if (pthread_create(&new_th, &new_attr, a_thread_func, NULL) != 0) {
|
||||
perror("Error creating thread\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Detach the thread. */
|
||||
if (pthread_detach(new_th) != 0) {
|
||||
printf("Error detaching thread\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
/* Now try and join it. This should fail. */
|
||||
ret = pthread_join(new_th, NULL);
|
||||
|
||||
/* Cleanup: Cancel the thread */
|
||||
pthread_cancel(new_th);
|
||||
|
||||
if (ret == 0) {
|
||||
printf("Test FAILED\n");
|
||||
return PTS_FAIL;
|
||||
} else if (ret == EINVAL) {
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
} else {
|
||||
perror("Error in pthread_join\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_detach.1-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_detach()
|
||||
*
|
||||
* If 'thread' has not terminated, pthread_detach() shall not cause it to
|
||||
* terminate. The effect of multiple pthread_detach() calls on the same
|
||||
*
|
||||
* STEPS:
|
||||
* 1.Create a joinable thread
|
||||
* 2.Detach that thread
|
||||
* 3.Verify that the thread did not terminate because of this
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
static void *a_thread_func()
|
||||
{
|
||||
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
|
||||
/* If the thread wasn't canceled in 10 seconds, time out */
|
||||
sleep(10);
|
||||
|
||||
perror("Thread couldn't be canceled (at cleanup time), timing out\n");
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_attr_t new_attr;
|
||||
pthread_t new_th;
|
||||
int ret;
|
||||
|
||||
/* Initialize attribute */
|
||||
if (pthread_attr_init(&new_attr) != 0) {
|
||||
perror("Cannot initialize attribute object\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Set the attribute object to be joinable */
|
||||
if (pthread_attr_setdetachstate(&new_attr, PTHREAD_CREATE_JOINABLE) !=
|
||||
0) {
|
||||
perror("Error in pthread_attr_setdetachstate()\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Create the thread */
|
||||
if (pthread_create(&new_th, &new_attr, a_thread_func, NULL) != 0) {
|
||||
perror("Error creating thread\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Detach the thread. */
|
||||
if (pthread_detach(new_th) != 0) {
|
||||
printf("Error detaching thread\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
/* Verify that it hasn't terminated the thread */
|
||||
ret = pthread_cancel(new_th);
|
||||
|
||||
if (ret != 0) {
|
||||
if (ret == ESRCH) {
|
||||
printf("Test FAILED\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
perror("Error canceling thread\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_detach.2-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_detach()
|
||||
*
|
||||
* Upon failure, it shall return an error number:
|
||||
* -[EINVAL] The implemenation has detected that the value specified by
|
||||
* 'thread' does not refer to a joinable thread.
|
||||
* -[ESRCH] No thread could be found corresponding to that thread
|
||||
|
||||
* It shall not return an error code of [EINTR]
|
||||
*
|
||||
* STEPS:
|
||||
* 1.Create a detached state thread
|
||||
* 2.Detach that thread
|
||||
* 3.Check the return value and make sure it is EINVAL
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
/* Thread function */
|
||||
static void *a_thread_func()
|
||||
{
|
||||
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
|
||||
/* If the thread wasn't canceled in 10 seconds, time out */
|
||||
sleep(10);
|
||||
|
||||
perror("Thread couldn't be canceled (at cleanup time), timing out\n");
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_attr_t new_attr;
|
||||
pthread_t new_th;
|
||||
int ret;
|
||||
|
||||
/* Initialize attribute */
|
||||
if (pthread_attr_init(&new_attr) != 0) {
|
||||
perror("Cannot initialize attribute object\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Set the attribute object to be detached */
|
||||
if (pthread_attr_setdetachstate(&new_attr, PTHREAD_CREATE_DETACHED) !=
|
||||
0) {
|
||||
perror("Error in pthread_attr_setdetachstate()\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Create the thread */
|
||||
if (pthread_create(&new_th, &new_attr, a_thread_func, NULL) != 0) {
|
||||
perror("Error creating thread\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Detach the thread. */
|
||||
ret = pthread_detach(new_th);
|
||||
|
||||
/* Cleanup and cancel the thread */
|
||||
pthread_cancel(new_th);
|
||||
|
||||
/* Check return value of pthread_detach() */
|
||||
if (ret != EINVAL) {
|
||||
if (ret == ESRCH) {
|
||||
perror("Error detaching thread\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
printf("Test FAILED: Incorrect return code\n");
|
||||
return PTS_FAIL;
|
||||
|
||||
}
|
||||
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_detach.4-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
|
||||
* Test that pthread_exit()
|
||||
*
|
||||
* terminates the calling thread and makes the value 'value_ptr' available
|
||||
* to any successful join with the terminating thread.
|
||||
*
|
||||
* Steps:
|
||||
* 1. Create a new thread. Have it return a return code on pthread_exit();
|
||||
* 2. Call pthread_join() in main(), and pass to it 'value_ptr'.
|
||||
* 3. Check to see of the value_ptr and the value returned by pthread_exit() are the same;
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
#define RETURN_CODE 100 /* Set a random return code number. This shall be the return code of the
|
||||
thread when using pthread_exit(). */
|
||||
|
||||
#define INTHREAD 0 /* Control going to or is already for Thread */
|
||||
#define INMAIN 1 /* Control going to or is already for Main */
|
||||
|
||||
static int sem; /* Manual semaphore used to indicate when the thread has been created. */
|
||||
|
||||
/* Thread's function. */
|
||||
static void *a_thread_func()
|
||||
{
|
||||
sem = INMAIN;
|
||||
pthread_exit((void *)RETURN_CODE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_t new_th;
|
||||
int *value_ptr;
|
||||
|
||||
/* Initializing variables. */
|
||||
value_ptr = 0;
|
||||
sem = INTHREAD;
|
||||
|
||||
/* Create a new thread. */
|
||||
if (pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) {
|
||||
perror("Error creating thread\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Make sure the thread was created before we join it. */
|
||||
while (sem == INTHREAD)
|
||||
sleep(1);
|
||||
|
||||
/* Wait for thread to return */
|
||||
if (pthread_join(new_th, (void *)&value_ptr) != 0) {
|
||||
perror("Error in pthread_join()\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Check to make sure that 'value_ptr' that was passed to pthread_join() and the
|
||||
* pthread_exit() return code that was used in the thread function are the same. */
|
||||
if ((long)value_ptr != RETURN_CODE) {
|
||||
printf
|
||||
("Test FAILED: pthread_exit() could not pass the return value of the thread in 'value_ptr' to pthread_join().\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_exit.1-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2002, Intel Corporation. All rights reserved.
|
||||
* Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
*
|
||||
* Test that pthread_join()
|
||||
*
|
||||
* shall suspend the execution of the calling thread until the target
|
||||
* 'thread' terminates, unless 'thread' has already terminated.
|
||||
*
|
||||
* Steps:
|
||||
* 1. Create a new thread. Have it sleep for 3 seconds.
|
||||
* 2. The main() thread should wait for the new thread to finish
|
||||
* execution before exiting out.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "posixtest.h"
|
||||
|
||||
static int end_exec;
|
||||
|
||||
static void *a_thread_func()
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Wait for 3 seconds for thread to finish execution:\n");
|
||||
for (i = 1; i < 4; i++) {
|
||||
printf("Waited (%d) second\n", i);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* Indicate that the thread has ended execution. */
|
||||
end_exec = 1;
|
||||
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int posix_testcase(void)
|
||||
{
|
||||
pthread_t new_th;
|
||||
|
||||
/* Initialize flag */
|
||||
end_exec = 0;
|
||||
|
||||
/* Create a new thread. */
|
||||
if (pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) {
|
||||
perror("Error creating thread\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
/* Wait for thread to return */
|
||||
if (pthread_join(new_th, NULL) != 0) {
|
||||
perror("Error in pthread_join()\n");
|
||||
return PTS_UNRESOLVED;
|
||||
}
|
||||
|
||||
if (end_exec == 0) {
|
||||
printf("Test FAILED: When using pthread_join(), "
|
||||
"main() did not wait for thread to finish "
|
||||
"execution before continuing.\n");
|
||||
return PTS_FAIL;
|
||||
}
|
||||
|
||||
printf("Test PASSED\n");
|
||||
return PTS_PASS;
|
||||
}
|
||||
#include <rtt_utest_internal.h>
|
||||
UTEST_TC_EXPORT(testcase, "posix.pthread_join.1-1.c", RT_NULL, RT_NULL, 10);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <utest.h>
|
||||
#include <pthread.h>
|
||||
static void posix_unit_test(void)
|
||||
{
|
||||
pthread_t new_th; /* Create a new thread. */
|
||||
int err_val;
|
||||
|
||||
if (pthread_create(&new_th, NULL, (void *(*)(void *))posix_testcase, NULL) != 0) {
|
||||
perror("Error creating thread\n");
|
||||
}
|
||||
|
||||
/* Wait for thread to return */
|
||||
if (pthread_join(new_th, (void*)&err_val) != 0) {
|
||||
perror("Error in pthread_join()\n");
|
||||
}
|
||||
|
||||
rt_thread_mdelay(1000);
|
||||
|
||||
uassert_true(err_val == 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(posix_unit_test);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Bull S.A.. All rights reserved.
|
||||
* Created by: Sebastien Decugis
|
||||
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
|
||||
* This file is a wrapper to use the tests from the NPTL Test & Trace Project
|
||||
* with either the Linux Test Project or the Open POSIX Test Suite.
|
||||
|
||||
* The following function are defined:
|
||||
* void output_init()
|
||||
* void output_fini()
|
||||
* void output(char * string, ...)
|
||||
*
|
||||
* The are used to output informative text (as a printf).
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* We use a mutex to avoid conflicts in traces */
|
||||
static pthread_mutex_t m_trace = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void output_init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void output(char *string, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct tm *now;
|
||||
time_t nw;
|
||||
int oldstate;
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
|
||||
pthread_mutex_lock(&m_trace);
|
||||
nw = time(NULL);
|
||||
now = localtime(&nw);
|
||||
if (now == NULL)
|
||||
printf("[??:??:??]\n");
|
||||
else
|
||||
printf("[%2.2d:%2.2d:%2.2d]\n",
|
||||
now->tm_hour, now->tm_min, now->tm_sec);
|
||||
va_start(ap, string);
|
||||
vprintf(string, ap);
|
||||
va_end(ap);
|
||||
pthread_mutex_unlock(&m_trace);
|
||||
pthread_setcancelstate(oldstate, NULL);
|
||||
}
|
||||
|
||||
static void output_fini(void)
|
||||
{
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Bull S.A.. All rights reserved.
|
||||
* Created by: Sebastien Decugis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* This file is a wrapper to use the tests from the NPTL Test & Trace Project
|
||||
* with either the Linux Test Project or the Open POSIX Test Suite.
|
||||
*
|
||||
* The following macros are defined here:
|
||||
* UNRESOLVED(ret, descr);
|
||||
* where descr is a description of the error and ret is
|
||||
* an int (error code for example)
|
||||
* FAILED(descr);
|
||||
* where descr is a short text saying why the test has failed.
|
||||
* PASSED();
|
||||
* No parameter.
|
||||
*
|
||||
* Both three macros shall terminate the calling process.
|
||||
* The testcase shall not terminate without calling one of those macros.
|
||||
*/
|
||||
|
||||
#include "posixtest.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define UNRESOLVED(x, s) \
|
||||
{ \
|
||||
output("Test %s unresolved: got %i (%s) on line %i (%s)\n", \
|
||||
__FILE__, x, strerror(x), __LINE__, s); \
|
||||
output_fini(); \
|
||||
exit(PTS_UNRESOLVED); \
|
||||
}
|
||||
|
||||
#define FAILED(s) \
|
||||
{ \
|
||||
output("Test %s FAILED: %s\n", __FILE__, s); \
|
||||
output_fini(); \
|
||||
exit(PTS_FAIL); \
|
||||
}
|
||||
|
||||
#define PASSED \
|
||||
{ \
|
||||
output_fini(); \
|
||||
exit(PTS_PASS); \
|
||||
}
|
||||
|
||||
#define UNTESTED(s) \
|
||||
{ \
|
||||
output("File %s cannot test: %s\n", __FILE__, s); \
|
||||
output_fini(); \
|
||||
exit(PTS_UNTESTED); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define UNRESOLVED(x, s) \
|
||||
{ \
|
||||
output("Test unresolved: got %i (%s) on line %i (%s)\n", \
|
||||
x, strerror(x), __LINE__, s); \
|
||||
output_fini(); \
|
||||
exit(PTS_UNRESOLVED); \
|
||||
}
|
||||
|
||||
#define FAILED(s) \
|
||||
{ \
|
||||
output("Test FAILED: %s\n", s); \
|
||||
output_fini(); \
|
||||
exit(PTS_FAIL); \
|
||||
}
|
||||
|
||||
#define PASSED \
|
||||
{ \
|
||||
output_fini(); \
|
||||
exit(PTS_PASS); \
|
||||
}
|
||||
|
||||
#define UNTESTED(s) \
|
||||
{ \
|
||||
output("Unable to test: %s\n", s); \
|
||||
output_fini(); \
|
||||
exit(PTS_UNTESTED); \
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,555 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Bull S.A.. All rights reserved.
|
||||
* Created by: Sebastien Decugis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* This file is a helper file for the pthread_create tests
|
||||
* It defines the following objects:
|
||||
* scenarii: array of struct __scenario type.
|
||||
* NSCENAR : macro giving the total # of scenarii
|
||||
* scenar_init(): function to call before use the scenarii array.
|
||||
* scenar_fini(): function to call after end of use of the scenarii array.
|
||||
*/
|
||||
|
||||
static struct __scenario {
|
||||
/*
|
||||
* Object to hold the given configuration,
|
||||
* and which will be used to create the threads
|
||||
*/
|
||||
pthread_attr_t ta;
|
||||
|
||||
/* General parameters */
|
||||
/* 0 => joinable; 1 => detached */
|
||||
int detached;
|
||||
|
||||
/* Scheduling parameters */
|
||||
/*
|
||||
* 0 => sched policy is inherited;
|
||||
* 1 => sched policy from the attr param
|
||||
*/
|
||||
int explicitsched;
|
||||
/* 0 => default; 1=> SCHED_FIFO; 2=> SCHED_RR */
|
||||
int schedpolicy;
|
||||
/*
|
||||
* 0 => default sched param;
|
||||
* 1 => max value for sched param;
|
||||
* -1 => min value for sched param
|
||||
*/
|
||||
int schedparam;
|
||||
/*
|
||||
* 0 => default contension scope;
|
||||
* 1 => alternative contension scope
|
||||
*/
|
||||
int altscope;
|
||||
|
||||
/* Stack parameters */
|
||||
/* 0 => system manages the stack; 1 => stack is provided */
|
||||
int altstack;
|
||||
/*
|
||||
* 0 => default guardsize;
|
||||
* 1=> guardsize is 0;
|
||||
* 2=> guard is 1 page
|
||||
* -- this setting only affect system stacks (not user's).
|
||||
*/
|
||||
int guard;
|
||||
/*
|
||||
* 0 => default stack size;
|
||||
* 1 => stack size specified (min value)
|
||||
* -- ignored when stack is provided
|
||||
*/
|
||||
int altsize;
|
||||
|
||||
/* Additionnal information */
|
||||
/* object description */
|
||||
char *descr;
|
||||
/* Stores the stack start when an alternate stack is required */
|
||||
void *bottom;
|
||||
/*
|
||||
* This thread creation is expected to:
|
||||
* 0 => succeed; 1 => fail; 2 => unknown
|
||||
*/
|
||||
int result;
|
||||
/*
|
||||
* This semaphore is used to signal the end of
|
||||
* the detached threads execution
|
||||
*/
|
||||
sem_t sem;
|
||||
} scenarii[] =
|
||||
#define CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, res) \
|
||||
{ \
|
||||
.detached = det, \
|
||||
.explicitsched = expl, \
|
||||
.schedpolicy = scp, \
|
||||
.schedparam = spa, \
|
||||
.altscope = sco, \
|
||||
.altstack = sta, \
|
||||
.guard = gua, \
|
||||
.altsize = ssi, \
|
||||
.descr = desc, \
|
||||
.bottom = NULL, \
|
||||
.result = res \
|
||||
}
|
||||
#define CASE_POS(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
|
||||
CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 0)
|
||||
#define CASE_NEG(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
|
||||
CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 1)
|
||||
#define CASE_UNK(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
|
||||
CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 2)
|
||||
/*
|
||||
* This array gives the different combinations of threads
|
||||
* attributes for the testcases.
|
||||
*
|
||||
* Some combinations must be avoided.
|
||||
* -> Do not have a detached thread use an alternative stack;
|
||||
* as we don't know when the thread terminates to free the stack memory
|
||||
* -> ... (to be completed)
|
||||
*/
|
||||
{
|
||||
/* Unary tests */
|
||||
CASE_POS(0, 0, 0, 0, 0, 0, 0, 0, "default"),
|
||||
CASE_POS(1, 0, 0, 0, 0, 0, 0, 0, "detached"),
|
||||
CASE_POS(0, 1, 0, 0, 0, 0, 0, 0, "Explicit sched"),
|
||||
CASE_UNK(0, 0, 1, 0, 0, 0, 0, 0, "FIFO Policy"),
|
||||
CASE_UNK(0, 0, 2, 0, 0, 0, 0, 0, "RR Policy"),
|
||||
CASE_UNK(0, 0, 0, 1, 0, 0, 0, 0, "Max sched param"),
|
||||
CASE_UNK(0, 0, 0, -1, 0, 0, 0, 0, "Min sched param"),
|
||||
CASE_POS(0, 0, 0, 0, 1, 0, 0, 0, "Alternative contension scope"),
|
||||
CASE_POS(0, 0, 0, 0, 0, 1, 0, 0, "Alternative stack"),
|
||||
CASE_POS(0, 0, 0, 0, 0, 0, 1, 0, "No guard size"),
|
||||
CASE_UNK(0, 0, 0, 0, 0, 0, 2, 0, "1p guard size"),
|
||||
CASE_POS(0, 0, 0, 0, 0, 0, 0, 1, "Min stack size"),
|
||||
/* Stack play */
|
||||
CASE_POS(0, 0, 0, 0, 0, 0, 1, 1, "Min stack size, no guard"),
|
||||
CASE_UNK(0, 0, 0, 0, 0, 0, 2, 1, "Min stack size, 1p guard"),
|
||||
CASE_POS(1, 0, 0, 0, 0, 1, 0, 0, "Detached, Alternative stack"),
|
||||
CASE_POS(1, 0, 0, 0, 0, 0, 1, 1,
|
||||
"Detached, Min stack size, no guard"), CASE_UNK(1, 0, 0, 0,
|
||||
0, 0, 2, 1,
|
||||
"Detached, Min stack size, 1p guard"),
|
||||
/*
|
||||
* Scheduling play
|
||||
* -- all results are unknown since it might depend on
|
||||
* the user priviledges
|
||||
*/
|
||||
CASE_UNK(0, 1, 1, 1, 0, 0, 0, 0, "Explicit FIFO max param"),
|
||||
CASE_UNK(0, 1, 2, 1, 0, 0, 0, 0,
|
||||
"Explicit RR max param"),
|
||||
CASE_UNK(0, 1, 1, -1, 0, 0, 0, 0,
|
||||
"Explicit FIFO min param"),
|
||||
CASE_UNK(0, 1, 2, -1, 0, 0, 0, 0,
|
||||
"Explicit RR min param"),
|
||||
CASE_UNK(0, 1, 1, 1, 1, 0, 0, 0,
|
||||
"Explicit FIFO max param, alt scope"),
|
||||
CASE_UNK(0, 1, 2, 1, 1, 0, 0, 0,
|
||||
"Explicit RR max param, alt scope"),
|
||||
CASE_UNK(0, 1, 1, -1, 1, 0, 0, 0,
|
||||
"Explicit FIFO min param, alt scope"),
|
||||
CASE_UNK(0, 1, 2, -1, 1, 0, 0, 0,
|
||||
"Explicit RR min param, alt scope"),
|
||||
CASE_UNK(1, 1, 1, 1, 0, 0, 0, 0,
|
||||
"Detached, explicit FIFO max param"),
|
||||
CASE_UNK(1, 1, 2, 1, 0, 0, 0, 0,
|
||||
"Detached, explicit RR max param"),
|
||||
CASE_UNK(1, 1, 1, -1, 0, 0, 0, 0,
|
||||
"Detached, explicit FIFO min param"),
|
||||
CASE_UNK(1, 1, 2, -1, 0, 0, 0, 0,
|
||||
"Detached, explicit RR min param"),
|
||||
CASE_UNK(1, 1, 1, 1, 1, 0, 0, 0,
|
||||
"Detached, explicit FIFO max param,"
|
||||
" alt scope"), CASE_UNK(1, 1, 2, 1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"Detached, explicit RR max param,"
|
||||
" alt scope"),
|
||||
CASE_UNK(1, 1, 1, -1, 1, 0, 0, 0,
|
||||
"Detached, explicit FIFO min param,"
|
||||
" alt scope"), CASE_UNK(1, 1, 2,
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"Detached, explicit RR min param,"
|
||||
" alt scope"),};
|
||||
|
||||
#define NSCENAR (sizeof(scenarii) / sizeof(scenarii[0]))
|
||||
|
||||
/*
|
||||
* This function will initialize every pthread_attr_t object
|
||||
* in the scenarii array
|
||||
*/
|
||||
static void scenar_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int i;
|
||||
int old;
|
||||
long pagesize, minstacksize;
|
||||
long tsa, tss, tps;
|
||||
|
||||
pagesize = sysconf(_SC_PAGESIZE);
|
||||
minstacksize = sysconf(_SC_THREAD_STACK_MIN);
|
||||
tsa = sysconf(_SC_THREAD_ATTR_STACKADDR);
|
||||
tss = sysconf(_SC_THREAD_ATTR_STACKSIZE);
|
||||
tps = sysconf(_SC_THREAD_PRIORITY_SCHEDULING);
|
||||
|
||||
#if VERBOSE > 0
|
||||
output("System abilities:\n");
|
||||
output(" TSA: %li\n", tsa);
|
||||
output(" TSS: %li\n", tss);
|
||||
output(" TPS: %li\n", tps);
|
||||
output(" pagesize: %li\n", pagesize);
|
||||
output(" min stack size: %li\n", minstacksize);
|
||||
#endif
|
||||
|
||||
if (minstacksize % pagesize)
|
||||
UNTESTED("The min stack size is not a multiple"
|
||||
" of the page size");
|
||||
|
||||
for (i = 0; i < NSCENAR; i++) {
|
||||
#if VERBOSE > 2
|
||||
output("Initializing attribute for scenario %i: %s\n",
|
||||
i, scenarii[i].descr);
|
||||
#endif
|
||||
|
||||
ret = pthread_attr_init(&scenarii[i].ta);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Failed to initialize a"
|
||||
" thread attribute object");
|
||||
|
||||
/* Set the attributes according to the scenario */
|
||||
if (scenarii[i].detached == 1) {
|
||||
ret = pthread_attr_setdetachstate(&scenarii[i].ta,
|
||||
PTHREAD_CREATE_DETACHED);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to set detachstate");
|
||||
} else {
|
||||
ret =
|
||||
pthread_attr_getdetachstate(&scenarii[i].ta, &old);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to get detachstate"
|
||||
" from initialized attribute");
|
||||
if (old != PTHREAD_CREATE_JOINABLE)
|
||||
FAILED("The default attribute is not"
|
||||
" PTHREAD_CREATE_JOINABLE");
|
||||
}
|
||||
#if VERBOSE > 4
|
||||
output("Detach state was set successfully\n");
|
||||
#endif
|
||||
|
||||
/* Sched related attributes */
|
||||
/*
|
||||
* This routine is dependent on the Thread Execution
|
||||
* Scheduling option
|
||||
*/
|
||||
if (tps > 0) {
|
||||
if (scenarii[i].explicitsched == 1)
|
||||
ret =
|
||||
pthread_attr_setinheritsched(&scenarii
|
||||
[i].ta,
|
||||
PTHREAD_EXPLICIT_SCHED);
|
||||
else
|
||||
ret =
|
||||
pthread_attr_setinheritsched(&scenarii
|
||||
[i].ta,
|
||||
PTHREAD_INHERIT_SCHED);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to set inheritsched"
|
||||
" attribute");
|
||||
#if VERBOSE > 4
|
||||
output("inheritsched state was set successfully\n");
|
||||
#endif
|
||||
}
|
||||
#if VERBOSE > 4
|
||||
else
|
||||
output("TPS unsupported => inheritsched parameter"
|
||||
" untouched\n");
|
||||
#endif
|
||||
|
||||
if (tps > 0) {
|
||||
if (scenarii[i].schedpolicy == 1)
|
||||
ret =
|
||||
pthread_attr_setschedpolicy(&scenarii[i].ta,
|
||||
SCHED_FIFO);
|
||||
if (scenarii[i].schedpolicy == 2)
|
||||
ret =
|
||||
pthread_attr_setschedpolicy(&scenarii[i].ta,
|
||||
SCHED_RR);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to set the"
|
||||
" sched policy");
|
||||
#if VERBOSE > 4
|
||||
if (scenarii[i].schedpolicy)
|
||||
output("Sched policy was set successfully\n");
|
||||
else
|
||||
output("Sched policy untouched\n");
|
||||
#endif
|
||||
}
|
||||
#if VERBOSE > 4
|
||||
else
|
||||
output("TPS unsupported => sched policy parameter"
|
||||
" untouched\n");
|
||||
#endif
|
||||
|
||||
if (scenarii[i].schedparam != 0) {
|
||||
struct sched_param sp;
|
||||
|
||||
ret =
|
||||
pthread_attr_getschedpolicy(&scenarii[i].ta, &old);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to get sched policy"
|
||||
" from attribute");
|
||||
|
||||
if (scenarii[i].schedparam == 1)
|
||||
sp.sched_priority = sched_get_priority_max(old);
|
||||
if (scenarii[i].schedparam == -1)
|
||||
sp.sched_priority = sched_get_priority_min(old);
|
||||
|
||||
ret = pthread_attr_setschedparam(&scenarii[i].ta, &sp);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret,
|
||||
"Failed to set the sched param");
|
||||
|
||||
#if VERBOSE > 4
|
||||
output("Sched param was set successfully to %i\n",
|
||||
sp.sched_priority);
|
||||
} else {
|
||||
output("Sched param untouched\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (tps > 0) {
|
||||
ret = pthread_attr_getscope(&scenarii[i].ta, &old);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Failed to get contension"
|
||||
" scope from thread attribute");
|
||||
|
||||
if (scenarii[i].altscope != 0) {
|
||||
if (old == PTHREAD_SCOPE_PROCESS)
|
||||
old = PTHREAD_SCOPE_SYSTEM;
|
||||
else
|
||||
old = PTHREAD_SCOPE_PROCESS;
|
||||
|
||||
ret =
|
||||
pthread_attr_setscope(&scenarii[i].ta, old);
|
||||
|
||||
#if VERBOSE > 0
|
||||
if (ret != 0)
|
||||
output("WARNING: The TPS option is"
|
||||
" claimed to be supported but"
|
||||
" setscope fails\n");
|
||||
#endif
|
||||
|
||||
#if VERBOSE > 4
|
||||
output("Contension scope set to %s\n",
|
||||
old == PTHREAD_SCOPE_PROCESS ?
|
||||
"PTHREAD_SCOPE_PROCESS" :
|
||||
"PTHREAD_SCOPE_SYSTEM");
|
||||
} else {
|
||||
output("Contension scope untouched (%s)\n",
|
||||
old == PTHREAD_SCOPE_PROCESS ?
|
||||
"PTHREAD_SCOPE_PROCESS" :
|
||||
"PTHREAD_SCOPE_SYSTEM");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if VERBOSE > 4
|
||||
else
|
||||
output("TPS unsupported => sched contension scope"
|
||||
" parameter untouched\n");
|
||||
#endif
|
||||
|
||||
/* Stack related attributes */
|
||||
/*
|
||||
* This routine is dependent on the Thread Stack Address
|
||||
* Attribute and Thread Stack Size Attribute options
|
||||
*/
|
||||
if ((tss > 0) && (tsa > 0)) {
|
||||
if (scenarii[i].altstack != 0) {
|
||||
/*
|
||||
* This is slightly more complicated.
|
||||
* We need to alloc a new stackand free
|
||||
* it upon test termination.
|
||||
* We will alloc with a simulated guardsize
|
||||
* of 1 pagesize */
|
||||
scenarii[i].bottom = malloc(minstacksize + pagesize);
|
||||
if (scenarii[i].bottom == NULL)
|
||||
UNRESOLVED(errno, "Unable to alloc"
|
||||
" enough memory for"
|
||||
" alternative stack");
|
||||
|
||||
ret = pthread_attr_setstack(&scenarii[i].ta,
|
||||
scenarii[i].bottom,
|
||||
minstacksize);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Failed to specify"
|
||||
" alternate stack");
|
||||
|
||||
#if VERBOSE > 1
|
||||
output("Alternate stack created successfully."
|
||||
" Bottom=%p, Size=%i\n",
|
||||
scenarii[i].bottom, minstacksize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if VERBOSE > 4
|
||||
else
|
||||
output("TSA or TSS unsupported => "
|
||||
"No alternative stack\n");
|
||||
#endif
|
||||
|
||||
#ifndef WITHOUT_XOPEN
|
||||
if (scenarii[i].guard != 0) {
|
||||
if (scenarii[i].guard == 1)
|
||||
ret =
|
||||
pthread_attr_setguardsize(&scenarii[i].ta,
|
||||
0);
|
||||
if (scenarii[i].guard == 2)
|
||||
ret =
|
||||
pthread_attr_setguardsize(&scenarii[i].ta,
|
||||
pagesize);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to set guard area"
|
||||
" size in thread stack");
|
||||
#if VERBOSE > 4
|
||||
output("Guard size set to %i\n",
|
||||
scenarii[i].guard == 1 ? 1 : pagesize);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tss > 0) {
|
||||
if (scenarii[i].altsize != 0) {
|
||||
ret = pthread_attr_setstacksize(&scenarii[i].ta,
|
||||
minstacksize);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to change"
|
||||
" stack size");
|
||||
#if VERBOSE > 4
|
||||
output("Stack size set to %i (this is the "
|
||||
"min)\n", minstacksize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if VERBOSE > 4
|
||||
else
|
||||
output("TSS unsupported => stack size unchanged\n");
|
||||
#endif
|
||||
|
||||
ret = sem_init(&scenarii[i].sem, 0, 0);
|
||||
if (ret == -1)
|
||||
UNRESOLVED(errno, "Unable to init a semaphore");
|
||||
|
||||
}
|
||||
#if VERBOSE > 0
|
||||
output("All %i thread attribute objects were initialized\n\n", NSCENAR);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will free all resources consumed
|
||||
* in the scenar_init() routine
|
||||
*/
|
||||
static void scenar_fini(void)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NSCENAR; i++) {
|
||||
if (scenarii[i].bottom != NULL)
|
||||
free(scenarii[i].bottom);
|
||||
|
||||
ret = sem_destroy(&scenarii[i].sem);
|
||||
if (ret == -1)
|
||||
UNRESOLVED(errno, "Unable to destroy a semaphore");
|
||||
|
||||
ret = pthread_attr_destroy(&scenarii[i].ta);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Failed to destroy a thread"
|
||||
" attribute object");
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int sc;
|
||||
|
||||
#ifdef STD_MAIN
|
||||
|
||||
static void *threaded(void *arg);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ret = 0;
|
||||
pthread_t child;
|
||||
|
||||
output_init();
|
||||
scenar_init();
|
||||
|
||||
for (sc = 0; sc < NSCENAR; sc++) {
|
||||
#if VERBOSE > 0
|
||||
output("-----\n");
|
||||
output("Starting test with scenario (%i): %s\n",
|
||||
sc, scenarii[sc].descr);
|
||||
#endif
|
||||
|
||||
ret = pthread_create(&child, &scenarii[sc].ta, threaded, NULL);
|
||||
switch (scenarii[sc].result) {
|
||||
case 0: /* Operation was expected to succeed */
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Failed to create this thread");
|
||||
break;
|
||||
case 1: /* Operation was expected to fail */
|
||||
if (ret == 0)
|
||||
UNRESOLVED(-1, "An error was expected but the"
|
||||
" thread creation succeeded");
|
||||
break;
|
||||
case 2: /* We did not know the expected result */
|
||||
default:
|
||||
#if VERBOSE > 0
|
||||
if (ret == 0)
|
||||
output("Thread has been created successfully"
|
||||
" for this scenario\n");
|
||||
else
|
||||
output("Thread creation failed with the error:"
|
||||
" %s\n", strerror(ret));
|
||||
#endif
|
||||
}
|
||||
if (ret == 0) {
|
||||
if (scenarii[sc].detached == 0) {
|
||||
ret = pthread_join(child, NULL);
|
||||
if (ret != 0)
|
||||
UNRESOLVED(ret, "Unable to join a"
|
||||
" thread");
|
||||
} else {
|
||||
/* Just wait for the thread to terminate */
|
||||
do {
|
||||
ret = sem_wait(&scenarii[sc].sem);
|
||||
} while ((ret == -1) && (errno == EINTR));
|
||||
if (ret == -1)
|
||||
UNRESOLVED(errno, "Failed to wait for"
|
||||
" the semaphore");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scenar_fini();
|
||||
#if VERBOSE > 0
|
||||
output("-----\n");
|
||||
output("All test data destroyed\n");
|
||||
output("Test PASSED\n");
|
||||
#endif
|
||||
|
||||
PASSED;
|
||||
}
|
||||
#endif
|
9
examples/utest/testcases/posix/sched_h/Kconfig
Normal file
9
examples/utest/testcases/posix/sched_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_SCHED_H
|
||||
bool "<sched.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_SCHED_H
|
||||
|
||||
# functions, TODO
|
||||
|
||||
endif
|
9
examples/utest/testcases/posix/semaphore_h/Kconfig
Normal file
9
examples/utest/testcases/posix/semaphore_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_SEMAPHORE_H
|
||||
bool "<semaphore.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_SEMAPHORE_H
|
||||
|
||||
# functions, TODO
|
||||
|
||||
endif
|
9
examples/utest/testcases/posix/setjmp_h/Kconfig
Normal file
9
examples/utest/testcases/posix/setjmp_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_SETJMP_H
|
||||
bool "<setjmp.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_SETJMP_H
|
||||
|
||||
# functions, TODO
|
||||
|
||||
endif
|
23
examples/utest/testcases/posix/signal_h/Kconfig
Normal file
23
examples/utest/testcases/posix/signal_h/Kconfig
Normal file
|
@ -0,0 +1,23 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_SIGNAL_H
|
||||
bool "<signal.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_SIGNAL_H
|
||||
|
||||
config SIGNAL_H_SIGACTION
|
||||
bool "<signal.h> -> sigaction"
|
||||
default n
|
||||
|
||||
config SIGNAL_H_SIGPROCMASK
|
||||
bool "<signal.h> -> sigprocmask"
|
||||
default n
|
||||
|
||||
config SIGNAL_H_RAISE
|
||||
bool "<signal.h> -> raise"
|
||||
default n
|
||||
|
||||
config SIGNAL_H_SIGNAL
|
||||
bool "<signal.h> -> signal"
|
||||
default n
|
||||
|
||||
endif
|
9
examples/utest/testcases/posix/stdarg_h/Kconfig
Normal file
9
examples/utest/testcases/posix/stdarg_h/Kconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_STDARG_H
|
||||
bool "<stdarg.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_STDARG_H
|
||||
|
||||
# functions, TODO
|
||||
|
||||
endif
|
149
examples/utest/testcases/posix/stdio_h/Kconfig
Normal file
149
examples/utest/testcases/posix/stdio_h/Kconfig
Normal file
|
@ -0,0 +1,149 @@
|
|||
menuconfig RTT_POSIX_TESTCASE_STDIO_H
|
||||
bool "<stdio.h>"
|
||||
default n
|
||||
|
||||
if RTT_POSIX_TESTCASE_STDIO_H
|
||||
|
||||
config STDIO_H_CLEARERR
|
||||
bool "<stdio.h> -> clearerr"
|
||||
default n
|
||||
|
||||
config STDIO_H_FCLOSE
|
||||
bool "<stdio.h> -> fclose"
|
||||
default n
|
||||
|
||||
config STDIO_H_FDOPEN
|
||||
bool "<stdio.h> -> fdopen"
|
||||
default n
|
||||
|
||||
config STDIO_H_FEOF
|
||||
bool "<stdio.h> -> feof"
|
||||
default n
|
||||
|
||||
config STDIO_H_FERROR
|
||||
bool "<stdio.h> -> ferror"
|
||||
default n
|
||||
|
||||
config STDIO_H_FFLUSH
|
||||
bool "<stdio.h> -> fflush"
|
||||
default n
|
||||
|
||||
config STDIO_H_FGETC
|
||||
bool "<stdio.h> -> fgetc"
|
||||
default n
|
||||
|
||||
config STDIO_H_FGETS
|
||||
bool "<stdio.h> -> fgets"
|
||||
default n
|
||||
|
||||
config STDIO_H_FILENO
|
||||
bool "<stdio.h> -> fileno"
|
||||
default n
|
||||
|
||||
config STDIO_H_FOPEN
|
||||
bool "<stdio.h> -> fopen"
|
||||
default n
|
||||
|
||||
config STDIO_H_FPRINTF
|
||||
bool "<stdio.h> -> fprintf"
|
||||
default n
|
||||
|
||||
config STDIO_H_FPUTC
|
||||
bool "<stdio.h> -> fputc"
|
||||
default n
|
||||
|
||||
config STDIO_H_FPUTS
|
||||
bool "<stdio.h> -> fputs"
|
||||
default n
|
||||
|
||||
config STDIO_H_FREAD
|
||||
bool "<stdio.h> -> fread"
|
||||
default n
|
||||
|
||||
config STDIO_H_FSCANF
|
||||
bool "<stdio.h> -> fscanf"
|
||||
default n
|
||||
|
||||
config STDIO_H_FSEEK
|
||||
bool "<stdio.h> -> fseek"
|
||||
default n
|
||||
|
||||
config STDIO_H_FTELL
|
||||
bool "<stdio.h> -> ftell"
|
||||
default n
|
||||
|
||||
config STDIO_H_FWRITE
|
||||
bool "<stdio.h> -> fwrite"
|
||||
default n
|
||||
|
||||
|
||||
|
||||
config STDIO_H_PERROR
|
||||
bool "<stdio.h> -> perror"
|
||||
default n
|
||||
|
||||
config STDIO_H_PRINTF
|
||||
bool "<stdio.h> -> printf"
|
||||
default n
|
||||
|
||||
config STDIO_H_PUTC
|
||||
bool "<stdio.h> -> putc"
|
||||
default n
|
||||
|
||||
config STDIO_H_PUTCHAR
|
||||
bool "<stdio.h> -> putchar"
|
||||
default n
|
||||
|
||||
config STDIO_H_PUTS
|
||||
bool "<stdio.h> -> puts"
|
||||
default n
|
||||
|
||||
config STDIO_H_REMOVE
|
||||
bool "<stdio.h> -> remove"
|
||||
default n
|
||||
|
||||
config STDIO_H_RENAME
|
||||
bool "<stdio.h> -> rename"
|
||||
default n
|
||||
|
||||
config STDIO_H_REWIND
|
||||
bool "<stdio.h> -> rewind"
|
||||
default n
|
||||
|
||||
config STDIO_H_SETBUF
|
||||
bool "<stdio.h> -> setbuf"
|
||||
default n
|
||||
|
||||
config STDIO_H_SETVBUF
|
||||
bool "<stdio.h> -> setvbuf"
|
||||
default n
|
||||
|
||||
config STDIO_H_SNPRINTF
|
||||
bool "<stdio.h> -> snprintf"
|
||||
default n
|
||||
|
||||
config STDIO_H_SPRINTF
|
||||
bool "<stdio.h> -> sprintf"
|
||||
default n
|
||||
|
||||
config STDIO_H_SSCANF
|
||||
bool "<stdio.h> -> sscanf"
|
||||
default n
|
||||
|
||||
config STDIO_H_VFPRINTF
|
||||
bool "<stdio.h> -> vfprintf"
|
||||
default n
|
||||
|
||||
config STDIO_H_VPRINTF
|
||||
bool "<stdio.h> -> vprintf"
|
||||
default n
|
||||
|
||||
config STDIO_H_VSNPRINTF
|
||||
bool "<stdio.h> -> vsnprintf"
|
||||
default n
|
||||
|
||||
config STDIO_H_VSPRINTF
|
||||
bool "<stdio.h> -> vsprintf"
|
||||
default n
|
||||
|
||||
endif
|
116
examples/utest/testcases/posix/stdio_h/SConscript
Normal file
116
examples/utest/testcases/posix/stdio_h/SConscript
Normal file
|
@ -0,0 +1,116 @@
|
|||
import rtconfig
|
||||
Import('RTT_ROOT')
|
||||
from building import *
|
||||
|
||||
# get current directory
|
||||
cwd = GetCurrentDir()
|
||||
path = [cwd]
|
||||
src = []
|
||||
|
||||
if GetDepend('RTT_POSIX_TESTCASE_STDIO_H'):
|
||||
src += Glob('./definitions/*.c')
|
||||
|
||||
|
||||
if GetDepend('STDIO_H_CLEARERR'):
|
||||
src += Glob('./functions/clearerr.c')
|
||||
|
||||
if GetDepend('STDIO_H_FCLOSE'):
|
||||
src += Glob('./functions/fclose.c')
|
||||
|
||||
if GetDepend('STDIO_H_FDOPEN'):
|
||||
src += Glob('./functions/fdopen_tc.c')
|
||||
|
||||
if GetDepend('STDIO_H_FEOF'):
|
||||
src += Glob('./functions/feof.c')
|
||||
|
||||
if GetDepend('STDIO_H_FERROR'):
|
||||
src += Glob('./functions/ferror.c')
|
||||
|
||||
if GetDepend('STDIO_H_FFLUSH'):
|
||||
src += Glob('./functions/fflush.c')
|
||||
|
||||
if GetDepend('STDIO_H_FGETC'):
|
||||
src += Glob('./functions/fgetc.c')
|
||||
|
||||
if GetDepend('STDIO_H_FGETS'):
|
||||
src += Glob('./functions/fgets.c')
|
||||
|
||||
if GetDepend('STDIO_H_FILENO'):
|
||||
src += Glob('./functions/fileno.c')
|
||||
|
||||
if GetDepend('STDIO_H_FOPEN'):
|
||||
src += Glob('./functions/fopen.c')
|
||||
|
||||
if GetDepend('STDIO_H_FPRINTF'):
|
||||
src += Glob('./functions/fprintf.c')
|
||||
|
||||
if GetDepend('STDIO_H_FPUTC'):
|
||||
src += Glob('./functions/fputc.c')
|
||||
|
||||
if GetDepend('STDIO_H_FPUTS'):
|
||||
src += Glob('./functions/fputs.c')
|
||||
|
||||
if GetDepend('STDIO_H_FREAD'):
|
||||
src += Glob('./functions/fread.c')
|
||||
|
||||
if GetDepend('STDIO_H_FSCANF'):
|
||||
src += Glob('./functions/fscanf.c')
|
||||
|
||||
if GetDepend('STDIO_H_FSEEK'):
|
||||
src += Glob('./functions/fseek.c')
|
||||
|
||||
if GetDepend('STDIO_H_FTELL'):
|
||||
src += Glob('./functions/ftell.c')
|
||||
|
||||
if GetDepend('STDIO_H_FWRITE'):
|
||||
src += Glob('./functions/fwrite.c')
|
||||
|
||||
|
||||
if GetDepend('STDIO_H_PERROR'):
|
||||
src += Glob('./functions/perror.c')
|
||||
|
||||
if GetDepend('STDIO_H_PRINTF'):
|
||||
src += Glob('./functions/printf.c')
|
||||
|
||||
if GetDepend('STDIO_H_PUTC'):
|
||||
src += Glob('./functions/puts.c')
|
||||
|
||||
if GetDepend('STDIO_H_REMOVE'):
|
||||
src += Glob('./functions/remove.c')
|
||||
|
||||
if GetDepend('STDIO_H_RENAME'):
|
||||
src += Glob('./functions/rename.c')
|
||||
|
||||
if GetDepend('STDIO_H_REWIND'):
|
||||
src += Glob('./functions/rewind.c')
|
||||
|
||||
if GetDepend('STDIO_H_SETBUF'):
|
||||
src += Glob('./functions/setbuf.c')
|
||||
|
||||
if GetDepend('STDIO_H_SETVBUF'):
|
||||
src += Glob('./functions/setvbuf.c')
|
||||
|
||||
if GetDepend('STDIO_H_SNPRINTF'):
|
||||
src += Glob('./functions/snprintf.c')
|
||||
|
||||
if GetDepend('STDIO_H_SPRINTF'):
|
||||
src += Glob('./functions/sprintf.c')
|
||||
|
||||
if GetDepend('STDIO_H_SSCANF'):
|
||||
src += Glob('./functions/sscanf.c')
|
||||
|
||||
if GetDepend('STDIO_H_VFPRINTF'):
|
||||
src += Glob('./functions/vfprintf.c')
|
||||
|
||||
if GetDepend('STDIO_H_VPRINTF'):
|
||||
src += Glob('./functions/vprintf.c')
|
||||
|
||||
if GetDepend('STDIO_H_VSNPRINTF'):
|
||||
src += Glob('./functions/vsnprintf.c')
|
||||
|
||||
if GetDepend('STDIO_H_VSPRINTF'):
|
||||
src += Glob('./functions/vsprintf.c')
|
||||
|
||||
group = DefineGroup('rtt_posix_testcase', src, depend = ['RTT_POSIX_TESTCASE_STDIO_H'], CPPPATH = path)
|
||||
|
||||
Return('group')
|
123
examples/utest/testcases/posix/stdio_h/definitions/stdio_h.c
Normal file
123
examples/utest/testcases/posix/stdio_h/definitions/stdio_h.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Bull SA. All rights reserved.
|
||||
* Created by: Laurent.Vivier@bull.net
|
||||
* This file is licensed under the GPL license. For the full content
|
||||
* of this license, see the COPYING file at the top level of this
|
||||
* source tree.
|
||||
*/
|
||||
|
||||
/* test if stdio.h exists and can be included */
|
||||
|
||||
// #define _POSIX_C_SOURCE 2
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void (*test_clearerr)(FILE *);
|
||||
int (*test_fclose)(FILE *);
|
||||
FILE * (*test_fdopen)(int, const char *);
|
||||
int (*test_feof)(FILE *);
|
||||
int (*test_ferror)(FILE *);
|
||||
int (*test_fflush)(FILE *);
|
||||
int (*test_fgetc)(FILE *);
|
||||
char * (*test_fgets)(char *__restrict, int, FILE *__restrict);
|
||||
int (*test_fileno)(FILE *);
|
||||
void (*test_flockfile)(FILE *);
|
||||
FILE * (*test_fopen)(const char *__restrict _name, const char *__restrict _type);
|
||||
int (*test_fprintf)(FILE *__restrict, const char *__restrict, ...);
|
||||
int (*test_fputc)(int, FILE *);
|
||||
int (*test_fputs)(const char *__restrict, FILE *__restrict);
|
||||
size_t (*test_fread)(void *__restrict, size_t _size, size_t _n, FILE *__restrict);
|
||||
FILE * (*test_freopen)(const char *__restrict, const char *__restrict, FILE *__restrict);
|
||||
int (*test_fscanf)(FILE *__restrict, const char *__restrict, ...);
|
||||
int (*test_ftrylockfile)(FILE *);
|
||||
void (*test_funlockfile)(FILE *);
|
||||
size_t (*test_fwrite)(const void *__restrict , size_t _size, size_t _n, FILE *);
|
||||
int (*test_getc)(FILE *);
|
||||
int (*test_getc_unlocked)(FILE *);
|
||||
int (*test_getchar)(void);
|
||||
int (*test_getchar_unlocked)(void);
|
||||
char * (*test_gets)(char *);
|
||||
void (*test_perror)(const char *);
|
||||
int (*test_printf)(const char *__restrict, ...);
|
||||
int (*test_putc)(int, FILE *);
|
||||
int (*test_putc_unlocked)(int, FILE *);
|
||||
int (*test_putchar)(int);
|
||||
int (*test_putchar_unlocked)(int);
|
||||
int (*test_puts)(const char *);
|
||||
int (*test_scanf)(const char *__restrict, ...);
|
||||
void (*test_setbuf)(FILE *__restrict, char *__restrict);
|
||||
int (*test_setvbuf)(FILE *__restrict, char *__restrict, int, size_t);
|
||||
int (*test_snprintf)(char *__restrict, size_t, const char *__restrict, ...);
|
||||
int (*test_sprintf)(char *__restrict, const char *__restrict, ...);
|
||||
int (*test_sscanf)(const char *__restrict, const char *__restrict, ...);
|
||||
int (*test_ungetc)(int, FILE *);
|
||||
|
||||
FILE *test_stderr;
|
||||
FILE *test_stdin;
|
||||
FILE *test_stdout;
|
||||
|
||||
int (*test_vfprintf)(FILE *restrict, const char *restrict, va_list);
|
||||
int (*test_vfscanf)(FILE *restrict, const char *restrict, va_list);
|
||||
int (*test_vprintf)(const char *restrict, va_list);
|
||||
int (*test_vscanf)(const char *restrict, va_list);
|
||||
int (*test_vsnprintf)(char *restrict, size_t, const char *restrict, va_list);
|
||||
int (*test_vsprintf)(char *restrict, const char *restrict, va_list);
|
||||
int (*test_vsscanf)(const char *restrict, const char *restrict, va_list);
|
||||
|
||||
__attribute__((unused)) static int test_defined()
|
||||
{
|
||||
test_clearerr = clearerr;
|
||||
test_fclose = fclose;
|
||||
// test_fdopen = fdopen;
|
||||
test_feof = feof;
|
||||
test_ferror = ferror;
|
||||
test_fflush = fflush;
|
||||
test_fgetc = fgetc;
|
||||
test_fgets = fgets;
|
||||
// test_fileno = fileno;
|
||||
// test_flockfile = flockfile;
|
||||
test_fopen = fopen;
|
||||
test_fprintf = fprintf;
|
||||
test_fputc = fputc;
|
||||
test_fputs = fputs;
|
||||
test_fread = fread;
|
||||
test_freopen = freopen;
|
||||
test_fscanf = fscanf;
|
||||
// test_ftrylockfile = ftrylockfile;
|
||||
// test_funlockfile = funlockfile;
|
||||
test_fwrite = fwrite;
|
||||
test_getc = getc;
|
||||
// test_getc_unlocked = getc_unlocked;
|
||||
test_getchar = getchar;
|
||||
test_gets = gets;
|
||||
test_perror = perror;
|
||||
test_printf = printf;
|
||||
test_putc = putc;
|
||||
// test_putc_unlocked = putc_unlocked;
|
||||
test_putchar = putchar;
|
||||
// test_putchar_unlocked = putchar_unlocked;
|
||||
test_puts = puts;
|
||||
test_scanf = scanf;
|
||||
test_setbuf = setbuf;
|
||||
test_setvbuf = setvbuf;
|
||||
test_snprintf = snprintf;
|
||||
test_sprintf = sprintf;
|
||||
test_sscanf = sscanf;
|
||||
test_ungetc = ungetc;
|
||||
|
||||
test_stderr = stderr;
|
||||
test_stdin = stdin;
|
||||
test_stdout = stdout;
|
||||
|
||||
test_vfprintf = vfprintf;
|
||||
test_vfscanf = vfscanf;
|
||||
test_vprintf = vprintf;
|
||||
test_vscanf = vscanf;
|
||||
test_vsnprintf = vsnprintf;
|
||||
test_vsprintf = vsprintf;
|
||||
test_vsscanf = vsscanf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static int clearerr_entry(void)
|
||||
{
|
||||
putc( 'c', stdin );
|
||||
if( ferror( stdin ) )
|
||||
{
|
||||
perror( "Write error" );
|
||||
clearerr( stdin );
|
||||
}
|
||||
|
||||
if( ferror( stdin ))
|
||||
{
|
||||
perror( "clearerr error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_clearerr(void)
|
||||
{
|
||||
uassert_int_equal(clearerr_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_clearerr);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.clearerr.c", RT_NULL, RT_NULL, 10);
|
||||
|
34
examples/utest/testcases/posix/stdio_h/functions/fclose_tc.c
Normal file
34
examples/utest/testcases/posix/stdio_h/functions/fclose_tc.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static int fclose_entry(void)
|
||||
{
|
||||
FILE *stream;
|
||||
stream = fopen("fopen_file.txt","a+");
|
||||
if (stream == NULL)
|
||||
{
|
||||
perror("fopen fail");
|
||||
return -1;
|
||||
}
|
||||
if(fclose(stream) != 0)
|
||||
{
|
||||
perror("fclose fail");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("fclose success \n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_fclose(void)
|
||||
{
|
||||
uassert_int_equal(fclose_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_fclose);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.fclose.c", RT_NULL, RT_NULL, 10);
|
||||
|
39
examples/utest/testcases/posix/stdio_h/functions/fdopen_tc.c
Normal file
39
examples/utest/testcases/posix/stdio_h/functions/fdopen_tc.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static int fdopen_entry(void)
|
||||
{
|
||||
int fd;
|
||||
FILE *stream;
|
||||
|
||||
fd = open("fdopen_file.txt", O_CREAT | O_RDWR | O_APPEND);
|
||||
if (fd < 0)
|
||||
{
|
||||
printf("open fail.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
stream = fdopen(fd, "w");
|
||||
if (stream == NULL)
|
||||
{
|
||||
printf("fdopen fail.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_fdopen(void)
|
||||
{
|
||||
uassert_int_equal(fdopen_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_fdopen);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.fdopen_tc.c", RT_NULL, RT_NULL, 10);
|
||||
|
55
examples/utest/testcases/posix/stdio_h/functions/feof_tc.c
Normal file
55
examples/utest/testcases/posix/stdio_h/functions/feof_tc.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int feof_entry(void)
|
||||
{
|
||||
FILE *stream;
|
||||
char data[] = "test fgetc";
|
||||
char getc[sizeof(data)] = {0};
|
||||
size_t size = 0;
|
||||
int ret = 0;
|
||||
int i=0;
|
||||
|
||||
stream = fopen("fopen_file.txt","w+");
|
||||
if (stream == NULL)
|
||||
{
|
||||
perror("fopen fail");
|
||||
ret = -1;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
fwrite(data, sizeof(data), 1, stream);
|
||||
fclose(stream);
|
||||
|
||||
stream = fopen("fopen_file.txt","r");
|
||||
while(1)
|
||||
{
|
||||
getc[i] = fgetc(stream);
|
||||
i++;
|
||||
if( feof(stream) )
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(getc, data))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(stream);
|
||||
__exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_feof(void)
|
||||
{
|
||||
uassert_int_equal(feof_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_feof);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.feof.c", RT_NULL, RT_NULL, 10);
|
||||
|
28
examples/utest/testcases/posix/stdio_h/functions/ferror_tc.c
Normal file
28
examples/utest/testcases/posix/stdio_h/functions/ferror_tc.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static int ferror_entry(void)
|
||||
{
|
||||
int c;
|
||||
putc( 'c', stdin );
|
||||
if( ferror( stdin ) )
|
||||
{
|
||||
clearerr( stdin );
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_ferror(void)
|
||||
{
|
||||
uassert_int_equal(ferror_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_ferror);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.ferror.c", RT_NULL, RT_NULL, 10);
|
||||
|
29
examples/utest/testcases/posix/stdio_h/functions/fflush_tc.c
Normal file
29
examples/utest/testcases/posix/stdio_h/functions/fflush_tc.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static int fflush_entry(void)
|
||||
{
|
||||
fflush(stdout);
|
||||
printf("test fflush\n");
|
||||
|
||||
printf("t");
|
||||
printf("e");
|
||||
printf("s");
|
||||
printf("t");
|
||||
fflush(stdout);
|
||||
printf(" fflush");
|
||||
fflush(stdout);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_fflush(void)
|
||||
{
|
||||
uassert_int_equal(fflush_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_fflush);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.fflush.c", RT_NULL, RT_NULL, 10);
|
||||
|
54
examples/utest/testcases/posix/stdio_h/functions/fgetc_tc.c
Normal file
54
examples/utest/testcases/posix/stdio_h/functions/fgetc_tc.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int fgetc_entry(void)
|
||||
{
|
||||
FILE *stream;
|
||||
char data[] = "test fgetc";
|
||||
char getc[sizeof(data)] = {0};
|
||||
size_t size = 0;
|
||||
int ret = 0;
|
||||
int i=0;
|
||||
|
||||
stream = fopen("fopen_file.txt","w+");
|
||||
if (stream == NULL)
|
||||
{
|
||||
perror("fopen fail");
|
||||
ret = -1;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
fwrite(data, sizeof(data), 1, stream);
|
||||
fclose(stream);
|
||||
|
||||
stream = fopen("fopen_file.txt","r");
|
||||
while(1)
|
||||
{
|
||||
getc[i] = fgetc(stream);
|
||||
i++;
|
||||
if( feof(stream) )
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(getc, data))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
fclose(stream);
|
||||
__exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_fgetc(void)
|
||||
{
|
||||
uassert_int_equal(fgetc_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_fgetc);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.fgetc.c", RT_NULL, RT_NULL, 10);
|
||||
|
50
examples/utest/testcases/posix/stdio_h/functions/fgets_tc.c
Normal file
50
examples/utest/testcases/posix/stdio_h/functions/fgets_tc.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static int fgets_entry(void)
|
||||
{
|
||||
FILE *stream;
|
||||
char data[] = "test fgets";
|
||||
char gets[sizeof(data)] = {0};
|
||||
size_t size = 0;
|
||||
int ret = 0;
|
||||
|
||||
stream = fopen("fopen_file.txt","w");
|
||||
if (stream == NULL)
|
||||
{
|
||||
perror("fopen fail");
|
||||
ret = -1;
|
||||
goto __exit;
|
||||
}
|
||||
fwrite(data, sizeof(data), 1, stream);
|
||||
fclose(stream);
|
||||
|
||||
stream = fopen("fopen_file.txt","r");
|
||||
if (stream == NULL)
|
||||
{
|
||||
perror("fopen fail");
|
||||
ret = -1;
|
||||
goto __exit;
|
||||
}
|
||||
fgets(gets, sizeof(gets), stream);
|
||||
|
||||
if(strcmp(gets, data))
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
fclose(stream);
|
||||
|
||||
__exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_fgets(void)
|
||||
{
|
||||
uassert_int_equal(fgets_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_fgets);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.fgets.c", RT_NULL, RT_NULL, 10);
|
||||
|
26
examples/utest/testcases/posix/stdio_h/functions/fileno_tc.c
Normal file
26
examples/utest/testcases/posix/stdio_h/functions/fileno_tc.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static int fdopen_entry(void)
|
||||
{
|
||||
int stdin_no = fileno(stdin);
|
||||
int stdout_no = fileno(stdout);
|
||||
int stderr_no = fileno(stderr);
|
||||
|
||||
if((stdin_no == 0) && (stdout_no == 1) && (stderr_no == 2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_fdopen(void)
|
||||
{
|
||||
uassert_int_equal(fdopen_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_fdopen);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.fileno.c", RT_NULL, RT_NULL, 10);
|
||||
|
28
examples/utest/testcases/posix/stdio_h/functions/fopen_tc.c
Normal file
28
examples/utest/testcases/posix/stdio_h/functions/fopen_tc.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static int fopen_entry(void)
|
||||
{
|
||||
FILE *stream;
|
||||
/* TODO: other mode fopen */
|
||||
stream = fopen("fopen_file.txt","a+");
|
||||
if (stream == NULL)
|
||||
{
|
||||
perror("fopen fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <utest.h>
|
||||
static void test_fopen(void)
|
||||
{
|
||||
uassert_int_equal(fopen_entry(), 0);
|
||||
}
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(test_fopen);
|
||||
}
|
||||
UTEST_TC_EXPORT(testcase, "posix.stdio_h.fopen.c", RT_NULL, RT_NULL, 10);
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue