]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/integration-test-wrapper.py
test: Default to linux qemu firmware
[thirdparty/systemd.git] / test / integration-test-wrapper.py
CommitLineData
b85e5496
DDM
1#!/usr/bin/python3
2# SPDX-License-Identifier: LGPL-2.1-or-later
3
4'''Test wrapper command for driving integration tests.
5
6Note: This is deliberately rough and only intended to drive existing tests
7with the expectation that as part of formally defining the API it will be tidy.
8
9'''
10
11import argparse
12import os
13import shlex
14import subprocess
15import sys
16import textwrap
17from pathlib import Path
18
19
20EMERGENCY_EXIT_DROPIN = """\
21[Unit]
22Wants=emergency-exit.service
23"""
24
25
26EMERGENCY_EXIT_SERVICE = """\
27[Unit]
28DefaultDependencies=no
29Conflicts=shutdown.target
30Conflicts=rescue.service
31Before=shutdown.target
32Before=rescue.service
33FailureAction=exit
34
35[Service]
36ExecStart=false
37"""
38
39
40def main():
cf5e1b5d
DDM
41 if not bool(int(os.getenv("SYSTEMD_INTEGRATION_TESTS", "0"))):
42 print("SYSTEMD_INTEGRATION_TESTS=1 not found in environment, skipping", file=sys.stderr)
43 exit(77)
44
b85e5496
DDM
45 parser = argparse.ArgumentParser(description=__doc__)
46 parser.add_argument('--meson-source-dir', required=True, type=Path)
47 parser.add_argument('--meson-build-dir', required=True, type=Path)
48 parser.add_argument('--test-name', required=True)
49 parser.add_argument('--test-number', required=True)
9a69900a 50 parser.add_argument('--storage', required=True)
1f2c9bda 51 parser.add_argument('--firmware', required=True)
b85e5496
DDM
52 parser.add_argument('mkosi_args', nargs="*")
53 args = parser.parse_args()
54
0596237e 55 name = args.test_name + (f"-{i}" if (i := os.getenv("MESON_TEST_ITERATION")) else "")
b85e5496
DDM
56 test_unit = f"testsuite-{args.test_number}.service"
57
58 dropin = textwrap.dedent(
59 """\
60 [Unit]
61 After=multi-user.target network.target
62 Requires=multi-user.target
d91bb1cb
DDM
63 SuccessAction=exit
64 SuccessActionExitStatus=123
b85e5496
DDM
65
66 [Service]
67 StandardOutput=journal+console
68 """
69 )
70
3cb61e0d
DDM
71 if os.getenv("TEST_MATCH_SUBTEST"):
72 dropin += textwrap.dedent(
73 f"""
74 [Service]
75 Environment=TEST_MATCH_SUBTEST={os.environ["TEST_MATCH_SUBTEST"]}
76 """
77 )
78
79 if os.getenv("TEST_MATCH_TESTCASE"):
80 dropin += textwrap.dedent(
81 f"""
82 [Service]
83 Environment=TEST_MATCH_TESTCASE={os.environ["TEST_MATCH_TESTCASE"]}
84 """
85 )
86
b85e5496
DDM
87 if not sys.stderr.isatty():
88 dropin += textwrap.dedent(
89 """
90 [Unit]
b85e5496
DDM
91 FailureAction=exit
92 """
93 )
94
0596237e 95 journal_file = (args.meson_build_dir / (f"test/journal/{name}.journal")).absolute()
b85e5496
DDM
96 journal_file.unlink(missing_ok=True)
97 else:
98 journal_file = None
99
100 cmd = [
101 'mkosi',
102 '--directory', os.fspath(args.meson_source_dir),
103 '--output-dir', os.fspath(args.meson_build_dir / 'mkosi.output'),
104 '--extra-search-path', os.fspath(args.meson_build_dir),
0596237e 105 '--machine', name,
b85e5496
DDM
106 '--ephemeral',
107 *(['--forward-journal', journal_file] if journal_file else []),
108 *(
109 [
110 '--credential',
111 f"systemd.extra-unit.emergency-exit.service={shlex.quote(EMERGENCY_EXIT_SERVICE)}",
112 '--credential',
113 f"systemd.unit-dropin.emergency.target={shlex.quote(EMERGENCY_EXIT_DROPIN)}",
b85e5496
DDM
114 ]
115 if not sys.stderr.isatty()
116 else []
117 ),
118 '--credential',
119 f"systemd.unit-dropin.{test_unit}={shlex.quote(dropin)}",
ab5f60cb 120 '--runtime-network=none',
d99deaaa 121 '--runtime-scratch=no',
b85e5496 122 '--append',
1f2c9bda 123 '--qemu-firmware', args.firmware,
b85e5496
DDM
124 '--kernel-command-line-extra',
125 ' '.join([
126 'systemd.hostname=H',
127 f"SYSTEMD_UNIT_PATH=/usr/lib/systemd/tests/testdata/testsuite-{args.test_number}.units:/usr/lib/systemd/tests/testdata/units:",
128 f"systemd.unit={test_unit}",
e911a335 129 'systemd.mask=systemd-networkd-wait-online.service',
06489e83
DDM
130 *(
131 [
132 "systemd.mask=serial-getty@.service",
133 "systemd.show_status=no",
134 "systemd.crash_shell=0",
27f166c5 135 "systemd.crash_action=poweroff",
06489e83
DDM
136 ]
137 if not sys.stderr.isatty()
138 else []
139 ),
b85e5496 140 ]),
bdade5f5 141 '--credential', f"journal.storage={'persistent' if sys.stderr.isatty() else args.storage}",
b85e5496
DDM
142 *args.mkosi_args,
143 'qemu',
144 ]
145
2fd84901
RM
146 result = subprocess.run(cmd)
147 # Return code 123 is the expected success code
d91bb1cb 148 if result.returncode != 123:
2fd84901 149 if result.returncode != 77 and journal_file:
b85e5496
DDM
150 cmd = [
151 'journalctl',
152 '--no-hostname',
153 '-o', 'short-monotonic',
154 '--file', journal_file,
155 '-u', test_unit,
156 '-p', 'info',
157 ]
158 print("Test failed, relevant logs can be viewed with: \n\n"
159 f"{shlex.join(str(a) for a in cmd)}\n", file=sys.stderr)
2fd84901 160 exit(result.returncode or 1)
b85e5496
DDM
161
162 # Do not keep journal files for tests that don't fail.
163 if journal_file:
164 journal_file.unlink(missing_ok=True)
165
166
167if __name__ == '__main__':
168 main()