#---*- Makefile -*-------------------------------------------------------
#$Author: saulius $
#$Date: 2019-03-07 15:48:47 +0000 (Thu, 07 Mar 2019) $
#$Revision: 190 $
#$URL: svn+ssh://saulius-grazulis.lt/home/saulius/svn-repositories/makefiles/perl-yapp-multiscript-tests/Makelocal-perl-yapp-multiscript-tests $
#------------------------------------------------------------------------

CWD := ${shell pwd}
TOP := ${dir ${CWD}}
PERL5LIB := ${CWD}/lib/perl5:${PERL5LIB}
PERL5LIB := ${TOP}/lib/perl5:${PERL5LIB}
export PERL5LIB

YAPP_SOURCES := $(wildcard $(addsuffix /*.yp, ${YAPP_MODULE_DIRS}))
YAPP_MODULES := ${YAPP_SOURCES:%.yp=%.pm}

.PRECIOUS: %.pm

#
# TEST variable should be defined in the Makeconf file, or on the
# command line, and specifies the main executable (target). This
# executable will be run for every file in ./inputs when 'make test'
# is invoked.
#

.PHONY: all tests

all: tests

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

%.pm: %.yp
	yapp -o $@ $<

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

# When 'make test' is invoked, a TARGET executable will be run for
# every file in inputs that has extension ${EXT}. The outputs will be
# compared with the sample outputs files in ./outputs/*.out, and any
# differences will be recorded in ./outputs/*.diff #

TEST_DIR       = ./inputs
OUTPUT_DIR     = ./outputs

TEST_FILES = ${wildcard ${TEST_DIR}/*${EXT}}
RES_FILES  = ${patsubst ${TEST_DIR}/%${EXT},${OUTPUT_DIR}/%.out,${TEST_FILES}}
DIFF_FILES = ${patsubst ${TEST_DIR}/%${EXT},${OUTPUT_DIR}/%.diff,${TEST_FILES}}


INP            = .inp
OPT            = .opt
SCRIPT_TST_DIR = ./tests
SCRIPT_INPUTS  = ${wildcard ${SCRIPT_TST_DIR}/*${INP}}
SCRIPT_OPTIONS = ${wildcard ${SCRIPT_TST_DIR}/*${OPT}}
SCRIPT_TESTS   = $(sort ${SCRIPT_INPUTS:%${INP}=%} ${SCRIPT_OPTIONS:%${OPT}=%})
SCRIPT_OUTPUTS = ${SCRIPT_TESTS:${SCRIPT_TST_DIR}/%=${OUTPUT_DIR}/%.out}
SCRIPT_DIFFS   = ${SCRIPT_TESTS:${SCRIPT_TST_DIR}/%=${OUTPUT_DIR}/%.diff}

#
# Outputs and tests from the shell-driven tests
#

SHELL_TSTDIR = ./shtests
SHELL_OUTDIR = ./shoutputs

SHELL_TESTS   = ${wildcard ${SHELL_TSTDIR}/*.sh}
SHELL_BASES   = ${notdir ${SHELL_TESTS}}
SHELL_OUTPUTS = ${addprefix ${SHELL_OUTDIR}/, ${SHELL_BASES:%.sh=%.out}}
SHELL_DIFFS   = ${addprefix ${SHELL_OUTDIR}/, ${SHELL_BASES:%.sh=%.diff}}

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

define filter_Ids
perl -pe 's/Id: [-\w]+ \d+ [-\d]+ [:\dZ]+ \w+/Id: <script_name> <revision_nr> <date> <time> <author>/' \
| perl -pe 's,at [-\.\/\w\d]+ line \d+\.,at <script_name> line <line_no>.,'
endef

.PHONY: out outputs test

out outputs: ${RES_FILES} ${TST_OUTPUTS} ${SCRIPT_OUTPUTS}

test: ${DIFF_FILES} ${TST_DIFFS} ${SCRIPT_DIFFS}

${TARGET}: ${YAPP_MODULES}

${OUTPUT_DIR}/%.diff: ${TARGET} ${TEST_DIR}/%${EXT}
	-@printf "%-30s " "$*:" ; \
	./$^ ${TEST_OPTIONS} 2>&1 \
	| ${filter_Ids} \
	| diff ${OUTPUT_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

${OUTPUT_DIR}/%.out: ${TARGET} ${TEST_DIR}/%${EXT}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || ./$^ ${TEST_OPTIONS} 2>&1 \
	| ${filter_Ids} \
	| tee $@
	-@touch $@

# Rules to run script-specific tests

${OUTPUT_DIR}/%.diff: ${SCRIPT_TST_DIR}/%${INP} ${SCRIPT_TST_DIR}/%${OPT} \
                      ${SCRIPT_FILES} ${YAPP_MODULES}
	-@printf "%-30s " "$<:" ; \
	./$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' ${word 2, $^}) \
	    $< \
	2>&1 \
	| ${filter_Ids} \
	| diff ${OUTPUT_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

${OUTPUT_DIR}/%.diff: ${SCRIPT_TST_DIR}/%${INP} ${SCRIPT_FILES} ${YAPP_MODULES}
	-@printf "%-30s " "$<:" ; \
	./$(shell echo $* | sed -e 's/_[0-9]*$$//') $< 2>&1 \
	| ${filter_Ids} \
	| diff ${OUTPUT_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

${OUTPUT_DIR}/%.diff: ${SCRIPT_TST_DIR}/%${OPT} ${SCRIPT_FILES} ${YAPP_MODULES}
	-@printf "%-30s " "$<:" ; \
	./$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	     $(shell grep -v '^#' ${word 1, $^}) \
	2>&1 \
	| ${filter_Ids} \
	| diff ${OUTPUT_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

${OUTPUT_DIR}/%.out: ${SCRIPT_TST_DIR}/%${INP} ${SCRIPT_TST_DIR}/%${OPT} ${YAPP_MODULES}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	./$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' ${word 2, $^}) \
	    $< \
	2>&1 \
	| ${filter_Ids} \
	| tee $@
	-@touch $@

${OUTPUT_DIR}/%.out: ${SCRIPT_TST_DIR}/%${INP} ${YAPP_MODULES}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	./$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $< \
	2>&1 \
	| ${filter_Ids} \
	| tee $@
	-@touch $@

${OUTPUT_DIR}/%.out: ${SCRIPT_TST_DIR}/%${OPT} ${YAPP_MODULES}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	./$(shell echo $* | sed -e 's/_[0-9]*$$//') \
	    $(shell grep -v '^#' ${word 1, $^}) \
	2>&1 \
	| ${filter_Ids} \
	| tee $@
	-@touch $@

# Rules to run standalone executable test drives:

${TST_OUT_DIR}/%.out: ${TST_EXE_DIR}/% ${YAPP_MODULES}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || $< 2>&1 | ${filter_Ids} | tee $@
	-@touch $@

${TST_OUT_DIR}/%.diff: ${TST_EXE_DIR}/% ${YAPP_MODULES}
	-@printf "%-30s " "$*:" ; \
	./$< 2>&1 \
	| ${filter_Ids} \
	| diff ${TST_OUT_DIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

.PHONY: shoutputs shout shtests shtest

shoutputs shout: ${SHELL_OUTPUTS}

shtest shtests: ${SHELL_DIFFS}

${SHELL_OUTDIR}/%.out: ${SHELL_TSTDIR}/%.sh ${TARGET} ${YAPP_MODULES}
	-@test -f $@ || echo "$@:"
	-@test -f $@ || $< ./${TARGET} 2>&1 | ${filter_Ids} | tee $@
	-@touch $@

${SHELL_OUTDIR}/%.diff: ${SHELL_TSTDIR}/%.sh ${TARGET} ${YAPP_MODULES}
	-@printf "%-30s " "$*:" ; \
	$< ./${TARGET} 2>&1 \
	| ${filter_Ids} \
	| diff ${SHELL_OUTDIR}/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

.PHONY: tests alltests

tests alltests: test shtests

.PHONY: listdiff

listdiff: # test
	@-( test -d ${OUTPUT_DIR} && \
	    ls -l ${OUTPUT_DIR}/*.diff | awk '{if( $$5 > 0 ) print}' ) || \
	    true
	@-( test -d ${SHELL_OUTDIR} && \
	    ls -l ${SHELL_OUTDIR}/*.diff | awk '{if( $$5 > 0 ) print}' ) || \
	    true

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

.PHONY: clean cleanAll distclean

clean:
	rm -f *~
	rm -f ${DIFF_FILES}
	rm -f ${SCRIPT_DIFFS}
	rm -f ${TST_DIFFS}
	rm -f ${SHELL_DIFFS}

cleanAll distclean: clean ${LOCAL_CLEAN_TARGETS}
	rm -f ${YAPP_MODULES}
