blob: ab7afd30c56ae9f73394d3413561aa9bd1bba779 [file] [log] [blame]
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -07001# Copyright 2015 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Tool to run ebuild unittests."""
6
Alex Klein95843e82020-12-28 11:27:32 -07007import argparse
Chris McDonald59650c32021-07-20 15:29:28 -06008import logging
Aviv Keshet01fcca42016-07-25 16:34:59 -07009import multiprocessing
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070010import os
11
Mike Frysinger06a51c82021-04-06 11:39:17 -040012from chromite.lib import build_target_lib
Chris McDonald59650c32021-07-20 15:29:28 -060013from chromite.lib import chroot_util
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070014from chromite.lib import commandline
Chris McDonalde69db662018-11-15 12:50:18 -070015from chromite.lib import constants
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070016from chromite.lib import cros_build_lib
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070017from chromite.lib import osutils
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070018from chromite.lib import portage_util
Chris McDonald59650c32021-07-20 15:29:28 -060019from chromite.lib import workon_helper
Chris McDonalde69db662018-11-15 12:50:18 -070020from chromite.scripts import cros_extract_deps
21
Mike Frysinger6a2b0f22020-02-20 13:34:07 -050022
Chris McDonalde69db662018-11-15 12:50:18 -070023BOARD_VIRTUAL_PACKAGES = (constants.TARGET_OS_PKG,
24 constants.TARGET_OS_DEV_PKG,
Chris McDonaldb0c021c2019-01-07 15:04:22 -070025 constants.TARGET_OS_TEST_PKG,
26 constants.TARGET_OS_FACTORY_PKG)
Chris McDonalde69db662018-11-15 12:50:18 -070027IMPLICIT_TEST_DEPS = ('virtual/implicit-system',)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070028
29
30def ParseArgs(argv):
31 """Parse arguments.
32
33 Args:
34 argv: array of arguments passed to the script.
35 """
36 parser = commandline.ArgumentParser(description=__doc__)
37
38 target = parser.add_mutually_exclusive_group(required=True)
39 target.add_argument('--sysroot', type='path', help='Path to the sysroot.')
40 target.add_argument('--board', help='Board name.')
41
42 parser.add_argument('--pretend', default=False, action='store_true',
43 help='Show the list of packages to be tested and return.')
44 parser.add_argument('--noinstalled_only', dest='installed', default=True,
45 action='store_false',
46 help='Test all testable packages, even if they are not '
47 'currently installed.')
48 parser.add_argument('--package_file', type='path',
49 help='Path to a file containing the list of packages '
Alex Klein95843e82020-12-28 11:27:32 -070050 'that should be tested.')
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070051 parser.add_argument('--packages',
52 help='Space-separated list of packages to test.')
Alex Klein95843e82020-12-28 11:27:32 -070053 parser.add_argument('--blacklist_packages',
54 dest='skip_packages',
55 deprecated='Use --skip-packages instead.',
56 help=argparse.SUPPRESS)
57 parser.add_argument('--skip-packages',
58 help='Space-separated list of packages to NOT test even '
59 'if they otherwise would have been tested.')
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070060 parser.add_argument('--nowithdebug', action='store_true',
61 help="Don't build the tests with USE=cros-debug")
Chris McDonalde69db662018-11-15 12:50:18 -070062 parser.add_argument('--assume-empty-sysroot', default=False,
63 action='store_true', dest='empty_sysroot',
64 help='Set up dependencies and run unit tests for all '
65 'packages that could be installed on target board '
66 'without assuming that any packages have actually '
67 'been merged yet.')
Alex Kleinfe6081c2020-03-16 10:02:24 -060068 parser.add_argument(
69 '-j',
70 '--jobs',
71 type=int,
72 default=multiprocessing.cpu_count(),
73 help='The limit for the number of possible concurrent jobs.')
Navil Perezbcd69ba2020-09-02 23:13:36 +000074 parser.add_argument(
75 '--no-testable-packages-ok',
76 default=False,
77 action='store_true',
78 dest='testable_packages_optional',
Navil Perez22269b32021-05-13 17:51:53 +000079 help='If specified, do not fail if no testable packages are found.')
80 parser.add_argument(
81 '--filter-only-cros-workon',
82 default=False,
83 action='store_true',
84 help='If specified and packages are given, filters out non-cros_workon '
85 'packages.')
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070086
87 options = parser.parse_args(argv)
88 options.Freeze()
89 return options
90
91
Manoj Gupta94596972021-12-01 17:55:11 +000092def determine_board_packages(sysroot, virtual_packages):
Chris McDonalde69db662018-11-15 12:50:18 -070093 """Returns a set of the dependencies for the given packages"""
Chris McDonaldd8a7f112019-11-01 10:35:07 -060094 deps, _bdeps = cros_extract_deps.ExtractDeps(
95 sysroot, virtual_packages, include_bdepend=False)
96 return set(
97 '%s/%s' % (atom['category'], atom['name']) for atom in deps.values())
Chris McDonalde69db662018-11-15 12:50:18 -070098
99
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700100def main(argv):
101 opts = ParseArgs(argv)
102
103 cros_build_lib.AssertInsideChroot()
104
Manoj Gupta94596972021-12-01 17:55:11 +0000105 sysroot = (opts.sysroot or
106 build_target_lib.get_default_sysroot_path(opts.board))
Alex Klein95843e82020-12-28 11:27:32 -0700107 skipped_packages = set()
108 if opts.skip_packages:
109 skipped_packages |= set(opts.skip_packages.split())
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700110
111 packages = set()
112 # The list of packages to test can be passed as a file containing a
113 # space-separated list of package names.
Nicolas Boichat02bb93e2021-04-01 09:01:44 +0800114 # This is used by the builder to test only the packages that were uprevved.
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700115 if opts.package_file and os.path.exists(opts.package_file):
116 packages = set(osutils.ReadFile(opts.package_file).split())
117
118 if opts.packages:
119 packages |= set(opts.packages.split())
120
121 # If no packages were specified, use all testable packages.
Chris McDonalde69db662018-11-15 12:50:18 -0700122 if not (opts.packages or opts.package_file) and not opts.empty_sysroot:
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700123 workon = workon_helper.WorkonHelper(sysroot)
124 packages = (workon.InstalledWorkonAtoms() if opts.installed
Chris McDonalde69db662018-11-15 12:50:18 -0700125 else set(workon.ListAtoms(use_all=True)))
126
127 if opts.empty_sysroot:
Manoj Gupta94596972021-12-01 17:55:11 +0000128 packages |= determine_board_packages(sysroot, BOARD_VIRTUAL_PACKAGES)
Chris McDonalde69db662018-11-15 12:50:18 -0700129 workon = workon_helper.WorkonHelper(sysroot)
130 workon_packages = set(workon.ListAtoms(use_all=True))
131 packages &= workon_packages
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700132
Alex Klein95843e82020-12-28 11:27:32 -0700133 for cp in packages & skipped_packages:
134 logging.info('Skipping package %s.', cp)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700135
Alex Klein95843e82020-12-28 11:27:32 -0700136 packages = packages - skipped_packages
Navil Perez22269b32021-05-13 17:51:53 +0000137 pkg_with_test = portage_util.PackagesWithTest(sysroot, packages,
138 opts.filter_only_cros_workon)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700139
140 if packages - pkg_with_test:
Mike Frysinger80aa9322019-09-01 15:38:56 -0400141 logging.warning('The following packages do not have tests:\n %s',
142 '\n '.join(sorted(packages - pkg_with_test)))
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700143
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400144 if not pkg_with_test:
Navil Perezbcd69ba2020-09-02 23:13:36 +0000145 if opts.testable_packages_optional:
146 logging.warning('No testable packages found!')
147 return 0
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400148 logging.error('No testable packages found!')
149 return 1
150
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700151 if opts.pretend:
152 print('\n'.join(sorted(pkg_with_test)))
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400153 return 0
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700154
Navil Perez03dc71a2021-07-22 18:38:49 +0000155 env = {}
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700156 if opts.nowithdebug:
157 use_flags = os.environ.get('USE', '')
158 use_flags += ' -cros-debug'
Navil Perez03dc71a2021-07-22 18:38:49 +0000159 env['USE'] = use_flags
160
161 metrics_dir = os.environ.get(constants.CROS_METRICS_DIR_ENVVAR)
162 if metrics_dir:
163 env[constants.CROS_METRICS_DIR_ENVVAR] = metrics_dir
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700164
Chris McDonalde69db662018-11-15 12:50:18 -0700165 if opts.empty_sysroot:
166 try:
167 chroot_util.Emerge(list(IMPLICIT_TEST_DEPS), sysroot, rebuild_deps=False,
168 use_binary=False)
169 chroot_util.Emerge(list(pkg_with_test), sysroot, rebuild_deps=False,
170 use_binary=False)
171 except cros_build_lib.RunCommandError:
172 logging.error('Failed building dependencies for unittests.')
Mike Frysingerd56bb812019-09-01 15:42:24 -0400173 return 1
Chris McDonalde69db662018-11-15 12:50:18 -0700174
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700175 try:
Alex Kleinfe6081c2020-03-16 10:02:24 -0600176 chroot_util.RunUnittests(
177 sysroot, pkg_with_test, extra_env=env, jobs=opts.jobs)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700178 except cros_build_lib.RunCommandError:
179 logging.error('Unittests failed.')
Mike Frysingerd56bb812019-09-01 15:42:24 -0400180 return 1