summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2012-09-17 16:23:10 +0200
committerAdam Borowski <kilobyte@angband.pl>2012-09-17 18:36:06 +0200
commit63922d78637766580b8fb38e19139c627b01dc55 (patch)
treebd9a56ede92a2c5c9baab24650897ce5c9bac31c
parent1be7ff606b0340eef754d415d0a85c90ac0f7547 (diff)
downloadcrawl-ref-63922d78637766580b8fb38e19139c627b01dc55.tar.gz
crawl-ref-63922d78637766580b8fb38e19139c627b01dc55.zip
A tool to run multiple tests concurrently, or without a terminal.
Merely redirecting stdout to /dev/null is not enough: Crawl and ncurses insist to be able to ioctl the terminal, check the window size, try to read from stdin and fail if it's in eof state, etc. Eliminating all such references would be quite a bit of work (ncurses assumes stdin/stdout are always a terminal even if newterm() is used), and would be probably too intrusive to be a faithful test. Because of no autoconf, the pty code is not very portable, but should work on Linux and BSD (hopefully including MacOS X). For a portable implementation, one could use http://angband.pl/svn/kbtin/trunk/run.c (+ autoconfage), but then, probably running on IRIX, pre-Solaris SunOS, HP UX or SCO isn't that important... and there are no real ptys on Windows.
-rw-r--r--crawl-ref/source/Makefile12
-rw-r--r--crawl-ref/source/util/fake_pty.c84
2 files changed, 96 insertions, 0 deletions
diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile
index 1a101d0349..b7566e168f 100644
--- a/crawl-ref/source/Makefile
+++ b/crawl-ref/source/Makefile
@@ -1735,3 +1735,15 @@ mac-app-tiles: all
mac-app-console: all
+$(MAKE) -j1 -C mac -f Makefile.app-bundle
+
+#############################################################################
+# Canned tests
+#
+
+tests: $(foreach i, 1 2 3 4 5 6 7, test-$(i))
+
+test-%: $(GAME) util/fake_pty
+ util/fake_pty test/stress/run $*
+
+util/fake_pty: util/fake_pty.c
+ $(if $(HOSTCC),$(HOSTCC),$(CC)) -Wall $< -o $@ -lutil
diff --git a/crawl-ref/source/util/fake_pty.c b/crawl-ref/source/util/fake_pty.c
new file mode 100644
index 0000000000..fbf0aaa999
--- /dev/null
+++ b/crawl-ref/source/util/fake_pty.c
@@ -0,0 +1,84 @@
+#include <pty.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <poll.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+
+static pid_t crawl;
+static int tty;
+
+static void sigalrm(int signum)
+{
+ kill(crawl, SIGTERM);
+}
+
+static void slurp_output()
+{
+ struct pollfd pfd;
+ char buf[1024];
+
+ signal(SIGALRM, sigalrm);
+ alarm(3600); // a hard limit of an hour (big tests on a Raspberry...)
+
+ pfd.fd = crawl;
+ pfd.events = POLLIN;
+
+ while (poll(&pfd, 1, 60000) > 0) // 60 seconds with no output -> kesim
+ {
+ if (read(tty, buf, sizeof(buf)) <= 0)
+ break;
+ }
+
+ kill(crawl, SIGTERM); // shooting a zombie is ok, let's make sure it's dead
+}
+
+int main(int argc, char * const *argv)
+{
+ struct winsize ws;
+ int slave;
+ int ret;
+
+ if (argc <= 1)
+ {
+ fprintf(stderr, "Usage: fake_pty program [args]\n");
+ return 1;
+ }
+
+ ws.ws_row = 24;
+ ws.ws_col = 80;
+ ws.ws_xpixel = ws.ws_ypixel = 0;
+
+ // We want to let stderr through, thus can't use forkpty().
+ if (openpty(&tty, &slave, 0, 0, &ws))
+ {
+ fprintf(stderr, "Can't create a pty: %s\n", strerror(errno));
+ return 1;
+ }
+
+ switch (crawl = fork())
+ {
+ case -1:
+ fprintf(stderr, "Can't fork: %s\n", strerror(errno));
+ return 1;
+
+ case 0:
+ close(tty);
+ dup2(slave, 0);
+ dup2(slave, 1); // but _not_ stderr!
+ close(slave);
+ execvp(argv[1], argv + 1);
+ fprintf(stderr, "Can't run '%s': %s\n", argv[1], strerror(errno));
+ return 1;
+
+ default:
+ close(slave);
+ slurp_output();
+ if (waitpid(crawl, &ret, 0) != crawl)
+ ret = 1; // can't happen
+ return ret;
+ }
+}