blob: 2e10ddefc309f9fb5a1a42a9652a14f9f1f3c4cb [file] [log] [blame]
Kuang-che Wu875c89a2020-01-08 14:30:55 +08001#!/usr/bin/env python3
Kuang-che Wu32f27242019-05-16 17:34:50 +08002# -*- coding: utf-8 -*-
3# Copyright 2019 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6"""Diagnose ChromeOS tast regressions.
7
8This is integrated bisection utility. Given ChromeOS, Chrome, Android source
9tree, and necessary parameters, this script can determine which components to
10bisect, and hopefully output the culprit CL of regression.
11
12Sometimes the script failed to figure out the final CL for various reasons, it
13will cut down the search range as narrow as it can.
14"""
15from __future__ import print_function
Kuang-che Wu32f27242019-05-16 17:34:50 +080016import logging
17
18from bisect_kit import cros_lab_util
19from bisect_kit import cros_util
20from bisect_kit import diagnoser_cros
21from bisect_kit import errors
Kuang-che Wu57fa3032020-10-22 14:43:22 +080022from bisect_kit import util
Kuang-che Wu32f27242019-05-16 17:34:50 +080023import setup_cros_bisect
24
25logger = logging.getLogger(__name__)
26
Kuang-che Wu32f27242019-05-16 17:34:50 +080027
28class DiagnoseTastCommandLine(diagnoser_cros.DiagnoseCommandLineBase):
29 """Diagnose command line interface."""
30
31 def check_options(self, opts, path_factory):
Kuang-che Wu6d91b8c2020-11-24 20:14:35 +080032 super().check_options(opts, path_factory)
Kuang-che Wu32f27242019-05-16 17:34:50 +080033 if not opts.test_name:
34 self.argument_parser.error('argument --test_name is required')
35
36 def init_hook(self, opts):
37 pass
38
39 def _build_cmds(self):
Kuang-che Wu5963ebf2020-10-21 09:01:04 +080040 # prebuilt version will be specified later.
41 common_switch_cmd = [
42 './switch_tast_prebuilt.py',
43 '--chromeos_root',
44 self.config['chromeos_root'],
45 '--board',
46 self.config['board'],
47 ]
Kuang-che Wu32f27242019-05-16 17:34:50 +080048 common_eval_cmd = [
49 './eval_cros_tast.py',
Kuang-che Wu4fc0f1c2019-08-02 21:56:49 +080050 '--with_private_bundles',
Kuang-che Wu32f27242019-05-16 17:34:50 +080051 '--chromeos_root', self.config['chromeos_root'],
52 '--test_name', self.config['test_name'],
53 ] # yapf: disable
54 if self.config['metric']:
55 common_eval_cmd += [
56 '--metric', self.config['metric'],
57 ] # yapf: disable
58 if self.config['fail_to_pass']:
59 common_eval_cmd.append('--fail_to_pass')
60 if self.config['reboot_before_test']:
61 common_eval_cmd.append('--reboot_before_test')
62
Kuang-che Wu5963ebf2020-10-21 09:01:04 +080063 return common_switch_cmd, common_eval_cmd
Kuang-che Wu32f27242019-05-16 17:34:50 +080064
65 def cmd_run(self, opts):
66 del opts # unused
67
68 self.states.load()
69
70 try:
71 path_factory = setup_cros_bisect.DefaultProjectPathFactory(
72 self.config['mirror_base'], self.config['work_base'],
73 self.config['session'])
Kuang-che Wu5963ebf2020-10-21 09:01:04 +080074 common_switch_cmd, common_eval_cmd = self._build_cmds()
Kuang-che Wu32f27242019-05-16 17:34:50 +080075
Kuang-che Wu30039b12021-01-18 10:10:33 +080076 lease_reason = cros_lab_util.make_lease_reason(self.config['session'])
Kuang-che Wu0c9b7942019-10-30 16:55:39 +080077 with cros_lab_util.dut_manager(
Kuang-che Wu30039b12021-01-18 10:10:33 +080078 self.config['dut'],
79 lease_reason, lambda: diagnoser_cros.grab_dut(self.config)) as dut:
Kuang-che Wu32f27242019-05-16 17:34:50 +080080 if not dut:
81 raise errors.NoDutAvailable('unable to allocate DUT')
Kuang-che Wu7cb08df2019-06-04 19:12:29 +080082 if not cros_util.is_good_dut(dut):
83 if not cros_lab_util.repair(dut):
84 raise errors.ExternalError('Not a good DUT and unable to repair')
Kuang-che Wu32f27242019-05-16 17:34:50 +080085 assert cros_util.is_dut(dut)
86 if self.config['dut'] == cros_lab_util.LAB_DUT:
87 self.config['allocated_dut'] = dut
88 self.states.save()
89 common_eval_cmd.append(dut)
90
91 diagnoser = diagnoser_cros.CrosDiagnoser(self.states, path_factory,
92 self.config, dut)
93
Kuang-che Wu5963ebf2020-10-21 09:01:04 +080094 eval_cmd = common_eval_cmd + ['--prebuilt']
95 extra_switch_cmd = common_switch_cmd
96 diagnoser.narrow_down_chromeos_prebuilt(
97 self.config['old'],
98 self.config['new'],
99 eval_cmd,
100 extra_switch_cmd=extra_switch_cmd)
Kuang-che Wu32f27242019-05-16 17:34:50 +0800101
102 diagnoser.switch_chromeos_to_old(force=self.config['always_reflash'])
Kuang-che Wu4b3da492020-10-23 17:29:45 +0800103 util.check_call(*(common_switch_cmd +
104 [diagnoser.cros_old, '--dut', dut]))
Kuang-che Wuc8c495d2019-08-19 17:48:58 +0800105 dut_os_version = cros_util.query_dut_short_version(dut)
Kuang-che Wu32f27242019-05-16 17:34:50 +0800106
107 try:
108 if diagnoser.narrow_down_android(common_eval_cmd):
109 return
110 except errors.DiagnoseContradiction:
111 raise
112 except Exception:
Kuang-che Wuc93d0f92020-05-20 20:55:23 +0800113 diagnoser.make_decision(
Kuang-che Wue4435b42020-05-21 20:06:24 +0800114 'Exception in Android bisector before verification; '
115 'assume the culprit is not inside Android and continue')
Kuang-che Wu32f27242019-05-16 17:34:50 +0800116 # Assume it's ok to leave random version of android prebuilt on DUT.
117
Kuang-che Wuc8c495d2019-08-19 17:48:58 +0800118 # Sanity check. The OS version should not change after android bisect.
Kuang-che Wu523bdf22019-08-20 12:11:09 +0800119 assert dut_os_version == cros_util.query_dut_short_version(dut), \
Kuang-che Wu59400312020-11-10 14:53:54 +0800120 'Someone else reflashed the DUT. DUT locking is not respected?'
Kuang-che Wuc8c495d2019-08-19 17:48:58 +0800121
Kuang-che Wu32f27242019-05-16 17:34:50 +0800122 try:
Zheng-Jie Chang7a076a52020-05-31 13:03:37 +0800123 buildbucket_build = (
124 cros_util.is_buildbucket_buildable(self.config['old']) and
125 self.config['enable_buildbucket_chrome'])
Kuang-che Wude5bfc32019-09-12 21:56:48 +0800126 if self.config['chrome_deploy_image']:
127 eval_cmd = common_eval_cmd + ['--tast_build']
128 else:
Kuang-che Wu5963ebf2020-10-21 09:01:04 +0800129 eval_cmd = common_eval_cmd + ['--prebuilt']
Zheng-Jie Chang7a076a52020-05-31 13:03:37 +0800130 if diagnoser.narrow_down_chrome(
131 eval_cmd, buildbucket_build=buildbucket_build):
Kuang-che Wu32f27242019-05-16 17:34:50 +0800132 return
133 except errors.DiagnoseContradiction:
134 raise
135 except Exception:
Kuang-che Wuc93d0f92020-05-20 20:55:23 +0800136 diagnoser.make_decision(
Kuang-che Wue4435b42020-05-21 20:06:24 +0800137 'Exception in Chrome bisector before verification; '
138 'assume the culprit is not inside Chrome and continue')
Kuang-che Wu32f27242019-05-16 17:34:50 +0800139
Zheng-Jie Chang7a076a52020-05-31 13:03:37 +0800140 if not self.config['chrome_deploy_image'] and not buildbucket_build:
Kuang-che Wude5bfc32019-09-12 21:56:48 +0800141 # Sanity check. The OS version should not change after chrome bisect.
142 assert dut_os_version == cros_util.query_dut_short_version(dut), \
Kuang-che Wu59400312020-11-10 14:53:54 +0800143 'Someone else reflashed the DUT. DUT locking is not respected?'
Kuang-che Wuc8c495d2019-08-19 17:48:58 +0800144
Zheng-Jie Chang61a645a2020-04-29 10:12:13 +0800145 buildbucket_build = (
146 cros_util.is_buildbucket_buildable(self.config['old']) and
147 not self.config['disable_buildbucket_chromeos'])
148
149 if not buildbucket_build:
Zheng-Jie Chang181be6f2020-03-17 16:16:08 +0800150 eval_cmd = common_eval_cmd + ['--tast_build']
Kuang-che Wu5963ebf2020-10-21 09:01:04 +0800151 extra_switch_cmd = None
Zheng-Jie Changd3fd8f12020-04-14 11:41:06 +0800152 else:
Kuang-che Wu5963ebf2020-10-21 09:01:04 +0800153 eval_cmd = common_eval_cmd + ['--prebuilt']
154 extra_switch_cmd = common_switch_cmd
Kuang-che Wu8d32dd42020-11-04 12:04:46 +0800155 diagnoser.narrow_down_chromeos_localbuild(
156 eval_cmd, buildbucket_build, extra_switch_cmd=extra_switch_cmd)
Kuang-che Wu32f27242019-05-16 17:34:50 +0800157 logger.info('%s done', __file__)
158 except Exception as e:
159 logger.exception('got exception; stop')
160 exception_name = e.__class__.__name__
161 self.states.add_history(
Kuang-che Wu0c2cb922020-06-16 23:34:53 +0800162 'failed',
163 text='%s: %s' % (exception_name, e),
164 exception=exception_name)
Kuang-che Wu32f27242019-05-16 17:34:50 +0800165
166
167if __name__ == '__main__':
168 DiagnoseTastCommandLine().main()