xref: /qemu/scripts/mtest2make.py (revision 4156325c)
1245dac4aSPaolo Bonzini#! /usr/bin/env python3
2245dac4aSPaolo Bonzini
3245dac4aSPaolo Bonzini# Create Makefile targets to run tests, from Meson's test introspection data.
4245dac4aSPaolo Bonzini#
5245dac4aSPaolo Bonzini# Author: Paolo Bonzini <pbonzini@redhat.com>
6245dac4aSPaolo Bonzini
7245dac4aSPaolo Bonzinifrom collections import defaultdict
848a81fd5SPaolo Bonziniimport itertools
9245dac4aSPaolo Bonziniimport json
10245dac4aSPaolo Bonziniimport os
11245dac4aSPaolo Bonziniimport shlex
12245dac4aSPaolo Bonziniimport sys
13245dac4aSPaolo Bonzini
14245dac4aSPaolo Bonziniclass Suite(object):
15245dac4aSPaolo Bonzini    def __init__(self):
163d2f73efSPaolo Bonzini        self.deps = set()
173d2f73efSPaolo Bonzini        self.speeds = ['quick']
183d2f73efSPaolo Bonzini
193d2f73efSPaolo Bonzini    def names(self, base):
203d2f73efSPaolo Bonzini        return [base if speed == 'quick' else f'{base}-{speed}' for speed in self.speeds]
213d2f73efSPaolo Bonzini
22245dac4aSPaolo Bonzini
23245dac4aSPaolo Bonziniprint('''
24245dac4aSPaolo BonziniSPEED = quick
25245dac4aSPaolo Bonzini
263e233e29SPaolo Bonzini.speed.quick = $(foreach s,$(sort $(filter-out %-slow %-thorough, $1)), --suite $s)
273e233e29SPaolo Bonzini.speed.slow = $(foreach s,$(sort $(filter-out %-thorough, $1)), --suite $s)
283e233e29SPaolo Bonzini.speed.thorough = $(foreach s,$(sort $1), --suite $s)
29245dac4aSPaolo Bonzini
304156325cSDaniel P. BerrangéTIMEOUT_MULTIPLIER = 1
314156325cSDaniel P. Berrangé.mtestargs = --no-rebuild -t $(TIMEOUT_MULTIPLIER)
323d2f73efSPaolo Bonziniifneq ($(SPEED), quick)
333d2f73efSPaolo Bonzini.mtestargs += --setup $(SPEED)
343d2f73efSPaolo Bonziniendif
353d2f73efSPaolo Bonzini.mtestargs += $(subst -j,--num-processes , $(filter-out -j, $(lastword -j1 $(filter -j%, $(MAKEFLAGS)))))
36245dac4aSPaolo Bonzini
373d2f73efSPaolo Bonzini.check.mtestargs = $(MTESTARGS) $(.mtestargs) $(if $(V),--verbose,--print-errorlogs)
383d2f73efSPaolo Bonzini.bench.mtestargs = $(MTESTARGS) $(.mtestargs) --benchmark --verbose''')
39245dac4aSPaolo Bonzini
4040d9b74eSPaolo Bonziniintrospect = json.load(sys.stdin)
4140d9b74eSPaolo Bonzini
4248a81fd5SPaolo Bonzinidef process_tests(test, targets, suites):
43cb23fd47SYonggang Luo    executable = test['cmd'][0]
44cb23fd47SYonggang Luo    try:
45cb23fd47SYonggang Luo        executable = os.path.relpath(executable)
46cb23fd47SYonggang Luo    except:
47cb23fd47SYonggang Luo        pass
4848a81fd5SPaolo Bonzini
4948a81fd5SPaolo Bonzini    deps = (targets.get(x, []) for x in test['depends'])
5048a81fd5SPaolo Bonzini    deps = itertools.chain.from_iterable(deps)
513d2f73efSPaolo Bonzini    deps = list(deps)
52245dac4aSPaolo Bonzini
53245dac4aSPaolo Bonzini    test_suites = test['suite'] or ['default']
54245dac4aSPaolo Bonzini    for s in test_suites:
55bc848265SMarc-André Lureau        # The suite name in the introspection info is "PROJECT" or "PROJECT:SUITE"
56bc848265SMarc-André Lureau        if ':' in s:
57245dac4aSPaolo Bonzini            s = s.split(':')[1]
583e233e29SPaolo Bonzini            if s == 'slow' or s == 'thorough':
593d2f73efSPaolo Bonzini                continue
60245dac4aSPaolo Bonzini        if s.endswith('-slow'):
61245dac4aSPaolo Bonzini            s = s[:-5]
623d2f73efSPaolo Bonzini            suites[s].speeds.append('slow')
633e233e29SPaolo Bonzini        if s.endswith('-thorough'):
643e233e29SPaolo Bonzini            s = s[:-9]
653e233e29SPaolo Bonzini            suites[s].speeds.append('thorough')
663d2f73efSPaolo Bonzini        suites[s].deps.update(deps)
67245dac4aSPaolo Bonzini
6840d9b74eSPaolo Bonzinidef emit_prolog(suites, prefix):
693d2f73efSPaolo Bonzini    all_targets = ' '.join((f'{prefix}-{k}' for k in suites.keys()))
703d2f73efSPaolo Bonzini    all_xml = ' '.join((f'{prefix}-report-{k}.junit.xml' for k in suites.keys()))
713d2f73efSPaolo Bonzini    print()
723d2f73efSPaolo Bonzini    print(f'all-{prefix}-targets = {all_targets}')
733d2f73efSPaolo Bonzini    print(f'all-{prefix}-xml = {all_xml}')
743d2f73efSPaolo Bonzini    print(f'.PHONY: {prefix} do-meson-{prefix} {prefix}-report.junit.xml $(all-{prefix}-targets) $(all-{prefix}-xml)')
753d2f73efSPaolo Bonzini    print(f'ifeq ($(filter {prefix}, $(MAKECMDGOALS)),)')
763d2f73efSPaolo Bonzini    print(f'.{prefix}.mtestargs += $(call .speed.$(SPEED), $(.{prefix}.mtest-suites))')
773d2f73efSPaolo Bonzini    print(f'endif')
783d2f73efSPaolo Bonzini    print(f'{prefix}-build: run-ninja')
793d2f73efSPaolo Bonzini    print(f'{prefix} $(all-{prefix}-targets): do-meson-{prefix}')
803d2f73efSPaolo Bonzini    print(f'do-meson-{prefix}: run-ninja; $(if $(MAKE.n),,+)$(MESON) test $(.{prefix}.mtestargs)')
813d2f73efSPaolo Bonzini    print(f'{prefix}-report.junit.xml $(all-{prefix}-xml): {prefix}-report%.junit.xml: run-ninja')
823d2f73efSPaolo Bonzini    print(f'\t$(MAKE) {prefix}$* MTESTARGS="$(MTESTARGS) --logbase {prefix}-report$*" && ln -f meson-logs/$@ .')
8340d9b74eSPaolo Bonzini
8498487b90SPaolo Bonzinidef emit_suite_deps(name, suite, prefix):
853d2f73efSPaolo Bonzini    deps = ' '.join(suite.deps)
869b32ba53SPaolo Bonzini    targets = [f'{prefix}-{name}', f'{prefix}-report-{name}.junit.xml', f'{prefix}', f'{prefix}-report.junit.xml',
879b32ba53SPaolo Bonzini               f'{prefix}-build']
883d2f73efSPaolo Bonzini    print()
893d2f73efSPaolo Bonzini    print(f'.{prefix}-{name}.deps = {deps}')
909b32ba53SPaolo Bonzini    for t in targets:
919b32ba53SPaolo Bonzini        print(f'.ninja-goals.{t} += $(.{prefix}-{name}.deps)')
9298487b90SPaolo Bonzini
9398487b90SPaolo Bonzinidef emit_suite(name, suite, prefix):
9498487b90SPaolo Bonzini    emit_suite_deps(name, suite, prefix)
9598487b90SPaolo Bonzini    targets = f'{prefix}-{name} {prefix}-report-{name}.junit.xml {prefix} {prefix}-report.junit.xml'
963d2f73efSPaolo Bonzini    print(f'ifneq ($(filter {targets}, $(MAKECMDGOALS)),)')
973d2f73efSPaolo Bonzini    print(f'.{prefix}.mtest-suites += ' + ' '.join(suite.names(name)))
983d2f73efSPaolo Bonzini    print(f'endif')
9940d9b74eSPaolo Bonzini
10048a81fd5SPaolo Bonzinitargets = {t['id']: [os.path.relpath(f) for f in t['filename']]
10148a81fd5SPaolo Bonzini           for t in introspect['targets']}
10248a81fd5SPaolo Bonzini
10340d9b74eSPaolo Bonzinitestsuites = defaultdict(Suite)
1049ed7247aSPaolo Bonzinifor test in introspect['tests']:
10548a81fd5SPaolo Bonzini    process_tests(test, targets, testsuites)
10640d9b74eSPaolo Bonziniemit_prolog(testsuites, 'check')
10740d9b74eSPaolo Bonzinifor name, suite in testsuites.items():
10840d9b74eSPaolo Bonzini    emit_suite(name, suite, 'check')
10940d9b74eSPaolo Bonzini
1109ed7247aSPaolo Bonzinibenchsuites = defaultdict(Suite)
1119ed7247aSPaolo Bonzinifor test in introspect['benchmarks']:
11248a81fd5SPaolo Bonzini    process_tests(test, targets, benchsuites)
1139ed7247aSPaolo Bonziniemit_prolog(benchsuites, 'bench')
1149ed7247aSPaolo Bonzinifor name, suite in benchsuites.items():
1159ed7247aSPaolo Bonzini    emit_suite(name, suite, 'bench')
116