Skip to content

Commit

Permalink
tests: kernel: pipe: Add new test cases for pipe API rework
Browse files Browse the repository at this point in the history
This commit adds new test cases for the pipe API rework.
* pipe_basic.c: Sanity check for pipe operations.
* pipe_concurrency.c: Test pipe operations with multiple threads.
* pipe_stress.c: Test pipe operations under stress conditions.

And moves the old pipe test cases to the deprecated folder.

Signed-off-by: Måns Ansgariusson <[email protected]>
  • Loading branch information
Mattemagikern committed Dec 23, 2024
1 parent 7565af1 commit 814edfd
Show file tree
Hide file tree
Showing 17 changed files with 355 additions and 12 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tests:
kernel.pipe:
kernel.deprecated.pipe:
tags:
- kernel
- userspace
Expand Down
8 changes: 8 additions & 0 deletions tests/kernel/pipe/deprecated/pipe_api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(pipe_api)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
7 changes: 7 additions & 0 deletions tests/kernel/pipe/deprecated/pipe_api/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CONFIG_ZTEST=y
CONFIG_IRQ_OFFLOAD=y
CONFIG_TEST_USERSPACE=y
CONFIG_DYNAMIC_OBJECTS=y
CONFIG_MP_MAX_NUM_CPUS=1
CONFIG_ZTEST_FATAL_HOOK=y
CONFIG_PIPES=y
File renamed without changes.
5 changes: 5 additions & 0 deletions tests/kernel/pipe/deprecated/pipe_api/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tests:
kernel.deprecated.pipe.api:
tags:
- kernel
- userspace
14 changes: 9 additions & 5 deletions tests/kernel/pipe/pipe_api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(pipe_api)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
project(app)

target_sources(app
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/basic.c
${CMAKE_CURRENT_SOURCE_DIR}/src/stress.c
${CMAKE_CURRENT_SOURCE_DIR}/src/concurrency.c
)
14 changes: 8 additions & 6 deletions tests/kernel/pipe/pipe_api/prj.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
CONFIG_ZTEST=y
CONFIG_IRQ_OFFLOAD=y
CONFIG_TEST_USERSPACE=y
CONFIG_DYNAMIC_OBJECTS=y
CONFIG_MP_MAX_NUM_CPUS=1
CONFIG_ZTEST_FATAL_HOOK=y
CONFIG_PIPES=y
CONFIG_ZTRESS=y

CONFIG_ZTEST_STACK_SIZE=4096
CONFIG_HEAP_MEM_POOL_SIZE=2048
CONFIG_MAIN_STACK_SIZE=4096

CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
148 changes: 148 additions & 0 deletions tests/kernel/pipe/pipe_api/src/basic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2024 Måns Ansgariusson <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/random/random.h>

ZTEST_SUITE(k_pipe_basic, NULL, NULL, NULL, NULL, NULL);

static void mkrandom(uint8_t *buffer, size_t size)
{
sys_rand_get(buffer, size);
}

K_PIPE_DEFINE(test_define, 256, 4);

ZTEST(k_pipe_basic, test_init)
{
struct k_pipe pipe;
uint8_t buffer[10];

k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(pipe.flags == PIPE_FLAG_OPEN, "pipe.flags should be k_pipe_FLAG_OPEN");
}

ZTEST(k_pipe_basic, test_write_read_one)
{
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t data = 0x55;
uint8_t read_data;

k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(k_pipe_write(&pipe, &data, 1, K_NO_WAIT) == 1, "k_pipe_write should return 1");
zassert_true(k_pipe_read(&pipe, &read_data, 1, K_NO_WAIT) == 1,
"k_pipe_read should return 1");
zassert_true(read_data == data, "read_data should be equal to data");
}

ZTEST(k_pipe_basic, test_write_read_multiple)
{
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t data = 0x55;
uint8_t read_data;

k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(k_pipe_write(&pipe, &data, 1, K_NO_WAIT) == 1, "k_pipe_write should return 1");
zassert_true(k_pipe_write(&pipe, &data, 1, K_NO_WAIT) == 1, "k_pipe_write should return 1");
zassert_true(k_pipe_read(&pipe, &read_data, 1, K_NO_WAIT) == 1,
"k_pipe_read should return 1");
zassert_true(read_data == data, "read_data should be equal to data");
zassert_true(k_pipe_read(&pipe, &read_data, 1, K_NO_WAIT) == 1,
"k_pipe_read should return 1");
zassert_true(read_data == data, "read_data should be equal to data");
}

ZTEST(k_pipe_basic, test_write_full)
{
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t data[10];

k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(k_pipe_write(&pipe, data, sizeof(data), K_NO_WAIT) == 10,
"k_pipe_write should return 10");
zassert_true(k_pipe_write(&pipe, data, sizeof(data), K_MSEC(1000)) == -EAGAIN,
"k_pipe_write should return 0");
}

