#---*- Makefile -*-------------------------------------------------------
#$Author: andrius $
#$Date: 2020-02-10 05:26:39 -0500 (Mon, 10 Feb 2020) $
#$Revision: 5927 $
#$URL: svn://saulius-grazulis.lt/restful/tags/v0.15.2/Makefile $
#------------------------------------------------------------------------

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

# USAGE:
#     make clean
#     make distclean
#     make tests
#     make

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

# Include local configuration files from this directory:

MAKECONF_FILES = ${filter-out %~, ${wildcard Makeconf*}}

ifneq ("${MAKECONF_FILES}","")
include ${MAKECONF_FILES}
endif

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

# Use local scripts as a fall-back when hey are not installed on the system:
PATH := ${PATH}:tools/scripts

BIN_DIR  = website/cgi-bin

TEST_DIR = tests/cases
OUTP_DIR = tests/outputs

INP_FILES  = ${wildcard ${TEST_DIR}/*.inp}
OPT_FILES  = ${wildcard ${TEST_DIR}/*.opt}
SH_FILES   = ${wildcard ${TEST_DIR}/*.sh}

INP_DIFFS = ${INP_FILES:${TEST_DIR}/%.inp=${OUTP_DIR}/%.diff}
INP_OUTS  = ${INP_FILES:${TEST_DIR}/%.inp=${OUTP_DIR}/%.out}

OPT_DIFFS = ${OPT_FILES:${TEST_DIR}/%.opt=${OUTP_DIR}/%.diff}
OPT_OUTS  = ${OPT_FILES:${TEST_DIR}/%.opt=${OUTP_DIR}/%.out}

SH_DIFFS = ${SH_FILES:${TEST_DIR}/%.sh=${OUTP_DIR}/%.diff}
SH_OUTS  = ${SH_FILES:${TEST_DIR}/%.sh=${OUTP_DIR}/%.out}

DIFF_FILES = $(sort ${INP_DIFFS} ${OPT_DIFFS} ${SH_DIFFS})
OUTP_FILES = $(sort ${INP_OUTS} ${OPT_OUTS} ${SH_OUTS})

.PHONY: all clean cleanAll distclean test tests out outputs display

all: ${COMPILED_MODULES} tests

display:
	@echo ${DIFF_FILES}

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

# Include Makefiles with additional rules for this directory:

MAKELOCAL_FILES = ${filter-out %~, ${wildcard Makelocal*}}

ifneq ("${MAKELOCAL_FILES}","")
include ${MAKELOCAL_FILES}
endif

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

test tests: ${DIFF_FILES}

${DIFF_FILES}: 

out outputs: ${OUTP_FILES}

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

# Dependencies for the test files:

include .depend .shdepend

.depend: ${INP_OUTS} ${OPT_OUTS} ${SH_OUTS}
	for i in $^; do \
		echo "$$i: $$(echo $$i | sed -e 's/_[0-9]*\..*$$//' \
			| sed 's,${OUTP_DIR},${BIN_DIR},')"; \
	done | grep -v '\.pm' | grep -v '\.js' | grep -v 'out$$' > $@

.shdepend: ${SH_FILES}
	BIN_DIR=${BIN_DIR} mkcomdepend $^ > $@

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

# Define common test frame components:

define source_environment
test -f $(dir $<)/$*.env && . $(dir $<)/$*.env
endef

define can_run_test
[ ! -e ${TEST_DIR}/$*.chk ] || ${TEST_DIR}/$*.chk
endef

define diff_outputs
diff -I 'Expires:\|Date:' ${OUTP_DIR}/$*.out -
endef

define report_differences
if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi
endef

# Filters for the test outputs:

define filter_perl_messages
tools/scripts/validate-inner-html | \
perl -pe '\
     s/Id: [-\w]+ \d+ [-\d]+ [:\dZ]+ \w+/Id: <script_name> <revision_nr> <date> <time> <author>/; \
     s,at ([-\.\/\w\d]+|\([^\)]+\)) line \d+\.?,at <script_name> line <line_no>.,; \
     s/, (<|&lt;)DATA(>|&gt;) line 1\.//g; \
     s/(unknown MySQL server host .*?)(\(\d*\))\.?$$/$$1(<error code>)./; \
     s/tmp\w+\d+sh\d+(\.db)?/<database>/g; \
     s/(DBI connect)\(.*\)( failed:)/$$1(<database args>)$$2/; \
     s/^(Date|Expires): \w{3}, \d{2} \w{3} \d{4} .*/$$1: <date>/; \
     s,tests/no-taint-checks/,website/cgi-bin/,; \
     s,tests/bin/,website/cgi-bin/,; \
     s/[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}/<uuid>/g; \
     s/\d{4}(-\d{2}){2}T\d{2}(:\d{2}){2}Z/<timestamp>/g; \
     s/RestfulDB version: v\d+\.\d+\.\d+/<version>/g; \
    '
endef

# Rules to run script-specific tests:

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.inp ${TEST_DIR}/%.opt ${OUTP_DIR}/%.out ${COMPILED_MODULES} ${PERL_MODULES} ${PERL_TOOLS}
	-@printf "%-50s " "$<:" ; \
	if ${can_run_test}; then \
		${source_environment} ; \
		${BIN_DIR}/$(shell echo $* | sed -e 's/_[0-9]*$$//') \
		    $(shell grep -v '^#' ${word 2, $^}) \
	    	< $< 2>&1 \
		| ${filter_perl_messages} \
		| ${diff_outputs} > $@ ; \
		${report_differences} ; \
	else \
		touch $@; \
	fi

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.inp ${OUTP_DIR}/%.out ${COMPILED_MODULES} ${PERL_MODULES} ${PERL_TOOLS}
	-@printf "%-50s " "$<:" ; \
	if ${can_run_test}; then \
		${source_environment} ; \
		${BIN_DIR}/$(shell echo $* | sed -e 's/_[0-9]*$$//') \
		    < $< 2>&1 \
		| ${filter_perl_messages} \
		| ${diff_outputs} > $@ ; \
		${report_differences} ; \
	else \
		touch $@; \
	fi

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.opt ${OUTP_DIR}/%.out ${COMPILED_MODULES} ${PERL_MODULES} ${PERL_TOOLS}
	-@printf "%-50s " "$<:" ; \
	if ${can_run_test}; then \
		${source_environment} ; \
		${BIN_DIR}/$(shell echo $* | sed -e 's/_[0-9]*$$//') \
		    $(shell grep -v '^#' $<) \
		< /dev/null 2>&1 \
		| ${filter_perl_messages} \
		| ${diff_outputs} > $@ ; \
		${report_differences} ; \
	else \
		touch $@; \
	fi

${OUTP_DIR}/%.diff: ${TEST_DIR}/%.sh ${OUTP_DIR}/%.out ${COMPILED_MODULES} ${PERL_MODULES} ${PERL_TOOLS}
	-@printf "%-50s " "$<:" ; \
	if ${can_run_test}; then \
		${source_environment} ; \
		$< 2>&1 \
		| ${filter_perl_messages} \
		| ${diff_outputs} > $@ ; \
		${report_differences} ; \
	else \
		touch $@; \
	fi

# Rules to generate sample test outputs:

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

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

${OUTP_DIR}/%.out: ${TEST_DIR}/%.opt ${COMPILED_MODULES} ${PERL_MODULES} ${PERL_TOOLS}
	-@test -f $@ || echo "$@:"
	-@${source_environment}; \
	test -f $@ || \
	${BIN_DIR}/$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' $<) \
	2>&1 \
	< /dev/null \
	| ${filter_perl_messages} \
	| tee $@
	-@touch $@

${OUTP_DIR}/%.out: ${TEST_DIR}/%.sh ${COMPILED_MODULES} ${PERL_MODULES} ${PERL_TOOLS}
	-@test -f $@ || echo "$@:"
	-@${source_environment}; \
	test -f $@ || \
	$< 2>&1 \
	| ${filter_perl_messages} \
	| tee $@
	-@touch $@

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

.PHONY: failed listdiff

failed listdiff: ## test
	@-find ${OUTP_DIR} -type f -name '*.diff' -size +0 | sort -u

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

clean:
	rm -f ${DIFF_FILES}

distclean cleanAll: clean
	rm -f .depend .shdepend
	rm -f ${PERL_MODULES}
	rm -f ${PERL_TOOLS}
