summaryrefslogtreecommitdiffstats
path: root/tools/run-bisect-manual-test.py
blob: e1e6aeb6121502fc18699b90506d44a3a1410030 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/env python
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Run Manual Test Bisect Tool

An example usage:
tools/run-bisect-manual-test.py -g 201281 -b 201290

On Linux platform, follow the instructions in this document
https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md
to setup the sandbox manually before running the script. Otherwise the script
fails to launch Chrome and exits with an error.

This script serves a similar function to bisect-builds.py, except it uses
the bisect_perf_regression.py. This means that that it can obtain builds of
Chromium for revisions where builds aren't available in cloud storage.
"""

import os
import subprocess
import sys

CROS_BOARD_ENV = 'BISECT_CROS_BOARD'
CROS_IP_ENV = 'BISECT_CROS_IP'
_TOOLS_DIR = os.path.abspath(os.path.dirname(__file__))
_BISECT_SCRIPT_PATH = os.path.join(
    _TOOLS_DIR, 'auto_bisect', 'bisect_perf_regression.py')

sys.path.append(os.path.join(_TOOLS_DIR, 'perf'))
from chrome_telemetry_build import chromium_config
sys.path.append(chromium_config.GetTelemetryDir())
from telemetry.internal.browser import browser_options


def _RunBisectionScript(options):
  """Attempts to execute the bisect script (bisect_perf_regression.py).

  Args:
    options: The configuration options to pass to the bisect script.

  Returns:
    An exit code; 0 for success, 1 for failure.
  """
  script_path = os.path.join(options.working_directory,
      'bisect', 'src', 'tools','bisect-manual-test.py')
  abs_script_path = os.path.abspath(script_path)

  test_command = ('python %s --browser=%s --chrome-root=.' %
                  (abs_script_path, options.browser_type))

  cmd = ['python', _BISECT_SCRIPT_PATH,
         '-c', test_command,
         '-g', options.good_revision,
         '-b', options.bad_revision,
         '-m', 'manual_test/manual_test',
         '-r', '1',
         '--working_directory', options.working_directory,
         '--build_preference', 'ninja',
         '--no_custom_deps',
         '--builder_type', options.builder_type]

  if options.extra_src:
    cmd.extend(['--extra_src', options.extra_src])

  if 'cros' in options.browser_type:
    cmd.extend(['--target_platform', 'cros'])

    if os.environ[CROS_BOARD_ENV] and os.environ[CROS_IP_ENV]:
      cmd.extend(['--cros_board', os.environ[CROS_BOARD_ENV]])
      cmd.extend(['--cros_remote_ip', os.environ[CROS_IP_ENV]])
    else:
      print ('Error: Cros build selected, but BISECT_CROS_IP or'
             'BISECT_CROS_BOARD undefined.\n')
      return 1
  elif 'android-chrome' == options.browser_type:
    if not options.extra_src:
      print 'Error: Missing --extra_src to run bisect for android-chrome.'
      sys.exit(-1)
    cmd.extend(['--target_platform', 'android-chrome'])
  elif 'android' in options.browser_type:
    cmd.extend(['--target_platform', 'android'])
  elif not options.target_build_type:
    cmd.extend(['--target_build_type', options.browser_type.title()])

  if options.target_build_type:
    cmd.extend(['--target_build_type', options.target_build_type])

  if options.goma_threads:
    cmd.extend(['--use_goma', '--goma_threads', options.goma_threads])

  cmd = [str(c) for c in cmd]

  return_code = subprocess.call(cmd)

  if return_code:
    print 'Error: bisect_perf_regression.py had exit code %d.' % return_code
    print

  return return_code


def main():
  """Does a bisect based on the command-line arguments passed in.

  The user will be prompted to classify each revision as good or bad.
  """
  usage = ('%prog [options]\n'
           'Used to run the bisection script with a manual test.')

  options = browser_options.BrowserFinderOptions('release')
  parser = options.CreateParser(usage)

  parser.add_option('-b', '--bad_revision',
                    type='str',
                    help='A bad revision to start bisection. ' +
                    'Must be later than good revision. May be either a git' +
                    ' or svn revision.')
  parser.add_option('-g', '--good_revision',
                    type='str',
                    help='A revision to start bisection where performance' +
                    ' test is known to pass. Must be earlier than the ' +
                    'bad revision. May be either a git or svn revision.')
  parser.add_option('-w', '--working_directory',
                    type='str',
                    default='..',
                    help='A working directory to supply to the bisection '
                    'script, which will use it as the location to checkout '
                    'a copy of the chromium depot.')
  parser.add_option('--extra_src',
                    type='str',
                    help='Path to extra source file. If this is supplied, '
                    'bisect script will use this to override default behavior.')
  parser.add_option('--target_build_type',
                    type='choice',
                    choices=['Release', 'Debug'],
                    help='The target build type. Choices are "Release" '
                    'or "Debug".')
  parser.add_option('--goma_threads', default=64,
                    type='int',
                    help='Number of goma threads to use.  0 will disable goma.')
  parser.add_option('--builder_type', default='',
                    choices=['perf',
                             'full',
                             'android-chrome-perf', ''],
                    help='Type of builder to get build from. This allows '
                    'script to use cached builds. By default (empty), binaries '
                    'are built locally.')
  options, _ = parser.parse_args()
  error_msg = ''
  if not options.good_revision:
    error_msg += 'Error: missing required parameter: --good_revision\n'
  if not options.bad_revision:
    error_msg += 'Error: missing required parameter: --bad_revision\n'

  if error_msg:
    print error_msg
    parser.print_help()
    return 1

  if 'android' not in options.browser_type and sys.platform.startswith('linux'):
    if not os.environ.get('CHROME_DEVEL_SANDBOX'):
      print 'SUID sandbox has not been setup.'\
            ' See https://chromium.googlesource.com/chromium/src/'\
            '+/master/docs/linux_suid_sandbox_development.md.'
      return 1

  return _RunBisectionScript(options)


if __name__ == '__main__':
  sys.exit(main())