1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-18 11:03:50 +01:00
RIOT/tests/unittests/tests-isrpipe/tests-isrpipe.c
Joshua DeWeese a749e3493d sys/isrpipe: add unit tests
This patch adds unit tests for the isrpipe module.
2025-04-08 20:17:04 -04:00

244 lines
6.8 KiB
C

/*
* Copyright (c) 2025 Prime Controls, Inc.(R)
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include <string.h>
#include "embUnit/embUnit.h"
#include "isrpipe.h"
#include "tests-isrpipe.h"
#include "ztimer.h"
/* ISR pipe to test */
static uint8_t _buffer[8];
static isrpipe_t _pipe;
/* reader thread's stack */
static char _reader_stack[THREAD_STACKSIZE_TINY];
/* entry point of reader thread */
static void* _reader_thread(void *arg)
{
uint8_t *read_buf = arg;
/* get the size of the read_buffer */
unsigned read_buf_size = read_buf[0];
/* keep reading until read_buf is full */
while (read_buf_size) {
const int res = isrpipe_read(&_pipe, read_buf, read_buf_size);
read_buf += res;
read_buf_size -= res;
}
thread_zombify();
return NULL;
}
static void setup_up(void)
{
/* clear buffer contents from previous tests */
memset(_buffer, 0, sizeof(_buffer));
/* prep the pipe */
isrpipe_init(&_pipe, _buffer, ARRAY_SIZE(_buffer));
}
static void test_init(void)
{
/* statically initialized isrpipe */
static const isrpipe_t pipe = ISRPIPE_INIT(_buffer);
/* check that static and runtime init produces the same result */
TEST_ASSERT_EQUAL_INT(0, memcmp(&_pipe, &pipe, sizeof(isrpipe_t)));
}
static void test_write_then_read(void)
{
const uint8_t write_buf[] = {1, 2, 3, 4, 5, 6};
uint8_t read_buf[2];
int res;
res = isrpipe_write(&_pipe, write_buf, ARRAY_SIZE(write_buf));
TEST_ASSERT_EQUAL_INT(ARRAY_SIZE(write_buf), res);
/* pipe now holds 1, 2, 3, 4, 5, 6 */
res = isrpipe_read(&_pipe, read_buf, 1);
TEST_ASSERT_EQUAL_INT(1, res);
TEST_ASSERT_EQUAL_INT(1, read_buf[0]);
/* pipe now holds 2, 3, 4, 5, 6 */
res = isrpipe_read(&_pipe, read_buf, 2);
TEST_ASSERT_EQUAL_INT(2, res);
TEST_ASSERT_EQUAL_INT(2, read_buf[0]);
TEST_ASSERT_EQUAL_INT(3, read_buf[1]);
/* pipe now holds 4, 5, 6 */
res = isrpipe_read(&_pipe, read_buf, 1);
TEST_ASSERT_EQUAL_INT(1, res);
TEST_ASSERT_EQUAL_INT(4, read_buf[0]);
/* pipe now holds 5, 6 */
res = isrpipe_read(&_pipe, read_buf, 2);
TEST_ASSERT_EQUAL_INT(2, res);
TEST_ASSERT_EQUAL_INT(5, read_buf[0]);
TEST_ASSERT_EQUAL_INT(6, read_buf[1]);
/* pipe now empty */
}
static void test_read_then_write(void)
{
uint8_t read_buf[3] = {0}; /* init contents to all zeros */
thread_t *writer_thread = thread_get_active();
const unsigned writer_priority = thread_get_priority(writer_thread);
const unsigned reader_priority = 0;
/* check assumptions */
TEST_ASSERT(writer_priority > reader_priority);
/* sneaky way to tell reader thread the size of the read_buf */
read_buf[0] = ARRAY_SIZE(read_buf);
/* create reader thread with priority higher than writer thread so that write
can only happen once reading blocks on the empty pipe */
const int reader_pid = thread_create(_reader_stack, sizeof(_reader_stack),
reader_priority, 0, _reader_thread, read_buf, "reader");
/* check assumptions */
TEST_ASSERT(reader_pid >= 0);
/* reader thread should have preempted us, but is now blocked by reading
from the empty pipe, which yielded the CPU back to us */
/* write to the pipe a byte at a time to demonstrate that the reader is
unblocking with each byte and placing the bytes into read_buf */
for (unsigned i = 0; i < ARRAY_SIZE(read_buf); i++) {
/* test that read_buf[i] is not equal to the value we are about to send
through the pipe */
TEST_ASSERT(i != read_buf[i]);
/* write a byte, reader thread will then unblock and write it into
read_buf[i] */
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, i));
/* check that reader got the byte from the pipe and put it into
read_buf[i]*/
TEST_ASSERT_EQUAL_INT(i, read_buf[i]);
}
/* cleanup */
TEST_ASSERT_EQUAL_INT(1, thread_kill_zombie(reader_pid));
}
static void test_overflow(void)
{
int res;
/* completely fill the pipe */
for (unsigned i = 0; i < ARRAY_SIZE(_buffer); i++) {
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, i));
}
/* pipe is now full */
/* isrpipe_write_one() should return -1 for error */
TEST_ASSERT_EQUAL_INT(-1, isrpipe_write_one(&_pipe, -1));
/* isrpipe_write() should return 0 bytes written */
const uint8_t write_buf[] = {1, 2, 3};
res = isrpipe_write(&_pipe, write_buf, ARRAY_SIZE(write_buf));
TEST_ASSERT_EQUAL_INT(0, res);
}
static void test_underflow(void)
{
const uint8_t write_buf[] = {1, 2, 3};
uint8_t read_buf[ARRAY_SIZE(write_buf) + 1];
int res;
res = isrpipe_write(&_pipe, write_buf, ARRAY_SIZE(write_buf));
TEST_ASSERT_EQUAL_INT(ARRAY_SIZE(write_buf), res);
/* pipe now holds 1, 2, 3 */
/* try to read more data than is in pipe */
res = isrpipe_read(&_pipe, read_buf, ARRAY_SIZE(read_buf));
TEST_ASSERT_EQUAL_INT(ARRAY_SIZE(write_buf), res);
}
static void test_write_one(void)
{
uint8_t read_buf[3];
int res;
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, 1));
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, 2));
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, 3));
/* pipe now holds 1, 2, 3 */
TEST_ASSERT_EQUAL_INT(1, isrpipe_read(&_pipe, read_buf, 1));
TEST_ASSERT_EQUAL_INT(1, read_buf[0]);
/* pipe now holds 2, 3 */
TEST_ASSERT_EQUAL_INT(1, isrpipe_read(&_pipe, read_buf, 1));
TEST_ASSERT_EQUAL_INT(2, read_buf[0]);
/* pipe now holds 3 */
TEST_ASSERT_EQUAL_INT(1, isrpipe_read(&_pipe, read_buf, 1));
TEST_ASSERT_EQUAL_INT(3, read_buf[0]);
/* pipe now empty */
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, 4));
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, 5));
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&_pipe, 6));
/* pipe now holds 4, 5, 6 */
res = isrpipe_read(&_pipe, read_buf, ARRAY_SIZE(read_buf));
TEST_ASSERT_EQUAL_INT(ARRAY_SIZE(read_buf), res);
TEST_ASSERT_EQUAL_INT(4, read_buf[0]);
TEST_ASSERT_EQUAL_INT(5, read_buf[1]);
TEST_ASSERT_EQUAL_INT(6, read_buf[2]);
/* pipe now empty */
}
Test *tests_isrpipe_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_init),
new_TestFixture(test_write_then_read),
new_TestFixture(test_read_then_write),
new_TestFixture(test_overflow),
new_TestFixture(test_underflow),
new_TestFixture(test_write_one),
};
EMB_UNIT_TESTCALLER(isrpipe_tests, setup_up, NULL, fixtures);
return (Test *)&isrpipe_tests;
}
void tests_isrpipe(void)
{
TESTS_RUN(tests_isrpipe_tests());
TESTS_RUN(tests_isrpipe_read_timeout_tests());
}