Kuang-che Wu | 875c89a | 2020-01-08 14:30:55 +0800 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 2 | # -*- 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 | |
| 8 | This is integrated bisection utility. Given ChromeOS, Chrome, Android source |
| 9 | tree, and necessary parameters, this script can determine which components to |
| 10 | bisect, and hopefully output the culprit CL of regression. |
| 11 | |
| 12 | Sometimes the script failed to figure out the final CL for various reasons, it |
| 13 | will cut down the search range as narrow as it can. |
| 14 | """ |
| 15 | from __future__ import print_function |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 16 | import logging |
| 17 | |
| 18 | from bisect_kit import cros_lab_util |
| 19 | from bisect_kit import cros_util |
| 20 | from bisect_kit import diagnoser_cros |
| 21 | from bisect_kit import errors |
| 22 | import setup_cros_bisect |
| 23 | |
| 24 | logger = logging.getLogger(__name__) |
| 25 | |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 26 | |
| 27 | class DiagnoseTastCommandLine(diagnoser_cros.DiagnoseCommandLineBase): |
| 28 | """Diagnose command line interface.""" |
| 29 | |
| 30 | def check_options(self, opts, path_factory): |
| 31 | super(DiagnoseTastCommandLine, self).check_options(opts, path_factory) |
| 32 | if not opts.test_name: |
| 33 | self.argument_parser.error('argument --test_name is required') |
| 34 | |
| 35 | def init_hook(self, opts): |
| 36 | pass |
| 37 | |
| 38 | def _build_cmds(self): |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 39 | # prebuilt version will be specified later. |
| 40 | common_switch_cmd = [ |
| 41 | './switch_tast_prebuilt.py', |
| 42 | '--chromeos_root', |
| 43 | self.config['chromeos_root'], |
| 44 | '--board', |
| 45 | self.config['board'], |
| 46 | ] |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 47 | common_eval_cmd = [ |
| 48 | './eval_cros_tast.py', |
Kuang-che Wu | 4fc0f1c | 2019-08-02 21:56:49 +0800 | [diff] [blame] | 49 | '--with_private_bundles', |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 50 | '--chromeos_root', self.config['chromeos_root'], |
| 51 | '--test_name', self.config['test_name'], |
| 52 | ] # yapf: disable |
| 53 | if self.config['metric']: |
| 54 | common_eval_cmd += [ |
| 55 | '--metric', self.config['metric'], |
| 56 | ] # yapf: disable |
| 57 | if self.config['fail_to_pass']: |
| 58 | common_eval_cmd.append('--fail_to_pass') |
| 59 | if self.config['reboot_before_test']: |
| 60 | common_eval_cmd.append('--reboot_before_test') |
| 61 | |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 62 | return common_switch_cmd, common_eval_cmd |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 63 | |
| 64 | def cmd_run(self, opts): |
| 65 | del opts # unused |
| 66 | |
| 67 | self.states.load() |
| 68 | |
| 69 | try: |
| 70 | path_factory = setup_cros_bisect.DefaultProjectPathFactory( |
| 71 | self.config['mirror_base'], self.config['work_base'], |
| 72 | self.config['session']) |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 73 | common_switch_cmd, common_eval_cmd = self._build_cmds() |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 74 | |
Kuang-che Wu | 0c9b794 | 2019-10-30 16:55:39 +0800 | [diff] [blame] | 75 | with cros_lab_util.dut_manager( |
Kuang-che Wu | d1b7415 | 2020-05-20 08:46:46 +0800 | [diff] [blame] | 76 | self.config['dut'], lambda: diagnoser_cros.grab_dut(self.config) |
| 77 | ) as dut: |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 78 | if not dut: |
| 79 | raise errors.NoDutAvailable('unable to allocate DUT') |
Kuang-che Wu | 7cb08df | 2019-06-04 19:12:29 +0800 | [diff] [blame] | 80 | if not cros_util.is_good_dut(dut): |
| 81 | if not cros_lab_util.repair(dut): |
| 82 | raise errors.ExternalError('Not a good DUT and unable to repair') |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 83 | assert cros_util.is_dut(dut) |
| 84 | if self.config['dut'] == cros_lab_util.LAB_DUT: |
| 85 | self.config['allocated_dut'] = dut |
| 86 | self.states.save() |
| 87 | common_eval_cmd.append(dut) |
| 88 | |
| 89 | diagnoser = diagnoser_cros.CrosDiagnoser(self.states, path_factory, |
| 90 | self.config, dut) |
| 91 | |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 92 | eval_cmd = common_eval_cmd + ['--prebuilt'] |
| 93 | extra_switch_cmd = common_switch_cmd |
| 94 | diagnoser.narrow_down_chromeos_prebuilt( |
| 95 | self.config['old'], |
| 96 | self.config['new'], |
| 97 | eval_cmd, |
| 98 | extra_switch_cmd=extra_switch_cmd) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 99 | |
| 100 | diagnoser.switch_chromeos_to_old(force=self.config['always_reflash']) |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 101 | util.check_call(*(common_switch_cmd + [diagnoser.cros_old])) |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 102 | dut_os_version = cros_util.query_dut_short_version(dut) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 103 | |
| 104 | try: |
| 105 | if diagnoser.narrow_down_android(common_eval_cmd): |
| 106 | return |
| 107 | except errors.DiagnoseContradiction: |
| 108 | raise |
| 109 | except Exception: |
Kuang-che Wu | c93d0f9 | 2020-05-20 20:55:23 +0800 | [diff] [blame] | 110 | diagnoser.make_decision( |
Kuang-che Wu | e4435b4 | 2020-05-21 20:06:24 +0800 | [diff] [blame] | 111 | 'Exception in Android bisector before verification; ' |
| 112 | 'assume the culprit is not inside Android and continue') |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 113 | # Assume it's ok to leave random version of android prebuilt on DUT. |
| 114 | |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 115 | # Sanity check. The OS version should not change after android bisect. |
Kuang-che Wu | 523bdf2 | 2019-08-20 12:11:09 +0800 | [diff] [blame] | 116 | assert dut_os_version == cros_util.query_dut_short_version(dut), \ |
| 117 | 'Someone else reflashed the DUT. ' \ |
| 118 | 'DUT locking is not respected? b/126141102' |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 119 | |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 120 | try: |
Zheng-Jie Chang | 7a076a5 | 2020-05-31 13:03:37 +0800 | [diff] [blame] | 121 | buildbucket_build = ( |
| 122 | cros_util.is_buildbucket_buildable(self.config['old']) and |
| 123 | self.config['enable_buildbucket_chrome']) |
Kuang-che Wu | de5bfc3 | 2019-09-12 21:56:48 +0800 | [diff] [blame] | 124 | if self.config['chrome_deploy_image']: |
| 125 | eval_cmd = common_eval_cmd + ['--tast_build'] |
| 126 | else: |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 127 | eval_cmd = common_eval_cmd + ['--prebuilt'] |
Zheng-Jie Chang | 7a076a5 | 2020-05-31 13:03:37 +0800 | [diff] [blame] | 128 | if diagnoser.narrow_down_chrome( |
| 129 | eval_cmd, buildbucket_build=buildbucket_build): |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 130 | return |
| 131 | except errors.DiagnoseContradiction: |
| 132 | raise |
| 133 | except Exception: |
Kuang-che Wu | c93d0f9 | 2020-05-20 20:55:23 +0800 | [diff] [blame] | 134 | diagnoser.make_decision( |
Kuang-che Wu | e4435b4 | 2020-05-21 20:06:24 +0800 | [diff] [blame] | 135 | 'Exception in Chrome bisector before verification; ' |
| 136 | 'assume the culprit is not inside Chrome and continue') |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 137 | |
Zheng-Jie Chang | 7a076a5 | 2020-05-31 13:03:37 +0800 | [diff] [blame] | 138 | if not self.config['chrome_deploy_image'] and not buildbucket_build: |
Kuang-che Wu | de5bfc3 | 2019-09-12 21:56:48 +0800 | [diff] [blame] | 139 | # Sanity check. The OS version should not change after chrome bisect. |
| 140 | assert dut_os_version == cros_util.query_dut_short_version(dut), \ |
| 141 | 'Someone else reflashed the DUT. ' \ |
| 142 | 'DUT locking is not respected? b/126141102' |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 143 | |
Zheng-Jie Chang | 61a645a | 2020-04-29 10:12:13 +0800 | [diff] [blame] | 144 | buildbucket_build = ( |
| 145 | cros_util.is_buildbucket_buildable(self.config['old']) and |
| 146 | not self.config['disable_buildbucket_chromeos']) |
| 147 | |
| 148 | if not buildbucket_build: |
Zheng-Jie Chang | 181be6f | 2020-03-17 16:16:08 +0800 | [diff] [blame] | 149 | eval_cmd = common_eval_cmd + ['--tast_build'] |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 150 | extra_switch_cmd = None |
Zheng-Jie Chang | d3fd8f1 | 2020-04-14 11:41:06 +0800 | [diff] [blame] | 151 | else: |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 152 | eval_cmd = common_eval_cmd + ['--prebuilt'] |
| 153 | extra_switch_cmd = common_switch_cmd |
Zheng-Jie Chang | 61a645a | 2020-04-29 10:12:13 +0800 | [diff] [blame] | 154 | diagnoser.narrow_down_chromeos_localbuild(eval_cmd, buildbucket_build) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 155 | logger.info('%s done', __file__) |
| 156 | except Exception as e: |
| 157 | logger.exception('got exception; stop') |
| 158 | exception_name = e.__class__.__name__ |
| 159 | self.states.add_history( |
Kuang-che Wu | 0c2cb92 | 2020-06-16 23:34:53 +0800 | [diff] [blame] | 160 | 'failed', |
| 161 | text='%s: %s' % (exception_name, e), |
| 162 | exception=exception_name) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 163 | |
| 164 | |
| 165 | if __name__ == '__main__': |
| 166 | DiagnoseTastCommandLine().main() |