qemu-iotests: add option to show qemu binary logs on stdout
[qemu/armbru.git] / tests / qemu-iotests / check
blobda1bfb839e6fb65860c98818c271144a005a9889
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('-makecheck', action='store_true',
36                    help='pretty print output for make check')
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 the test output')
41     p.add_argument('-gdb', action='store_true',
42                    help="start gdbserver with $GDB_OPTIONS options \
43                         ('localhost:12345' if $GDB_OPTIONS is empty)")
44     p.add_argument('-valgrind', action='store_true',
45                     help='use valgrind, sets VALGRIND_QEMU environment '
46                     'variable')
48     p.add_argument('-misalign', action='store_true',
49                    help='misalign memory allocations')
50     p.add_argument('--color', choices=['on', 'off', 'auto'],
51                    default='auto', help="use terminal colors. The default "
52                    "'auto' value means use colors if terminal stdout detected")
54     g_env = p.add_argument_group('test environment options')
55     mg = g_env.add_mutually_exclusive_group()
56     # We don't set default for cachemode, as we need to distinguish default
57     # from user input later.
58     mg.add_argument('-nocache', dest='cachemode', action='store_const',
59                     const='none', help='set cache mode "none" (O_DIRECT), '
60                     'sets CACHEMODE environment variable')
61     mg.add_argument('-c', dest='cachemode',
62                     help='sets CACHEMODE environment variable')
64     g_env.add_argument('-i', dest='aiomode', default='threads',
65                        help='sets AIOMODE environment variable')
67     p.set_defaults(imgfmt='raw', imgproto='file')
69     format_list = ['raw', 'bochs', 'cloop', 'parallels', 'qcow', 'qcow2',
70                    'qed', 'vdi', 'vpc', 'vhdx', 'vmdk', 'luks', 'dmg']
71     g_fmt = p.add_argument_group(
72         '  image format options',
73         'The following options set the IMGFMT environment variable. '
74         'At most one choice is allowed, default is "raw"')
75     mg = g_fmt.add_mutually_exclusive_group()
76     for fmt in format_list:
77         mg.add_argument('-' + fmt, dest='imgfmt', action='store_const',
78                         const=fmt, help=f'test {fmt}')
80     protocol_list = ['file', 'rbd', 'nbd', 'ssh', 'nfs', 'fuse']
81     g_prt = p.add_argument_group(
82         '  image protocol options',
83         'The following options set the IMGPROTO environment variable. '
84         'At most one choice is allowed, default is "file"')
85     mg = g_prt.add_mutually_exclusive_group()
86     for prt in protocol_list:
87         mg.add_argument('-' + prt, dest='imgproto', action='store_const',
88                         const=prt, help=f'test {prt}')
90     g_bash = p.add_argument_group('bash tests options',
91                                   'The following options are ignored by '
92                                   'python tests.')
93     # TODO: make support for the following options in iotests.py
94     g_bash.add_argument('-o', dest='imgopts',
95                         help='options to pass to qemu-img create/convert, '
96                         'sets IMGOPTS environment variable')
98     g_sel = p.add_argument_group('test selecting options',
99                                  'The following options specify test set '
100                                  'to run.')
101     g_sel.add_argument('-g', '--groups', metavar='group1,...',
102                        help='include tests from these groups')
103     g_sel.add_argument('-x', '--exclude-groups', metavar='group1,...',
104                        help='exclude tests from these groups')
105     g_sel.add_argument('--start-from', metavar='TEST',
106                        help='Start from specified test: make sorted sequence '
107                        'of tests as usual and then drop tests from the first '
108                        'one to TEST (not inclusive). This may be used to '
109                        'rerun failed ./check command, starting from the '
110                        'middle of the process.')
111     g_sel.add_argument('tests', metavar='TEST_FILES', nargs='*',
112                        help='tests to run, or "--" followed by a command')
114     return p
117 if __name__ == '__main__':
118     args = make_argparser().parse_args()
120     env = TestEnv(imgfmt=args.imgfmt, imgproto=args.imgproto,
121                   aiomode=args.aiomode, cachemode=args.cachemode,
122                   imgopts=args.imgopts, misalign=args.misalign,
123                   debug=args.debug, valgrind=args.valgrind,
124                   gdb=args.gdb, qprint=args.print)
126     if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
127         if not args.tests:
128             sys.exit("missing command after '--'")
129         cmd = args.tests
130         env.print_env()
131         exec_pathstr = shutil.which(cmd[0])
132         if exec_pathstr is None:
133             sys.exit('command not found: ' + cmd[0])
134         exec_path = Path(exec_pathstr).resolve()
135         cmd[0] = str(exec_path)
136         full_env = env.prepare_subprocess(cmd)
137         os.chdir(exec_path.parent)
138         os.execve(cmd[0], cmd, full_env)
140     testfinder = TestFinder(test_dir=env.source_iotests)
142     groups = args.groups.split(',') if args.groups else None
143     x_groups = args.exclude_groups.split(',') if args.exclude_groups else None
145     group_local = os.path.join(env.source_iotests, 'group.local')
146     if os.path.isfile(group_local):
147         try:
148             testfinder.add_group_file(group_local)
149         except ValueError as e:
150             sys.exit(f"Failed to parse group file '{group_local}': {e}")
152     try:
153         tests = testfinder.find_tests(groups=groups, exclude_groups=x_groups,
154                                       tests=args.tests,
155                                       start_from=args.start_from)
156         if not tests:
157             raise ValueError('No tests selected')
158     except ValueError as e:
159         sys.exit(e)
161     if args.dry_run:
162         print('\n'.join(tests))
163     else:
164         with TestRunner(env, makecheck=args.makecheck,
165                         color=args.color) as tr:
166             paths = [os.path.join(env.source_iotests, t) for t in tests]
167             ok = tr.run_tests(paths)
168             if not ok:
169                 sys.exit(1)