blob: d2506e18b0fe864354d686b8ee5af59beecaba21 [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)
Sloan Johnsona85640f2021-10-01 22:32:40 +000027SDK_VIRTUAL_PACKAGES = (constants.TARGET_SDK,)
Chris McDonalde69db662018-11-15 12:50:18 -070028IMPLICIT_TEST_DEPS = ('virtual/implicit-system',)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070029
30
31def ParseArgs(argv):
32 """Parse arguments.
33
34 Args:
35 argv: array of arguments passed to the script.
36 """
37 parser = commandline.ArgumentParser(description=__doc__)
38
39 target = parser.add_mutually_exclusive_group(required=True)
40 target.add_argument('--sysroot', type='path', help='Path to the sysroot.')
41 target.add_argument('--board', help='Board name.')
Sloan Johnsona85640f2021-10-01 22:32:40 +000042 target.add_argument('--host', action='store_true',
43 help='Run tests for the host SDK.')
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070044
45 parser.add_argument('--pretend', default=False, action='store_true',
46 help='Show the list of packages to be tested and return.')
47 parser.add_argument('--noinstalled_only', dest='installed', default=True,
48 action='store_false',
49 help='Test all testable packages, even if they are not '
50 'currently installed.')
51 parser.add_argument('--package_file', type='path',
52 help='Path to a file containing the list of packages '
Alex Klein95843e82020-12-28 11:27:32 -070053 'that should be tested.')
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070054 parser.add_argument('--packages',
55 help='Space-separated list of packages to test.')
Alex Klein95843e82020-12-28 11:27:32 -070056 parser.add_argument('--blacklist_packages',
57 dest='skip_packages',
58 deprecated='Use --skip-packages instead.',
59 help=argparse.SUPPRESS)
60 parser.add_argument('--skip-packages',
61 help='Space-separated list of packages to NOT test even '
62 'if they otherwise would have been tested.')
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070063 parser.add_argument('--nowithdebug', action='store_true',
64 help="Don't build the tests with USE=cros-debug")
Chris McDonalde69db662018-11-15 12:50:18 -070065 parser.add_argument('--assume-empty-sysroot', default=False,
66 action='store_true', dest='empty_sysroot',
67 help='Set up dependencies and run unit tests for all '
68 'packages that could be installed on target board '
69 'without assuming that any packages have actually '
70 'been merged yet.')
Alex Kleinfe6081c2020-03-16 10:02:24 -060071 parser.add_argument(
72 '-j',
73 '--jobs',
74 type=int,
75 default=multiprocessing.cpu_count(),
76 help='The limit for the number of possible concurrent jobs.')
Navil Perezbcd69ba2020-09-02 23:13:36 +000077 parser.add_argument(
78 '--no-testable-packages-ok',
79 default=False,
80 action='store_true',
81 dest='testable_packages_optional',
Navil Perez22269b32021-05-13 17:51:53 +000082 help='If specified, do not fail if no testable packages are found.')
83 parser.add_argument(
84 '--filter-only-cros-workon',
85 default=False,
86 action='store_true',
87 help='If specified and packages are given, filters out non-cros_workon '
88 'packages.')
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -070089
90 options = parser.parse_args(argv)
91 options.Freeze()
92 return options
93
94
Sloan Johnsona85640f2021-10-01 22:32:40 +000095def determine_packages(sysroot, virtual_packages):
Chris McDonalde69db662018-11-15 12:50:18 -070096 """Returns a set of the dependencies for the given packages"""
Chris McDonaldd8a7f112019-11-01 10:35:07 -060097 deps, _bdeps = cros_extract_deps.ExtractDeps(
98 sysroot, virtual_packages, include_bdepend=False)
99 return set(
100 '%s/%s' % (atom['category'], atom['name']) for atom in deps.values())
Chris McDonalde69db662018-11-15 12:50:18 -0700101
102
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700103def main(argv):
104 opts = ParseArgs(argv)
105
106 cros_build_lib.AssertInsideChroot()
107
Sloan Johnsona85640f2021-10-01 22:32:40 +0000108 sysroot = (opts.sysroot or '/' if opts.host
109 else build_target_lib.get_default_sysroot_path(opts.board))
Alex Klein95843e82020-12-28 11:27:32 -0700110 skipped_packages = set()
111 if opts.skip_packages:
112 skipped_packages |= set(opts.skip_packages.split())
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700113
114 packages = set()
115 # The list of packages to test can be passed as a file containing a
116 # space-separated list of package names.
Nicolas Boichat02bb93e2021-04-01 09:01:44 +0800117 # This is used by the builder to test only the packages that were uprevved.
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700118 if opts.package_file and os.path.exists(opts.package_file):
119 packages = set(osutils.ReadFile(opts.package_file).split())
120
121 if opts.packages:
122 packages |= set(opts.packages.split())
123
124 # If no packages were specified, use all testable packages.
Chris McDonalde69db662018-11-15 12:50:18 -0700125 if not (opts.packages or opts.package_file) and not opts.empty_sysroot:
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700126 workon = workon_helper.WorkonHelper(sysroot)
127 packages = (workon.InstalledWorkonAtoms() if opts.installed
Chris McDonalde69db662018-11-15 12:50:18 -0700128 else set(workon.ListAtoms(use_all=True)))
129
130 if opts.empty_sysroot:
Sloan Johnsona85640f2021-10-01 22:32:40 +0000131 packages |= determine_packages(sysroot, SDK_VIRTUAL_PACKAGES if opts.host
132 else BOARD_VIRTUAL_PACKAGES)
Chris McDonalde69db662018-11-15 12:50:18 -0700133 workon = workon_helper.WorkonHelper(sysroot)
134 workon_packages = set(workon.ListAtoms(use_all=True))
135 packages &= workon_packages
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700136
Alex Klein95843e82020-12-28 11:27:32 -0700137 for cp in packages & skipped_packages:
138 logging.info('Skipping package %s.', cp)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700139
Alex Klein95843e82020-12-28 11:27:32 -0700140 packages = packages - skipped_packages
Navil Perez22269b32021-05-13 17:51:53 +0000141 pkg_with_test = portage_util.PackagesWithTest(sysroot, packages,
142 opts.filter_only_cros_workon)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700143
144 if packages - pkg_with_test:
Mike Frysinger80aa9322019-09-01 15:38:56 -0400145 logging.warning('The following packages do not have tests:\n %s',
146 '\n '.join(sorted(packages - pkg_with_test)))
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700147
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400148 if not pkg_with_test:
Navil Perezbcd69ba2020-09-02 23:13:36 +0000149 if opts.testable_packages_optional:
150 logging.warning('No testable packages found!')
151 return 0
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400152 logging.error('No testable packages found!')
153 return 1
154
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700155 if opts.pretend:
156 print('\n'.join(sorted(pkg_with_test)))
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400157 return 0
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700158
Navil Perez03dc71a2021-07-22 18:38:49 +0000159 env = {}
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700160 if opts.nowithdebug:
161 use_flags = os.environ.get('USE', '')
162 use_flags += ' -cros-debug'
Navil Perez03dc71a2021-07-22 18:38:49 +0000163 env['USE'] = use_flags
164
165 metrics_dir = os.environ.get(constants.CROS_METRICS_DIR_ENVVAR)
166 if metrics_dir:
167 env[constants.CROS_METRICS_DIR_ENVVAR] = metrics_dir
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700168
Chris McDonalde69db662018-11-15 12:50:18 -0700169 if opts.empty_sysroot:
170 try:
171 chroot_util.Emerge(list(IMPLICIT_TEST_DEPS), sysroot, rebuild_deps=False,
172 use_binary=False)
173 chroot_util.Emerge(list(pkg_with_test), sysroot, rebuild_deps=False,
174 use_binary=False)
175 except cros_build_lib.RunCommandError:
176 logging.error('Failed building dependencies for unittests.')
Mike Frysingerd56bb812019-09-01 15:42:24 -0400177 return 1
Chris McDonalde69db662018-11-15 12:50:18 -0700178
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700179 try:
Alex Kleinfe6081c2020-03-16 10:02:24 -0600180 chroot_util.RunUnittests(
181 sysroot, pkg_with_test, extra_env=env, jobs=opts.jobs)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700182 except cros_build_lib.RunCommandError:
183 logging.error('Unittests failed.')
Mike Frysingerd56bb812019-09-01 15:42:24 -0400184 return 1