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 3/3 libc-test] functional:time:timer_settime test
Date: Tue,  5 Nov 2024 22:44:37 +0000	[thread overview]
Message-ID: <20241105224437.67-3-ryan.p.gardner@boeing.com> (raw)
In-Reply-To: <20241105224437.67-1-ryan.p.gardner@boeing.com>

Testing of musl API against POSIX 2008 standard.

Tests added:

- EINVAL is returned when value value struct is invalid
- setting an already armed timer results in a reset
- setting an already armed timer with it_value = 0 results
  in the timer being disarmed
- timer expires repeatedly when given non-zero interval value
- ovalue is set correctly

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

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

diff --git a/src/functional/timer_settime.c b/src/functional/timer_settime.c
new file mode 100644
index 0000000..d5597fb
--- /dev/null
+++ b/src/functional/timer_settime.c
@@ -0,0 +1,212 @@
+/*
+ * timer_settime unit test
+ */
+
+#include "test.h"
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#define TEST(c, ...) ((c) || (t_error(#c " failed: " __VA_ARGS__), 0))
+#define TIME_NANO 500000
+#define OVERSIZED_NANOSECONDS 1000000001
+#define NUM_REPEATS 5
+
+volatile int timeout_count = 0;
+static void timeout_signal_counter(int signum) { timeout_count++; }
+
+static void test_settime(void)
+{
+	timer_t timerid = NULL;
+	if (timer_create(CLOCK_REALTIME, NULL, &timerid) == -1) {
+		t_error("Failed to create timer. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	struct itimerspec its = {
+	    .it_value = {1, TIME_NANO},
+	    .it_interval = {1, TIME_NANO},
+	};
+
+	// test timer_settime() returns 0 when successful
+	TEST(timer_settime(timerid, 0, &its, NULL) == 0,
+	     "Failed to set timer. Errno: %s\n", strerror(errno));
+
+	struct itimerspec res;
+	if (timer_gettime(timerid, &res) == -1) {
+		t_error("Failed to get timer time. Errno: %s\n", strerror(errno));
+		timer_delete(timerid);
+		return;
+	}
+
+	// test values from timer_settime() are set properly
+	TEST(res.it_value.tv_sec == 1 && res.it_value.tv_nsec != 0 &&
+	         res.it_interval.tv_sec == 1 &&
+	         res.it_interval.tv_nsec == TIME_NANO,
+	     "Failed to set correct timer values\n");
+
+	timer_delete(timerid);
+}
+
+static void test_periodic_timer(void)
+{
+	// setup signal handler
+	struct sigaction sa;
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = timeout_signal_counter;
+	sigaction(SIGALRM, &sa, NULL);
+
+	timer_t timerid = NULL;
+	if (timer_create(CLOCK_REALTIME, NULL, &timerid) == -1) {
+		t_error("Failed to create timer. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	struct itimerspec its = {
+	    .it_value = {0, TIME_NANO},
+	    .it_interval = {0, TIME_NANO},
+	};
+
+	TEST(timer_settime(timerid, 0, &its, NULL) == 0,
+	     "Failed to set timer. Errno: %s\n", strerror(errno));
+
+	struct timespec sleep_time = {
+	    .tv_sec = 1,
+	    .tv_nsec = 0,
+	};
+
+	// sleep for 1 second or until 5 timer timeouts have occured
+	while (
+	    clock_nanosleep(CLOCK_REALTIME, 0, &sleep_time, &sleep_time) == EINTR &&
+	    timeout_count < NUM_REPEATS) {
+		continue;
+	};
+
+	// test that the timer repeats after timeout
+	TEST(timeout_count >= NUM_REPEATS,
+	     "Failed periodic timer test. Expected timeout_count value >= 5, got "
+	     "%d\n",
+	     timeout_count);
+
+	timer_delete(timerid);
+}
+
+static void test_invalid_inputs(void)
+{
+	timer_t timerid = NULL;
+	if (timer_create(CLOCK_REALTIME, NULL, &timerid) == -1) {
+		t_error("Failed to create timer. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	struct itimerspec its = {
+	    .it_value = {0, OVERSIZED_NANOSECONDS},
+	    .it_interval = {0, 0},
+	};
+
+	TEST(timer_settime(timerid, 0, &its, NULL) == -1 && errno == EINVAL,
+	     "Oversized nanoseconds test failed, expected %s,got %s\n",
+	     strerror(EINVAL), strerror(errno));
+
+	errno = 0;
+	its.it_value.tv_nsec = -1;
+
+	TEST(timer_settime(timerid, 0, &its, NULL) == -1 && errno == EINVAL,
+	     "Undersized nanoseconds test failed, expected %s,got %s\n",
+	     strerror(EINVAL), strerror(errno));
+
+	timer_delete(timerid);
+}
+
+static void test_timer_resets(void)
+{
+	timer_t timerid = NULL;
+	if (timer_create(CLOCK_REALTIME, NULL, &timerid) == -1) {
+		t_error("Failed to create timer. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	struct itimerspec its = {
+	    .it_value = {0, TIME_NANO},
+	    .it_interval = {0, 0},
+	};
+
+	TEST(timer_settime(timerid, 0, &its, NULL) == 0,
+	     "Failed to set time. Errno: %s\n", strerror(errno));
+
+	its.it_value.tv_sec = 1;
+	its.it_value.tv_nsec = 0;
+
+	struct itimerspec ovalue = {.it_value.tv_nsec = 0};
+
+	TEST(timer_settime(timerid, 0, &its, &ovalue) == 0,
+	     "Failed to set time. Errno: %s\n", strerror(errno));
+
+	struct itimerspec res;
+	if (timer_gettime(timerid, &res) == -1) {
+		t_error("Failed to get timer time. Errno: %s\n", strerror(errno));
+		timer_delete(timerid);
+		return;
+	}
+
+	// check that it_value has been overwritten
+	TEST(res.it_value.tv_nsec > TIME_NANO,
+	     "Timer reset test failed, expected time until expiry > %d, got %ld\n",
+	     TIME_NANO, res.it_value.tv_nsec);
+
+	// check ovalue is set correctly
+	TEST(ovalue.it_value.tv_nsec != 0,
+	     "timer_settime() failed to set ovalue correctly\n");
+
+	timer_delete(timerid);
+}
+
+static void test_disarm_timer(void)
+{
+	timer_t timerid = NULL;
+	if (timer_create(CLOCK_REALTIME, NULL, &timerid) == -1) {
+		t_error("Failed to create timer. Errno: %s\n", strerror(errno));
+		return;
+	}
+
+	struct itimerspec its = {
+	    .it_value = {0, TIME_NANO},
+	    .it_interval = {0, 0},
+	};
+
+	TEST(timer_settime(timerid, 0, &its, NULL) == 0,
+	     "Failed to set time. Errno: %s\n", strerror(errno));
+
+	its.it_value.tv_nsec = 0;
+
+	TEST(timer_settime(timerid, 0, &its, NULL) == 0,
+	     "Failed to set time. Errno: %s\n", strerror(errno));
+
+	struct itimerspec res;
+
+	if (timer_gettime(timerid, &res) == -1) {
+		t_error("Failed to get timer time. Errno: %s\n", strerror(errno));
+		timer_delete(timerid);
+		return;
+	}
+
+	// setting the it_value of an armed timer to 0 should result in the timer
+	// being disarmed
+	TEST(res.it_value.tv_sec == 0 && res.it_value.tv_nsec == 0,
+	     "Disarm timer test failed, expected it_value.tv_sec = 0, got %ld, "
+	     "expected it_value.tv_nsec = 0, got %ld\n",
+	     res.it_value.tv_sec, res.it_value.tv_nsec);
+
+	timer_delete(timerid);
+}
+
+int main(void)
+{
+	test_settime();
+	test_periodic_timer();
+	test_invalid_inputs();
+	test_timer_resets();
+	test_disarm_timer();
+	return t_status;
+}
-- 
2.34.1


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

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-05 22:44 [musl] [PATCH 1/3 libc-test] functional:time:clock_nanosleep test Ryan Gardner
2024-11-05 22:44 ` [musl] [PATCH 2/3 libc-test] functional:time:timer_delete test Ryan Gardner
2024-11-05 22:44 ` Ryan Gardner [this message]
2024-11-06  7:38 ` [musl] [PATCH 1/3 libc-test] functional:time:clock_nanosleep test Szabolcs Nagy

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-3-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).