tests: add a test for select syscall decoding

Convert test/select.c into a regular test.

* test/Makefile (PROGS): Remove select.
* test/.gitignore: Likewise.
* test/select.c: Rewrite to ...
* tests/select.c: ... new file.
* tests/select.awk: New file.
* tests/select.test: New test.
* tests/Makefile.am (check_PROGRAMS): Add select.
(TESTS): Add select.test.
(EXTRA_DIST): Add select.awk.
* tests/.gitignore: Add select.
diff --git a/test/.gitignore b/test/.gitignore
index c73b64a..7eb39cf 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -10,5 +10,4 @@
 threaded_execve
 mtd
 ubi
-select
 sigreturn
diff --git a/test/Makefile b/test/Makefile
index cc7d47a..92142b1 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -3,7 +3,7 @@
 PROGS = \
     vfork fork sig skodic clone leaderkill childthread \
     sigkill_rain wait_must_be_interruptible threaded_execve \
-    mtd ubi select sigreturn
+    mtd ubi sigreturn
 
 all: $(PROGS)
 
diff --git a/test/select.c b/test/select.c
deleted file mode 100644
index 0810fff..0000000
--- a/test/select.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* dave@treblig.org */
-#include <sys/select.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-char buffer[1024*1024*2];
-
-int main()
-{
-	fd_set rds;
-	struct timeval timeout;
-
-	FD_ZERO(&rds);
-	FD_SET(2, &rds);
-	/* Start with a nice simple select */
-	select(3, &rds, &rds, &rds, NULL);
-
-	/* Now the crash case that trinity found, negative nfds
-	 * but with a pointer to a large chunk of valid memory.
-	 */
-	FD_ZERO((fd_set*)buffer);
-	FD_SET(2,(fd_set*)buffer);
-	select(-1, (fd_set *)buffer, NULL, NULL, NULL);
-
-	/* Another variant, with nfds exceeding allowed limit. */
-	timeout.tv_sec = 0;
-	timeout.tv_usec = 100;
-	select(FD_SETSIZE + 1, (fd_set *)buffer, NULL, NULL, &timeout);
-
-	return 0;
-}
diff --git a/tests/.gitignore b/tests/.gitignore
index c96ee1f..f276b9b 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -10,6 +10,7 @@
 netlink_inet_diag
 netlink_unix_diag
 scm_rights
+select
 set_ptracer_any
 sigaction
 stack-fcall
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 901df50..db3561e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,6 +15,7 @@
 	netlink_inet_diag \
 	netlink_unix_diag \
 	scm_rights \
+	select \
 	set_ptracer_any \
 	sigaction \
 	stack-fcall \
@@ -46,6 +47,7 @@
 	ipc_shm.test \
 	ipc_sem.test \
 	scm_rights-fd.test \
+	select.test \
 	sigaction.test \
 	stat.test \
 	stat32-v.test \
@@ -78,6 +80,7 @@
 	     mmsg.expected \
 	     net-yy-accept.awk \
 	     net-yy-connect.awk \
+	     select.awk \
 	     sigaction.awk \
 	     uid.awk \
 	     unix-yy-accept.awk \
diff --git a/tests/select.awk b/tests/select.awk
new file mode 100644
index 0000000..142504a
--- /dev/null
+++ b/tests/select.awk
@@ -0,0 +1,26 @@
+BEGIN {
+	r[1] = "^select\\(2, \\[0 1\\], \\[0 1\\], \\[0 1\\], NULL\\) += 1 \\(\\)$"
+	r[2] = "^select\\(-1, NULL, 0x[0-9a-f]+, NULL, NULL\\) += -1 "
+	r[3] = "^select\\(1025, \\[0\\], \\[\\], NULL, \\{0, 100\\}\\) += 0 \\(Timeout\\)$"
+	r[4] = "^\\+\\+\\+ exited with 0 \\+\\+\\+$"
+	lines = 4
+	fail = 0
+}
+
+NR > lines { exit 1 }
+
+{
+	if (match($0, r[NR]))
+		next
+
+	print "Line " NR " does not match."
+	fail = 1
+}
+
+END {
+	if (fail == 0 && NR != lines) {
+		fail = 1
+		print "Expected " lines " lines, found " NR " line(s)."
+	}
+	exit fail
+}
diff --git a/tests/select.c b/tests/select.c
new file mode 100644
index 0000000..4ed644d
--- /dev/null
+++ b/tests/select.c
@@ -0,0 +1,43 @@
+/*
+ * Based on test by Dr. David Alan Gilbert <dave@treblig.org>
+ */
+#include <assert.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+static fd_set set[0x1000000 / sizeof(fd_set)];
+
+int main()
+{
+	int fds[2];
+	struct timeval timeout = { .tv_sec = 0, .tv_usec = 100 };
+
+	(void) close(0);
+	(void) close(1);
+	assert(pipe(fds) == 0);
+
+	/*
+	 * Start with a nice simple select.
+	 */
+	FD_ZERO(set);
+	FD_SET(0, set);
+	FD_SET(1, set);
+	assert(select(2, set, set, set, NULL) == 1);
+
+	/*
+	 * Now the crash case that trinity found, negative nfds
+	 * but with a pointer to a large chunk of valid memory.
+	 */
+	FD_ZERO(set);
+	FD_SET(1,set);
+	assert(select(-1, NULL, set, NULL, NULL) == -1);
+
+	/*
+	 * Another variant, with nfds exceeding FD_SETSIZE limit.
+	 */
+	FD_ZERO(set);
+	FD_SET(0,set);
+	assert(select(FD_SETSIZE + 1, set, set + 1, NULL, &timeout) == 0);
+
+	return 0;
+}
diff --git a/tests/select.test b/tests/select.test
new file mode 100755
index 0000000..339a8e4
--- /dev/null
+++ b/tests/select.test
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Check select syscall decoding.
+
+. "${srcdir=.}/init.sh"
+
+check_prog awk
+
+./select ||
+	framework_skip_ 'select syscall does not behave as expected'
+
+args="-eselect ./select"
+$STRACE -o "$LOG" $args || {
+	cat "$LOG"
+	fail_ "$STRACE $args failed"
+}
+
+awk -f "$srcdir"/select.awk "$LOG" || {
+	cat "$LOG"
+	fail_ 'unexpected output'
+}
+
+exit 0