Merge from default.
This commit is contained in:
commit
07e654d6e3
2
Makefile
2
Makefile
|
@ -63,7 +63,7 @@ PLATDEP = $(INSDIR)/lib/ack
|
||||||
|
|
||||||
.NOTPARALLEL:
|
.NOTPARALLEL:
|
||||||
|
|
||||||
MAKECMDGOALS ?= +ack
|
MAKECMDGOALS ?= +ack +tests
|
||||||
BUILD_FILES = $(shell find * -name '*.lua')
|
BUILD_FILES = $(shell find * -name '*.lua')
|
||||||
|
|
||||||
ifneq ($(shell which ninja),)
|
ifneq ($(shell which ninja),)
|
||||||
|
|
16
build.lua
16
build.lua
|
@ -47,8 +47,18 @@ installable {
|
||||||
"examples+pkg",
|
"examples+pkg",
|
||||||
plat_packages
|
plat_packages
|
||||||
},
|
},
|
||||||
deps = {
|
|
||||||
test_packages
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normalrule {
|
||||||
|
name = "tests",
|
||||||
|
ins = {
|
||||||
|
"first/testsummary.sh",
|
||||||
|
test_packages
|
||||||
|
},
|
||||||
|
outleaves = {
|
||||||
|
"stamp"
|
||||||
|
},
|
||||||
|
commands = {
|
||||||
|
"%{ins}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
37
first/testsummary.sh
Executable file
37
first/testsummary.sh
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/sh
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
succeeding="$(find "$@" -size 0)"
|
||||||
|
notsucceeding="$(find "$@" ! -size 0)"
|
||||||
|
skipped="$(grep -l @@SKIPPED $notsucceeding)"
|
||||||
|
timedout="$(grep -l @@TIMEDOUT $notsucceeding)"
|
||||||
|
failed="$(grep -l @@FAIL $notsucceeding)"
|
||||||
|
|
||||||
|
for a in $failed $timedout; do
|
||||||
|
echo "**** $a"
|
||||||
|
cat $a
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$(echo $succeeding | wc -w) tests passed"
|
||||||
|
echo "$(echo $notsucceeding | wc -w) tests failed to pass"
|
||||||
|
echo "$(echo $skipped | wc -w) were skipped (see build log for details)"
|
||||||
|
echo "$(echo $timedout | wc -w) timed out"
|
||||||
|
echo "$(echo $failed | wc -w) failed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$failed" != "" -o "$timedout" != "" ]; then
|
||||||
|
echo "Test status: SAD FACE (tests are failing)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "$succeeding" = "" ]; then
|
||||||
|
echo "Test status: PUZZLED FACE (all tests were skipped)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ "$skipped" != "" ]; then
|
||||||
|
echo "Test status: MILDLY PLEASED FACE (some tests were skipped, but the rest pass)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Test status: HAPPY FACE (all tests are passing)"
|
||||||
|
exit 0
|
||||||
|
|
|
@ -6,4 +6,3 @@ void _m_a_i_n(void)
|
||||||
ASSERT(0 == 0);
|
ASSERT(0 == 0);
|
||||||
finished();
|
finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,23 +42,21 @@ definerule("plat_testsuite",
|
||||||
|
|
||||||
tests[#tests+1] = normalrule {
|
tests[#tests+1] = normalrule {
|
||||||
name = fs,
|
name = fs,
|
||||||
outleaves = { "stamp" },
|
outleaves = { e.plat.."-"..fs.."-testlog.txt" },
|
||||||
ins = {
|
ins = {
|
||||||
bin,
|
bin,
|
||||||
"tests/plat/testdriver.sh"
|
"tests/plat/testdriver.sh",
|
||||||
|
"util/build+testrunner"
|
||||||
},
|
},
|
||||||
commands = {
|
commands = {
|
||||||
"%{ins[2]} "..e.method.." %{ins[1]} 5",
|
"(%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]} || echo FAILED) 2>&1 > %{outs}",
|
||||||
"touch %{outs}"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
return normalrule {
|
return bundle {
|
||||||
name = e.name,
|
name = e.name,
|
||||||
outleaves = { "stamp" },
|
srcs = tests,
|
||||||
ins = tests,
|
|
||||||
commands = { "touch %{outs}" }
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
)
|
)
|
|
@ -26,7 +26,10 @@ void writehex(uint32_t code)
|
||||||
|
|
||||||
void fail(uint32_t code)
|
void fail(uint32_t code)
|
||||||
{
|
{
|
||||||
write(1, "@@FAIL 0x", 10);
|
static const char fail_msg[] = "@@FAIL 0x";
|
||||||
|
static const char nl_msg[] = "\n";
|
||||||
|
|
||||||
|
write(1, fail_msg, sizeof(fail_msg)-1);
|
||||||
writehex(code);
|
writehex(code);
|
||||||
write(1, "\n", 1);
|
write(1, nl_msg, sizeof(nl_msg)-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,50 +2,51 @@
|
||||||
method=$1
|
method=$1
|
||||||
img=$2
|
img=$2
|
||||||
timeout=$3
|
timeout=$3
|
||||||
|
timeoutprog=$4
|
||||||
|
|
||||||
pipe=/tmp/$$.testdriver.pipe
|
set -e
|
||||||
mknod $pipe p
|
|
||||||
trap "rm -f $pipe" EXIT
|
|
||||||
|
|
||||||
result=/tmp/$$.testdriver.result
|
result=/tmp/$$.testdriver.result
|
||||||
trap "rm -f $result" EXIT
|
trap "rm -f $result" EXIT
|
||||||
|
|
||||||
pidfile=/tmp/$$.testdriver.pid
|
errcho() {
|
||||||
trap "rm -f $pidfile" EXIT
|
>&2 echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
case $method in
|
get_test_output() {
|
||||||
qemu-system-*)
|
case $method in
|
||||||
if ! command -v $method >/dev/null 2>&1 ; then
|
qemu-system-*)
|
||||||
echo "Warning: $method not installed, skipping test"
|
if ! command -v $method >/dev/null 2>&1 ; then
|
||||||
exit 0
|
errcho "Warning: $method not installed, skipping test"
|
||||||
fi
|
echo "@@SKIPPED"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
case $method in
|
case $method in
|
||||||
qemu-system-i386) img="-drive file=$img,if=floppy,format=raw" ;;
|
qemu-system-i386) img="-drive file=$img,if=floppy,format=raw" ;;
|
||||||
qemu-system-ppc) img="-kernel $img" ;;
|
qemu-system-ppc) img="-kernel $img" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
( $method -nographic $img 2>&1 & echo $! > $pidfile ) \
|
$timeoutprog -t $timeout -- $method -nographic $img 2>&1 > $result
|
||||||
| tee $result \
|
;;
|
||||||
| ( timeout $timeout grep -l -q @@FINISHED ; echo ) \
|
|
||||||
| ( read dummy && kill $(cat $pidfile) )
|
|
||||||
|
|
||||||
;;
|
|
||||||
|
|
||||||
qemu-*)
|
qemu-*)
|
||||||
if ! command -v $method >/dev/null 2>&1 ; then
|
if ! command -v $method >/dev/null 2>&1 ; then
|
||||||
echo "Warning: $method not installed, skipping test"
|
errcho "Warning: $method not installed, skipping test"
|
||||||
exit 0
|
echo "@@SKIPPED"
|
||||||
fi
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
$method $img > $result
|
$method $img 2>&1 > $result
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "Error: $method not known by testdriver"
|
errcho "Error: $method not known by testdriver"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1
|
get_test_output
|
||||||
|
( grep -q '@@FAIL\|@@SKIPPED' $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1
|
||||||
exit 0
|
exit 0
|
||||||
|
|
8
util/build/build.lua
Normal file
8
util/build/build.lua
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
cprogram {
|
||||||
|
name = "testrunner",
|
||||||
|
srcs = { "./testrunner.c" },
|
||||||
|
deps = {
|
||||||
|
"modules/src/data+lib"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
117
util/build/testrunner.c
Normal file
117
util/build/testrunner.c
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "diagnostics.h"
|
||||||
|
|
||||||
|
static bool timed_out = false;
|
||||||
|
static bool child_exited = false;
|
||||||
|
static char* const* command = NULL;
|
||||||
|
static int timeout = 0;
|
||||||
|
static int pid = 0;
|
||||||
|
|
||||||
|
static void parse_arguments(int argc, char* const argv[])
|
||||||
|
{
|
||||||
|
program_name = argv[0];
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int c = getopt(argc, argv, "t:");
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 't':
|
||||||
|
timeout = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fatal("syntax: testrunner <timeout in secs> -- <command>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command = &argv[optind];
|
||||||
|
if (!command[0])
|
||||||
|
fatal("you must supply a command");
|
||||||
|
if (timeout <= 0)
|
||||||
|
fatal("timeout missing or invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sigalrm_cb(int sigraised)
|
||||||
|
{
|
||||||
|
timed_out = true;
|
||||||
|
if (pid)
|
||||||
|
kill(pid, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* const argv[])
|
||||||
|
{
|
||||||
|
const int READ = 0;
|
||||||
|
const int WRITE = 1;
|
||||||
|
|
||||||
|
int fds[2];
|
||||||
|
FILE* childin;
|
||||||
|
int wstatus;
|
||||||
|
char buffer[4096];
|
||||||
|
char* p;
|
||||||
|
|
||||||
|
parse_arguments(argc, argv);
|
||||||
|
|
||||||
|
pipe(fds);
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
/* Child */
|
||||||
|
close(fds[READ]);
|
||||||
|
close(0);
|
||||||
|
dup2(fds[WRITE], 1);
|
||||||
|
dup2(fds[WRITE], 2);
|
||||||
|
execvp(command[0], command);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Parent */
|
||||||
|
close(fds[WRITE]);
|
||||||
|
signal(SIGALRM, sigalrm_cb);
|
||||||
|
alarm(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
childin = fdopen(fds[READ], "r");
|
||||||
|
if (!childin)
|
||||||
|
fatal("cannot open pipe");
|
||||||
|
|
||||||
|
while (!timed_out)
|
||||||
|
{
|
||||||
|
if (!fgets(buffer, sizeof(buffer), childin))
|
||||||
|
break;
|
||||||
|
fputs(buffer, stdout);
|
||||||
|
|
||||||
|
p = buffer;
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (strcmp(p, "@@FINISHED\n") == 0)
|
||||||
|
break;
|
||||||
|
if (strcmp(p, "@@FINISHED\r\n") == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reached via EOF or seeing a @@FINISHED. */
|
||||||
|
|
||||||
|
alarm(0);
|
||||||
|
|
||||||
|
kill(pid, SIGKILL);
|
||||||
|
waitpid(pid, &wstatus, 0);
|
||||||
|
if (timed_out)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "@@TIMEDOUT\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
exit(WEXITSTATUS(wstatus));
|
||||||
|
}
|
Loading…
Reference in a new issue