####################################################################### # v # The Coq Proof Assistant / The Coq Development Team # # /dev/null 2>&1) # read out an emacs config and look for coq-prog-args; if such exists, return it get_coq_prog_args_helper = sed -n s'/^.*coq-prog-args:[[:space:]]*(\([^)]*\)).*/\1/p' $(1) get_coq_prog_args = $(strip $(filter-out "-emacs-U" "-emacs",$(shell $(call get_coq_prog_args_helper,$(1))))) SINGLE_QUOTE=" #" # double up on the quotes, in a comment, to appease the emacs syntax highlighter # wrap the arguments in parens, but only if they exist get_coq_prog_args_in_parens = $(subst $(SINGLE_QUOTE),,$(if $(call get_coq_prog_args,$(1)), ($(call get_coq_prog_args,$(1))))) bogomips:= ifneq (,$(wildcard /proc/cpuinfo)) sedbogo := -e "s/bogomips.*: \([0-9]*\).*/\1/p" # i386, ppc sedbogo += -e "s/Cpu0Bogo.*: \([0-9]*\).*/\1/p" # sparc sedbogo += -e "s/BogoMIPS.*: \([0-9]*\).*/\1/p" # alpha bogomips := $(shell sed -n $(sedbogo) /proc/cpuinfo | head -1) endif ifeq (,$(bogomips)) $(warning cannot run complexity tests (no bogomips found)) endif log_success = "==========> SUCCESS <==========" log_failure = "==========> FAILURE <==========" log_intro = "==========> TESTING $(1) <==========" ####################################################################### # Testing subsystems ####################################################################### # Apart so that it can be easily skipped with overriding COMPLEXITY := $(if $(bogomips),complexity) BUGS := bugs/opened bugs/closed VSUBSYSTEMS := prerequisite success failure $(BUGS) output \ interactive micromega $(COMPLEXITY) modules stm # All subsystems SUBSYSTEMS := $(VSUBSYSTEMS) misc bugs ide ####################################################################### # Phony targets ####################################################################### .DELETE_ON_ERROR: .PHONY: all run clean $(SUBSYSTEMS) all: run $(MAKE) --quiet summary.log run: $(SUBSYSTEMS) bugs: $(BUGS) clean: rm -f trace lia.cache $(SHOW) "RM <**/*.stamp> <**/*.vo> <**/*.log>" $(HIDE)find . \( \ -name '*.stamp' -o -name '*.vo' -o -name '*.log' \ \) -print0 | xargs -0 rm -f distclean: clean $(HIDE)find . -name '*.log' -print0 | xargs -0 rm -f ####################################################################### # Per-subsystem targets ####################################################################### define mkstamp $(1): $(1).stamp ; @true $(1).stamp: $(patsubst %.v,%.v.log,$(wildcard $(1)/*.v)) ; \ $(HIDE)touch $$@ endef $(foreach S,$(VSUBSYSTEMS),$(eval $(call mkstamp,$(S)))) ####################################################################### # Summary ####################################################################### summary_dir = echo $(1); find $(2) -name '*.log' -print0 | xargs -0 -n 1 tail -n1 | sort .PHONY: summary summary.log summary: @{ \ $(call summary_dir, "Preparing tests", prerequisite); \ $(call summary_dir, "Success tests", success); \ $(call summary_dir, "Failure tests", failure); \ $(call summary_dir, "Bugs tests", bugs); \ $(call summary_dir, "Output tests", output); \ $(call summary_dir, "Interactive tests", interactive); \ $(call summary_dir, "Micromega tests", micromega); \ $(call summary_dir, "Miscellaneous tests", misc); \ $(call summary_dir, "Complexity tests", complexity); \ $(call summary_dir, "Module tests", modules); \ $(call summary_dir, "STM tests", stm); \ $(call summary_dir, "IDE tests", ide); \ nb_success=`find . -name '*.log' -exec tail -n2 '{}' \; | grep -e $(log_success) | wc -l`; \ nb_failure=`find . -name '*.log' -exec tail -n2 '{}' \; | grep -e $(log_failure) | wc -l`; \ nb_tests=`expr $$nb_success + $$nb_failure`; \ pourcentage=`expr 100 \* $$nb_success / $$nb_tests`; \ echo; \ echo "$$nb_success tests passed over $$nb_tests, i.e. $$pourcentage %"; \ } summary.log: $(SHOW) SUMMARY $(HIDE)$(MAKE) --quiet summary > "$@" ####################################################################### # Regression (and progression) tests ####################################################################### # Process verifications concerning submitted bugs. A message is # printed for all opened bugs (still active or seems to be closed). # For closed bugs that behave as expected, no message is printed # All files are assumed to have <# of the bug>.v as a name # Opened bugs that should not fail $(addsuffix .log,$(wildcard bugs/opened/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ $(command) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...still active"; \ else \ echo $(log_failure); \ echo " $<...Error! (bug seems to be closed, please check)"; \ fi; \ } > "$@" # Closed bugs that should succeed $(addsuffix .log,$(wildcard bugs/closed/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ $(command) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error! (bug seems to be opened, please check)"; \ fi; \ } > "$@" ####################################################################### # Other generic tests ####################################################################### $(addsuffix .log,$(wildcard prerequisite/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ $(coqc) "$*" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \ if [ $$R != 0 ]; then \ echo $(log_failure); \ echo " $<...could not be prepared" ; \ else \ echo $(log_success); \ echo " $<...correctly prepared" ; \ fi; \ } > "$@" $(addsuffix .log,$(wildcard success/*.v micromega/*.v modules/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ opts="$(if $(findstring modules/,$<),-R modules Mods -impredicative-set)"; \ echo $(call log_intro,$<); \ $(command) "$<" $(call get_coq_prog_args,"$<") $$opts 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error! (should be accepted)"; \ fi; \ } > "$@" stm: $(wildcard stm/*.v:%.v=%.v.log) $(addsuffix .log,$(wildcard stm/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ $(coqc) "$*" $(call get_coq_prog_args,"$<") -async-proofs on \ -async-proofs-private-flags fallback-to-lazy-if-marshal-error=no,fallback-to-lazy-if-slave-dies=no \ $$opts 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error! (should be accepted)"; \ fi; \ } > "$@" $(addsuffix .log,$(wildcard failure/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ $(command) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error! (should be rejected)"; \ fi; \ } > "$@" $(addsuffix .log,$(wildcard output/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ tmpoutput=`mktemp /tmp/coqcheck.XXXXXX`; \ $(command) "$<" $(call get_coq_prog_args,"$<") 2>&1 \ | grep -v "Welcome to Coq" \ | grep -v "\[Loading ML file" \ | grep -v "Skipping rcfile loading" \ > $$tmpoutput; \ diff -u $*.out $$tmpoutput 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error! (unexpected output)"; \ fi; \ rm $$tmpoutput; \ } > "$@" $(addsuffix .log,$(wildcard interactive/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ $(coqtop) $(call get_coq_prog_args,"$<") < "$<" 2>&1; R=$$?; times; \ if [ $$R = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error! (should be accepted)"; \ fi; \ } > "$@" # Complexity test. Expects a line "(* Expected time < XXX.YYs *)" in # the .v file with exactly two digits after the dot. The reference for # time is a 6120 bogomips cpu. ifneq (,$(bogomips)) $(addsuffix .log,$(wildcard complexity/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ true "extract effective user time"; \ res=`$(command) "$<" $(call get_coq_prog_args,"$<") 2>&1 | sed -n -e "s/Finished transaction in .*(\([0-9]*\.[0-9]*\)u.*)/\1/p" | head -1`; \ R=$$?; times; \ if [ $$R != 0 ]; then \ echo $(log_failure); \ echo " $<...Error! (should be accepted)" ; \ elif [ "$$res" = "" ]; then \ echo $(log_failure); \ echo " $<...Error! (couldn't find a time measure)"; \ else \ true "express effective time in centiseconds"; \ res=`echo "$$res"00 | sed -n -e "s/\([0-9]*\)\.\([0-9][0-9]\).*/\1\2/p"`; \ true "find expected time * 100"; \ exp=`sed -n -e "s/(\*.*Expected time < \([0-9]\).\([0-9][0-9]\)s.*\*)/\1\2/p" "$<"`; \ ok=`expr \( $$res \* $(bogomips) \) "<" \( $$exp \* 6120 \)`; \ if [ "$$ok" = 1 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error! (should run faster)"; \ fi; \ fi; \ } > "$@" endif # Ideal-features tests $(addsuffix .log,$(wildcard ideal-features/*.v)): %.v.log: %.v @echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")" $(HIDE){ \ echo $(call log_intro,$<); \ $(command) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \ if [ $$R != 0 ]; then \ echo $(log_success); \ echo " $<...still wished"; \ else \ echo $(log_failure); \ echo " $<...Good news! (wish seems to be granted, please check)"; \ fi; \ } > "$@" # Additionnal dependencies for module tests $(addsuffix .log,$(wildcard modules/*.v)): %.v.log: modules/Nat.vo modules/plik.vo modules/%.vo: modules/%.v $(HIDE)$(coqtop) -R modules Mods -compile $(<:.v=) ####################################################################### # Miscellaneous tests ####################################################################### misc: misc/deps-order.log misc/universes.log # Check that both coqdep and coqtop/coqc supports -R # Check that both coqdep and coqtop/coqc takes the later -R # See bugs 2242, 2337, 2339 deps-order: misc/deps-order.log misc/deps-order.log: @echo "TEST misc/deps-order" $(HIDE){ \ echo $(call log_intro,deps-order); \ rm -f misc/deps/*/*.vo; \ tmpoutput=`mktemp /tmp/coqcheck.XXXXXX`; \ $(coqdep) -R misc/deps/lib lib -R misc/deps/client client misc/deps/client/bar.v 2>&1 \ | head -n 1 > $$tmpoutput; \ diff -u misc/deps/deps.out $$tmpoutput 2>&1; R=$$?; times; \ $(bincoqc) -R misc/deps/lib lib misc/deps/lib/foo.v 2>&1; \ $(bincoqc) -R misc/deps/lib lib -R misc/deps/client client misc/deps/client/foo.v 2>&1; \ $(coqtop) -R misc/deps/lib lib -R misc/deps/client client -load-vernac-source misc/deps/client/bar.v 2>&1; \ S=$$?; times; \ if [ $$R = 0 -a $$S = 0 ]; then \ echo $(log_success); \ echo " misc/deps-order...Ok"; \ else \ echo $(log_failure); \ echo " misc/deps-order...Error! (unexpected order)"; \ fi; \ rm $$tmpoutput; \ } > "$@" # Sort universes for the whole standard library EXPECTED_UNIVERSES := 4 universes: misc/universes.log misc/universes.log: misc/universes/all_stdlib.v @echo "TEST misc/universes" $(HIDE){ \ $(bincoqc) -R misc/universes Universes misc/universes/all_stdlib 2>&1; \ $(bincoqc) -R misc/universes Universes misc/universes/universes 2>&1; \ mv universes.txt misc/universes; \ N=`awk '{print $$3}' misc/universes/universes.txt | sort -u | wc -l`; \ times; \ if [ "$$N" -eq $(EXPECTED_UNIVERSES) ]; then \ echo $(log_success); \ echo " misc/universes...Ok ($(EXPECTED_UNIVERSES) universes)"; \ else \ echo $(log_failure); \ echo " misc/universes...Error! ($$N/$(EXPECTED_UNIVERSES) universes)"; \ fi; \ } > "$@" misc/universes/all_stdlib.v: cd .. && $(MAKE) test-suite/$@ # IDE : some tests of backtracking for coqtop -ideslave ide : $(patsubst %.fake,%.fake.log,$(wildcard ide/*.fake)) %.fake.log : %.fake @echo "TEST $<" $(HIDE){ \ echo $(call log_intro,$<); \ $(BIN)fake_ide $< "$(BIN)coqtop -boot -async-proofs on -async-proofs-always-delegate" 2>&1; \ if [ $$? = 0 ]; then \ echo $(log_success); \ echo " $<...Ok"; \ else \ echo $(log_failure); \ echo " $<...Error!"; \ fi; \ } > "$@"