diff --git a/Makefile b/Makefile index 96cc89a..3383bad 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SRCS:=$(sort $(wildcard src/*/*.c)) OBJS:=$(SRCS:%.c=%.o) -DIRS:=$(sort $(wildcard src/*)) +DIRS:=$(filter-out src/common,$(sort $(wildcard src/*))) NAMES:=$(OBJS:.o=) SPEC_PATTERNS:=src/common/% src/api/% src/math/% CFLAGS:=-Isrc/common @@ -29,6 +29,13 @@ BINS:=$(foreach n,$(NAMES),$($(n).BINS)) src/api/main $(MBINS) LIBS:=$(foreach n,$(NAMES),$($(n).LIBS)) ERRS:=$(BINS:%=%.err) +debug: + @echo MBINS $(MBINS) + @echo BINS $(BINS) + @echo LIBS $(LIBS) + @echo ERRS $(ERRS) + @echo DIRS $(DIRS) + define target_template $(1)/all: $(1)/REPORT $(1)/clean: @@ -41,11 +48,16 @@ endef $(foreach d,$(DIRS),$(eval $(call target_template,$(d)))) -src/common/all: src/common/libtest.a +src/common/all: src/common/REPORT +src/common/REPORT: src/common/run + cat src/common/*.err >$@ +REPORT: src/common/REPORT +src/common/run: src/common/run.o src/common/libtest.a +$(ERRS): src/common/run all:REPORT clean: - rm -f $(OBJS) $(BINS) $(LIBS) src/common/libtest.a src/*/*.err + rm -f $(OBJS) $(BINS) $(LIBS) src/common/libtest.a src/common/run src/*/*.err cleanall: clean rm -f REPORT src/*/REPORT REPORT: @@ -89,7 +101,7 @@ $(IOBJS):CFLAGS+=-DX_PS -DX_TPS -DX_SS touch $@ %.err: % # TODO: proper wrapping that records exit status - ./$< 2>/dev/null >$@ || true + src/common/run ./$< 2>/dev/null >$@ || true .PHONY: all clean cleanall diff --git a/src/common/path.c b/src/common/path.c index 4fd7633..6ca9951 100644 --- a/src/common/path.c +++ b/src/common/path.c @@ -1,4 +1,5 @@ #include +#include #include "test.h" /* relative path to p */ diff --git a/src/common/print.c b/src/common/print.c new file mode 100644 index 0000000..45a4fd5 --- /dev/null +++ b/src/common/print.c @@ -0,0 +1,27 @@ +#include +#include +#include + +volatile int t_status = 0; + +int t_printf(const char *s, ...) +{ + va_list ap; + char buf[512]; + int n; + + t_status = 1; + va_start(ap, s); + n = vsnprintf(buf, sizeof buf, s, ap); + va_end(ap); + if (n < 0) + n = 0; + else if (n >= sizeof buf) { + n = sizeof buf; + buf[n - 1] = '\n'; + buf[n - 2] = '.'; + buf[n - 3] = '.'; + buf[n - 4] = '.'; + } + return write(1, buf, n); +} diff --git a/src/common/run.c b/src/common/run.c new file mode 100644 index 0000000..8a2a0f3 --- /dev/null +++ b/src/common/run.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test.h" + +static void handler(int s) +{ +} + +static void setrl(int r, long lim) { + struct rlimit rl; + + if (getrlimit(r, &rl)) + t_error("getrlimit %d: %s\n", r, strerror(errno)); + rl.rlim_cur = lim; + if (lim < rl.rlim_max) + rl.rlim_max = lim; + if (setrlimit(r, &rl)) + t_error("setrlimit %d: %s\n", r, strerror(errno)); +} + +static int start(char *argv[]) +{ + int pid; + + pid = fork(); + if (pid == 0) { + setrl(RLIMIT_STACK, 100*1024); + setrl(RLIMIT_CPU, 2); + execv(argv[0], argv); + t_error("%s exec failed: %s\n", argv[0], strerror(errno)); + exit(1); + } + if (pid == -1) { + t_error("%s fork failed: %s\n", argv[0], strerror(errno)); + exit(-1); + } + return pid; +} + +int main(int argc, char *argv[]) +{ + int status; + sigset_t set; + int timeout = 0; + int sig = 0; + int pid; + + if (argc < 2) { + t_error("usage: ./run cmd [args..]\n"); + return -1; + } + argv++; + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, 0); + signal(SIGCHLD, handler); + pid = start(argv); + if (sigtimedwait(&set, 0, &(struct timespec){5,0}) == -1) { + if (errno == EAGAIN) + timeout = 1; + if (kill(pid, SIGKILL) == -1) + t_error("%s kill failed: %s\n", argv[0], strerror(errno)); + } + if (waitpid(pid, &status, 0) != pid) { + t_error("%s waitpid failed: %s\n", argv[0], strerror(errno)); + return -1; + } + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) + return 0; + t_printf("FAIL %s [status %d]\n", argv[0], WEXITSTATUS(status)); + } else if (timeout) { + t_printf("FAIL %s [timed out]\n", argv[0]); + } else if (WIFSIGNALED(status)) { + t_printf("FAIL %s [signal %s]\n", argv[0], strsignal(WTERMSIG(status))); + } else + t_printf("FAIL %s [unknown]\n", argv[0]); + return 1; +} diff --git a/src/common/setrlim.c b/src/common/setrlim.c new file mode 100644 index 0000000..fc76a8e --- /dev/null +++ b/src/common/setrlim.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include "test.h" + +int t_setrlim(int r, long lim) +{ + struct rlimit rl; + + if (getrlimit(r, &rl)) { + t_error("getrlimit %d: %s\n", r, strerror(errno)); + return -1; + } + if (lim > rl.rlim_max) + return -1; + if (lim == rl.rlim_max && lim == rl.rlim_cur) + return 0; + rl.rlim_max = lim; + rl.rlim_cur = lim; + if (setrlimit(r, &rl)) { + t_error("setrlimit %d: %s\n", r, strerror(errno)); + return -1; + } + return 0; +} + diff --git a/src/common/test.h b/src/common/test.h index e24a1db..21e5caf 100644 --- a/src/common/test.h +++ b/src/common/test.h @@ -1,36 +1,14 @@ #include -#include -#include #include /* TODO: not thread-safe nor fork-safe */ -static volatile int t_status; +extern volatile int t_status; #define T_LOC2(l) __FILE__ ":" #l #define T_LOC1(l) T_LOC2(l) -#define t_error(...) t_printf("ERROR " T_LOC1(__LINE__) ": " __VA_ARGS__) - -static int t_printf(const char *s, ...) -{ - va_list ap; - char buf[512]; - int n; - - t_status = 1; - va_start(ap, s); - n = vsnprintf(buf, sizeof buf, s, ap); - va_end(ap); - if (n < 0) - n = 0; - else if (n >= sizeof buf) { - n = sizeof buf; - buf[n - 1] = '\n'; - buf[n - 2] = '.'; - buf[n - 3] = '.'; - buf[n - 4] = '.'; - } - return write(1, buf, n); -} +#define t_error(...) t_printf(T_LOC1(__LINE__) ": " __VA_ARGS__) + +int t_printf(const char *s, ...); int t_vmfill(void **, size_t *, int); @@ -45,3 +23,5 @@ int t_choose(uint64_t n, size_t k, uint64_t *p); char *t_pathrel(char *buf, size_t n, char *argv0, char *p); +int t_setrlim(int r, long lim); + diff --git a/src/functional/sem.c b/src/functional/sem.c index d953a8e..86662b6 100644 --- a/src/functional/sem.c +++ b/src/functional/sem.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/src/functional/sscanf_long.c b/src/functional/sscanf_long.c index 160648b..c9208af 100644 --- a/src/functional/sscanf_long.c +++ b/src/functional/sscanf_long.c @@ -6,17 +6,6 @@ #include #include "test.h" -static void setrl(int r, long lim) -{ - struct rlimit rl; - - if (getrlimit(r, &rl)) - t_error("getrlimit %d: %s\n", r, strerror(errno)); - rl.rlim_cur = lim; - if (setrlimit(r, &rl)) - t_error("setrlimit %d: %s\n", r, strerror(errno)); -} - int main(void) { enum {n = 8*1024*1024}; @@ -27,7 +16,7 @@ int main(void) if (!s) return t_error("out of memory"); - setrl(RLIMIT_STACK, 128*1024); + t_setrlim(RLIMIT_STACK, 100*1024); for (i = 0; i < n; i++) s[i] = '1'; s[n-3] = ' ';