mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Ryan Gardner <ryan.p.gardner@boeing.com>
To: musl@lists.openwall.com
Cc: Ryan Gardner <ryan.p.gardner@boeing.com>
Subject: [musl] [PATCH 1/3 libc-test] functional:time:clock_nanosleep test
Date: Tue,  5 Nov 2024 22:44:35 +0000	[thread overview]
Message-ID: <20241105224437.67-1-ryan.p.gardner@boeing.com> (raw)

Testing of musl API against POSIX 2008 standard.

Tests added:

- EINTR is returned when sleep is interupted by a signal
- ENOTSUP is returned when clock_id specifies an unsupported clock
- EINVAL is returned when tv_nsec is out of range
- EINVAL is returned when clock_id specifies an unknown clock
- EINVAL is returned when clokc_id specifies the CPU-time clock of calling thread
- rmtp is set to the remaining unslept time when interupted.
- time elapses as expected

References:
- https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_nanosleep.html

Signed-off-by: Ryan Gardner <ryan.p.gardner@boeing.com>
---
 src/functional/clock_nanosleep.c | 133 +++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)
 create mode 100644 src/functional/clock_nanosleep.c

diff --git a/src/functional/clock_nanosleep.c b/src/functional/clock_nanosleep.c
new file mode 100644
index 0000000..071000a
--- /dev/null
+++ b/src/functional/clock_nanosleep.c
@@ -0,0 +1,133 @@
+/*
+ * clock_nanosleep unit test
+ */
+
+#include "test.h"
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#define MAX_NSEC 1000000000
+#define SLEEP_NANO 500000
+#define TEST(c, ...) ((c) || (t_error(#c " failed: " __VA_ARGS__), 0))
+
+static void dummy_signal_handler(int signum) {}
+
+static void test_time_elapsed(void)
+{
+	// get start time
+	struct timespec time1;
+	if (clock_gettime(CLOCK_MONOTONIC, &time1) == -1) {
+		t_error("clock_gettime() failed. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	struct timespec ts = {0, SLEEP_NANO};
+	TEST(clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts) == 0,
+	     "clock_nanosleep failed with clock id %d\n", CLOCK_MONOTONIC);
+
+	// get finish time
+	struct timespec time2;
+	if (clock_gettime(CLOCK_MONOTONIC, &time2) == -1) {
+		t_error("clock_gettime() failed. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	// calculate elapsed time
+	time_t elapsed = time2.tv_sec > time1.tv_sec
+	                     ? time2.tv_nsec + (MAX_NSEC - time1.tv_nsec)
+	                     : time2.tv_nsec - time1.tv_nsec;
+
+	TEST(elapsed >= SLEEP_NANO,
+	     "Elapsed time test failed: expected >= %d "
+	     "nanoseconds, got %ld nanoseconds.\n",
+	     SLEEP_NANO, elapsed);
+}
+
+static void test_invalid_inputs(void)
+{
+	struct timespec ts = {1, 0};
+
+	// check EINVAL is returned when tv_nsec is too big
+	ts.tv_nsec = MAX_NSEC;
+	int retval = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
+	TEST(retval == EINVAL,
+	     "Oversized tv_nsec test failed: Expected %s, got %s\n",
+	     strerror(EINVAL), strerror(retval));
+
+	// check EINVAL is returned when tv_nsec is too small
+	ts.tv_nsec = -1;
+	retval = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
+	TEST(retval == EINVAL,
+	     "Undersized tv_nsec test failed: Expected %s, got %s\n",
+	     strerror(EINVAL), strerror(retval));
+
+	// check EINVAL is returned when given CPU_time clock of calling thread
+	retval = clock_nanosleep(CLOCK_THREAD_CPUTIME_ID, 0, &ts, NULL);
+	TEST(retval == EINVAL,
+	     "Calling threads cpu clock id test failed: Expected %s, got %s\n",
+	     strerror(EINVAL), strerror(retval));
+
+	const int unknown_clock = 123;
+
+	// check EINVAL is returned when given unknown clock
+	retval = clock_nanosleep(unknown_clock, 0, &ts, NULL);
+	TEST(retval == EINVAL,
+	     "Unknown clock id test failed: Expected %s, got %s\n",
+	     strerror(EINVAL), strerror(retval));
+
+	// check ENOTSUP is returned when given an unsupported clock
+	retval = clock_nanosleep(CLOCK_MONOTONIC_COARSE, 0, &ts, NULL);
+	TEST(retval == ENOTSUP,
+	     "Unsupported clock test failed. Expected %s, got %s\n",
+	     strerror(ENOTSUP), strerror(retval));
+}
+
+static void test_interupted_sleep()
+{
+	// check EINTR is returned when sleep is interupted by a signal handler
+	struct sigaction sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = dummy_signal_handler;
+	sigaction(SIGALRM, &sa, NULL);
+
+	timer_t timerid = NULL;
+	if (timer_create(CLOCK_MONOTONIC, NULL, &timerid) == -1) {
+		t_error("timer_create() failed. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	struct itimerspec its = {
+	    .it_value.tv_sec = 0,
+	    .it_value.tv_nsec = SLEEP_NANO,
+	};
+	if (timer_settime(timerid, 0, &its, NULL) == -1) {
+		t_error("timer_settime() failed. Errno: %s\n", strerror(errno));
+		timer_delete(timerid);
+		return;
+	}
+
+	struct timespec ts = {2, 0};
+	struct timespec rmtp = {0, 0};
+	int retval = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &rmtp);
+
+	TEST(retval == EINTR, "Interupted sleep test failed: Expected %s, got %s\n",
+	     strerror(EINTR), strerror(retval));
+
+	// check that the remaining unslept time is returned into rmtp
+	TEST(rmtp.tv_sec > 0 || rmtp.tv_nsec > 0,
+	     "rmtp test failed: Expected value > 0, got rmpt.tv_sec = %lu, "
+	     "rmtp.tv_nsec = %lu\n",
+	     rmtp.tv_sec, rmtp.tv_nsec);
+
+	timer_delete(timerid);
+}
+
+int main(void)
+{
+	test_time_elapsed();
+	test_invalid_inputs();
+	test_interupted_sleep();
+	return t_status;
+}
-- 
2.34.1


             reply	other threads:[~2024-11-05 22:45 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-05 22:44 Ryan Gardner [this message]
2024-11-05 22:44 ` [musl] [PATCH 2/3 libc-test] functional:time:timer_delete test Ryan Gardner
2024-11-05 22:44 ` [musl] [PATCH 3/3 libc-test] functional:time:timer_settime test Ryan Gardner
2024-11-06  7:38 ` [musl] [PATCH 1/3 libc-test] functional:time:clock_nanosleep test Szabolcs Nagy
2024-11-07  4:39 Gardner, Ryan P
2024-11-10 11:45 ` Szabolcs Nagy
2024-11-13 11:51 ` Szabolcs Nagy
2024-11-15  5:16 Gardner, Ryan P

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241105224437.67-1-ryan.p.gardner@boeing.com \
    --to=ryan.p.gardner@boeing.com \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).