ZTEST(k_pipe_basic, test_read_empty)
{
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t read_data;

k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(k_pipe_read(&pipe, &read_data, 1, K_MSEC(1000)) == -EAGAIN,
"k_pipe_read should return 0");
}

ZTEST(k_pipe_basic, test_read_write_full)
{
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t input[10];
uint8_t res[10];

mkrandom(input, sizeof(input));
k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(k_pipe_write(&pipe, input, sizeof(input), K_NO_WAIT) == sizeof(input),
"k_pipe_write should return sizeof input");
zassert_true(k_pipe_read(&pipe, res, sizeof(res), K_NO_WAIT) == sizeof(res),
"k_pipe_read should return sizeof res");
zassert_true(memcmp(input, res, sizeof(input)) == 0, "input and res should be equal");
}

ZTEST(k_pipe_basic, test_read_write_wrapp_around)
{
struct k_pipe pipe;
uint8_t buffer[12];
uint8_t input[8];
uint8_t res[16];

mkrandom(input, sizeof(input));
k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(k_pipe_write(&pipe, input, sizeof(input), K_NO_WAIT) == sizeof(input),
"k_pipe_write should return sizeof input");
zassert_true(k_pipe_read(&pipe, res, 5, K_NO_WAIT) == 5,
"k_pipe_read should return sizeof res");
zassert_true(memcmp(input, res, 5) == 0, "input and res should be equal");

zassert_true(k_pipe_write(&pipe, input, sizeof(input), K_NO_WAIT) == sizeof(input),
"k_pipe_write should return sizeof input");
zassert_true(k_pipe_read(&pipe, res, sizeof(input) * 2 - 5, K_NO_WAIT) ==
sizeof(input) * 2 - 5,
"read failed");

zassert_true(memcmp(&input[5], res, sizeof(input) - 5) == 0,
"input and res should be equal");
zassert_true(memcmp(input, &res[sizeof(input) - 5], sizeof(input)) == 0,
"input and res should be equal");
}

ZTEST(k_pipe_basic, test_close)
{
struct k_pipe pipe;
uint8_t buffer[12];
uint8_t input[8];
uint8_t res[16];

mkrandom(input, sizeof(input));
k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(k_pipe_write(&pipe, input, sizeof(input), K_NO_WAIT) == sizeof(input),
"k_pipe_write should return sizeof input");
k_pipe_close(&pipe);

zassert_true(k_pipe_write(&pipe, input, sizeof(input), K_NO_WAIT) == -EPIPE,
"k_pipe_write should return sizeof input");
zassert_true(k_pipe_read(&pipe, res, 5, K_NO_WAIT) == 5, "k_pipe_read should return 0");
zassert_true(memcmp(input, res, 5) == 0, "input and res should be equal");
zassert_true(k_pipe_read(&pipe, res, 5, K_NO_WAIT) == 3, "k_pipe_read should return 0");
zassert_true(k_pipe_read(&pipe, res, 5, K_NO_WAIT) == -EPIPE,
"k_pipe_read should return 0");
}
101 changes: 101 additions & 0 deletions tests/kernel/pipe/pipe_api/src/concurrency.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2024 Måns Ansgariusson <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/random/random.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(k_pipe_concurrency, LOG_LEVEL_DBG);
ZTEST_SUITE(k_pipe_concurrency, NULL, NULL, NULL, NULL, NULL);

#define STACK_SIZE 1024

static struct k_thread close_thread;
static K_THREAD_STACK_DEFINE(close_stack, STACK_SIZE);
static struct k_thread flush_thread;
static K_THREAD_STACK_DEFINE(flush_stack, STACK_SIZE);

static void thread_close(void *arg1, void *arg2, void *arg3)
{
k_pipe_close((struct k_pipe *)arg1);
}

static void thread_flush(void *arg1, void *arg2, void *arg3)
{
k_pipe_flush((struct k_pipe *)arg1);
}

ZTEST(k_pipe_concurrency, test_close_on_read)
{
k_tid_t tid;
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t res;

k_pipe_init(&pipe, buffer, sizeof(buffer));
tid = k_thread_create(&close_thread, close_stack, K_THREAD_STACK_SIZEOF(close_stack),
thread_close, &pipe, NULL, NULL, K_PRIO_COOP(0), 0, K_MSEC(100));
zassert_true(tid, "k_thread_create failed");
zassert_true(k_pipe_read(&pipe, &res, sizeof(res), K_MSEC(1000)) == -EPIPE,
"close_on_read should return -EPIPE");
k_thread_join(&close_thread, K_FOREVER);
}

