OBJECTS=lists.o CFLAGS=-Wall -g CXXFLAGS=-Wall -g SHELL=/bin/bash TIMEOUT=8 TESTS_DIR=tests TESTS_SH:=$(wildcard $(TESTS_DIR)/*.sh) TESTS_SH_NAMES:=$(patsubst $(TESTS_DIR)/%.sh, %, $(TESTS_SH)) TESTS_IO:=$(wildcard $(TESTS_DIR)/*.in) TESTS_IO_NAMES:=$(patsubst $(TESTS_DIR)/%.in, %, $(TESTS_IO)) TESTS_C:=$(wildcard $(TESTS_DIR)/*.c) TESTS_CXX:=$(wildcard $(TESTS_DIR)/*.cc) TESTS_BIN:=$(patsubst $(TESTS_DIR)/%.c, $(TESTS_DIR)/%, $(TESTS_C)) \ $(patsubst $(TESTS_DIR)/%.cc, $(TESTS_DIR)/%, $(TESTS_CXX)) TESTS_BIN_NAMES:=$(patsubst $(TESTS_DIR)/%.c, %, $(TESTS_C)) $(patsubst $(TESTS_DIR)/%.cc, %, $(TESTS_CXX)) .PHONY: all all: compile check .PHONY: compile-program compile: $(PROGRAMS) $(OBJECTS) .PHONY: check check: check-bin check-io-sh .PHONY: check-io-sh check-io-sh: compile $(TESTS_IO) $(TESTS_SH) @exec 2> /dev/null; \ for p in $(foreach prog,$(PROGRAMS),$(dir $(prog))$(prog)); do \ echo "Testing $${p}:" ; \ for t in $(TESTS_IO_NAMES); do \ echo -n "Running test $$t..." ; \ "$$p" < "$(TESTS_DIR)/$$t.in" > "$$t.out" 2>&1 & \ prog_pid=$$!; \ ( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \ killer_pid=$$!; \ wait $$prog_pid; \ res=$$?; \ if test $$res -gt 128; \ then \ case `kill -l $$(($$res - 128))` in \ ABRT ) echo "FAIL"; ;; \ TERM ) echo "TIME OUT"; ;; \ * ) echo "UNKNOWN ERROR"; ;; \ esac ; \ echo "see $(TESTS_DIR)/$$t.in" ;\ echo "you may run $$p < $(TESTS_DIR)/$$t.in" ;\ echo "to see what went wrong";\ rm -f "$$t.out" ;\ else \ kill $$killer_pid > /dev/null 2>&1 ;\ wait $$killer_pid; \ if cmp -s "$$t.out" "$(TESTS_DIR)/$$t.expected"; \ then \ echo "PASS" ;\ rm -f "$$t.out" ;\ else \ echo "FAIL" ;\ echo "see $(TESTS_DIR)/$$t.sh" ;\ echo "run diff $$t.out $(TESTS_DIR)/$$t.expected";\ echo "to see the difference between the actual and expected output";\ fi; \ fi; \ done; \ for t in $(TESTS_SH_NAMES); do \ echo -n "Running test $$t..." ; \ $(SHELL) "$(TESTS_DIR)/$$t.sh" "$$p" > "$$t.out" 2>&1 & \ prog_pid=$$!; \ ( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \ killer_pid=$$!; \ wait $$prog_pid; \ res=$$?; \ if test $$res -gt 128; \ then \ case `kill -l $$(($$res - 128))` in \ ABRT ) echo "FAIL"; ;; \ TERM ) echo "TIME OUT"; ;; \ * ) echo "UNKNOWN ERROR"; ;; \ esac ; \ echo "see $(TESTS_DIR)/$$t.sh" ;\ echo "you may run $(TESTS_DIR)/$$t.sh $$p" ;\ echo "to see what went wrong";\ rm -f "$$t.out" ;\ else \ kill $$killer_pid > /dev/null 2>&1 ;\ wait $$killer_pid; \ if cmp -s "$$t.out" "$(TESTS_DIR)/$$t.expected"; \ then \ echo "PASS" ;\ rm -f "$$t.out" ;\ else \ echo "FAIL" ;\ echo "see $(TESTS_DIR)/$$t.sh" ;\ echo "run diff $$t.out $(TESTS_DIR)/$$t.expected";\ echo "to see the difference between the actual and expected output";\ fi; \ fi; \ done; \ done $(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@ $(TESTS_DIR)/%: $(TESTS_DIR)/%.cc $(OBJECTS) $(CXX) $(CXXFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.cc $(OBJECTS) -o $@ .PHONY: check-bin check-bin: $(TESTS_BIN) @exec 2> /dev/null; \ for t in $(TESTS_BIN_NAMES); do \ echo -n "Running test $$t..." ; \ "$(TESTS_DIR)/$$t" &\ prog_pid=$$!; \ ( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \ killer_pid=$$!; \ wait $$prog_pid; \ res=$$?; \ if test $$res -gt 128; \ then \ case `kill -l $$(($$res - 128))` in \ ABRT ) echo "FAIL"; ;; \ TERM ) echo "TIME OUT"; ;; \ * ) echo "UNKNOWN ERROR"; ;; \ esac ; \ echo "you may run $(TESTS_DIR)/$$t to see what went wrong" ;\ else \ kill $$killer_pid > /dev/null 2>&1 ;\ wait $$killer_pid; \ echo "PASS" ;\ fi; \ done .PHONY: clean clean: rm -f $(PROGRAMS) $(OBJECTS) tests/*.o $(TESTS_BIN)