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 |
Kuang-che Wu | 57fa303 | 2020-10-22 14:43:22 +0800 | [diff] [blame] | 22 | from bisect_kit import util |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 23 | import setup_cros_bisect |
| 24 | |
| 25 | logger = logging.getLogger(__name__) |
| 26 | |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 27 | |
| 28 | class DiagnoseTastCommandLine(diagnoser_cros.DiagnoseCommandLineBase): |
| 29 | """Diagnose command line interface.""" |
| 30 | |
| 31 | def check_options(self, opts, path_factory): |
Kuang-che Wu | 6d91b8c | 2020-11-24 20:14:35 +0800 | [diff] [blame] | 32 | super().check_options(opts, path_factory) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 33 | 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 Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 40 | # 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 Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 48 | common_eval_cmd = [ |
| 49 | './eval_cros_tast.py', |
Kuang-che Wu | 4fc0f1c | 2019-08-02 21:56:49 +0800 | [diff] [blame] | 50 | '--with_private_bundles', |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 51 | '--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 Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 63 | return common_switch_cmd, common_eval_cmd |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 64 | |
| 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 Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 74 | common_switch_cmd, common_eval_cmd = self._build_cmds() |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 75 | |
Kuang-che Wu | 30039b1 | 2021-01-18 10:10:33 +0800 | [diff] [blame] | 76 | lease_reason = cros_lab_util.make_lease_reason(self.config['session']) |
Kuang-che Wu | 0c9b794 | 2019-10-30 16:55:39 +0800 | [diff] [blame] | 77 | with cros_lab_util.dut_manager( |
Kuang-che Wu | 30039b1 | 2021-01-18 10:10:33 +0800 | [diff] [blame] | 78 | self.config['dut'], |
| 79 | lease_reason, lambda: diagnoser_cros.grab_dut(self.config)) as dut: |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 80 | if not dut: |
| 81 | raise errors.NoDutAvailable('unable to allocate DUT') |
Kuang-che Wu | 7cb08df | 2019-06-04 19:12:29 +0800 | [diff] [blame] | 82 | 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 Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 85 | 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 Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 94 | 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 Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 101 | |
| 102 | diagnoser.switch_chromeos_to_old(force=self.config['always_reflash']) |
Kuang-che Wu | 4b3da49 | 2020-10-23 17:29:45 +0800 | [diff] [blame] | 103 | util.check_call(*(common_switch_cmd + |
| 104 | [diagnoser.cros_old, '--dut', dut])) |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 105 | dut_os_version = cros_util.query_dut_short_version(dut) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 106 | |
| 107 | try: |
| 108 | if diagnoser.narrow_down_android(common_eval_cmd): |
| 109 | return |
| 110 | except errors.DiagnoseContradiction: |
| 111 | raise |
| 112 | except Exception: |
Kuang-che Wu | c93d0f9 | 2020-05-20 20:55:23 +0800 | [diff] [blame] | 113 | diagnoser.make_decision( |
Kuang-che Wu | e4435b4 | 2020-05-21 20:06:24 +0800 | [diff] [blame] | 114 | 'Exception in Android bisector before verification; ' |
| 115 | 'assume the culprit is not inside Android and continue') |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 116 | # Assume it's ok to leave random version of android prebuilt on DUT. |
| 117 | |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 118 | # Sanity check. The OS version should not change after android bisect. |
Kuang-che Wu | 523bdf2 | 2019-08-20 12:11:09 +0800 | [diff] [blame] | 119 | assert dut_os_version == cros_util.query_dut_short_version(dut), \ |
Kuang-che Wu | 5940031 | 2020-11-10 14:53:54 +0800 | [diff] [blame] | 120 | 'Someone else reflashed the DUT. DUT locking is not respected?' |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 121 | |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 122 | try: |
Zheng-Jie Chang | 7a076a5 | 2020-05-31 13:03:37 +0800 | [diff] [blame] | 123 | buildbucket_build = ( |
| 124 | cros_util.is_buildbucket_buildable(self.config['old']) and |
| 125 | self.config['enable_buildbucket_chrome']) |
Kuang-che Wu | de5bfc3 | 2019-09-12 21:56:48 +0800 | [diff] [blame] | 126 | if self.config['chrome_deploy_image']: |
| 127 | eval_cmd = common_eval_cmd + ['--tast_build'] |
| 128 | else: |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 129 | eval_cmd = common_eval_cmd + ['--prebuilt'] |
Zheng-Jie Chang | 7a076a5 | 2020-05-31 13:03:37 +0800 | [diff] [blame] | 130 | if diagnoser.narrow_down_chrome( |
| 131 | eval_cmd, buildbucket_build=buildbucket_build): |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 132 | return |
| 133 | except errors.DiagnoseContradiction: |
| 134 | raise |
| 135 | except Exception: |
Kuang-che Wu | c93d0f9 | 2020-05-20 20:55:23 +0800 | [diff] [blame] | 136 | diagnoser.make_decision( |
Kuang-che Wu | e4435b4 | 2020-05-21 20:06:24 +0800 | [diff] [blame] | 137 | 'Exception in Chrome bisector before verification; ' |
| 138 | 'assume the culprit is not inside Chrome and continue') |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 139 | |
Zheng-Jie Chang | 7a076a5 | 2020-05-31 13:03:37 +0800 | [diff] [blame] | 140 | if not self.config['chrome_deploy_image'] and not buildbucket_build: |
Kuang-che Wu | de5bfc3 | 2019-09-12 21:56:48 +0800 | [diff] [blame] | 141 | # 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 Wu | 5940031 | 2020-11-10 14:53:54 +0800 | [diff] [blame] | 143 | 'Someone else reflashed the DUT. DUT locking is not respected?' |
Kuang-che Wu | c8c495d | 2019-08-19 17:48:58 +0800 | [diff] [blame] | 144 | |
Zheng-Jie Chang | 61a645a | 2020-04-29 10:12:13 +0800 | [diff] [blame] | 145 | 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 Chang | 181be6f | 2020-03-17 16:16:08 +0800 | [diff] [blame] | 150 | eval_cmd = common_eval_cmd + ['--tast_build'] |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 151 | extra_switch_cmd = None |
Zheng-Jie Chang | d3fd8f1 | 2020-04-14 11:41:06 +0800 | [diff] [blame] | 152 | else: |
Kuang-che Wu | 5963ebf | 2020-10-21 09:01:04 +0800 | [diff] [blame] | 153 | eval_cmd = common_eval_cmd + ['--prebuilt'] |
| 154 | extra_switch_cmd = common_switch_cmd |
Kuang-che Wu | 8d32dd4 | 2020-11-04 12:04:46 +0800 | [diff] [blame] | 155 | diagnoser.narrow_down_chromeos_localbuild( |
| 156 | eval_cmd, buildbucket_build, extra_switch_cmd=extra_switch_cmd) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 157 | 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 Wu | 0c2cb92 | 2020-06-16 23:34:53 +0800 | [diff] [blame] | 162 | 'failed', |
| 163 | text='%s: %s' % (exception_name, e), |
| 164 | exception=exception_name) |
Kuang-che Wu | 32f2724 | 2019-05-16 17:34:50 +0800 | [diff] [blame] | 165 | |
| 166 | |
| 167 | if __name__ == '__main__': |
| 168 | DiagnoseTastCommandLine().main() |