#---*- Makefile -*-------------------------------------------------------
# Run tests in a test directory (tests/cases by default) and report if
# all tests pass.

TOOL_DIR ?= tests/tools

BIN_DIR ?= ./tests/scripts/

TEST_DIR = tests/cases
OUTP_DIR = tests/outputs

TEST_FILES = ${wildcard ${TEST_DIR}/*.inp}
TEST_DIFF_FILES = ${TEST_FILES:${TEST_DIR}/%.inp=${OUTP_DIR}/%.diff}
TEST_OUTP_FILES = ${TEST_FILES:${TEST_DIR}/%.inp=${OUTP_DIR}/%.out}

OPT_FILES = ${wildcard ${TEST_DIR}/*.opt}
OPT_DIFF_FILES = ${OPT_FILES:${TEST_DIR}/%.opt=${OUTP_DIR}/%.diff}
OPT_OUTP_FILES = ${OPT_FILES:${TEST_DIR}/%.opt=${OUTP_DIR}/%.out}

SH_FILES = ${wildcard ${TEST_DIR}/*.sh}
SH_DIFF_FILES = ${SH_FILES:${TEST_DIR}/%.sh=${OUTP_DIR}/%.diff}
SH_OUTP_FILES = ${SH_FILES:${TEST_DIR}/%.sh=${OUTP_DIR}/%.out}

DIFF_FILES = $(sort ${TEST_DIFF_FILES} ${OPT_DIFF_FILES} ${SH_DIFF_FILES})
OUTP_FILES = $(sort ${TEST_OUTP_FILES} ${OPT_OUTP_FILES} ${SH_OUTP_FILES})

.PHONY: tests

all: tests

#------------------------------------------------------------------------------

# Automatic dependency generation:

PATH := ${PATH}:${TOOL_DIR}/mkdepend

export PATH

DEPEND=${SH_FILES:${TEST_DIR}/%.sh=${TEST_DIR}/.%.d}

include ${DEPEND}

${TEST_DIR}/.%.d: ${TEST_DIR}/%.sh
	mkcomdepend $< \
	| sed 's,^tests/cases/,tests/outputs/,; s/^\(.*\)\.sh.log:/\1.diff:/' \
	> $@
	mkcomdepend $< \
	| sed 's,^tests/cases/,tests/outputs/,; s/^\(.*\)\.sh.log:/\1.out:/' \
	| grep '\.out: ' \
	>> $@

#------------------------------------------------------------------------------

.PHONY: check test tests out outputs

check test tests: ${DIFF_FILES}

out outputs: ${OUTP_FILES}

EXTRA_TEST_DEPS = ${GRAMMATIKER_LOG}

#------------------------------------------------------------------------------

define filter_output
perl -pe 's/^(\s*\w+)\((\d+)\)/$$1(9999)/'
endef

# Rules to run script-specific tests:

DIFF_CMD = diff -I '/dev/fd/[0-9][0-9]*'

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.inp ${TEST_DIR}/%.opt | ${EXTRA_TEST_DEPS}
	-@printf "%-30s " "$<:" ; \
	${BIN_DIR}$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' ${word 2, $^}) \
	    $< \
	2>&1 \
	| ${filter_output} \
	| ${DIFF_CMD} ${OUTP_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.opt | ${EXTRA_TEST_DEPS}
	-@printf "%-30s " "$<:" ; \
	${BIN_DIR}$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' ${word 1, $^}) \
	2>&1 \
	| ${filter_output} \
	| ${DIFF_CMD} ${OUTP_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.inp | ${EXTRA_TEST_DEPS}
	-@printf "%-30s " "$<:" ; \
	${BIN_DIR}$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $< \
	2>&1 \
	| ${filter_output} \
	| ${DIFF_CMD} ${OUTP_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

# Shell-script based tests:

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.sh | ${EXTRA_TEST_DEPS}
	-@printf "%-30s " "$<:" ; \
	$< 2>&1 \
	| ${filter_output} \
	| ${DIFF_CMD} ${OUTP_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

# Rules to generate sample test outputs:

${OUTP_DIR}/%.out: ${TEST_DIR}/%.inp ${TEST_DIR}/%.opt | ${EXTRA_TEST_DEPS}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	${BIN_DIR}$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' ${word 2, $^}) \
	    $< \
	2>&1 \
	| ${filter_output} \
	| tee $@
	-@touch $@

${OUTP_DIR}/%.out: ${TEST_DIR}/%.opt | ${EXTRA_TEST_DEPS}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	${BIN_DIR}$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' ${word 1, $^}) \
	2>&1 \
	| ${filter_output} \
	| tee $@
	-@touch $@

${OUTP_DIR}/%.out: ${TEST_DIR}/%.inp | ${EXTRA_TEST_DEPS}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	${BIN_DIR}$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $< \
	2>&1 \
	| tee $@
	-@touch $@

${OUTP_DIR}/%.out: ${TEST_DIR}/%.sh | ${EXTRA_TEST_DEPS}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	$< 2>&1 \
	| ${filter_output} \
	| tee $@
	-@touch $@

#------------------------------------------------------------------------------

.PHONY: listdiff

listdiff: ## test
	@- if [ -d ${OUTP_DIR} ]; then \
	   find ${OUTP_DIR} -name '*.diff' -size +0 | sort -u; \
	fi

#------------------------------------------------------------------------------

.PHONY: test-clean test-distclean test-cleanAll

test-clean:
	rm -f ${DIFF_FILES}

test-distclean test-cleanAll: test-clean
	rm -f ${DEPEND}

clean: test-clean

distclean: test-distclean

cleanAll: test-cleanAll
