mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-18 02:53:52 +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