3d2f73ef75
"meson test" starting with version 0.57 is just as capable and easy to use as QEMU's own TAP driver. All existing options for "make check" work. The only required code change involves how to mark "slow" tests; they need to belong to an additional "slow" suite. The rules for .tap output are replaced by JUnit XML; GitLab is able to parse that output and present it in the CI pipeline report. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
106 lines
3.6 KiB
Python
106 lines
3.6 KiB
Python
#! /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 itertools
|
|
import json
|
|
import os
|
|
import shlex
|
|
import sys
|
|
|
|
class Suite(object):
|
|
def __init__(self):
|
|
self.deps = set()
|
|
self.speeds = ['quick']
|
|
|
|
def names(self, base):
|
|
return [base if speed == 'quick' else f'{base}-{speed}' for speed in self.speeds]
|
|
|
|
|
|
print('''
|
|
SPEED = quick
|
|
|
|
.speed.quick = $(foreach s,$(sort $(filter-out %-slow, $1)), --suite $s)
|
|
.speed.slow = $(foreach s,$(sort $1), --suite $s)
|
|
|
|
.mtestargs = --no-rebuild -t 0
|
|
ifneq ($(SPEED), quick)
|
|
.mtestargs += --setup $(SPEED)
|
|
endif
|
|
.mtestargs += $(subst -j,--num-processes , $(filter-out -j, $(lastword -j1 $(filter -j%, $(MAKEFLAGS)))))
|
|
|
|
.check.mtestargs = $(MTESTARGS) $(.mtestargs) $(if $(V),--verbose,--print-errorlogs)
|
|
.bench.mtestargs = $(MTESTARGS) $(.mtestargs) --benchmark --verbose''')
|
|
|
|
introspect = json.load(sys.stdin)
|
|
|
|
def process_tests(test, targets, suites):
|
|
executable = test['cmd'][0]
|
|
try:
|
|
executable = os.path.relpath(executable)
|
|
except:
|
|
pass
|
|
|
|
deps = (targets.get(x, []) for x in test['depends'])
|
|
deps = itertools.chain.from_iterable(deps)
|
|
deps = list(deps)
|
|
|
|
test_suites = test['suite'] or ['default']
|
|
for s in test_suites:
|
|
# The suite name in the introspection info is "PROJECT:SUITE"
|
|
s = s.split(':')[1]
|
|
if s == 'slow':
|
|
continue
|
|
if s.endswith('-slow'):
|
|
s = s[:-5]
|
|
suites[s].speeds.append('slow')
|
|
suites[s].deps.update(deps)
|
|
|
|
def emit_prolog(suites, prefix):
|
|
all_targets = ' '.join((f'{prefix}-{k}' for k in suites.keys()))
|
|
all_xml = ' '.join((f'{prefix}-report-{k}.junit.xml' for k in suites.keys()))
|
|
print()
|
|
print(f'all-{prefix}-targets = {all_targets}')
|
|
print(f'all-{prefix}-xml = {all_xml}')
|
|
print(f'.PHONY: {prefix} do-meson-{prefix} {prefix}-report.junit.xml $(all-{prefix}-targets) $(all-{prefix}-xml)')
|
|
print(f'ifeq ($(filter {prefix}, $(MAKECMDGOALS)),)')
|
|
print(f'.{prefix}.mtestargs += $(call .speed.$(SPEED), $(.{prefix}.mtest-suites))')
|
|
print(f'endif')
|
|
print(f'{prefix}-build: run-ninja')
|
|
print(f'{prefix} $(all-{prefix}-targets): do-meson-{prefix}')
|
|
print(f'do-meson-{prefix}: run-ninja; $(if $(MAKE.n),,+)$(MESON) test $(.{prefix}.mtestargs)')
|
|
print(f'{prefix}-report.junit.xml $(all-{prefix}-xml): {prefix}-report%.junit.xml: run-ninja')
|
|
print(f'\t$(MAKE) {prefix}$* MTESTARGS="$(MTESTARGS) --logbase {prefix}-report$*" && ln -f meson-logs/$@ .')
|
|
|
|
def emit_suite(name, suite, prefix):
|
|
deps = ' '.join(suite.deps)
|
|
targets = f'{prefix}-{name} {prefix}-report-{name}.junit.xml {prefix} {prefix}-report.junit.xml'
|
|
print()
|
|
print(f'.{prefix}-{name}.deps = {deps}')
|
|
print(f'ifneq ($(filter {prefix}-build {targets}, $(MAKECMDGOALS)),)')
|
|
print(f'.{prefix}.build-suites += {name}')
|
|
print(f'endif')
|
|
print(f'ifneq ($(filter {targets}, $(MAKECMDGOALS)),)')
|
|
print(f'.{prefix}.mtest-suites += ' + ' '.join(suite.names(name)))
|
|
print(f'endif')
|
|
|
|
targets = {t['id']: [os.path.relpath(f) for f in t['filename']]
|
|
for t in introspect['targets']}
|
|
|
|
testsuites = defaultdict(Suite)
|
|
for test in introspect['tests']:
|
|
process_tests(test, targets, testsuites)
|
|
emit_prolog(testsuites, 'check')
|
|
for name, suite in testsuites.items():
|
|
emit_suite(name, suite, 'check')
|
|
|
|
benchsuites = defaultdict(Suite)
|
|
for test in introspect['benchmarks']:
|
|
process_tests(test, targets, benchsuites)
|
|
emit_prolog(benchsuites, 'bench')
|
|
for name, suite in benchsuites.items():
|
|
emit_suite(name, suite, 'bench')
|