blob: c76de9ebac5b3c5584341237aafa58d7a45e1ddb [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
Hengxiang Hu2e33c712022-01-25 19:11:07 -0800102def get_keep_going():
103 """Check if should enable keep_going parameter.
104
105 If the 'USE' environment contains 'coverage' then enable keep_going option
106 to prevent certain package failure from breaking the whole coverage
107 generation workflow, otherwise leave it to default settings
108 """
109 return 'coverage' in os.environ.get('USE', '')
Chris McDonalde69db662018-11-15 12:50:18 -0700110
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700111def main(argv):
112 opts = ParseArgs(argv)
113
114 cros_build_lib.AssertInsideChroot()
115
Sloan Johnsona85640f2021-10-01 22:32:40 +0000116 sysroot = (opts.sysroot or '/' if opts.host
117 else build_target_lib.get_default_sysroot_path(opts.board))
Alex Klein95843e82020-12-28 11:27:32 -0700118 skipped_packages = set()
119 if opts.skip_packages:
120 skipped_packages |= set(opts.skip_packages.split())
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700121
122 packages = set()
123 # The list of packages to test can be passed as a file containing a
124 # space-separated list of package names.
Nicolas Boichat02bb93e2021-04-01 09:01:44 +0800125 # This is used by the builder to test only the packages that were uprevved.
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700126 if opts.package_file and os.path.exists(opts.package_file):
127 packages = set(osutils.ReadFile(opts.package_file).split())
128
129 if opts.packages:
130 packages |= set(opts.packages.split())
131
132 # If no packages were specified, use all testable packages.
Chris McDonalde69db662018-11-15 12:50:18 -0700133 if not (opts.packages or opts.package_file) and not opts.empty_sysroot:
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700134 workon = workon_helper.WorkonHelper(sysroot)
135 packages = (workon.InstalledWorkonAtoms() if opts.installed
Chris McDonalde69db662018-11-15 12:50:18 -0700136 else set(workon.ListAtoms(use_all=True)))
137
138 if opts.empty_sysroot:
Sloan Johnsona85640f2021-10-01 22:32:40 +0000139 packages |= determine_packages(sysroot, SDK_VIRTUAL_PACKAGES if opts.host
140 else BOARD_VIRTUAL_PACKAGES)
Chris McDonalde69db662018-11-15 12:50:18 -0700141 workon = workon_helper.WorkonHelper(sysroot)
142 workon_packages = set(workon.ListAtoms(use_all=True))
143 packages &= workon_packages
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700144
Alex Klein95843e82020-12-28 11:27:32 -0700145 for cp in packages & skipped_packages:
146 logging.info('Skipping package %s.', cp)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700147
Alex Klein95843e82020-12-28 11:27:32 -0700148 packages = packages - skipped_packages
Navil Perez22269b32021-05-13 17:51:53 +0000149 pkg_with_test = portage_util.PackagesWithTest(sysroot, packages,
150 opts.filter_only_cros_workon)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700151
152 if packages - pkg_with_test:
Mike Frysinger80aa9322019-09-01 15:38:56 -0400153 logging.warning('The following packages do not have tests:\n %s',
154 '\n '.join(sorted(packages - pkg_with_test)))
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700155
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400156 if not pkg_with_test:
Navil Perezbcd69ba2020-09-02 23:13:36 +0000157 if opts.testable_packages_optional:
158 logging.warning('No testable packages found!')
159 return 0
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400160 logging.error('No testable packages found!')
161 return 1
162
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700163 if opts.pretend:
164 print('\n'.join(sorted(pkg_with_test)))
Mike Frysingerdcb680f2019-09-02 00:21:44 -0400165 return 0
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700166
Navil Perez03dc71a2021-07-22 18:38:49 +0000167 env = {}
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700168 if opts.nowithdebug:
169 use_flags = os.environ.get('USE', '')
170 use_flags += ' -cros-debug'
Navil Perez03dc71a2021-07-22 18:38:49 +0000171 env['USE'] = use_flags
172
Hengxiang Hu2e33c712022-01-25 19:11:07 -0800173 keep_going = get_keep_going()
174
Navil Perez03dc71a2021-07-22 18:38:49 +0000175 metrics_dir = os.environ.get(constants.CROS_METRICS_DIR_ENVVAR)
176 if metrics_dir:
177 env[constants.CROS_METRICS_DIR_ENVVAR] = metrics_dir
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700178
Chris McDonalde69db662018-11-15 12:50:18 -0700179 if opts.empty_sysroot:
180 try:
181 chroot_util.Emerge(list(IMPLICIT_TEST_DEPS), sysroot, rebuild_deps=False,
182 use_binary=False)
183 chroot_util.Emerge(list(pkg_with_test), sysroot, rebuild_deps=False,
184 use_binary=False)
185 except cros_build_lib.RunCommandError:
186 logging.error('Failed building dependencies for unittests.')
Mike Frysingerd56bb812019-09-01 15:42:24 -0400187 return 1
Chris McDonalde69db662018-11-15 12:50:18 -0700188
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700189 try:
Hengxiang Hu2e33c712022-01-25 19:11:07 -0800190 chroot_util.RunUnittests(sysroot, pkg_with_test, extra_env=env,
191 keep_going=keep_going, jobs=opts.jobs)
Bertrand SIMONNETe025a0e2015-05-06 14:17:43 -0700192 except cros_build_lib.RunCommandError:
193 logging.error('Unittests failed.')
Mike Frysingerd56bb812019-09-01 15:42:24 -0400194 return 1