Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / tests / qemu-iotests / check
blob9bdda1394e73aea76a86d25fed66e46abc4a78c8
1 #!/usr/bin/env python3
3 # Configure environment and run group of tests in it.
5 # Copyright (c) 2020-2021 Virtuozzo International GmbH
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation.
11 # This program is distributed in the hope that it would be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 import os
20 import sys
21 import argparse
22 import shutil
23 from pathlib import Path
25 from findtests import TestFinder
26 from testenv import TestEnv
27 from testrunner import TestRunner
30 def make_argparser() -> argparse.ArgumentParser:
31     p = argparse.ArgumentParser(description="Test run options")
33     p.add_argument('-n', '--dry-run', action='store_true',
34                    help='show me, do not run tests')
35     p.add_argument('-j', dest='jobs', type=int, default=1,
36                    help='run tests in multiple parallel jobs')
38     p.add_argument('-d', dest='debug', action='store_true', help='debug')
39     p.add_argument('-p', dest='print', action='store_true',
40                    help='redirects qemu\'s stdout and stderr to '
41                         'the test output')
42     p.add_argument('-gdb', action='store_true',
43                    help="start gdbserver with $GDB_OPTIONS options "
44                         "('localhost:12345' if $GDB_OPTIONS is empty)")
45     p.add_argument('-valgrind', action='store_true',
46                    help='use valgrind, sets VALGRIND_QEMU environment '
47                         'variable')
49     p.add_argument('-misalign', action='store_true',
50                    help='misalign memory allocations')
51     p.add_argument('--color', choices=['on', 'off', 'auto'],
52                    default='auto', help="use terminal colors. The default "
53                    "'auto' value means use colors if terminal stdout detected")
54     p.add_argument('-tap', action='store_true',
55                    help='produce TAP output')
57     g_env = p.add_argument_group('test environment options')
58     mg = g_env.add_mutually_exclusive_group()
59     # We don't set default for cachemode, as we need to distinguish default
60     # from user input later.
61     mg.add_argument('-nocache', dest='cachemode', action='store_const',
62                     const='none', help='set cache mode "none" (O_DIRECT), '
63                     'sets CACHEMODE environment variable')
64     mg.add_argument('-c', dest='cachemode',
65                     help='sets CACHEMODE environment variable')
67     g_env.add_argument('-i', dest='aiomode', default='threads',
68                        help='sets AIOMODE environment variable')
70     p.set_defaults(imgfmt='raw', imgproto='file')
72     format_list = ['raw', 'bochs', 'cloop', 'parallels', 'qcow', 'qcow2',
73                    'qed', 'vdi', 'vpc', 'vhdx', 'vmdk', 'luks', 'dmg']
74     g_fmt = p.add_argument_group(
75         '  image format options',
76         'The following options set the IMGFMT environment variable. '
77         'At most one choice is allowed, default is "raw"')
78     mg = g_fmt.add_mutually_exclusive_group()
79     for fmt in format_list:
80         mg.add_argument('-' + fmt, dest='imgfmt', action='store_const',
81                         const=fmt, help=f'test {fmt}')
83     protocol_list = ['file', 'rbd', 'nbd', 'ssh', 'nfs', 'fuse']
84     g_prt = p.add_argument_group(
85         '  image protocol options',
86         'The following options set the IMGPROTO environment variable. '
87         'At most one choice is allowed, default is "file"')
88     mg = g_prt.add_mutually_exclusive_group()
89     for prt in protocol_list:
90         mg.add_argument('-' + prt, dest='imgproto', action='store_const',
91                         const=prt, help=f'test {prt}')
93     g_bash = p.add_argument_group('bash tests options',
94                                   'The following options are ignored by '
95                                   'python tests.')
96     # TODO: make support for the following options in iotests.py
97     g_bash.add_argument('-o', dest='imgopts',
98                         help='options to pass to qemu-img create/convert, '
99                         'sets IMGOPTS environment variable')
101     g_sel = p.add_argument_group('test selecting options',
102                                  'The following options specify test set '
103                                  'to run.')
104     g_sel.add_argument('-g', '--groups', metavar='group1,...',
105                        help='include tests from these groups')
106     g_sel.add_argument('-x', '--exclude-groups', metavar='group1,...',
107                        help='exclude tests from these groups')
108     g_sel.add_argument('--start-from', metavar='TEST',
109                        help='Start from specified test: make sorted sequence '
110                        'of tests as usual and then drop tests from the first '
111                        'one to TEST (not inclusive). This may be used to '
112                        'rerun failed ./check command, starting from the '
113                        'middle of the process.')
114     g_sel.add_argument('tests', metavar='TEST_FILES', nargs='*',
115                        help='tests to run, or "--" followed by a command')
117     return p
120 if __name__ == '__main__':
121     args = make_argparser().parse_args()
123     env = TestEnv(imgfmt=args.imgfmt, imgproto=args.imgproto,
124                   aiomode=args.aiomode, cachemode=args.cachemode,
125                   imgopts=args.imgopts, misalign=args.misalign,
126                   debug=args.debug, valgrind=args.valgrind,
127                   gdb=args.gdb, qprint=args.print)
129     if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
130         if not args.tests:
131             sys.exit("missing command after '--'")
132         cmd = args.tests
133         env.print_env()
134         exec_pathstr = shutil.which(cmd[0])
135         if exec_pathstr is None:
136             sys.exit('command not found: ' + cmd[0])
137         exec_path = Path(exec_pathstr).resolve()
138         cmd[0] = str(exec_path)
139         full_env = env.prepare_subprocess(cmd)
140         os.chdir(exec_path.parent)
141         os.execve(cmd[0], cmd, full_env)
143     testfinder = TestFinder(test_dir=env.source_iotests)
145     groups = args.groups.split(',') if args.groups else None
146     x_groups = args.exclude_groups.split(',') if args.exclude_groups else None
148     group_local = os.path.join(env.source_iotests, 'group.local')
149     if os.path.isfile(group_local):
150         try:
151             testfinder.add_group_file(group_local)
152         except ValueError as e:
153             sys.exit(f"Failed to parse group file '{group_local}': {e}")
155     try:
156         tests = testfinder.find_tests(groups=groups, exclude_groups=x_groups,
157                                       tests=args.tests,
158                                       start_from=args.start_from)
159         if not tests:
160             raise ValueError('No tests selected')
161     except ValueError as e:
162         sys.exit(str(e))
164     if args.dry_run:
165         print('\n'.join(tests))
166     else:
167         with TestRunner(env, tap=args.tap,
168                         color=args.color) as tr:
169             paths = [os.path.join(env.source_iotests, t) for t in tests]
170             ok = tr.run_tests(paths, args.jobs)
171             if not ok:
172                 sys.exit(1)