mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-18 11:03:50 +01:00
sys/isrpipe: add unit tests
This patch adds unit tests for the isrpipe module.
This commit is contained in:
parent
9774a0ce48
commit
a749e3493d
1
tests/unittests/tests-isrpipe/Makefile
Normal file
1
tests/unittests/tests-isrpipe/Makefile
Normal file
@ -0,0 +1 @@
|
|||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
2
tests/unittests/tests-isrpipe/Makefile.include
Normal file
2
tests/unittests/tests-isrpipe/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
USEMODULE += isrpipe
|
||||||
|
USEMODULE += isrpipe_read_timeout
|
||||||
95
tests/unittests/tests-isrpipe/tests-isrpipe-read_timeout.c
Normal file
95
tests/unittests/tests-isrpipe/tests-isrpipe-read_timeout.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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 <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "embUnit/embUnit.h"
|
||||||
|
|
||||||
|
#include "isrpipe/read_timeout.h"
|
||||||
|
#include "tests-isrpipe.h"
|
||||||
|
|
||||||
|
static void test_read_timeout(void)
|
||||||
|
{
|
||||||
|
uint8_t buffer[2] = {0};
|
||||||
|
uint8_t read_buf[2];
|
||||||
|
isrpipe_t pipe;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* prep the pipe */
|
||||||
|
isrpipe_init(&pipe, buffer, ARRAY_SIZE(buffer));
|
||||||
|
|
||||||
|
/* test timeout */
|
||||||
|
res = isrpipe_read_timeout(&pipe, read_buf, ARRAY_SIZE(read_buf), 1);
|
||||||
|
TEST_ASSERT_EQUAL_INT(-ETIMEDOUT, res);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&pipe, 1));
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&pipe, 2));
|
||||||
|
|
||||||
|
/* pipe now holds 1, 2 */
|
||||||
|
|
||||||
|
/* test successful read */
|
||||||
|
res = isrpipe_read_timeout(&pipe, read_buf, ARRAY_SIZE(read_buf), 1);
|
||||||
|
TEST_ASSERT_EQUAL_INT(ARRAY_SIZE(read_buf), res);
|
||||||
|
|
||||||
|
/* pipe now empty */
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&pipe, 3));
|
||||||
|
|
||||||
|
/* pipe now holds 3 */
|
||||||
|
|
||||||
|
/* test partial read */
|
||||||
|
res = isrpipe_read_timeout(&pipe, read_buf, ARRAY_SIZE(read_buf), 1);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_read_all_timeout(void)
|
||||||
|
{
|
||||||
|
uint8_t buffer[2] = {0};
|
||||||
|
uint8_t read_buf[2];
|
||||||
|
isrpipe_t pipe;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* prep the pipe */
|
||||||
|
isrpipe_init(&pipe, buffer, ARRAY_SIZE(buffer));
|
||||||
|
|
||||||
|
/* test timeout */
|
||||||
|
res = isrpipe_read_all_timeout(&pipe, read_buf, ARRAY_SIZE(read_buf), 1);
|
||||||
|
TEST_ASSERT_EQUAL_INT(-ETIMEDOUT, res);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&pipe, 1));
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&pipe, 2));
|
||||||
|
|
||||||
|
/* pipe now holds 1, 2 */
|
||||||
|
|
||||||
|
/* test successful read */
|
||||||
|
res = isrpipe_read_all_timeout(&pipe, read_buf, ARRAY_SIZE(read_buf), 1);
|
||||||
|
TEST_ASSERT_EQUAL_INT(ARRAY_SIZE(read_buf), res);
|
||||||
|
|
||||||
|
/* pipe now empty */
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, isrpipe_write_one(&pipe, 3));
|
||||||
|
|
||||||
|
/* pipe now holds 3 */
|
||||||
|
|
||||||
|
/* test timeout - isrpipe_read_all_timeout() does not allow partial reads */
|
||||||
|
res = isrpipe_read_all_timeout(&pipe, read_buf, ARRAY_SIZE(read_buf), 1);
|
||||||
|
TEST_ASSERT_EQUAL_INT(-ETIMEDOUT, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test *tests_isrpipe_read_timeout_tests(void)
|
||||||
|
{
|
||||||
|
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||||
|
new_TestFixture(test_read_timeout),
|
||||||
|
new_TestFixture(test_read_all_timeout),
|
||||||
|
};
|
||||||
|
|
||||||
|
EMB_UNIT_TESTCALLER(isrpipe_tests, NULL, NULL, fixtures);
|
||||||
|
|
||||||
|
return (Test *)&isrpipe_tests;
|
||||||
|
}
|
||||||
243
tests/unittests/tests-isrpipe/tests-isrpipe.c
Normal file
243
tests/unittests/tests-isrpipe/tests-isrpipe.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
* 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());
|
||||||
|
}
|
||||||
50
tests/unittests/tests-isrpipe/tests-isrpipe.h
Normal file
50
tests/unittests/tests-isrpipe/tests-isrpipe.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup unittests
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Unittests for ISR pipe
|
||||||
|
*
|
||||||
|
* @author Joshua DeWeese <jdeweese@primecontrols.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "embUnit.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Entry point of the test suite
|
||||||
|
*/
|
||||||
|
void tests_isrpipe(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates tests for isrpipe.h
|
||||||
|
*
|
||||||
|
* @return embUnit tests if successful, NULL if not.
|
||||||
|
*/
|
||||||
|
Test *tests_isrpipe_tests(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates tests for isrpipe/read_timeout.h
|
||||||
|
*
|
||||||
|
* @return embUnit tests if successful, NULL if not.
|
||||||
|
*/
|
||||||
|
Test *tests_isrpipe_read_timeout_tests(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
Loading…
x
Reference in New Issue
Block a user