ZTEST(k_pipe_concurrency, test_close_on_write)
{
k_tid_t tid;
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t trash[10];

k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(sizeof(trash) == k_pipe_write(&pipe, trash, sizeof(trash), K_MSEC(1000)),
"k_k_pipe_write should return number of bytes written");

tid = k_thread_create(&close_thread, close_stack, K_THREAD_STACK_SIZEOF(close_stack),
thread_close, &pipe, NULL, NULL, K_PRIO_COOP(0), 0, K_MSEC(100));
zassert_true(tid, "k_thread_create failed");
zassert_true(k_pipe_write(&pipe, trash, sizeof(trash), K_MSEC(1000)) == -EPIPE,
"close_on_write should return -EPIPE");
k_thread_join(&close_thread, K_FOREVER);
}

ZTEST(k_pipe_concurrency, test_flush_on_read)
{
k_tid_t tid;
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t res;

k_pipe_init(&pipe, buffer, sizeof(buffer));

tid = k_thread_create(&flush_thread, flush_stack, K_THREAD_STACK_SIZEOF(flush_stack),
thread_flush, &pipe, NULL, NULL, K_PRIO_COOP(0), 0, K_MSEC(100));
zassert_true(tid, "k_thread_create failed");
zassert_true(k_pipe_read(&pipe, &res, sizeof(res), K_MSEC(1000)) == -ECANCELED,
"flush on read should return -ECANCELED");
k_thread_join(&flush_thread, K_FOREVER);
}

ZTEST(k_pipe_concurrency, test_flush_on_write)
{
k_tid_t tid;
struct k_pipe pipe;
uint8_t buffer[10];
uint8_t trash[10];

k_pipe_init(&pipe, buffer, sizeof(buffer));
zassert_true(sizeof(trash) == k_pipe_write(&pipe, trash, sizeof(trash), K_MSEC(1000)),
"k_k_pipe_write should return number of bytes written");

tid = k_thread_create(&flush_thread, flush_stack, K_THREAD_STACK_SIZEOF(flush_stack),
thread_flush, &pipe, NULL, NULL, K_PRIO_COOP(0), 0, K_MSEC(100));
zassert_true(tid, "k_thread_create failed");
zassert_true(k_pipe_write(&pipe, trash, sizeof(trash), K_MSEC(1000)) == -ECANCELED,
"flush on write should return -ECANCELED");
k_thread_join(&flush_thread, K_FOREVER);
}
68 changes: 68 additions & 0 deletions tests/kernel/pipe/pipe_api/src/stress.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024 Måns Ansgariusson <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/ztest.h>
#include <zephyr/kernel.h>
#include <zephyr/ztress.h>
#include <zephyr/logging/log.h>
#include <zephyr/random/random.h>
#include <zephyr/timing/timing.h>

LOG_MODULE_REGISTER(k_k_pipe_stress, LOG_LEVEL_INF);

ZTEST_SUITE(k_pipe_stress, NULL, NULL, NULL, NULL, NULL);

ZTEST(k_pipe_stress, test_write)
{
int rc;
struct k_pipe pipe;
size_t len = 512;
uint8_t buffer[len];
uint8_t buf[len];
size_t sent;
uint32_t start_cycles, end_cycles;

k_pipe_init(&pipe, buffer, sizeof(buffer));
start_cycles = k_uptime_get_32();
sent = 0;
while (sent < len) {
rc = k_pipe_write(&pipe, &buf[sent], len - sent, K_FOREVER);
zassert_true(rc > 0, "k_k_pipe_write failed");
sent += rc;
}
end_cycles = k_uptime_get_32();
LOG_INF("Elapsed cycles: %u\n", end_cycles - start_cycles);
}

ZTEST(k_pipe_stress, test_read)
{
int rc;
struct k_pipe pipe;
size_t len = 512;
uint8_t buffer[len];
uint8_t buf[len];
size_t sent, read;
uint32_t start_cycles, end_cycles;

k_pipe_init(&pipe, buffer, sizeof(buffer));
start_cycles = k_uptime_get_32();
for (int i = 0; i < 100000; i++) {
sent = 0;
while (sent < len) {
rc = k_pipe_write(&pipe, &buf[sent], len - sent, K_FOREVER);
zassert_true(rc > 0, "k_k_pipe_write failed");
sent += rc;
}
read = 0;
while (read < len) {
rc = k_pipe_read(&pipe, &buf[read], len - read, K_FOREVER);
zassert_true(rc > 0, "k_k_pipe_write failed");
read += rc;
}
}
end_cycles = k_uptime_get_32();
LOG_INF("Elapsed cycles: %u\n", end_cycles - start_cycles);
}

0 comments on commit 814edfd

Please sign in to comment.