From 0988ffce2aa2e9046662ee0579524072200ed0a7 Mon Sep 17 00:00:00 2001
From: Patrick Mooney <pmooney@pfmooney.com>
Date: Tue, 9 Aug 2022 22:02:46 +0000
Subject: [PATCH 3/9] XXX: more tests

---
 usr/src/test/os-tests/tests/signalfd/Makefile |  2 +-
 .../test/os-tests/tests/signalfd/basic_args.c |  4 -
 .../test/os-tests/tests/signalfd/basic_read.c | 95 +++++++++++++++++++
 usr/src/test/os-tests/tests/signalfd/common.c | 20 ++++
 4 files changed, 116 insertions(+), 5 deletions(-)
 create mode 100644 usr/src/test/os-tests/tests/signalfd/basic_read.c

diff --git a/usr/src/test/os-tests/tests/signalfd/Makefile b/usr/src/test/os-tests/tests/signalfd/Makefile
index 69237d4f03..7843e14a43 100644
--- a/usr/src/test/os-tests/tests/signalfd/Makefile
+++ b/usr/src/test/os-tests/tests/signalfd/Makefile
@@ -16,7 +16,7 @@
 include $(SRC)/cmd/Makefile.cmd
 include $(SRC)/test/Makefile.com
 
-PROGS = basic_args
+PROGS = basic_args basic_read
 COMMON_OBJS = common.o
 
 poll_test := LDLIBS += -lsocket
diff --git a/usr/src/test/os-tests/tests/signalfd/basic_args.c b/usr/src/test/os-tests/tests/signalfd/basic_args.c
index 841ecdc3cb..4f564acc20 100644
--- a/usr/src/test/os-tests/tests/signalfd/basic_args.c
+++ b/usr/src/test/os-tests/tests/signalfd/basic_args.c
@@ -15,11 +15,7 @@
 
 #include <stdlib.h>
 #include <unistd.h>
-#include <errno.h>
-#include <assert.h>
-#include <signal.h>
 #include <fcntl.h>
-#include <sys/signalfd.h>
 
 #include "common.h"
 
diff --git a/usr/src/test/os-tests/tests/signalfd/basic_read.c b/usr/src/test/os-tests/tests/signalfd/basic_read.c
new file mode 100644
index 0000000000..2185b1a003
--- /dev/null
+++ b/usr/src/test/os-tests/tests/signalfd/basic_read.c
@@ -0,0 +1,95 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2022 Oxide Computer Company
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "common.h"
+
+int
+main(void)
+{
+	int err;
+	ssize_t sz;
+	signalfd_siginfo_t info[3];
+
+	const int fd = test_basic_prep(0);
+
+	/* A too-small read should yield EINVAL */
+	sz = read(fd, info, sizeof (signalfd_siginfo_t) - 1);
+	err = errno;
+	if (sz != -1 || errno != EINVAL) {
+		test_fail("expected EINVAL for too-small read, "
+		    "found res=%ld errno=%d", sz, err);
+	}
+
+	const int pid = getpid();
+
+	/* simple single read */
+	assert(kill(pid, SIGUSR1) == 0);
+	sz = read(fd, info, sizeof (signalfd_siginfo_t));
+	err = errno;
+	if (sz != sizeof (signalfd_siginfo_t)) {
+		test_fail("bad read result, found sz=%ld errno=%d", sz, err);
+	}
+	if (info[0].ssi_signo != SIGUSR1) {
+		test_fail("bad ssi_signo %d != %d", info[0].ssi_signo, SIGUSR1);
+	}
+
+	struct sigevent sigev = {
+		.sigev_notify = SIGEV_SIGNAL,
+		.sigev_signo = SIGALRM,
+	};
+	timer_t tid;
+	struct itimerspec its_1ms = {
+		.it_value = {
+			.tv_sec = 0,
+			.tv_nsec = MSEC2NSEC(1),
+		}
+	};
+
+	/* block for a single read: a SIGALRM 1ms in the future */
+	assert(timer_create(CLOCK_HIGHRES, &sigev, &tid) == 0);
+	assert(timer_settime(tid, 0, &its_1ms, NULL) == 0);
+	sz = read(fd, info, sizeof (signalfd_siginfo_t));
+	err = errno;
+	if (sz != sizeof (signalfd_siginfo_t)) {
+		test_fail("bad read result, found sz=%ld errno=%d", sz, err);
+	}
+	if (info[0].ssi_signo != SIGALRM) {
+		test_fail("bad ssi_signo %d != %d", info[0].ssi_signo, SIGALRM);
+	}
+
+	/*
+	 * If we get a result during a read, we should not block until the
+	 * entire buffer is full, but rather return what we have.
+	 */
+	assert(kill(pid, SIGUSR1) == 0);
+	assert(kill(pid, SIGUSR2) == 0);
+	sz = read(fd, info, sizeof (info));
+	err = errno;
+	if (sz != (2 * sizeof (signalfd_siginfo_t))) {
+		test_fail("bad read result, found sz=%ld errno=%d", sz, err);
+	}
+	if (info[0].ssi_signo != SIGUSR1) {
+		test_fail("bad ssi_signo %d != %d", info[0].ssi_signo, SIGUSR1);
+	}
+	if (info[1].ssi_signo != SIGUSR2) {
+		test_fail("bad ssi_signo %d != %d", info[1].ssi_signo, SIGUSR2);
+	}
+
+	test_pass();
+}
diff --git a/usr/src/test/os-tests/tests/signalfd/common.c b/usr/src/test/os-tests/tests/signalfd/common.c
index 6016f4a450..6fc1db4c21 100644
--- a/usr/src/test/os-tests/tests/signalfd/common.c
+++ b/usr/src/test/os-tests/tests/signalfd/common.c
@@ -17,6 +17,8 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "common.h"
+
 void
 test_fail(const char *fmt, ...)
 {
@@ -36,3 +38,21 @@ test_pass(void)
 	errx(EXIT_SUCCESS, "TEST PASSED");
 	/* NOTREATCHED */
 }
+
+int
+test_basic_prep(int sigfd_flags)
+{
+	sigset_t mask;
+
+	assert(sigemptyset(&mask) == 0);
+	assert(sigaddset(&mask, SIGUSR1) == 0);
+	assert(sigaddset(&mask, SIGUSR2) == 0);
+	assert(sigaddset(&mask, SIGALRM) == 0);
+
+	int fd = signalfd(-1, &mask, sigfd_flags);
+	assert(fd >= 0);
+
+	assert(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
+
+	return (fd);
+}
-- 
2.37.3

