posix: clock_nanosleep tests
Adds error and lower bounds tests for the posix clock_nanosleep function. Refactors common test functions to be shared by both clock_nanosleep and nanosleep tests. Signed-off-by: Tom Finet <tom.codeninja@gmail.com>
This commit is contained in:
parent
d09a1c39f9
commit
ceb59951c5
1 changed files with 124 additions and 23 deletions
|
@ -11,7 +11,19 @@
|
|||
#include <zephyr/sys_clock.h>
|
||||
#include <zephyr/ztest.h>
|
||||
|
||||
ZTEST(posix_apis, test_nanosleep_errors_errno)
|
||||
#define SELECT_NANOSLEEP 1
|
||||
#define SELECT_CLOCK_NANOSLEEP 0
|
||||
|
||||
static inline int select_nanosleep(int selection, clockid_t clock_id, int flags,
|
||||
const struct timespec *rqtp, struct timespec *rmtp)
|
||||
{
|
||||
if (selection == SELECT_NANOSLEEP) {
|
||||
return nanosleep(rqtp, rmtp);
|
||||
}
|
||||
return clock_nanosleep(clock_id, flags, rqtp, rmtp);
|
||||
}
|
||||
|
||||
static void common_errors(int selection, clockid_t clock_id, int flags)
|
||||
{
|
||||
struct timespec rem = {};
|
||||
struct timespec req = {};
|
||||
|
@ -19,12 +31,12 @@ ZTEST(posix_apis, test_nanosleep_errors_errno)
|
|||
/*
|
||||
* invalid parameters
|
||||
*/
|
||||
zassert_equal(nanosleep(NULL, NULL), -1);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, NULL, NULL), -1);
|
||||
zassert_equal(errno, EFAULT);
|
||||
|
||||
/* NULL request */
|
||||
errno = 0;
|
||||
zassert_equal(nanosleep(NULL, &rem), -1);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, NULL, &rem), -1);
|
||||
zassert_equal(errno, EFAULT);
|
||||
/* Expect rem to be the same when function returns */
|
||||
zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d", rem.tv_sec, 0);
|
||||
|
@ -33,23 +45,23 @@ ZTEST(posix_apis, test_nanosleep_errors_errno)
|
|||
/* negative times */
|
||||
errno = 0;
|
||||
req = (struct timespec){.tv_sec = -1, .tv_nsec = 0};
|
||||
zassert_equal(nanosleep(&req, NULL), -1);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, &req, NULL), -1);
|
||||
zassert_equal(errno, EINVAL);
|
||||
|
||||
errno = 0;
|
||||
req = (struct timespec){.tv_sec = 0, .tv_nsec = -1};
|
||||
zassert_equal(nanosleep(&req, NULL), -1);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, &req, NULL), -1);
|
||||
zassert_equal(errno, EINVAL);
|
||||
|
||||
errno = 0;
|
||||
req = (struct timespec){.tv_sec = -1, .tv_nsec = -1};
|
||||
zassert_equal(nanosleep(&req, NULL), -1);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, &req, NULL), -1);
|
||||
zassert_equal(errno, EINVAL);
|
||||
|
||||
/* nanoseconds too high */
|
||||
errno = 0;
|
||||
req = (struct timespec){.tv_sec = 0, .tv_nsec = 1000000000};
|
||||
zassert_equal(nanosleep(&req, NULL), -1);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, &req, NULL), -1);
|
||||
zassert_equal(errno, EINVAL);
|
||||
|
||||
/*
|
||||
|
@ -59,13 +71,13 @@ ZTEST(posix_apis, test_nanosleep_errors_errno)
|
|||
|
||||
/* Happy path, plus make sure the const input is unmodified */
|
||||
req = (struct timespec){.tv_sec = 1, .tv_nsec = 1};
|
||||
zassert_equal(nanosleep(&req, NULL), 0);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, &req, NULL), 0);
|
||||
zassert_equal(errno, 0);
|
||||
zassert_equal(req.tv_sec, 1);
|
||||
zassert_equal(req.tv_nsec, 1);
|
||||
|
||||
/* Sleep for 0.0 s. Expect req & rem to be the same when function returns */
|
||||
zassert_equal(nanosleep(&req, &rem), 0);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, &req, &rem), 0);
|
||||
zassert_equal(errno, 0);
|
||||
zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d", rem.tv_sec, 0);
|
||||
zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0);
|
||||
|
@ -77,15 +89,43 @@ ZTEST(posix_apis, test_nanosleep_errors_errno)
|
|||
* Expect rem to be zero after returning.
|
||||
*/
|
||||
req = (struct timespec){.tv_sec = 0, .tv_nsec = 1};
|
||||
zassert_equal(nanosleep(&req, &req), 0);
|
||||
zassert_equal(select_nanosleep(selection, clock_id, flags, &req, &req), 0);
|
||||
zassert_equal(errno, 0);
|
||||
zassert_equal(req.tv_sec, 0, "actual: %d expected: %d", req.tv_sec, 0);
|
||||
zassert_equal(req.tv_nsec, 0, "actual: %d expected: %d", req.tv_nsec, 0);
|
||||
}
|
||||
|
||||
static void common(const uint32_t s, uint32_t ns)
|
||||
ZTEST(posix_apis, test_nanosleep_errors_errno)
|
||||
{
|
||||
common_errors(SELECT_NANOSLEEP, CLOCK_REALTIME, 0);
|
||||
}
|
||||
|
||||
ZTEST(posix_apis, test_clock_nanosleep_errors_errno)
|
||||
{
|
||||
struct timespec rem = {};
|
||||
struct timespec req = {};
|
||||
|
||||
common_errors(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME);
|
||||
|
||||
/* Absolute timeout in the past. */
|
||||
clock_gettime(CLOCK_MONOTONIC, &req);
|
||||
zassert_equal(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &req, &rem), 0);
|
||||
zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d", rem.tv_sec, 0);
|
||||
zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0);
|
||||
|
||||
/* Absolute timeout in the past relative to the realtime clock. */
|
||||
clock_gettime(CLOCK_REALTIME, &req);
|
||||
zassert_equal(clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &req, &rem), 0);
|
||||
zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d", rem.tv_sec, 0);
|
||||
zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0);
|
||||
}
|
||||
|
||||
static void common_lower_bound_check(int selection, clockid_t clock_id, int flags, const uint32_t s,
|
||||
uint32_t ns)
|
||||
{
|
||||
int r;
|
||||
uint64_t actual_ns;
|
||||
uint64_t exp_ns;
|
||||
uint32_t now;
|
||||
uint32_t then;
|
||||
struct timespec rem = {0, 0};
|
||||
|
@ -93,24 +133,24 @@ static void common(const uint32_t s, uint32_t ns)
|
|||
|
||||
errno = 0;
|
||||
then = k_cycle_get_32();
|
||||
r = nanosleep(&req, &rem);
|
||||
r = select_nanosleep(selection, clock_id, flags, &req, &rem);
|
||||
now = k_cycle_get_32();
|
||||
|
||||
zassert_equal(r, 0, "actual: %d expected: %d", r, -1);
|
||||
zassert_equal(r, 0, "actual: %d expected: %d", r, 0);
|
||||
zassert_equal(errno, 0, "actual: %d expected: %d", errno, 0);
|
||||
zassert_equal(req.tv_sec, s, "actual: %d expected: %d", req.tv_sec, s);
|
||||
zassert_equal(req.tv_nsec, ns, "actual: %d expected: %d", req.tv_nsec, ns);
|
||||
zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d", rem.tv_sec, 0);
|
||||
zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d", rem.tv_nsec, 0);
|
||||
|
||||
uint64_t actual_ns = k_cyc_to_ns_ceil64((now - then));
|
||||
uint64_t exp_ns = (uint64_t)s * NSEC_PER_SEC + ns;
|
||||
actual_ns = k_cyc_to_ns_ceil64((now - then * selection));
|
||||
|
||||
exp_ns = (uint64_t)s * NSEC_PER_SEC + ns;
|
||||
/* round up to the nearest microsecond for k_busy_wait() */
|
||||
exp_ns = DIV_ROUND_UP(exp_ns, NSEC_PER_USEC) * NSEC_PER_USEC;
|
||||
|
||||
/* lower bounds check */
|
||||
zassert_true(actual_ns >= exp_ns,
|
||||
"actual: %llu expected: %llu", actual_ns, exp_ns);
|
||||
zassert_true(actual_ns >= exp_ns, "actual: %llu expected: %llu", actual_ns, exp_ns);
|
||||
|
||||
/* TODO: Upper bounds check when hr timers are available */
|
||||
}
|
||||
|
@ -118,20 +158,81 @@ static void common(const uint32_t s, uint32_t ns)
|
|||
ZTEST(posix_apis, test_nanosleep_execution)
|
||||
{
|
||||
/* sleep for 1ns */
|
||||
common(0, 1);
|
||||
common_lower_bound_check(SELECT_NANOSLEEP, 0, 0, 0, 1);
|
||||
|
||||
/* sleep for 1us + 1ns */
|
||||
common(0, 1001);
|
||||
common_lower_bound_check(SELECT_NANOSLEEP, 0, 0, 0, 1001);
|
||||
|
||||
/* sleep for 500000000ns */
|
||||
common(0, 500000000);
|
||||
common_lower_bound_check(SELECT_NANOSLEEP, 0, 0, 0, 500000000);
|
||||
|
||||
/* sleep for 1s */
|
||||
common(1, 0);
|
||||
common_lower_bound_check(SELECT_NANOSLEEP, 0, 0, 1, 0);
|
||||
|
||||
/* sleep for 1s + 1ns */
|
||||
common(1, 1);
|
||||
common_lower_bound_check(SELECT_NANOSLEEP, 0, 0, 1, 1);
|
||||
|
||||
/* sleep for 1s + 1us + 1ns */
|
||||
common(1, 1001);
|
||||
common_lower_bound_check(SELECT_NANOSLEEP, 0, 0, 1, 1001);
|
||||
}
|
||||
|
||||
ZTEST(posix_apis, test_clock_nanosleep_execution)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
|
||||
/* absolute sleeps with the monotonic clock and reference time ts */
|
||||
|
||||
/* until 1s + 1ns past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
|
||||
ts.tv_sec + 1, 1);
|
||||
|
||||
/* until 1s + 1us past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
|
||||
ts.tv_sec + 1, 1000);
|
||||
|
||||
/* until 1s + 500000000ns past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
|
||||
ts.tv_sec + 1, 500000000);
|
||||
|
||||
/* until 2s past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
|
||||
ts.tv_sec + 2, 0);
|
||||
|
||||
/* until 2s + 1ns past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
|
||||
ts.tv_sec + 2, 1);
|
||||
|
||||
/* until 2s + 1us + 1ns past reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_MONOTONIC, TIMER_ABSTIME,
|
||||
ts.tv_sec + 2, 1001);
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
/* absolute sleeps with the real time clock and adjusted reference time ts */
|
||||
|
||||
/* until 1s + 1ns past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
|
||||
ts.tv_sec + 1, 1);
|
||||
|
||||
/* until 1s + 1us past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
|
||||
ts.tv_sec + 1, 1000);
|
||||
|
||||
/* until 1s + 500000000ns past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
|
||||
ts.tv_sec + 1, 500000000);
|
||||
|
||||
/* until 2s past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
|
||||
ts.tv_sec + 2, 0);
|
||||
|
||||
/* until 2s + 1ns past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
|
||||
ts.tv_sec + 2, 1);
|
||||
|
||||
/* until 2s + 1us + 1ns past the reference time */
|
||||
common_lower_bound_check(SELECT_CLOCK_NANOSLEEP, CLOCK_REALTIME, TIMER_ABSTIME,
|
||||
ts.tv_sec + 2, 1001);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue