#---*- Makefile -*-------------------------------------------------------------
#$Author: antanas $
#$Date: 2024-04-29 00:04:23 +0300 (Mon, 29 Apr 2024) $
#$Revision: 10001 $
#$URL: svn+ssh://www.crystallography.net/home/coder/svn-repositories/cod-tools/tags/v3.11.0/makefiles/Makelocal-unit-test $
#------------------------------------------------------------------------------
#*
#  Runs unit tests for an individual module. Requires test driver script(s).
#  The makefile is also capable of creating test output files (*.out)
#  from test input files (*.inp), producing the list of tests that
#  did not pass and removing old test results.
#**

# The following variables should be predefined in the Makeconf file:
# $(TEST_MODULE)
#                   Full path to the module that is being tested.
# $(TEST_DEPEND)
#                   Additional dependencies that should be assembled
#                   before carrying out the tests (for example, *.so
#                   files that are generated by SWIG).
TEST_MODULE ?= $(notdir $(shell pwd)).pm
TEST_DEPEND ?=

TEST_DIR = tests

SHELL = /bin/bash

.PRECIOUS: $(TEST_MODULE) $(TEST_DEPEND)
.PHONY: all tests alltests

all:

check tests alltests: test shtest

define buffer_output
perl -0777 -lne 'print $$_;'
endef

#------------------------------------------------------------------------------
# Tests that use the driver scripts:

SCRIPT_DIR = $(TEST_DIR)/scripts
INP_DIR    = $(TEST_DIR)/cases
OUTP_DIR   = $(TEST_DIR)/outputs

TEST_FILES = $(wildcard $(INP_DIR)/*.inp)
DIFF_FILES = $(TEST_FILES:$(INP_DIR)/%.inp=$(OUTP_DIR)/%.diff)
OUTP_FILES = $(TEST_FILES:$(INP_DIR)/%.inp=$(OUTP_DIR)/%.out)

.PHONY: test out outputs

test: $(sort $(DIFF_FILES))

out outputs: $(OUTP_FILES)

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

$(OUTP_DIR)/%.diff: $(INP_DIR)/%.inp $(TEST_MODULE) $(TEST_DEPEND)
	-@printf "%-30s " "$<:" ; \
	( $(SCRIPT_DIR)/$(shell echo $* | sed -e 's/_[0-9]*$$//') \
		$< \
	| $(buffer_output)) 2>&1 \
	| diff $(OUTP_DIR)/$*.out - \
		> $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

$(OUTP_DIR)/%.out: $(INP_DIR)/%.inp $(INP_DIR)/%.opt $(TEST_MODULE) $(TEST_DEPEND)
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	( $(SCRIPT_DIR)/$(shell echo $* | sed -e 's/_[0-9]*$$//') \
		$(shell grep -v '^#' $(word 2, $^)) \
		$< \
	| $(buffer_output)) 2>&1 \
	| tee $@
	-@touch $@

$(OUTP_DIR)/%.out: $(INP_DIR)/%.inp $(TEST_MODULE) $(TEST_DEPEND)
	-@test -f $@ || echo "$@:"
	-@test -f $@ || \
	( $(SCRIPT_DIR)/$(shell echo $* | sed -e 's/_[0-9]*$$//') \
		$< \
	| $(buffer_output)) 2>&1 \
	| tee $@
	-@touch $@

#------------------------------------------------------------------------------
# Shell-driven tests:

SHELL_TSTDIR = ./$(TEST_DIR)/shtests
SHELL_OUTDIR = ./$(TEST_DIR)/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))

.PHONY: shtest shtests shout shoutputs

shtest shtests: $(sort $(SHELL_DIFFS))

shout shoutputs: $(SHELL_OUTPUTS)

$(SHELL_OUTDIR)/%.out: $(SHELL_TSTDIR)/%.sh $(TEST_MODULE) $(TEST_DEPEND)
	-@test -f $@ || echo "$@:"
	-@test -f $@ || ( $< $(TEST_MODULE) | $(buffer_output) ) 2>&1 | tee $@
	-@touch $@

$(SHELL_OUTDIR)/%.diff: $(SHELL_TSTDIR)/%.sh $(TEST_MODULE) $(TEST_DEPEND)
	-@printf "%-30s " "$*:" ; \
	( $< $(TEST_MODULE) | $(buffer_output) ) 2>&1 \
	| diff $(SHELL_OUTDIR)/$*.out - > $@ ; \
	if [ $$? = 0 ]; then echo "OK"; else echo "FAILED:"; cat $@; fi

#------------------------------------------------------------------------------
# Generate a list of tests that did not pass:

.PHONY: listdiff

listdiff: $(DIFF_FILES) $(SHELL_DIFFS)
	@find $(OUTP_DIR) $(SHELL_OUTDIR) -name \*.diff -size +0 \
	| sort -u | xargs --no-run-if-empty ls -l

#------------------------------------------------------------------------------
# Remove old tests results:

.PHONY: clean cleanAll distclean

clean cleanAll distclean: clean-YAPP-test

clean-YAPP-test:
	rm -f $(DIFF_FILES)
	rm -f $(SHELL_DIFFS)
