aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2020-01-28 14:48:54 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2020-08-21 06:30:07 -0400
commit245dac4a1bef719d648e20c84bbf3dcaf50de988 (patch)
tree1edcc6c1c051e496bf88eb3ecb05ba2b406ac908
parent968b4db38a717d334db9298fb7b6f6ba71d08806 (diff)
meson: add testsuite Makefile generator
Rules to execute tests are generated by a simple Python program that integrates into the existing "make check" mechanism. This provides familiarity for developers, and also allows piecewise conversion of the testsuite Makefiles to meson. The generated rules are based on QEMU's existing test harness Makefile and TAP parser. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--Makefile10
-rw-r--r--scripts/mtest2make.py102
-rw-r--r--tests/Makefile.include1
3 files changed, 111 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 81c9642a30..5f9aae6e3e 100644
--- a/Makefile
+++ b/Makefile
@@ -68,6 +68,14 @@ Makefile.ninja: build.ninja ninjatool
${ninja-targets-c_COMPILER} ${ninja-targets-cpp_COMPILER}: .var.command += -MP
+# If MESON is empty, the rule will be re-evaluated after Makefiles are
+# reread (and MESON won't be empty anymore).
+ifneq ($(MESON),)
+Makefile.mtest: build.ninja scripts/mtest2make.py
+ $(MESON) introspect --tests | $(PYTHON) scripts/mtest2make.py > $@
+-include Makefile.mtest
+endif
+
.git-submodule-status: git-submodule-update config-host.mak
# Check that we're not trying to do an out-of-tree build from
@@ -825,7 +833,7 @@ distclean: clean ninja-distclean
rm -f roms/seabios/config.mak roms/vgabios/config.mak
rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
rm -rf meson-private meson-logs meson-info compile_commands.json
- rm -f Makefile.ninja ninjatool ninjatool.stamp
+ rm -f Makefile.ninja ninjatool ninjatool.stamp Makefile.mtest
rm -f config.log
rm -f linux-headers/asm
rm -f docs/version.texi
diff --git a/scripts/mtest2make.py b/scripts/mtest2make.py
new file mode 100644
index 0000000000..bdb257bbd9
--- /dev/null
+++ b/scripts/mtest2make.py
@@ -0,0 +1,102 @@
+#! /usr/bin/env python3
+
+# Create Makefile targets to run tests, from Meson's test introspection data.
+#
+# Author: Paolo Bonzini <pbonzini@redhat.com>
+
+from collections import defaultdict
+import json
+import os
+import shlex
+import sys
+
+class Suite(object):
+ def __init__(self):
+ self.tests = list()
+ self.slow_tests = list()
+ self.executables = set()
+
+print('''
+SPEED = quick
+
+# $1 = test command, $2 = test name
+.test-human-tap = $1 < /dev/null | ./scripts/tap-driver.pl --test-name="$2" $(if $(V),,--show-failures-only)
+.test-human-exitcode = $1 < /dev/null
+.test-tap-tap = $1 < /dev/null | sed "s/^[a-z][a-z]* [0-9]*/& $2/" || true
+.test-tap-exitcode = printf "%s\\n" 1..1 "`$1 < /dev/null > /dev/null || echo "not "`ok 1 $2"
+.test.print = echo $(if $(V),'$1','Running test $2') >&3
+.test.env = MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))}
+
+# $1 = test name, $2 = test target (human or tap)
+.test.run = $(call .test.print,$(.test.cmd.$1),$(.test.name.$1)) && $(call .test-$2-$(.test.driver.$1),$(.test.cmd.$1),$(.test.name.$1))
+
+define .test.human_k
+ @exec 3>&1; rc=0; $(foreach TEST, $1, $(call .test.run,$(TEST),human) || rc=$$?;) \\
+ exit $$rc
+endef
+define .test.human_no_k
+ $(foreach TEST, $1, @exec 3>&1; $(call .test.run,$(TEST),human)
+)
+endef
+.test.human = \\
+ $(if $(findstring k, $(MAKEFLAGS)), $(.test.human_k), $(.test.human_no_k))
+
+define .test.tap
+ @exec 3>&1; { $(foreach TEST, $1, $(call .test.run,$(TEST),tap); ) } \\
+ | ./scripts/tap-merge.pl | tee "$@" \\
+ | ./scripts/tap-driver.pl $(if $(V),, --show-failures-only)
+endef
+''')
+
+suites = defaultdict(Suite)
+i = 0
+for test in json.load(sys.stdin):
+ env = ' '.join(('%s=%s' % (shlex.quote(k), shlex.quote(v))
+ for k, v in test['env'].items()))
+ executable = os.path.relpath(test['cmd'][0])
+ if test['workdir'] is not None:
+ test['cmd'][0] = os.path.relpath(test['cmd'][0], test['workdir'])
+ else:
+ test['cmd'][0] = executable
+ cmd = '$(.test.env) %s %s' % (env, ' '.join((shlex.quote(x) for x in test['cmd'])))
+ if test['workdir'] is not None:
+ cmd = '(cd %s && %s)' % (shlex.quote(test['workdir']), cmd)
+ driver = test['protocol'] if 'protocol' in test else 'exitcode'
+
+ i += 1
+ print('.test.name.%d := %s' % (i, test['name']))
+ print('.test.driver.%d := %s' % (i, driver))
+ print('.test.cmd.%d := %s' % (i, cmd))
+
+ test_suites = test['suite'] or ['default']
+ is_slow = any(s.endswith('-slow') for s in test_suites)
+ for s in test_suites:
+ # The suite name in the introspection info is "PROJECT:SUITE"
+ s = s.split(':')[1]
+ if s.endswith('-slow'):
+ s = s[:-5]
+ if is_slow:
+ suites[s].slow_tests.append(i)
+ else:
+ suites[s].tests.append(i)
+ suites[s].executables.add(executable)
+
+print('.PHONY: check check-report.tap')
+print('check:')
+print('check-report.tap:')
+print('\t@cat $^ | scripts/tap-merge.pl >$@')
+for name, suite in suites.items():
+ executables = ' '.join(suite.executables)
+ slow_test_numbers = ' '.join((str(x) for x in suite.slow_tests))
+ test_numbers = ' '.join((str(x) for x in suite.tests))
+ print('.test.suite-quick.%s := %s' % (name, test_numbers))
+ print('.test.suite-slow.%s := $(.test.suite-quick.%s) %s' % (name, name, slow_test_numbers))
+ print('check-build: %s' % executables)
+ print('.PHONY: check-%s' % name)
+ print('.PHONY: check-report-%s.tap' % name)
+ print('check: check-%s' % name)
+ print('check-%s: all %s' % (name, executables))
+ print('\t$(call .test.human, $(.test.suite-$(SPEED).%s))' % (name, ))
+ print('check-report.tap: check-report-%s.tap' % name)
+ print('check-report-%s.tap: %s' % (name, executables))
+ print('\t$(call .test.tap, $(.test.suite-$(SPEED).%s))' % (name, ))
diff --git a/tests/Makefile.include b/tests/Makefile.include
index c7e4646ded..ad54100369 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -674,7 +674,6 @@ check-report-unit.tap: $(check-unit-y)
# Reports and overall runs
check-report.tap: $(patsubst %,check-report-qtest-%.tap, $(QTEST_TARGETS)) check-report-unit.tap
- $(call quiet-command, cat $^ | scripts/tap-merge.pl >$@,"GEN","$@")
# FPU Emulation tests (aka softfloat)
#