blob: 1e7f871137c14077c02962af6587d88c3c1132b9 [file] [log] [blame]
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/ztress.h>
volatile int ztress_dummy;
bool ztress_handler_busy(void *user_data, uint32_t cnt, bool last, int prio)
{
/* On nios2 k_busy_wait in k_timer handler context is hanging. */
if (IS_ENABLED(CONFIG_NIOS2) && k_is_in_isr()) {
for (int i = 0; i < 1000; i++) {
ztress_dummy++;
}
} else {
k_busy_wait((prio+1) * 100);
}
return true;
}
ZTEST(ztress, test_timeout)
{
int64_t d;
uint32_t repeat = 1000000;
k_timeout_t t = Z_TIMEOUT_TICKS(20);
int err;
int timeout = 1000;
ztress_set_timeout(K_MSEC(timeout));
d = k_uptime_get();
/* Set of two threads */
ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, t),
ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 1000, t));
d = k_uptime_get() - d;
zassert_within(d, 1000, 200);
/* Set of two threads and timer. Test is setup manually, without helper macro. */
struct ztress_context_data timer_data =
ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 0, t);
struct ztress_context_data thread_data[] = {
ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t),
ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t)
};
d = k_uptime_get();
err = ztress_execute(&timer_data, thread_data, ARRAY_SIZE(thread_data));
zassert_equal(err, 0, "ztress_execute failed (err: %d)", err);
d = k_uptime_get() - d;
zassert_within(d, timeout + 500, 500);
ztress_set_timeout(K_NO_WAIT);
}
static void timeout_abort(struct k_timer *timer)
{
ztress_abort();
}
ZTEST(ztress, test_abort)
{
struct k_timer timer;
uint32_t repeat = 10000000;
k_timer_init(&timer, timeout_abort, NULL);
k_timer_start(&timer, K_MSEC(100), K_NO_WAIT);
ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, K_MSEC(1)),
ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, K_MSEC(1)));
zassert_true(ztress_exec_count(0) < repeat);
zassert_true(ztress_exec_count(1) < repeat);
}
ZTEST(ztress, test_repeat_completion)
{
uint32_t repeat = 10;
/* Set of two threads */
ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(20)),
ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(20)));
for (int i = 0; i < 2; i++) {
uint32_t exec_cnt = ztress_exec_count(i);
zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10);
}
/* Set of two threads and timer */
ZTRESS_EXECUTE(ZTRESS_TIMER(ztress_handler_busy, NULL, repeat, Z_TIMEOUT_TICKS(30)),
ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(30)),
ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(30)));
for (int i = 0; i < 3; i++) {
uint32_t exec_cnt = ztress_exec_count(i);
zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10);
}
}
ZTEST(ztress, test_no_context_requirements)
{
uint32_t repeat = 10;
/* Set of two threads. First thread has no ending condition (exec_cnt and
* preempt_cnt are 0)
*/
ZTRESS_EXECUTE(ZTRESS_THREAD(ztress_handler_busy, NULL, 0, 0, Z_TIMEOUT_TICKS(20)),
ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(20)));
uint32_t exec_cnt = ztress_exec_count(1);
zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10, "exec_cnt: %u", exec_cnt);
/* Set of two threads. Second thread and timer context has no ending
* condition (exec_cnt and preempt_cnt are 0).
*/
ZTRESS_EXECUTE(ZTRESS_TIMER(ztress_handler_busy, NULL, 0, Z_TIMEOUT_TICKS(30)),
ZTRESS_THREAD(ztress_handler_busy, NULL, repeat, 0, Z_TIMEOUT_TICKS(30)),
ZTRESS_THREAD(ztress_handler_busy, NULL, 0, 0, Z_TIMEOUT_TICKS(30)));
exec_cnt = ztress_exec_count(1);
zassert_true(exec_cnt >= repeat && exec_cnt < repeat + 10);
}
ZTEST(ztress, test_too_many_threads)
{
uint32_t repeat = 10;
k_timeout_t t = Z_TIMEOUT_TICKS(20);
int err;
/* Negative check on too many threads set and a timer.
* Assuming ZTRESS_MAX_THREADS=3
*/
struct ztress_context_data timer_data =
ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 0, t);
struct ztress_context_data thread_data[] = {
ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t),
ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t),
ZTRESS_CONTEXT_INITIALIZER(ztress_handler_busy, NULL, repeat, 1000, t)
};
err = ztress_execute(&timer_data, thread_data, ARRAY_SIZE(thread_data));
zassert_equal(err, -EINVAL, "ztress_execute: unexpected err=%d (expected -EINVAL)", err);
}
ZTEST_SUITE(ztress, NULL, NULL, NULL, NULL, NULL);