summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoranton <anton@openbsd.org>2018-11-16 20:19:21 +0000
committeranton <anton@openbsd.org>2018-11-16 20:19:21 +0000
commit7d954e700aa226029d73054677009aad9f800434 (patch)
tree2405ad3a027e39914a5dce9b04522b59d490b51f
parentAdd support for Allwinner A64's eMMC controller. It is essentially (diff)
downloadwireguard-openbsd-7d954e700aa226029d73054677009aad9f800434.tar.xz
wireguard-openbsd-7d954e700aa226029d73054677009aad9f800434.zip
Add wscons regress tests, currently limited to SIGIO handling.
-rw-r--r--regress/sys/dev/wscons/Makefile23
-rw-r--r--regress/sys/dev/wscons/sigio.c251
2 files changed, 274 insertions, 0 deletions
diff --git a/regress/sys/dev/wscons/Makefile b/regress/sys/dev/wscons/Makefile
new file mode 100644
index 00000000000..3d74dc5b560
--- /dev/null
+++ b/regress/sys/dev/wscons/Makefile
@@ -0,0 +1,23 @@
+# $OpenBSD: Makefile,v 1.1 2018/11/16 20:19:21 anton Exp $
+
+PROG= sigio
+
+WARNINGS= yes
+
+.for d in wskbd0 wsmouse0 wskbd
+. for t in setown spgrp sigio
+REGRESS_TARGETS+= $d-$t
+$d-$t: ${PROG}
+ @echo "\n======== ${@} ========"
+ if ./${PROG} -p -d /dev/$d $t; then \
+ ./${PROG} -d /dev/$d $t; \
+ else \
+ echo "SKIPPED"; \
+ fi
+. endfor
+.endfor
+
+# SIGIO is limited to wsmux devices.
+REGRESS_SKIP_TARGETS+= wskbd0-sigio wsmouse0-sigio
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/dev/wscons/sigio.c b/regress/sys/dev/wscons/sigio.c
new file mode 100644
index 00000000000..6aed48bca64
--- /dev/null
+++ b/regress/sys/dev/wscons/sigio.c
@@ -0,0 +1,251 @@
+/* $OpenBSD: sigio.c,v 1.1 2018/11/16 20:19:21 anton Exp $ */
+
+/*
+ * Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <dev/wscons/wsconsio.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int test_setown(int);
+static int test_sigio(int);
+static int test_spgrp(int);
+
+static void sigio(int);
+static void syncrecv(int, int);
+static void syncsend(int, int);
+static __dead void usage(void);
+
+static volatile sig_atomic_t nsigio;
+
+static struct {
+ const char *name;
+ int (*fn)(int);
+} tests[] = {
+ { "setown", test_setown },
+ { "sigio", test_sigio },
+ { "spgrp", test_spgrp },
+ { NULL, NULL },
+};
+
+int
+main(int argc, char *argv[])
+{
+ int (*fn)(int) = NULL;
+ const char *dev = NULL;
+ int c, fd, i;
+ int prereq = 0;
+
+ while ((c = getopt(argc, argv, "d:p")) != -1)
+ switch (c) {
+ case 'd':
+ dev = optarg;
+ break;
+ case 'p':
+ prereq = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (dev == NULL || argc != 1)
+ usage();
+
+ fd = open(dev, O_RDWR);
+ if (fd == -1)
+ err(1, "open: %s", dev);
+ if (prereq)
+ return 0;
+
+ for (i = 0; tests[i].name != NULL; i++) {
+ if (strcmp(argv[0], tests[i].name))
+ continue;
+
+ fn = tests[i].fn;
+ break;
+ }
+ if (fn == NULL)
+ errx(1, "%s: no such test", argv[0]);
+
+ return fn(fd);
+}
+
+static int
+test_setown(int fd)
+{
+ int arg;
+
+ /* The process must be able to receive SIGIO. */
+ arg = getpid();
+ if (ioctl(fd, FIOSETOWN, &arg) == -1)
+ errx(1, "ioctl: FIOSETOWN");
+
+ /* The process group must be able to receive SIGIO. */
+ arg = -getpgrp();
+ if (ioctl(fd, FIOSETOWN, &arg) == -1)
+ errx(1, "ioctl: FIOSETOWN");
+
+ /* A bogus process must be rejected. */
+ arg = 1000000;
+ if (ioctl(fd, FIOSETOWN, &arg) != -1)
+ errx(1, "ioctl: FIOSETOWN: bogus process accepted");
+
+ /* A bogus process group must be rejected. */
+ arg = -1000000;
+ if (ioctl(fd, FIOSETOWN, &arg) != -1)
+ errx(1, "ioctl: FIOSETOWN: bogus process group accepted");
+
+ return 0;
+}
+
+static int
+test_sigio(int fd)
+{
+ struct wscons_event ev;
+ int cfd[2], pfd[2];
+ ssize_t n;
+ pid_t pid;
+ int arg, len, status;
+
+ if (pipe(cfd) == -1)
+ err(1, "pipe");
+ if (pipe(pfd) == -1)
+ err(1, "pipe");
+
+ arg = getpid();
+ if (ioctl(fd, FIOSETOWN, &arg) == -1)
+ err(1, "ioctl: FIOSETOWN");
+
+ /* Enable async IO. */
+ arg = 1;
+ if (ioctl(fd, FIOASYNC, &arg) == -1)
+ err(1, "ioctl: FIOASYNC");
+
+ pid = fork();
+ if (pid == -1)
+ err(1, "fork");
+ if (pid == 0) {
+ close(cfd[1]);
+ close(pfd[0]);
+
+ syncsend(pfd[1], 1);
+ syncrecv(cfd[0], 2);
+
+ memset(&ev, 0, sizeof(ev));
+ if (ioctl(fd, WSMUXIO_INJECTEVENT, &ev) == -1)
+ err(1, "ioctl: WSMUXIO_INJECTEVENT");
+
+ close(cfd[0]);
+ close(pfd[1]);
+ _exit(0);
+ }
+ close(cfd[0]);
+ close(pfd[1]);
+
+ syncrecv(pfd[0], 1);
+
+ if (signal(SIGIO, sigio) == SIG_ERR)
+ err(1, "signal");
+
+ syncsend(cfd[1], 2);
+
+ if (waitpid(pid, &status, 0) == -1)
+ err(1, "waitpid");
+ if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
+ errx(1, "child exited %d", WEXITSTATUS(status));
+ if (WIFSIGNALED(status))
+ errx(1, "child killed by signal %d", WTERMSIG(status));
+
+ if (nsigio != 1)
+ errx(1, "expected SIGIO to be received once, got %d", nsigio);
+
+ len = sizeof(ev);
+ n = read(fd, &ev, len);
+ if (n == -1)
+ err(1, "read");
+ if (n != len)
+ errx(1, "read: expected %d bytes, got %ld", len, n);
+
+ /* Disable async IO. */
+ arg = 0;
+ if (ioctl(fd, FIOASYNC, &arg) == -1)
+ err(1, "ioctl: FIOASYNC");
+
+ return 0;
+}
+
+static int
+test_spgrp(int fd)
+{
+ int arg;
+
+ /* The process group must be able to receive SIGIO. */
+ arg = getpgrp();
+ if (ioctl(fd, TIOCSPGRP, &arg) == -1)
+ errx(1, "ioctl: TIOCSPGRP");
+
+ /* Bogus process groups must be rejected. */
+ arg = -getpgrp();
+ if (ioctl(fd, TIOCSPGRP, &arg) != -1)
+ errx(1, "ioctl: TIOCSPGRP: %d accepted", arg);
+ arg = 1000000;
+ if (ioctl(fd, TIOCSPGRP, &arg) != -1)
+ errx(1, "ioctl: TIOCSPGRP: %d accepted", arg);
+
+ return 0;
+}
+
+static void
+sigio(int signo)
+{
+ nsigio++;
+}
+
+static void
+syncrecv(int fd, int id)
+{
+ int r;
+
+ if (read(fd, &r, sizeof(r)) == -1)
+ err(1, "%s: read", __func__);
+ if (r != id)
+ errx(1, "%s: expected %d, got %d", __func__, id, r);
+}
+
+static void
+syncsend(int fd, int id)
+{
+ if (write(fd, &id, sizeof(id)) == -1)
+ err(1, "%s: write", __func__);
+}
+
+static __dead void
+usage(void)
+{
+ fprintf(stderr, "usage: sigio [-p] -d device test\n");
+ exit(1);
+}