You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
4.2 KiB
104 lines
4.2 KiB
4 months ago
|
# from https://github.com/box/Makefile.test
|
||
|
# `make -C test -j`
|
||
|
|
||
|
# Makefile that has a convenient check target.
|
||
|
# It can be included from another Makefile that only has a TESTS variable
|
||
|
# defined like this
|
||
|
#
|
||
|
# TESTS ?=
|
||
|
#
|
||
|
# Runs the specified test executables. Prepends the test's name to each test's output
|
||
|
# and gives a nice summary at the end of test execution about passed failed
|
||
|
# tests.
|
||
|
|
||
|
# Only bash is supported
|
||
|
SHELL := /bin/bash
|
||
|
|
||
|
THIS_FILE := $(realpath $(lastword $(MAKEFILE_LIST)))
|
||
|
# The directory where Makefile.test (this file) resides
|
||
|
THIS_FILE_DIR := $(shell dirname $(THIS_FILE))
|
||
|
|
||
|
# FIRST_MAKEFILE may be passed from parent make to child make. If it is not
|
||
|
# absent, do not overwrite it.
|
||
|
FIRST_MAKEFILE ?= $(realpath $(firstword $(MAKEFILE_LIST)))
|
||
|
export FIRST_MAKEFILE
|
||
|
|
||
|
# The directory where the Makefile, that is invoked from the command line,
|
||
|
# resides. That makefile would define the TESTS variable. We assume that the
|
||
|
# binaries defined in the TESTS variable also reside in the directory as
|
||
|
# the Makefile. The generated intermediate files will also go to this directory.
|
||
|
FIRST_MAKEFILE_DIR ?= $(shell dirname $(FIRST_MAKEFILE))
|
||
|
export FIRST_MAKEFILE_DIR
|
||
|
|
||
|
# So that the child makefiles can see the same TESTS variable.
|
||
|
export TESTS
|
||
|
|
||
|
failedTestsName := .makefile_test_failed_tests
|
||
|
executedTestsName := .makefile_test_executed_tests
|
||
|
TEST_TARGETS := $(TESTS:%=TARGET_FOR_%)
|
||
|
export TEST_TARGETS
|
||
|
|
||
|
# If the tests need a different environment one can append to this variable.
|
||
|
TEST_ENVIRONMENT = PYTHONPATH=$(THIS_FILE_DIR):$$PYTHONPATH PATH=$(THIS_FILE_DIR):$$PATH
|
||
|
|
||
|
# TODO: Only write to intermediate files, if they exist already.
|
||
|
# https://unix.stackexchange.com/q/405497/212862
|
||
|
# There is still a race condition here. Maybe we should use sed for appending.
|
||
|
define RUN_ONE_TEST
|
||
|
TARGET_FOR_$(1): $$(FIRST_MAKEFILE_DIR)/$(1)
|
||
|
+@export PATH=$$$$(pwd):$$$$PATH; \
|
||
|
if [ -e $$(FIRST_MAKEFILE_DIR)/$$(executedTestsName) ]; then \
|
||
|
echo $$< >> $$(FIRST_MAKEFILE_DIR)/$$(executedTestsName); \
|
||
|
fi; \
|
||
|
$$(TEST_ENVIRONMENT) $$< 2>&1 | sed "s/^/ [$$$$(basename $$<)] /"; test $$$${PIPESTATUS[0]} -eq 0; \
|
||
|
if [ $$$$? -eq 0 ]; then \
|
||
|
echo " PASSED: $$$$(basename $$<)"; \
|
||
|
else \
|
||
|
echo " FAILED: $$$$(basename $$<)"; \
|
||
|
if [ -e $$(FIRST_MAKEFILE_DIR)/$$(failedTestsName) ]; then \
|
||
|
echo $$< >> $$(FIRST_MAKEFILE_DIR)/$$(failedTestsName); \
|
||
|
fi; \
|
||
|
fi;
|
||
|
endef
|
||
|
|
||
|
# Build the above rule to run one test, for all tests.
|
||
|
$(foreach currtest,$(TESTS),$(eval $(call RUN_ONE_TEST,$(currtest))))
|
||
|
|
||
|
# execute the tests and look at the generated temp files afterwards.
|
||
|
actualCheck: $(TEST_TARGETS)
|
||
|
+@failed_tests=$$(cat $(FIRST_MAKEFILE_DIR)/$(failedTestsName) 2> /dev/null | wc -l;); \
|
||
|
executed_tests=$$(cat $(FIRST_MAKEFILE_DIR)/$(executedTestsName) 2> /dev/null | wc -l;); \
|
||
|
if [ $$failed_tests -ne 0 -a $$executed_tests -ne 0 ]; then \
|
||
|
echo ---------------------------------; \
|
||
|
echo "Failed $$failed_tests out of $$executed_tests tests"; \
|
||
|
echo ---------------------------------; \
|
||
|
elif [ $$failed_tests -eq 0 ]; then \
|
||
|
echo ---------------------------------; \
|
||
|
echo "All $$executed_tests tests passed"; \
|
||
|
echo ---------------------------------; \
|
||
|
fi; \
|
||
|
exit $$failed_tests;
|
||
|
|
||
|
# A commonly used bash command to clean intermediate files. Instead of writing
|
||
|
# it every time re-use this variable.
|
||
|
RM_INTERMEDIATE_FILES := rm -f $(FIRST_MAKEFILE_DIR)/$(failedTestsName) $(FIRST_MAKEFILE_DIR)/$(executedTestsName)
|
||
|
|
||
|
# At the start of the make, we want to start with empty intermediate files.
|
||
|
TRUNCATE_INTERMEDIATE_FILES := cat /dev/null > $(FIRST_MAKEFILE_DIR)/$(failedTestsName) && cat /dev/null > $(FIRST_MAKEFILE_DIR)/$(executedTestsName)
|
||
|
|
||
|
# With trap make sure the clean step is always executed before and after the
|
||
|
# tests run time. Do not leave residual files in the repo.
|
||
|
check:
|
||
|
+@trap "code=\$$?; \
|
||
|
$(RM_INTERMEDIATE_FILES); \
|
||
|
exit \$${code};" EXIT; \
|
||
|
$(TRUNCATE_INTERMEDIATE_FILES); \
|
||
|
$(MAKE) -f $(THIS_FILE) actualCheck;
|
||
|
|
||
|
all: check
|
||
|
|
||
|
.PHONY: all check preCheck actualCheck $(TEST_TARGETS)
|
||
|
.DEFAULT_GOAL := all
|
||
|
|
||
|
|