tests/kernel: Add k_poll test for polling on message queues
Add tests for message queue polling functionality. Fixes: #26728 Signed-off-by: Nick Graves <nicholas.graves@samsara.com>
This commit is contained in:
parent
b445f13462
commit
56b9a422f7
3 changed files with 137 additions and 14 deletions
|
@ -22,6 +22,7 @@ extern void test_k_poll_user_mem_err(void);
|
|||
extern void test_k_poll_user_type_sem_err(void);
|
||||
extern void test_k_poll_user_type_signal_err(void);
|
||||
extern void test_k_poll_user_type_fifo_err(void);
|
||||
extern void test_k_poll_user_type_msgq_err(void);
|
||||
extern void test_poll_signal_init_null(void);
|
||||
extern void test_poll_signal_check_obj(void);
|
||||
extern void test_poll_signal_check_signal(void);
|
||||
|
@ -40,6 +41,7 @@ dummy_test(test_k_poll_user_mem_err);
|
|||
dummy_test(test_k_poll_user_type_sem_err);
|
||||
dummy_test(test_k_poll_user_type_signal_err);
|
||||
dummy_test(test_k_poll_user_type_fifo_err);
|
||||
dummy_test(test_k_poll_user_type_msgq_err);
|
||||
dummy_test(test_poll_signal_init_null);
|
||||
dummy_test(test_poll_signal_check_obj);
|
||||
dummy_test(test_poll_signal_check_signal);
|
||||
|
@ -79,6 +81,7 @@ void test_main(void)
|
|||
ztest_user_unit_test(test_k_poll_user_type_sem_err),
|
||||
ztest_user_unit_test(test_k_poll_user_type_signal_err),
|
||||
ztest_user_unit_test(test_k_poll_user_type_fifo_err),
|
||||
ztest_user_unit_test(test_k_poll_user_type_msgq_err),
|
||||
ztest_user_unit_test(test_poll_signal_init_null),
|
||||
ztest_user_unit_test(test_poll_signal_check_obj),
|
||||
ztest_user_unit_test(test_poll_signal_check_signal),
|
||||
|
|
|
@ -15,12 +15,18 @@ struct fifo_msg {
|
|||
|
||||
#define SIGNAL_RESULT 0x1ee7d00d
|
||||
#define FIFO_MSG_VALUE 0xdeadbeef
|
||||
#define MSGQ_MSG_SIZE 4
|
||||
#define MSGQ_MAX_MSGS 16
|
||||
#define MSGQ_MSG_VALUE {'a', 'b', 'c', 'd'}
|
||||
#define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
|
||||
/* verify k_poll() without waiting */
|
||||
static struct k_sem no_wait_sem;
|
||||
static struct k_fifo no_wait_fifo;
|
||||
static struct k_poll_signal no_wait_signal;
|
||||
#ifndef CONFIG_USERSPACE
|
||||
static struct k_msgq no_wait_msgq;
|
||||
#endif
|
||||
static struct k_sem zero_events_sem;
|
||||
static struct k_thread test_thread;
|
||||
static struct k_thread test_loprio_thread;
|
||||
|
@ -50,12 +56,23 @@ void test_poll_no_wait(void)
|
|||
{
|
||||
struct fifo_msg msg = { NULL, FIFO_MSG_VALUE }, *msg_ptr;
|
||||
unsigned int signaled;
|
||||
char msgq_recv_buf[MSGQ_MSG_SIZE] = {0};
|
||||
char msgq_msg[MSGQ_MSG_SIZE] = MSGQ_MSG_VALUE;
|
||||
int result;
|
||||
struct k_msgq *mq;
|
||||
#ifdef CONFIG_USERSPACE
|
||||
mq = k_object_alloc(K_OBJ_MSGQ);
|
||||
zassert_not_null(mq, "");
|
||||
#else
|
||||
mq = &no_wait_msgq;
|
||||
#endif
|
||||
|
||||
k_sem_init(&no_wait_sem, 1, 1);
|
||||
k_fifo_init(&no_wait_fifo);
|
||||
k_poll_signal_init(&no_wait_signal);
|
||||
|
||||
k_msgq_alloc_init(mq, MSGQ_MSG_SIZE, MSGQ_MAX_MSGS);
|
||||
|
||||
struct k_poll_event events[] = {
|
||||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
|
@ -69,6 +86,9 @@ void test_poll_no_wait(void)
|
|||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_IGNORE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
NULL),
|
||||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
mq),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
@ -107,6 +127,7 @@ void test_poll_no_wait(void)
|
|||
/* test polling events that are already ready */
|
||||
zassert_false(k_fifo_alloc_put(&no_wait_fifo, &msg), NULL);
|
||||
k_poll_signal_raise(&no_wait_signal, SIGNAL_RESULT);
|
||||
zassert_false(k_msgq_put(mq, msgq_msg, K_NO_WAIT), NULL);
|
||||
|
||||
zassert_equal(k_poll(events, ARRAY_SIZE(events), K_NO_WAIT), 0, "");
|
||||
|
||||
|
@ -126,11 +147,16 @@ void test_poll_no_wait(void)
|
|||
|
||||
zassert_equal(events[3].state, K_POLL_STATE_NOT_READY, "");
|
||||
|
||||
zassert_equal(events[4].state, K_POLL_STATE_MSGQ_DATA_AVAILABLE, "");
|
||||
zassert_false(k_msgq_get(mq, msgq_recv_buf, K_NO_WAIT), NULL);
|
||||
zassert_false(memcmp(msgq_msg, msgq_recv_buf, MSGQ_MSG_SIZE), "");
|
||||
|
||||
/* verify events are not ready anymore (user has to clear them first) */
|
||||
events[0].state = K_POLL_STATE_NOT_READY;
|
||||
events[1].state = K_POLL_STATE_NOT_READY;
|
||||
events[2].state = K_POLL_STATE_NOT_READY;
|
||||
events[3].state = K_POLL_STATE_NOT_READY;
|
||||
events[4].state = K_POLL_STATE_NOT_READY;
|
||||
k_poll_signal_reset(&no_wait_signal);
|
||||
|
||||
zassert_equal(k_poll(events, ARRAY_SIZE(events), K_NO_WAIT), -EAGAIN,
|
||||
|
@ -139,12 +165,17 @@ void test_poll_no_wait(void)
|
|||
zassert_equal(events[1].state, K_POLL_STATE_NOT_READY, "");
|
||||
zassert_equal(events[2].state, K_POLL_STATE_NOT_READY, "");
|
||||
zassert_equal(events[3].state, K_POLL_STATE_NOT_READY, "");
|
||||
zassert_equal(events[4].state, K_POLL_STATE_NOT_READY, "");
|
||||
|
||||
zassert_not_equal(k_sem_take(&no_wait_sem, K_NO_WAIT), 0, "");
|
||||
zassert_is_null(k_fifo_get(&no_wait_fifo, K_NO_WAIT), "");
|
||||
zassert_not_equal(k_msgq_get(mq, msgq_recv_buf, K_NO_WAIT), 0,
|
||||
"");
|
||||
}
|
||||
|
||||
/* verify k_poll() that has to wait */
|
||||
static struct k_msgq wait_msgq;
|
||||
static struct k_msgq *wait_msgq_ptr;
|
||||
|
||||
static K_SEM_DEFINE(wait_sem, 0, 1);
|
||||
static K_FIFO_DEFINE(wait_fifo);
|
||||
|
@ -156,6 +187,7 @@ struct fifo_msg wait_msg = { NULL, FIFO_MSG_VALUE };
|
|||
#define TAG_0 10
|
||||
#define TAG_1 11
|
||||
#define TAG_2 12
|
||||
#define TAG_3 13
|
||||
|
||||
struct k_poll_event wait_events[] = {
|
||||
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
|
||||
|
@ -170,21 +202,35 @@ struct k_poll_event wait_events[] = {
|
|||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_IGNORE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
NULL),
|
||||
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
&wait_msgq, TAG_3),
|
||||
};
|
||||
|
||||
static void poll_wait_helper(void *use_fifo, void *p2, void *p3)
|
||||
#define USE_FIFO (1 << 0)
|
||||
#define USE_MSGQ (1 << 1)
|
||||
|
||||
static void poll_wait_helper(void *use_queuelike, void *msgq, void *p3)
|
||||
{
|
||||
(void)p2; (void)p3;
|
||||
(void)p3;
|
||||
|
||||
k_sleep(K_MSEC(250));
|
||||
|
||||
k_sem_give(&wait_sem);
|
||||
|
||||
if ((intptr_t)use_fifo) {
|
||||
uintptr_t flags = (uintptr_t)use_queuelike;
|
||||
|
||||
if (flags & USE_FIFO) {
|
||||
k_fifo_alloc_put(&wait_fifo, &wait_msg);
|
||||
}
|
||||
|
||||
k_poll_signal_raise(&wait_signal, SIGNAL_RESULT);
|
||||
|
||||
if (flags & USE_MSGQ) {
|
||||
char m[] = MSGQ_MSG_VALUE;
|
||||
|
||||
k_msgq_put(msgq, &m[0], K_FOREVER);
|
||||
}
|
||||
}
|
||||
|
||||
/* check results for multiple events */
|
||||
|
@ -192,6 +238,8 @@ void check_results(struct k_poll_event *events, uint32_t event_type,
|
|||
bool is_available)
|
||||
{
|
||||
struct fifo_msg *msg_ptr;
|
||||
char msgq_recv_buf[MSGQ_MSG_SIZE] = {0};
|
||||
char msg[] = MSGQ_MSG_VALUE;
|
||||
|
||||
switch (event_type) {
|
||||
case K_POLL_TYPE_SEM_AVAILABLE:
|
||||
|
@ -244,6 +292,24 @@ void check_results(struct k_poll_event *events, uint32_t event_type,
|
|||
case K_POLL_TYPE_IGNORE:
|
||||
zassert_equal(wait_events[3].state, K_POLL_STATE_NOT_READY, "");
|
||||
break;
|
||||
case K_POLL_TYPE_MSGQ_DATA_AVAILABLE:
|
||||
if (is_available) {
|
||||
zassert_equal(events->state,
|
||||
K_POLL_STATE_MSGQ_DATA_AVAILABLE, "");
|
||||
|
||||
zassert_false(k_msgq_get(wait_msgq_ptr, msgq_recv_buf,
|
||||
K_NO_WAIT), "");
|
||||
zassert_false(memcmp(msg, msgq_recv_buf,
|
||||
MSGQ_MSG_SIZE), "");
|
||||
zassert_equal(events->tag, TAG_3, "");
|
||||
/* reset to not ready */
|
||||
events->state = K_POLL_STATE_NOT_READY;
|
||||
} else {
|
||||
zassert_equal(events->state, K_POLL_STATE_NOT_READY,
|
||||
"");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
__ASSERT(false, "invalid event type (0x%x)\n", event_type);
|
||||
break;
|
||||
|
@ -276,19 +342,20 @@ void check_results(struct k_poll_event *events, uint32_t event_type,
|
|||
* - N/A
|
||||
*
|
||||
* Test Procedure:
|
||||
* -# Use FIFO/semaphore/signal object to define poll event.
|
||||
* -# Initialize the FIFO/semaphore/signal object.
|
||||
* -# Use FIFO/semaphore/signal/message queue object to define poll event.
|
||||
* -# Initialize the FIFO/semaphore/signal/message queue object.
|
||||
* -# Create a thread to put FIFO,
|
||||
* give semaphore and raise signal.
|
||||
* give semaphore, raise signal, and put message queue.
|
||||
* -# Check the result when signal is raised,
|
||||
* semaphore is givn and fifo is filled.
|
||||
* semaphore is given, fifo is filled, and message is received.
|
||||
* -# Check the result when no event is satisfied.
|
||||
* -# Check the result when only semaphore is given.
|
||||
* -# Check the result when only FIFO is filled.
|
||||
* -# Check the result when only signal is raised.
|
||||
* -# Check the result when only message is received.
|
||||
*
|
||||
* Expected Test Result:
|
||||
* - FIFO/semaphore/signal events available/waitable in poll.
|
||||
* - FIFO/semaphore/signal/message queue events available/waitable in poll.
|
||||
*
|
||||
* Pass/Fail Criteria:
|
||||
* - Successful if check points in test procedure are all passed, otherwise failure.
|
||||
|
@ -302,20 +369,33 @@ void test_poll_wait(void)
|
|||
{
|
||||
const int main_low_prio = 10;
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
wait_msgq_ptr = k_object_alloc(K_OBJ_MSGQ);
|
||||
k_msgq_alloc_init(wait_msgq_ptr, MSGQ_MSG_SIZE, MSGQ_MAX_MSGS);
|
||||
|
||||
k_poll_event_init(&wait_events[4],
|
||||
K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
wait_msgq_ptr);
|
||||
wait_events[4].tag = TAG_3;
|
||||
#else
|
||||
wait_msgq_ptr = &wait_msgq;
|
||||
k_msgq_alloc_init(wait_msgq_ptr, MSGQ_MSG_SIZE, MSGQ_MAX_MSGS);
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
int old_prio = k_thread_priority_get(k_current_get());
|
||||
|
||||
k_poll_signal_init(&wait_signal);
|
||||
/*
|
||||
* Wait for 3 non-ready events to become ready from a higher priority
|
||||
* Wait for 4 non-ready events to become ready from a higher priority
|
||||
* thread.
|
||||
*/
|
||||
k_thread_priority_set(k_current_get(), main_low_prio);
|
||||
|
||||
k_thread_create(&test_thread, test_stack,
|
||||
K_THREAD_STACK_SIZEOF(test_stack),
|
||||
poll_wait_helper, (void *)1, 0, 0,
|
||||
poll_wait_helper, (void *)(USE_FIFO | USE_MSGQ), wait_msgq_ptr, 0,
|
||||
main_low_prio - 1, K_USER | K_INHERIT_PERMS,
|
||||
K_NO_WAIT);
|
||||
|
||||
|
@ -328,22 +408,26 @@ void test_poll_wait(void)
|
|||
|
||||
zassert_equal(rc, 0, "");
|
||||
/* all events should be available. */
|
||||
|
||||
check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, true);
|
||||
check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, true);
|
||||
check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, true);
|
||||
check_results(&wait_events[3], K_POLL_TYPE_IGNORE, true);
|
||||
check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, true);
|
||||
|
||||
/* verify events are not ready anymore */
|
||||
zassert_equal(k_poll(wait_events, ARRAY_SIZE(wait_events),
|
||||
K_SECONDS(1)), -EAGAIN, "");
|
||||
/* all events should not be available. */
|
||||
|
||||
check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
|
||||
check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
|
||||
check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
|
||||
check_results(&wait_events[3], K_POLL_TYPE_IGNORE, false);
|
||||
check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
|
||||
|
||||
/*
|
||||
* Wait for 2 out of 3 non-ready events to become ready from a higher
|
||||
* Wait for 2 out of 4 non-ready events to become ready from a higher
|
||||
* priority thread.
|
||||
*/
|
||||
k_thread_priority_set(k_current_get(), main_low_prio);
|
||||
|
@ -362,6 +446,7 @@ void test_poll_wait(void)
|
|||
check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, true);
|
||||
check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
|
||||
check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, true);
|
||||
check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
|
||||
|
||||
/*
|
||||
* Wait for each event to be ready from a lower priority thread, one at
|
||||
|
@ -370,17 +455,16 @@ void test_poll_wait(void)
|
|||
k_thread_create(&test_thread, test_stack,
|
||||
K_THREAD_STACK_SIZEOF(test_stack),
|
||||
poll_wait_helper,
|
||||
(void *)1, 0, 0, old_prio + 1,
|
||||
(void *)(USE_FIFO | USE_MSGQ), wait_msgq_ptr, 0, old_prio + 1,
|
||||
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
|
||||
|
||||
/* semaphore */
|
||||
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
||||
|
||||
zassert_equal(rc, 0, "");
|
||||
|
||||
check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, true);
|
||||
check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
|
||||
check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
|
||||
check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
|
||||
|
||||
/* fifo */
|
||||
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
||||
|
@ -390,6 +474,7 @@ void test_poll_wait(void)
|
|||
check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
|
||||
check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, true);
|
||||
check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
|
||||
check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
|
||||
|
||||
/* poll signal */
|
||||
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
||||
|
@ -399,6 +484,18 @@ void test_poll_wait(void)
|
|||
check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
|
||||
check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
|
||||
check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, true);
|
||||
check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, false);
|
||||
|
||||
/* message queue */
|
||||
rc = k_poll(wait_events, ARRAY_SIZE(wait_events), K_SECONDS(1));
|
||||
|
||||
zassert_equal(rc, 0, "");
|
||||
|
||||
check_results(&wait_events[0], K_POLL_TYPE_SEM_AVAILABLE, false);
|
||||
check_results(&wait_events[1], K_POLL_TYPE_DATA_AVAILABLE, false);
|
||||
check_results(&wait_events[2], K_POLL_TYPE_SIGNAL, false);
|
||||
check_results(&wait_events[4], K_POLL_TYPE_MSGQ_DATA_AVAILABLE, true);
|
||||
|
||||
}
|
||||
|
||||
/* verify k_poll() that waits on object which gets cancellation */
|
||||
|
|
|
@ -212,6 +212,29 @@ void test_k_poll_user_type_fifo_err(void)
|
|||
k_poll(event, 1, K_NO_WAIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test API k_poll with NULL message queue event in user mode
|
||||
*
|
||||
* @details Define a poll, and using API k_poll with NULL message queue
|
||||
* as parameter to check if a error will be met.
|
||||
*
|
||||
* @see k_poll()
|
||||
*
|
||||
* @ingroup kernel_poll_tests
|
||||
*/
|
||||
void test_k_poll_user_type_msgq_err(void)
|
||||
{
|
||||
struct k_poll_event event[] = {
|
||||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
||||
K_POLL_MODE_NOTIFY_ONLY,
|
||||
NULL),
|
||||
};
|
||||
|
||||
ztest_set_fault_valid(true);
|
||||
k_poll(event, 1, K_NO_WAIT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Test API k_poll_signal_init with NULL in user mode
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue