Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: tools/bisect-perf-regression.py

Issue 468633005: Quick spelling clean-up in the auto-bisect code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/auto_bisect/source_control.py ('k') | tools/prepare-bisect-perf-regression.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Performance Test Bisect Tool 6 """Performance Test Bisect Tool
7 7
8 This script bisects a series of changelists using binary search. It starts at 8 This script bisects a series of changelists using binary search. It starts at
9 a bad revision where a performance metric has regressed, and asks for a last 9 a bad revision where a performance metric has regressed, and asks for a last
10 known-good revision. It will then binary search across this revision range by 10 known-good revision. It will then binary search across this revision range by
11 syncing, building, and running a performance test. If the change is 11 syncing, building, and running a performance test. If the change is
12 suspected to occur as a result of WebKit/V8 changes, the script will 12 suspected to occur as a result of WebKit/V8 changes, the script will
13 further bisect changes to those depots and attempt to narrow down the revision 13 further bisect changes to those depots and attempt to narrow down the revision
14 range. 14 range.
15 15
16 16 Example usage using SVN revisions:
17 An example usage (using svn cl's):
18 17
19 ./tools/bisect-perf-regression.py -c\ 18 ./tools/bisect-perf-regression.py -c\
20 "out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\ 19 "out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\
21 -g 168222 -b 168232 -m shutdown/simple-user-quit 20 -g 168222 -b 168232 -m shutdown/simple-user-quit
22 21
23 Be aware that if you're using the git workflow and specify an svn revision, 22 Be aware that if you're using the git workflow and specify an SVN revision,
24 the script will attempt to find the git SHA1 where svn changes up to that 23 the script will attempt to find the git SHA1 where SVN changes up to that
25 revision were merged in. 24 revision were merged in.
26 25
27 26 Example usage using git hashes:
28 An example usage (using git hashes):
29 27
30 ./tools/bisect-perf-regression.py -c\ 28 ./tools/bisect-perf-regression.py -c\
31 "out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\ 29 "out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\
32 -g 1f6e67861535121c5c819c16a666f2436c207e7b\ 30 -g 1f6e67861535121c5c819c16a666f2436c207e7b\
33 -b b732f23b4f81c382db0b23b9035f3dadc7d925bb\ 31 -b b732f23b4f81c382db0b23b9035f3dadc7d925bb\
34 -m shutdown/simple-user-quit 32 -m shutdown/simple-user-quit
35 """ 33 """
36 34
37 import copy 35 import copy
38 import datetime 36 import datetime
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 150
153 DEPOT_NAMES = DEPOT_DEPS_NAME.keys() 151 DEPOT_NAMES = DEPOT_DEPS_NAME.keys()
154 152
155 CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome' 153 CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome'
156 154
157 # Possible return values from BisectPerformanceMetrics.SyncBuildAndRunRevision. 155 # Possible return values from BisectPerformanceMetrics.SyncBuildAndRunRevision.
158 BUILD_RESULT_SUCCEED = 0 156 BUILD_RESULT_SUCCEED = 0
159 BUILD_RESULT_FAIL = 1 157 BUILD_RESULT_FAIL = 1
160 BUILD_RESULT_SKIPPED = 2 158 BUILD_RESULT_SKIPPED = 2
161 159
162 # Maximum time in seconds to wait after posting build request to tryserver. 160 # Maximum time in seconds to wait after posting build request to the try server.
163 # TODO: Change these values based on the actual time taken by buildbots on 161 # TODO: Change these values based on the actual time taken by buildbots on
164 # the tryserver. 162 # the try server.
165 MAX_MAC_BUILD_TIME = 14400 163 MAX_MAC_BUILD_TIME = 14400
166 MAX_WIN_BUILD_TIME = 14400 164 MAX_WIN_BUILD_TIME = 14400
167 MAX_LINUX_BUILD_TIME = 14400 165 MAX_LINUX_BUILD_TIME = 14400
168 166
169 # The confidence percentage at which confidence can be consider "high". 167 # The confidence percentage at which confidence can be consider "high".
170 HIGH_CONFIDENCE = 95 168 HIGH_CONFIDENCE = 95
171 169
172 # Patch template to add a new file, DEPS.sha under src folder. 170 # Patch template to add a new file, DEPS.sha under src folder.
173 # This file contains SHA1 value of the DEPS changes made while bisecting 171 # This file contains SHA1 value of the DEPS changes made while bisecting
174 # dependency repositories. This patch send along with DEPS patch to tryserver. 172 # dependency repositories. This patch send along with DEPS patch to try server.
175 # When a build requested is posted with a patch, bisect builders on tryserver, 173 # When a build requested is posted with a patch, bisect builders on try server,
176 # once build is produced, it reads SHA value from this file and appends it 174 # once build is produced, it reads SHA value from this file and appends it
177 # to build archive filename. 175 # to build archive filename.
178 DEPS_SHA_PATCH = """diff --git src/DEPS.sha src/DEPS.sha 176 DEPS_SHA_PATCH = """diff --git src/DEPS.sha src/DEPS.sha
179 new file mode 100644 177 new file mode 100644
180 --- /dev/null 178 --- /dev/null
181 +++ src/DEPS.sha 179 +++ src/DEPS.sha
182 @@ -0,0 +1 @@ 180 @@ -0,0 +1 @@
183 +%(deps_sha)s 181 +%(deps_sha)s
184 """ 182 """
185 183
(...skipping 24 matching lines...) Expand all
210 Author : %(author)s%(email_info)s%(commit_info)s 208 Author : %(author)s%(email_info)s%(commit_info)s
211 Commit : %(cl)s 209 Commit : %(cl)s
212 Date : %(cl_date)s""" 210 Date : %(cl_date)s"""
213 211
214 REPRO_STEPS_LOCAL = """ 212 REPRO_STEPS_LOCAL = """
215 ==== INSTRUCTIONS TO REPRODUCE ==== 213 ==== INSTRUCTIONS TO REPRODUCE ====
216 To run locally: 214 To run locally:
217 $%(command)s""" 215 $%(command)s"""
218 216
219 REPRO_STEPS_TRYJOB = """ 217 REPRO_STEPS_TRYJOB = """
220 To reproduce on Performance trybot: 218 To reproduce on a performance try bot:
221 1. Create new git branch or check out existing branch. 219 1. Create new git branch or check out existing branch.
222 2. Edit tools/run-perf-test.cfg (instructions in file) or \ 220 2. Edit tools/run-perf-test.cfg (instructions in file) or \
223 third_party/WebKit/Tools/run-perf-test.cfg. 221 third_party/WebKit/Tools/run-perf-test.cfg.
224 a) Take care to strip any src/ directories from the head of \ 222 a) Take care to strip any src/ directories from the head of \
225 relative path names. 223 relative path names.
226 b) On desktop, only --browser=release is supported, on android \ 224 b) On desktop, only --browser=release is supported, on android \
227 --browser=android-chromium-testshell. 225 --browser=android-chromium-testshell.
228 c) Test command to use: %(command)s 226 c) Test command to use: %(command)s
229 3. Upload your patch. --bypass-hooks is necessary to upload the changes you \ 227 3. Upload your patch. --bypass-hooks is necessary to upload the changes you \
230 committed locally to run-perf-test.cfg. 228 committed locally to run-perf-test.cfg.
231 Note: *DO NOT* commit run-perf-test.cfg changes to the project repository. 229 Note: *DO NOT* commit run-perf-test.cfg changes to the project repository.
232 $ git cl upload --bypass-hooks 230 $ git cl upload --bypass-hooks
233 4. Send your try job to the tryserver. \ 231 4. Send your try job to the try server. \
234 [Please make sure to use appropriate bot to reproduce] 232 [Please make sure to use appropriate bot to reproduce]
235 $ git cl try -m tryserver.chromium.perf -b <bot> 233 $ git cl try -m tryserver.chromium.perf -b <bot>
236 234
237 For more details please visit 235 For more details please visit
238 https://sites.google.com/a/chromium.org/dev/developers/performance-try-bots""" 236 https://sites.google.com/a/chromium.org/dev/developers/performance-try-bots"""
239 237
240 RESULTS_THANKYOU = """ 238 RESULTS_THANKYOU = """
241 ===== THANK YOU FOR CHOOSING BISECT AIRLINES ===== 239 ===== THANK YOU FOR CHOOSING BISECT AIRLINES =====
242 Visit http://www.chromium.org/developers/core-principles for Chrome's policy 240 Visit http://www.chromium.org/developers/core-principles for Chrome's policy
243 on perf regressions. 241 on perf regressions.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 def GetSHA1HexDigest(contents): 300 def GetSHA1HexDigest(contents):
303 """Returns SHA1 hex digest of the given string.""" 301 """Returns SHA1 hex digest of the given string."""
304 return hashlib.sha1(contents).hexdigest() 302 return hashlib.sha1(contents).hexdigest()
305 303
306 304
307 def GetZipFileName(build_revision=None, target_arch='ia32', patch_sha=None): 305 def GetZipFileName(build_revision=None, target_arch='ia32', patch_sha=None):
308 """Gets the archive file name for the given revision.""" 306 """Gets the archive file name for the given revision."""
309 def PlatformName(): 307 def PlatformName():
310 """Return a string to be used in paths for the platform.""" 308 """Return a string to be used in paths for the platform."""
311 if bisect_utils.IsWindowsHost(): 309 if bisect_utils.IsWindowsHost():
312 # Build archive for x64 is still stored with 'win32'suffix 310 # Build archive for x64 is still stored with the "win32" suffix.
313 # (chromium_utils.PlatformName()). 311 # See chromium_utils.PlatformName().
314 if bisect_utils.Is64BitWindows() and target_arch == 'x64': 312 if bisect_utils.Is64BitWindows() and target_arch == 'x64':
315 return 'win32' 313 return 'win32'
316 return 'win32' 314 return 'win32'
317 if bisect_utils.IsLinuxHost(): 315 if bisect_utils.IsLinuxHost():
318 # Android builds too are archived with full-build-linux* prefix. 316 # Android builds are also archived with the "full-build-linux prefix.
319 return 'linux' 317 return 'linux'
320 if bisect_utils.IsMacHost(): 318 if bisect_utils.IsMacHost():
321 return 'mac' 319 return 'mac'
322 raise NotImplementedError('Unknown platform "%s".' % sys.platform) 320 raise NotImplementedError('Unknown platform "%s".' % sys.platform)
323 321
324 base_name = 'full-build-%s' % PlatformName() 322 base_name = 'full-build-%s' % PlatformName()
325 if not build_revision: 323 if not build_revision:
326 return base_name 324 return base_name
327 if patch_sha: 325 if patch_sha:
328 build_revision = '%s_%s' % (build_revision , patch_sha) 326 build_revision = '%s_%s' % (build_revision , patch_sha)
329 return '%s_%s.zip' % (base_name, build_revision) 327 return '%s_%s.zip' % (base_name, build_revision)
330 328
331 329
332 def GetRemoteBuildPath(build_revision, target_platform='chromium', 330 def GetRemoteBuildPath(build_revision, target_platform='chromium',
333 target_arch='ia32', patch_sha=None): 331 target_arch='ia32', patch_sha=None):
334 """Compute the url to download the build from.""" 332 """Returns the URL to download the build from."""
335 def GetGSRootFolderName(target_platform): 333 def GetGSRootFolderName(target_platform):
336 """Gets Google Cloud Storage root folder names""" 334 """Returns the Google Cloud Storage root folder name."""
337 if bisect_utils.IsWindowsHost(): 335 if bisect_utils.IsWindowsHost():
338 if bisect_utils.Is64BitWindows() and target_arch == 'x64': 336 if bisect_utils.Is64BitWindows() and target_arch == 'x64':
339 return 'Win x64 Builder' 337 return 'Win x64 Builder'
340 return 'Win Builder' 338 return 'Win Builder'
341 if bisect_utils.IsLinuxHost(): 339 if bisect_utils.IsLinuxHost():
342 if target_platform == 'android': 340 if target_platform == 'android':
343 return 'android_perf_rel' 341 return 'android_perf_rel'
344 return 'Linux Builder' 342 return 'Linux Builder'
345 if bisect_utils.IsMacHost(): 343 if bisect_utils.IsMacHost():
346 return 'Mac Builder' 344 return 'Mac Builder'
347 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) 345 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform)
348 346
349 base_filename = GetZipFileName( 347 base_filename = GetZipFileName(
350 build_revision, target_arch, patch_sha) 348 build_revision, target_arch, patch_sha)
351 builder_folder = GetGSRootFolderName(target_platform) 349 builder_folder = GetGSRootFolderName(target_platform)
352 return '%s/%s' % (builder_folder, base_filename) 350 return '%s/%s' % (builder_folder, base_filename)
353 351
354 352
355 def FetchFromCloudStorage(bucket_name, source_path, destination_path): 353 def FetchFromCloudStorage(bucket_name, source_path, destination_path):
356 """Fetches file(s) from the Google Cloud Storage. 354 """Fetches file(s) from the Google Cloud Storage.
357 355
358 Args: 356 Args:
359 bucket_name: Google Storage bucket name. 357 bucket_name: Google Storage bucket name.
360 source_path: Source file path. 358 source_path: Source file path.
361 destination_path: Destination file path. 359 destination_path: Destination file path.
362 360
363 Returns: 361 Returns:
364 Downloaded file path if exisits, otherwise None. 362 Downloaded file path if exists, otherwise None.
365 """ 363 """
366 target_file = os.path.join(destination_path, os.path.basename(source_path)) 364 target_file = os.path.join(destination_path, os.path.basename(source_path))
367 try: 365 try:
368 if cloud_storage.Exists(bucket_name, source_path): 366 if cloud_storage.Exists(bucket_name, source_path):
369 print 'Fetching file from gs//%s/%s ...' % (bucket_name, source_path) 367 print 'Fetching file from gs//%s/%s ...' % (bucket_name, source_path)
370 cloud_storage.Get(bucket_name, source_path, destination_path) 368 cloud_storage.Get(bucket_name, source_path, destination_path)
371 if os.path.exists(target_file): 369 if os.path.exists(target_file):
372 return target_file 370 return target_file
373 else: 371 else:
374 print ('File gs://%s/%s not found in cloud storage.' % ( 372 print ('File gs://%s/%s not found in cloud storage.' % (
375 bucket_name, source_path)) 373 bucket_name, source_path))
376 except Exception as e: 374 except Exception as e:
377 print 'Something went wrong while fetching file from cloud: %s' % e 375 print 'Something went wrong while fetching file from cloud: %s' % e
378 if os.path.exists(target_file): 376 if os.path.exists(target_file):
379 os.remove(target_file) 377 os.remove(target_file)
380 return None 378 return None
381 379
382 380
383 # This is copied from Chromium's project build/scripts/common/chromium_utils.py. 381 # This is copied from build/scripts/common/chromium_utils.py.
384 def MaybeMakeDirectory(*path): 382 def MaybeMakeDirectory(*path):
385 """Creates an entire path, if it doesn't already exist.""" 383 """Creates an entire path, if it doesn't already exist."""
386 file_path = os.path.join(*path) 384 file_path = os.path.join(*path)
387 try: 385 try:
388 os.makedirs(file_path) 386 os.makedirs(file_path)
389 except OSError as e: 387 except OSError as e:
390 if e.errno != errno.EEXIST: 388 if e.errno != errno.EEXIST:
391 return False 389 return False
392 return True 390 return True
393 391
394 392
395 # This is copied from Chromium's project build/scripts/common/chromium_utils.py. 393 # This was copied from build/scripts/common/chromium_utils.py.
396 def ExtractZip(filename, output_dir, verbose=True): 394 def ExtractZip(filename, output_dir, verbose=True):
397 """ Extract the zip archive in the output directory.""" 395 """ Extract the zip archive in the output directory."""
398 MaybeMakeDirectory(output_dir) 396 MaybeMakeDirectory(output_dir)
399 397
400 # On Linux and Mac, we use the unzip command as it will 398 # On Linux and Mac, we use the unzip command as it will
401 # handle links and file bits (executable), which is much 399 # handle links and file bits (executable), which is much
402 # easier then trying to do that with ZipInfo options. 400 # easier then trying to do that with ZipInfo options.
403 # 401 #
404 # The Mac Version of unzip unfortunately does not support Zip64, whereas 402 # The Mac Version of unzip unfortunately does not support Zip64, whereas
405 # the python module does, so we have to fallback to the python zip module 403 # the python module does, so we have to fall back to the python zip module
406 # on Mac if the filesize is greater than 4GB. 404 # on Mac if the file size is greater than 4GB.
407 # 405 #
408 # On Windows, try to use 7z if it is installed, otherwise fall back to python 406 # On Windows, try to use 7z if it is installed, otherwise fall back to python
409 # zip module and pray we don't have files larger than 512MB to unzip. 407 # zip module and pray we don't have files larger than 512MB to unzip.
410 unzip_cmd = None 408 unzip_cmd = None
411 if ((bisect_utils.IsMacHost() 409 if ((bisect_utils.IsMacHost()
412 and os.path.getsize(filename) < 4 * 1024 * 1024 * 1024) 410 and os.path.getsize(filename) < 4 * 1024 * 1024 * 1024)
413 or bisect_utils.IsLinuxHost()): 411 or bisect_utils.IsLinuxHost()):
414 unzip_cmd = ['unzip', '-o'] 412 unzip_cmd = ['unzip', '-o']
415 elif (bisect_utils.IsWindowsHost() 413 elif (bisect_utils.IsWindowsHost()
416 and os.path.exists('C:\\Program Files\\7-Zip\\7z.exe')): 414 and os.path.exists('C:\\Program Files\\7-Zip\\7z.exe')):
(...skipping 16 matching lines...) Expand all
433 if verbose: 431 if verbose:
434 print 'Extracting %s' % name 432 print 'Extracting %s' % name
435 zf.extract(name, output_dir) 433 zf.extract(name, output_dir)
436 if bisect_utils.IsMacHost(): 434 if bisect_utils.IsMacHost():
437 # Restore permission bits. 435 # Restore permission bits.
438 os.chmod(os.path.join(output_dir, name), 436 os.chmod(os.path.join(output_dir, name),
439 zf.getinfo(name).external_attr >> 16L) 437 zf.getinfo(name).external_attr >> 16L)
440 438
441 439
442 def WriteStringToFile(text, file_name): 440 def WriteStringToFile(text, file_name):
441 """Writes text to a file, raising an RuntimeError on failure."""
443 try: 442 try:
444 with open(file_name, 'wb') as f: 443 with open(file_name, 'wb') as f:
445 f.write(text) 444 f.write(text)
446 except IOError: 445 except IOError:
447 raise RuntimeError('Error writing to file [%s]' % file_name ) 446 raise RuntimeError('Error writing to file [%s]' % file_name )
448 447
449 448
450 def ReadStringFromFile(file_name): 449 def ReadStringFromFile(file_name):
450 """Writes text to a file, raising an RuntimeError on failure."""
451 try: 451 try:
452 with open(file_name) as f: 452 with open(file_name) as f:
453 return f.read() 453 return f.read()
454 except IOError: 454 except IOError:
455 raise RuntimeError('Error reading file [%s]' % file_name ) 455 raise RuntimeError('Error reading file [%s]' % file_name )
456 456
457 457
458 def ChangeBackslashToSlashInPatch(diff_text): 458 def ChangeBackslashToSlashInPatch(diff_text):
459 """Formats file paths in the given text to unix-style paths.""" 459 """Formats file paths in the given patch text to Unix-style paths."""
460 if diff_text: 460 if not diff_text:
461 diff_lines = diff_text.split('\n') 461 return None
462 for i in range(len(diff_lines)): 462 diff_lines = diff_text.split('\n')
463 if (diff_lines[i].startswith('--- ') or 463 for i in range(len(diff_lines)):
464 diff_lines[i].startswith('+++ ')): 464 line = diff_lines[i]
465 diff_lines[i] = diff_lines[i].replace('\\', '/') 465 if line.startswith('--- ') or line.startswith('+++ '):
466 return '\n'.join(diff_lines) 466 diff_lines[i] = line.replace('\\', '/')
467 return None 467 return '\n'.join(diff_lines)
468 468
469 469
470 def _ParseRevisionsFromDEPSFileManually(deps_file_contents): 470 def _ParseRevisionsFromDEPSFileManually(deps_file_contents):
471 """Parses the vars section of the DEPS file with regex. 471 """Parses the vars section of the DEPS file using regular expressions.
472 472
473 Args: 473 Args:
474 deps_file_contents: The DEPS file contents as a string. 474 deps_file_contents: The DEPS file contents as a string.
475 475
476 Returns: 476 Returns:
477 A dict in the format {depot:revision} if successful, otherwise None. 477 A dictionary in the format {depot: revision} if successful, otherwise None.
478 """ 478 """
479 # We'll parse the "vars" section of the DEPS file. 479 # We'll parse the "vars" section of the DEPS file.
480 rxp = re.compile('vars = {(?P<vars_body>[^}]+)', re.MULTILINE) 480 rxp = re.compile('vars = {(?P<vars_body>[^}]+)', re.MULTILINE)
481 re_results = rxp.search(deps_file_contents) 481 re_results = rxp.search(deps_file_contents)
482 482
483 if not re_results: 483 if not re_results:
484 return None 484 return None
485 485
486 # We should be left with a series of entries in the vars component of 486 # We should be left with a series of entries in the vars component of
487 # the DEPS file with the following format: 487 # the DEPS file with the following format:
488 # 'depot_name': 'revision', 488 # 'depot_name': 'revision',
489 vars_body = re_results.group('vars_body') 489 vars_body = re_results.group('vars_body')
490 rxp = re.compile("'(?P<depot_body>[\w_-]+)':[\s]+'(?P<rev_body>[\w@]+)'", 490 rxp = re.compile("'(?P<depot_body>[\w_-]+)':[\s]+'(?P<rev_body>[\w@]+)'",
491 re.MULTILINE) 491 re.MULTILINE)
492 re_results = rxp.findall(vars_body) 492 re_results = rxp.findall(vars_body)
493 493
494 return dict(re_results) 494 return dict(re_results)
495 495
496 496
497 def _WaitUntilBuildIsReady( 497 def _WaitUntilBuildIsReady(
498 fetch_build, bot_name, builder_host, builder_port, build_request_id, 498 fetch_build, bot_name, builder_host, builder_port, build_request_id,
499 max_timeout): 499 max_timeout):
500 """Waits until build is produced by bisect builder on tryserver. 500 """Waits until build is produced by bisect builder on try server.
501 501
502 Args: 502 Args:
503 fetch_build: Function to check and download build from cloud storage. 503 fetch_build: Function to check and download build from cloud storage.
504 bot_name: Builder bot name on tryserver. 504 bot_name: Builder bot name on try server.
505 builder_host Tryserver hostname. 505 builder_host Try server host name.
506 builder_port: Tryserver port. 506 builder_port: Try server port.
507 build_request_id: A unique ID of the build request posted to tryserver. 507 build_request_id: A unique ID of the build request posted to try server.
508 max_timeout: Maximum time to wait for the build. 508 max_timeout: Maximum time to wait for the build.
509 509
510 Returns: 510 Returns:
511 Downloaded archive file path if exists, otherwise None. 511 Downloaded archive file path if exists, otherwise None.
512 """ 512 """
513 # Build number on the tryserver. 513 # Build number on the try server.
514 build_num = None 514 build_num = None
515 # Interval to check build on cloud storage. 515 # Interval to check build on cloud storage.
516 poll_interval = 60 516 poll_interval = 60
517 # Interval to check build status on tryserver. 517 # Interval to check build status on try server in seconds.
518 status_check_interval = 600 518 status_check_interval = 600
519 last_status_check = time.time() 519 last_status_check = time.time()
520 start_time = time.time() 520 start_time = time.time()
521 while True: 521 while True:
522 # Checks for build on gs://chrome-perf and download if exists. 522 # Checks for build on gs://chrome-perf and download if exists.
523 res = fetch_build() 523 res = fetch_build()
524 if res: 524 if res:
525 return (res, 'Build successfully found') 525 return (res, 'Build successfully found')
526 elapsed_status_check = time.time() - last_status_check 526 elapsed_status_check = time.time() - last_status_check
527 # To avoid overloading tryserver with status check requests, we check 527 # To avoid overloading try server with status check requests, we check
528 # build status for every 10 mins. 528 # build status for every 10 minutes.
529 if elapsed_status_check > status_check_interval: 529 if elapsed_status_check > status_check_interval:
530 last_status_check = time.time() 530 last_status_check = time.time()
531 if not build_num: 531 if not build_num:
532 # Get the build number on tryserver for the current build. 532 # Get the build number on try server for the current build.
533 build_num = bisect_builder.GetBuildNumFromBuilder( 533 build_num = bisect_builder.GetBuildNumFromBuilder(
534 build_request_id, bot_name, builder_host, builder_port) 534 build_request_id, bot_name, builder_host, builder_port)
535 # Check the status of build using the build number. 535 # Check the status of build using the build number.
536 # Note: Build is treated as PENDING if build number is not found 536 # Note: Build is treated as PENDING if build number is not found
537 # on the the tryserver. 537 # on the the try server.
538 build_status, status_link = bisect_builder.GetBuildStatus( 538 build_status, status_link = bisect_builder.GetBuildStatus(
539 build_num, bot_name, builder_host, builder_port) 539 build_num, bot_name, builder_host, builder_port)
540 if build_status == bisect_builder.FAILED: 540 if build_status == bisect_builder.FAILED:
541 return (None, 'Failed to produce build, log: %s' % status_link) 541 return (None, 'Failed to produce build, log: %s' % status_link)
542 elapsed_time = time.time() - start_time 542 elapsed_time = time.time() - start_time
543 if elapsed_time > max_timeout: 543 if elapsed_time > max_timeout:
544 return (None, 'Timed out: %ss without build' % max_timeout) 544 return (None, 'Timed out: %ss without build' % max_timeout)
545 545
546 print 'Time elapsed: %ss without build.' % elapsed_time 546 print 'Time elapsed: %ss without build.' % elapsed_time
547 time.sleep(poll_interval) 547 time.sleep(poll_interval)
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 if arg_dict.has_key('--profile-dir') and arg_dict.has_key('--browser'): 776 if arg_dict.has_key('--profile-dir') and arg_dict.has_key('--browser'):
777 profile_path, profile_type = os.path.split(arg_dict['--profile-dir']) 777 profile_path, profile_type = os.path.split(arg_dict['--profile-dir'])
778 return not bisect_utils.RunProcess(['python', path_to_generate, 778 return not bisect_utils.RunProcess(['python', path_to_generate,
779 '--profile-type-to-generate', profile_type, 779 '--profile-type-to-generate', profile_type,
780 '--browser', arg_dict['--browser'], '--output-dir', profile_path]) 780 '--browser', arg_dict['--browser'], '--output-dir', profile_path])
781 return False 781 return False
782 return True 782 return True
783 783
784 784
785 def _AddRevisionsIntoRevisionData(revisions, depot, sort, revision_data): 785 def _AddRevisionsIntoRevisionData(revisions, depot, sort, revision_data):
786 """Adds new revisions to the revision_data dict and initializes them. 786 """Adds new revisions to the revision_data dictionary and initializes them.
787 787
788 Args: 788 Args:
789 revisions: List of revisions to add. 789 revisions: List of revisions to add.
790 depot: Depot that's currently in use (src, webkit, etc...) 790 depot: Depot that's currently in use (src, webkit, etc...)
791 sort: Sorting key for displaying revisions. 791 sort: Sorting key for displaying revisions.
792 revision_data: A dict to add the new revisions into. Existing revisions 792 revision_data: A dictionary to add the new revisions into.
793 will have their sort keys offset. 793 Existing revisions will have their sort keys adjusted.
794 """ 794 """
795 num_depot_revisions = len(revisions) 795 num_depot_revisions = len(revisions)
796 796
797 for _, v in revision_data.iteritems(): 797 for _, v in revision_data.iteritems():
798 if v['sort'] > sort: 798 if v['sort'] > sort:
799 v['sort'] += num_depot_revisions 799 v['sort'] += num_depot_revisions
800 800
801 for i in xrange(num_depot_revisions): 801 for i in xrange(num_depot_revisions):
802 r = revisions[i] 802 r = revisions[i]
803 revision_data[r] = { 803 revision_data[r] = {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 print 'Average build time : %s' % datetime.timedelta( 850 print 'Average build time : %s' % datetime.timedelta(
851 seconds=int(step_build_time_avg)) 851 seconds=int(step_build_time_avg))
852 print 'Average test time : %s' % datetime.timedelta( 852 print 'Average test time : %s' % datetime.timedelta(
853 seconds=int(step_perf_time_avg)) 853 seconds=int(step_perf_time_avg))
854 854
855 855
856 def _FindOtherRegressions(revision_data_sorted, bad_greater_than_good): 856 def _FindOtherRegressions(revision_data_sorted, bad_greater_than_good):
857 """Compiles a list of other possible regressions from the revision data. 857 """Compiles a list of other possible regressions from the revision data.
858 858
859 Args: 859 Args:
860 revision_data_sorted: Sorted list of (revision, revision data dict) pairs. 860 revision_data_sorted: Sorted list of (revision, revision data) pairs.
861 bad_greater_than_good: Whether the result value at the "bad" revision is 861 bad_greater_than_good: Whether the result value at the "bad" revision is
862 numerically greater than the result value at the "good" revision. 862 numerically greater than the result value at the "good" revision.
863 863
864 Returns: 864 Returns:
865 A list of [current_rev, previous_rev, confidence] for other places where 865 A list of [current_rev, previous_rev, confidence] for other places where
866 there may have been a regression. 866 there may have been a regression.
867 """ 867 """
868 other_regressions = [] 868 other_regressions = []
869 previous_values = [] 869 previous_values = []
870 previous_id = None 870 previous_id = None
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 if (depot_data.get('recurse') and depot in depot_data.get('from')): 1080 if (depot_data.get('recurse') and depot in depot_data.get('from')):
1081 depot_data_src = depot_data.get('src') or depot_data.get('src_old') 1081 depot_data_src = depot_data.get('src') or depot_data.get('src_old')
1082 src_dir = deps_data.get(depot_data_src) 1082 src_dir = deps_data.get(depot_data_src)
1083 if src_dir: 1083 if src_dir:
1084 self.depot_cwd[depot_name] = os.path.join(self.src_cwd, 1084 self.depot_cwd[depot_name] = os.path.join(self.src_cwd,
1085 depot_data_src[4:]) 1085 depot_data_src[4:])
1086 re_results = rxp.search(src_dir) 1086 re_results = rxp.search(src_dir)
1087 if re_results: 1087 if re_results:
1088 results[depot_name] = re_results.group('revision') 1088 results[depot_name] = re_results.group('revision')
1089 else: 1089 else:
1090 warning_text = ('Couldn\'t parse revision for %s while bisecting ' 1090 warning_text = ('Could not parse revision for %s while bisecting '
1091 '%s' % (depot_name, depot)) 1091 '%s' % (depot_name, depot))
1092 if not warning_text in self.warnings: 1092 if not warning_text in self.warnings:
1093 self.warnings.append(warning_text) 1093 self.warnings.append(warning_text)
1094 else: 1094 else:
1095 results[depot_name] = None 1095 results[depot_name] = None
1096 return results 1096 return results
1097 except ImportError: 1097 except ImportError:
1098 deps_file_contents = ReadStringFromFile(bisect_utils.FILE_DEPS_GIT) 1098 deps_file_contents = ReadStringFromFile(bisect_utils.FILE_DEPS_GIT)
1099 parse_results = _ParseRevisionsFromDEPSFileManually(deps_file_contents) 1099 parse_results = _ParseRevisionsFromDEPSFileManually(deps_file_contents)
1100 results = {} 1100 results = {}
1101 for depot_name, depot_revision in parse_results.iteritems(): 1101 for depot_name, depot_revision in parse_results.iteritems():
1102 depot_revision = depot_revision.strip('@') 1102 depot_revision = depot_revision.strip('@')
1103 print depot_name, depot_revision 1103 print depot_name, depot_revision
1104 for current_name, current_data in DEPOT_DEPS_NAME.iteritems(): 1104 for current_name, current_data in DEPOT_DEPS_NAME.iteritems():
1105 if (current_data.has_key('deps_var') and 1105 if (current_data.has_key('deps_var') and
1106 current_data['deps_var'] == depot_name): 1106 current_data['deps_var'] == depot_name):
1107 src_name = current_name 1107 src_name = current_name
1108 results[src_name] = depot_revision 1108 results[src_name] = depot_revision
1109 break 1109 break
1110 return results 1110 return results
1111 1111
1112 def _Get3rdPartyRevisions(self, depot): 1112 def _Get3rdPartyRevisions(self, depot):
1113 """Parses the DEPS file to determine WebKit/v8/etc... versions. 1113 """Parses the DEPS file to determine WebKit/v8/etc... versions.
1114 1114
1115 Args:
1116 depot: A depot name. Should be in the DEPOT_NAMES list.
1117
1115 Returns: 1118 Returns:
1116 A dict in the format {depot:revision} if successful, otherwise None. 1119 A dict in the format {depot: revision} if successful, otherwise None.
1117 """ 1120 """
1118 cwd = os.getcwd() 1121 cwd = os.getcwd()
1119 self.ChangeToDepotWorkingDirectory(depot) 1122 self.ChangeToDepotWorkingDirectory(depot)
1120 1123
1121 results = {} 1124 results = {}
1122 1125
1123 if depot == 'chromium' or depot == 'android-chrome': 1126 if depot == 'chromium' or depot == 'android-chrome':
1124 results = self._ParseRevisionsFromDEPSFile(depot) 1127 results = self._ParseRevisionsFromDEPSFile(depot)
1125 os.chdir(cwd) 1128 os.chdir(cwd)
1126 1129
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 # Cleanup any leftovers from unzipping. 1297 # Cleanup any leftovers from unzipping.
1295 if os.path.exists(output_dir): 1298 if os.path.exists(output_dir):
1296 RmTreeAndMkDir(output_dir, skip_makedir=True) 1299 RmTreeAndMkDir(output_dir, skip_makedir=True)
1297 finally: 1300 finally:
1298 # Delete downloaded archive 1301 # Delete downloaded archive
1299 if os.path.exists(downloaded_file): 1302 if os.path.exists(downloaded_file):
1300 os.remove(downloaded_file) 1303 os.remove(downloaded_file)
1301 return False 1304 return False
1302 1305
1303 def PostBuildRequestAndWait(self, revision, fetch_build, patch=None): 1306 def PostBuildRequestAndWait(self, revision, fetch_build, patch=None):
1304 """POSTs the build request job to the tryserver instance. 1307 """POSTs the build request job to the try server instance.
1305 1308
1306 A try job build request is posted to tryserver.chromium.perf master, 1309 A try job build request is posted to tryserver.chromium.perf master,
1307 and waits for the binaries to be produced and archived on cloud storage. 1310 and waits for the binaries to be produced and archived on cloud storage.
1308 Once the build is ready and stored onto cloud, build archive is downloaded 1311 Once the build is ready and stored onto cloud, build archive is downloaded
1309 into the output folder. 1312 into the output folder.
1310 1313
1311 Args: 1314 Args:
1312 revision: A Git hash revision. 1315 revision: A Git hash revision.
1313 fetch_build: Function to check and download build from cloud storage. 1316 fetch_build: Function to check and download build from cloud storage.
1314 patch: A DEPS patch (used while bisecting 3rd party repositories). 1317 patch: A DEPS patch (used while bisecting 3rd party repositories).
(...skipping 23 matching lines...) Expand all
1338 if bisect_utils.IsMacHost(): 1341 if bisect_utils.IsMacHost():
1339 return ('mac_perf_bisect_builder', MAX_MAC_BUILD_TIME) 1342 return ('mac_perf_bisect_builder', MAX_MAC_BUILD_TIME)
1340 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) 1343 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform)
1341 if not fetch_build: 1344 if not fetch_build:
1342 return False 1345 return False
1343 1346
1344 bot_name, build_timeout = GetBuilderNameAndBuildTime( 1347 bot_name, build_timeout = GetBuilderNameAndBuildTime(
1345 self.opts.target_platform, self.opts.target_arch) 1348 self.opts.target_platform, self.opts.target_arch)
1346 builder_host = self.opts.builder_host 1349 builder_host = self.opts.builder_host
1347 builder_port = self.opts.builder_port 1350 builder_port = self.opts.builder_port
1348 # Create a unique ID for each build request posted to tryserver builders. 1351 # Create a unique ID for each build request posted to try server builders.
1349 # This ID is added to "Reason" property in build's json. 1352 # This ID is added to "Reason" property of the build.
1350 build_request_id = GetSHA1HexDigest( 1353 build_request_id = GetSHA1HexDigest(
1351 '%s-%s-%s' % (svn_revision, patch, time.time())) 1354 '%s-%s-%s' % (svn_revision, patch, time.time()))
1352 1355
1353 # Creates a try job description. 1356 # Creates a try job description.
1354 job_args = { 1357 job_args = {
1355 'revision': 'src@%s' % svn_revision, 1358 'revision': 'src@%s' % svn_revision,
1356 'bot': bot_name, 1359 'bot': bot_name,
1357 'name': build_request_id, 1360 'name': build_request_id,
1358 } 1361 }
1359 # Update patch information if supplied. 1362 # Update patch information if supplied.
1360 if patch: 1363 if patch:
1361 job_args['patch'] = patch 1364 job_args['patch'] = patch
1362 # Posts job to build the revision on the server. 1365 # Posts job to build the revision on the server.
1363 if bisect_builder.PostTryJob(builder_host, builder_port, job_args): 1366 if bisect_builder.PostTryJob(builder_host, builder_port, job_args):
1364 target_file, error_msg = _WaitUntilBuildIsReady( 1367 target_file, error_msg = _WaitUntilBuildIsReady(
1365 fetch_build, bot_name, builder_host, builder_port, build_request_id, 1368 fetch_build, bot_name, builder_host, builder_port, build_request_id,
1366 build_timeout) 1369 build_timeout)
1367 if not target_file: 1370 if not target_file:
1368 print '%s [revision: %s]' % (error_msg, svn_revision) 1371 print '%s [revision: %s]' % (error_msg, svn_revision)
1369 return None 1372 return None
1370 return target_file 1373 return target_file
1371 print 'Failed to post build request for revision: [%s]' % svn_revision 1374 print 'Failed to post build request for revision: [%s]' % svn_revision
1372 return None 1375 return None
1373 1376
1374 def IsDownloadable(self, depot): 1377 def IsDownloadable(self, depot):
1375 """Checks if build is downloadable based on target platform and depot.""" 1378 """Checks if build can be downloaded based on target platform and depot."""
1376 if (self.opts.target_platform in ['chromium', 'android'] and 1379 if (self.opts.target_platform in ['chromium', 'android'] and
1377 self.opts.gs_bucket): 1380 self.opts.gs_bucket):
1378 return (depot == 'chromium' or 1381 return (depot == 'chromium' or
1379 'chromium' in DEPOT_DEPS_NAME[depot]['from'] or 1382 'chromium' in DEPOT_DEPS_NAME[depot]['from'] or
1380 'v8' in DEPOT_DEPS_NAME[depot]['from']) 1383 'v8' in DEPOT_DEPS_NAME[depot]['from'])
1381 return False 1384 return False
1382 1385
1383 def UpdateDeps(self, revision, depot, deps_file): 1386 def UpdateDeps(self, revision, depot, deps_file):
1384 """Updates DEPS file with new revision of dependency repository. 1387 """Updates DEPS file with new revision of dependency repository.
1385 1388
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 def _IsBisectModeReturnCode(self): 1533 def _IsBisectModeReturnCode(self):
1531 return self.opts.bisect_mode in [BISECT_MODE_RETURN_CODE] 1534 return self.opts.bisect_mode in [BISECT_MODE_RETURN_CODE]
1532 1535
1533 def _IsBisectModeStandardDeviation(self): 1536 def _IsBisectModeStandardDeviation(self):
1534 return self.opts.bisect_mode in [BISECT_MODE_STD_DEV] 1537 return self.opts.bisect_mode in [BISECT_MODE_STD_DEV]
1535 1538
1536 def GetCompatibleCommand(self, command_to_run, revision, depot): 1539 def GetCompatibleCommand(self, command_to_run, revision, depot):
1537 # Prior to crrev.com/274857 *only* android-chromium-testshell 1540 # Prior to crrev.com/274857 *only* android-chromium-testshell
1538 # Then until crrev.com/276628 *both* (android-chromium-testshell and 1541 # Then until crrev.com/276628 *both* (android-chromium-testshell and
1539 # android-chrome-shell) work. After that rev 276628 *only* 1542 # android-chrome-shell) work. After that rev 276628 *only*
1540 # android-chrome-shell works. bisect-perf-reggresion.py script should 1543 # android-chrome-shell works. bisect-perf-regression.py script should
1541 # handle these cases and set appropriate browser type based on revision. 1544 # handle these cases and set appropriate browser type based on revision.
1542 if self.opts.target_platform in ['android']: 1545 if self.opts.target_platform in ['android']:
1543 # When its a third_party depot, get the chromium revision. 1546 # When its a third_party depot, get the chromium revision.
1544 if depot != 'chromium': 1547 if depot != 'chromium':
1545 revision = bisect_utils.CheckRunGit( 1548 revision = bisect_utils.CheckRunGit(
1546 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip() 1549 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip()
1547 svn_revision = self.source_control.SVNFindRev(revision, cwd=self.src_cwd) 1550 svn_revision = self.source_control.SVNFindRev(revision, cwd=self.src_cwd)
1548 if not svn_revision: 1551 if not svn_revision:
1549 return command_to_run 1552 return command_to_run
1550 cmd_re = re.compile('--browser=(?P<browser_type>\S+)') 1553 cmd_re = re.compile('--browser=(?P<browser_type>\S+)')
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 'std_dev': standard_dev, 1699 'std_dev': standard_dev,
1697 'values': metric_values, 1700 'values': metric_values,
1698 } 1701 }
1699 1702
1700 print 'Results of performance test: %12f %12f' % ( 1703 print 'Results of performance test: %12f %12f' % (
1701 truncated_mean, standard_err) 1704 truncated_mean, standard_err)
1702 print 1705 print
1703 return (values, success_code, output_of_all_runs) 1706 return (values, success_code, output_of_all_runs)
1704 1707
1705 def FindAllRevisionsToSync(self, revision, depot): 1708 def FindAllRevisionsToSync(self, revision, depot):
1706 """Finds all dependant revisions and depots that need to be synced for a 1709 """Finds all dependent revisions and depots that need to be synced.
1707 given revision. This is only useful in the git workflow, as an svn depot
1708 may be split into multiple mirrors.
1709 1710
1710 ie. skia is broken up into 3 git mirrors over skia/src, skia/gyp, and 1711 For example skia is broken up into 3 git mirrors over skia/src,
1711 skia/include. To sync skia/src properly, one has to find the proper 1712 skia/gyp, and skia/include. To sync skia/src properly, one has to find
1712 revisions in skia/gyp and skia/include. 1713 the proper revisions in skia/gyp and skia/include.
1714
1715 This is only useful in the git workflow, as an SVN depot may be split into
1716 multiple mirrors.
1713 1717
1714 Args: 1718 Args:
1715 revision: The revision to sync to. 1719 revision: The revision to sync to.
1716 depot: The depot in use at the moment (probably skia). 1720 depot: The depot in use at the moment (probably skia).
1717 1721
1718 Returns: 1722 Returns:
1719 A list of [depot, revision] pairs that need to be synced. 1723 A list of [depot, revision] pairs that need to be synced.
1720 """ 1724 """
1721 revisions_to_sync = [[depot, revision]] 1725 revisions_to_sync = [[depot, revision]]
1722 1726
1723 is_base = ((depot == 'chromium') or (depot == 'cros') or 1727 is_base = ((depot == 'chromium') or (depot == 'cros') or
1724 (depot == 'android-chrome')) 1728 (depot == 'android-chrome'))
1725 1729
1726 # Some SVN depots were split into multiple git depots, so we need to 1730 # Some SVN depots were split into multiple git depots, so we need to
1727 # figure out for each mirror which git revision to grab. There's no 1731 # figure out for each mirror which git revision to grab. There's no
1728 # guarantee that the SVN revision will exist for each of the dependant 1732 # guarantee that the SVN revision will exist for each of the dependent
1729 # depots, so we have to grep the git logs and grab the next earlier one. 1733 # depots, so we have to grep the git logs and grab the next earlier one.
1730 if (not is_base 1734 if (not is_base
1731 and DEPOT_DEPS_NAME[depot]['depends'] 1735 and DEPOT_DEPS_NAME[depot]['depends']
1732 and self.source_control.IsGit()): 1736 and self.source_control.IsGit()):
1733 svn_rev = self.source_control.SVNFindRev(revision) 1737 svn_rev = self.source_control.SVNFindRev(revision)
1734 1738
1735 for d in DEPOT_DEPS_NAME[depot]['depends']: 1739 for d in DEPOT_DEPS_NAME[depot]['depends']:
1736 self.ChangeToDepotWorkingDirectory(d) 1740 self.ChangeToDepotWorkingDirectory(d)
1737 1741
1738 dependant_rev = self.source_control.ResolveToRevision( 1742 dependant_rev = self.source_control.ResolveToRevision(
1739 svn_rev, d, DEPOT_DEPS_NAME, -1000) 1743 svn_rev, d, DEPOT_DEPS_NAME, -1000)
1740 1744
1741 if dependant_rev: 1745 if dependant_rev:
1742 revisions_to_sync.append([d, dependant_rev]) 1746 revisions_to_sync.append([d, dependant_rev])
1743 1747
1744 num_resolved = len(revisions_to_sync) 1748 num_resolved = len(revisions_to_sync)
1745 num_needed = len(DEPOT_DEPS_NAME[depot]['depends']) 1749 num_needed = len(DEPOT_DEPS_NAME[depot]['depends'])
1746 1750
1747 self.ChangeToDepotWorkingDirectory(depot) 1751 self.ChangeToDepotWorkingDirectory(depot)
1748 1752
1749 if not ((num_resolved - 1) == num_needed): 1753 if not ((num_resolved - 1) == num_needed):
1750 return None 1754 return None
1751 1755
1752 return revisions_to_sync 1756 return revisions_to_sync
1753 1757
1754 def PerformPreBuildCleanup(self): 1758 def PerformPreBuildCleanup(self):
1755 """Performs necessary cleanup between runs.""" 1759 """Performs cleanup between runs."""
1756 print 'Cleaning up between runs.' 1760 print 'Cleaning up between runs.'
1757 print 1761 print
1758 1762
1759 # Having these pyc files around between runs can confuse the 1763 # Leaving these .pyc files around between runs may disrupt some perf tests.
1760 # perf tests and cause them to crash.
1761 for (path, _, files) in os.walk(self.src_cwd): 1764 for (path, _, files) in os.walk(self.src_cwd):
1762 for cur_file in files: 1765 for cur_file in files:
1763 if cur_file.endswith('.pyc'): 1766 if cur_file.endswith('.pyc'):
1764 path_to_file = os.path.join(path, cur_file) 1767 path_to_file = os.path.join(path, cur_file)
1765 os.remove(path_to_file) 1768 os.remove(path_to_file)
1766 1769
1767 def PerformWebkitDirectoryCleanup(self, revision): 1770 def PerformWebkitDirectoryCleanup(self, revision):
1768 """If the script is switching between Blink and WebKit during bisect, 1771 """Cleans up the Webkit directory before syncing another revision.
1772
1773 If the script is switching between Blink and WebKit during bisect,
1769 its faster to just delete the directory rather than leave it up to git 1774 its faster to just delete the directory rather than leave it up to git
1770 to sync. 1775 to sync.
1771 1776
1772 Returns: 1777 Returns:
1773 True if successful. 1778 True if successful.
1774 """ 1779 """
1775 if not self.source_control.CheckoutFileAtRevision( 1780 if not self.source_control.CheckoutFileAtRevision(
1776 bisect_utils.FILE_DEPS_GIT, revision, cwd=self.src_cwd): 1781 bisect_utils.FILE_DEPS_GIT, revision, cwd=self.src_cwd):
1777 return False 1782 return False
1778 1783
(...skipping 11 matching lines...) Expand all
1790 if self.was_blink != is_blink: 1795 if self.was_blink != is_blink:
1791 self.was_blink = is_blink 1796 self.was_blink = is_blink
1792 # Removes third_party/Webkit directory. 1797 # Removes third_party/Webkit directory.
1793 return bisect_utils.RemoveThirdPartyDirectory('Webkit') 1798 return bisect_utils.RemoveThirdPartyDirectory('Webkit')
1794 return True 1799 return True
1795 1800
1796 def PerformCrosChrootCleanup(self): 1801 def PerformCrosChrootCleanup(self):
1797 """Deletes the chroot. 1802 """Deletes the chroot.
1798 1803
1799 Returns: 1804 Returns:
1800 True if successful. 1805 True if successful.
1801 """ 1806 """
1802 cwd = os.getcwd() 1807 cwd = os.getcwd()
1803 self.ChangeToDepotWorkingDirectory('cros') 1808 self.ChangeToDepotWorkingDirectory('cros')
1804 cmd = [bisect_utils.CROS_SDK_PATH, '--delete'] 1809 cmd = [bisect_utils.CROS_SDK_PATH, '--delete']
1805 return_code = bisect_utils.RunProcess(cmd) 1810 return_code = bisect_utils.RunProcess(cmd)
1806 os.chdir(cwd) 1811 os.chdir(cwd)
1807 return not return_code 1812 return not return_code
1808 1813
1809 def CreateCrosChroot(self): 1814 def CreateCrosChroot(self):
1810 """Creates a new chroot. 1815 """Creates a new chroot.
1811 1816
1812 Returns: 1817 Returns:
1813 True if successful. 1818 True if successful.
1814 """ 1819 """
1815 cwd = os.getcwd() 1820 cwd = os.getcwd()
1816 self.ChangeToDepotWorkingDirectory('cros') 1821 self.ChangeToDepotWorkingDirectory('cros')
1817 cmd = [bisect_utils.CROS_SDK_PATH, '--create'] 1822 cmd = [bisect_utils.CROS_SDK_PATH, '--create']
1818 return_code = bisect_utils.RunProcess(cmd) 1823 return_code = bisect_utils.RunProcess(cmd)
1819 os.chdir(cwd) 1824 os.chdir(cwd)
1820 return not return_code 1825 return not return_code
1821 1826
1822 def PerformPreSyncCleanup(self, revision, depot): 1827 def PerformPreSyncCleanup(self, revision, depot):
1823 """Performs any necessary cleanup before syncing. 1828 """Performs any necessary cleanup before syncing.
1824 1829
1825 Returns: 1830 Returns:
1826 True if successful. 1831 True if successful.
1827 """ 1832 """
1828 if depot == 'chromium' or depot == 'android-chrome': 1833 if depot == 'chromium' or depot == 'android-chrome':
1829 # Removes third_party/libjingle. At some point, libjingle was causing 1834 # Removes third_party/libjingle. At some point, libjingle was causing
1830 # issues syncing when using the git workflow (crbug.com/266324). 1835 # issues syncing when using the git workflow (crbug.com/266324).
1831 os.chdir(self.src_cwd) 1836 os.chdir(self.src_cwd)
1832 if not bisect_utils.RemoveThirdPartyDirectory('libjingle'): 1837 if not bisect_utils.RemoveThirdPartyDirectory('libjingle'):
1833 return False 1838 return False
1834 # Removes third_party/skia. At some point, skia was causing 1839 # Removes third_party/skia. At some point, skia was causing
1835 # issues syncing when using the git workflow (crbug.com/377951). 1840 # issues syncing when using the git workflow (crbug.com/377951).
1836 if not bisect_utils.RemoveThirdPartyDirectory('skia'): 1841 if not bisect_utils.RemoveThirdPartyDirectory('skia'):
1837 return False 1842 return False
1838 if depot == 'chromium': 1843 if depot == 'chromium':
1839 # The fast webkit cleanup doesn't work for android_chrome 1844 # The fast webkit cleanup doesn't work for android_chrome
1840 # The switch from Webkit to Blink that this deals with now happened 1845 # The switch from Webkit to Blink that this deals with now happened
1841 # quite a long time ago so this is unlikely to be a problem. 1846 # quite a long time ago so this is unlikely to be a problem.
1842 return self.PerformWebkitDirectoryCleanup(revision) 1847 return self.PerformWebkitDirectoryCleanup(revision)
1843 elif depot == 'cros': 1848 elif depot == 'cros':
1844 return self.PerformCrosChrootCleanup() 1849 return self.PerformCrosChrootCleanup()
1845 return True 1850 return True
1846 1851
1847 def RunPostSync(self, depot): 1852 def RunPostSync(self, depot):
1848 """Performs any work after syncing. 1853 """Performs any work after syncing.
1849 1854
1850 Returns: 1855 Returns:
1851 True if successful. 1856 True if successful.
1852 """ 1857 """
1853 if self.opts.target_platform == 'android': 1858 if self.opts.target_platform == 'android':
1854 if not builder.SetupAndroidBuildEnvironment(self.opts, 1859 if not builder.SetupAndroidBuildEnvironment(self.opts,
1855 path_to_src=self.src_cwd): 1860 path_to_src=self.src_cwd):
1856 return False 1861 return False
1857 1862
1858 if depot == 'cros': 1863 if depot == 'cros':
1859 return self.CreateCrosChroot() 1864 return self.CreateCrosChroot()
1860 else: 1865 else:
1861 return self.RunGClientHooks() 1866 return self.RunGClientHooks()
1862 return True 1867 return True
1863 1868
1864 def ShouldSkipRevision(self, depot, revision): 1869 def ShouldSkipRevision(self, depot, revision):
1865 """Some commits can be safely skipped (such as a DEPS roll), since the tool 1870 """Checks whether a particular revision can be safely skipped.
1871
1872 Some commits can be safely skipped (such as a DEPS roll), since the tool
1866 is git based those changes would have no effect. 1873 is git based those changes would have no effect.
1867 1874
1868 Args: 1875 Args:
1869 depot: The depot being bisected. 1876 depot: The depot being bisected.
1870 revision: Current revision we're synced to. 1877 revision: Current revision we're synced to.
1871 1878
1872 Returns: 1879 Returns:
1873 True if we should skip building/testing this revision. 1880 True if we should skip building/testing this revision.
1874 """ 1881 """
1875 if depot == 'chromium': 1882 if depot == 'chromium':
(...skipping 24 matching lines...) Expand all
1900 """ 1907 """
1901 sync_client = None 1908 sync_client = None
1902 if depot == 'chromium' or depot == 'android-chrome': 1909 if depot == 'chromium' or depot == 'android-chrome':
1903 sync_client = 'gclient' 1910 sync_client = 'gclient'
1904 elif depot == 'cros': 1911 elif depot == 'cros':
1905 sync_client = 'repo' 1912 sync_client = 'repo'
1906 1913
1907 revisions_to_sync = self.FindAllRevisionsToSync(revision, depot) 1914 revisions_to_sync = self.FindAllRevisionsToSync(revision, depot)
1908 1915
1909 if not revisions_to_sync: 1916 if not revisions_to_sync:
1910 return ('Failed to resolve dependant depots.', BUILD_RESULT_FAIL) 1917 return ('Failed to resolve dependent depots.', BUILD_RESULT_FAIL)
1911 1918
1912 if not self.PerformPreSyncCleanup(revision, depot): 1919 if not self.PerformPreSyncCleanup(revision, depot):
1913 return ('Failed to perform pre-sync cleanup.', BUILD_RESULT_FAIL) 1920 return ('Failed to perform pre-sync cleanup.', BUILD_RESULT_FAIL)
1914 1921
1915 success = True 1922 success = True
1916 1923
1917 if not self.opts.debug_ignore_sync: 1924 if not self.opts.debug_ignore_sync:
1918 for r in revisions_to_sync: 1925 for r in revisions_to_sync:
1919 self.ChangeToDepotWorkingDirectory(r[0]) 1926 self.ChangeToDepotWorkingDirectory(r[0])
1920 1927
1921 if sync_client: 1928 if sync_client:
1922 self.PerformPreBuildCleanup() 1929 self.PerformPreBuildCleanup()
1923 1930
1924 # If you're using gclient to sync, you need to specify the depot you 1931 # If you're using gclient to sync, you need to specify the depot you
1925 # want so that all the dependencies sync properly as well. 1932 # want so that all the dependencies sync properly as well.
1926 # ie. gclient sync src@<SHA1> 1933 # i.e. gclient sync src@<SHA1>
1927 current_revision = r[1] 1934 current_revision = r[1]
1928 if sync_client == 'gclient': 1935 if sync_client == 'gclient':
1929 current_revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], 1936 current_revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'],
1930 current_revision) 1937 current_revision)
1931 if not self.source_control.SyncToRevision(current_revision, 1938 if not self.source_control.SyncToRevision(current_revision,
1932 sync_client): 1939 sync_client):
1933 success = False 1940 success = False
1934 1941
1935 break 1942 break
1936 1943
1937 if success: 1944 if success:
1938 success = self.RunPostSync(depot) 1945 success = self.RunPostSync(depot)
1939 if success: 1946 if success:
1940 if skippable and self.ShouldSkipRevision(depot, revision): 1947 if skippable and self.ShouldSkipRevision(depot, revision):
1941 return ('Skipped revision: [%s]' % str(revision), 1948 return ('Skipped revision: [%s]' % str(revision),
1942 BUILD_RESULT_SKIPPED) 1949 BUILD_RESULT_SKIPPED)
1943 1950
1944 start_build_time = time.time() 1951 start_build_time = time.time()
1945 if self.BuildCurrentRevision(depot, revision): 1952 if self.BuildCurrentRevision(depot, revision):
1946 after_build_time = time.time() 1953 after_build_time = time.time()
1947 # Hack to support things that got changed. 1954 # Hack to support things that got changed.
1948 command_to_run = self.GetCompatibleCommand( 1955 command_to_run = self.GetCompatibleCommand(
1949 command_to_run, revision, depot) 1956 command_to_run, revision, depot)
1950 results = self.RunPerformanceTestAndParseResults(command_to_run, 1957 results = self.RunPerformanceTestAndParseResults(command_to_run,
1951 metric) 1958 metric)
1952 # Restore build output directory once the tests are done, to avoid 1959 # Restore build output directory once the tests are done, to avoid
1953 # any descrepancy. 1960 # any discrepancies.
1954 if self.IsDownloadable(depot) and revision: 1961 if self.IsDownloadable(depot) and revision:
1955 self.BackupOrRestoreOutputdirectory(restore=True) 1962 self.BackupOrRestoreOutputdirectory(restore=True)
1956 1963
1957 if results[1] == 0: 1964 if results[1] == 0:
1958 external_revisions = self._Get3rdPartyRevisions(depot) 1965 external_revisions = self._Get3rdPartyRevisions(depot)
1959 1966
1960 if not external_revisions is None: 1967 if not external_revisions is None:
1961 return (results[0], results[1], external_revisions, 1968 return (results[0], results[1], external_revisions,
1962 time.time() - after_build_time, after_build_time - 1969 time.time() - after_build_time, after_build_time -
1963 start_build_time) 1970 start_build_time)
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 2237
2231 output = bisect_utils.CheckRunGit(cmd, cwd=cwd) 2238 output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
2232 good_commit_time = int(output) 2239 good_commit_time = int(output)
2233 2240
2234 cmd = ['log', '--format=%ct', '-1', bad_revision] 2241 cmd = ['log', '--format=%ct', '-1', bad_revision]
2235 output = bisect_utils.CheckRunGit(cmd, cwd=cwd) 2242 output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
2236 bad_commit_time = int(output) 2243 bad_commit_time = int(output)
2237 2244
2238 return good_commit_time <= bad_commit_time 2245 return good_commit_time <= bad_commit_time
2239 else: 2246 else:
2240 # Cros/svn use integers 2247 # CrOS and SVN use integers.
2241 return int(good_revision) <= int(bad_revision) 2248 return int(good_revision) <= int(bad_revision)
2242 2249
2243 def CanPerformBisect(self, revision_to_check): 2250 def CanPerformBisect(self, revision_to_check):
2244 """Checks whether a given revision is bisectable. 2251 """Checks whether a given revision is bisectable.
2245 2252
2246 Note: At present it checks whether a given revision is bisectable on 2253 Note: At present it checks whether a given revision is bisectable on
2247 android bots(refer crbug.com/385324). 2254 android bots(refer crbug.com/385324).
2248 2255
2249 Args: 2256 Args:
2250 revision_to_check: Known good revision. 2257 revision_to_check: Known good revision.
2251 2258
2252 Returns: 2259 Returns:
2253 A dictionary indicating the result. If revision is not bisectable, 2260 A dictionary indicating the result. If revision is not bisectable,
2254 this will contain the field "error", otherwise None. 2261 this will contain the field "error", otherwise None.
2255 """ 2262 """
2256 if self.opts.target_platform == 'android': 2263 if self.opts.target_platform == 'android':
2257 revision_to_check = self.source_control.SVNFindRev(revision_to_check) 2264 revision_to_check = self.source_control.SVNFindRev(revision_to_check)
2258 if (bisect_utils.IsStringInt(revision_to_check) 2265 if (bisect_utils.IsStringInt(revision_to_check)
2259 and revision_to_check < 265549): 2266 and revision_to_check < 265549):
2260 return {'error': ( 2267 return {'error': (
2261 'Bisect cannot conitnue for the given revision range.\n' 2268 'Bisect cannot continue for the given revision range.\n'
2262 'It is impossible to bisect Android regressions ' 2269 'It is impossible to bisect Android regressions '
2263 'prior to r265549, which allows the bisect bot to ' 2270 'prior to r265549, which allows the bisect bot to '
2264 'rely on Telemetry to do apk installation of the most recently ' 2271 'rely on Telemetry to do apk installation of the most recently '
2265 'built local ChromeShell(refer to crbug.com/385324).\n' 2272 'built local ChromeShell(refer to crbug.com/385324).\n'
2266 'Please try bisecting revisions greater than or equal to r265549.')} 2273 'Please try bisecting revisions greater than or equal to r265549.')}
2267 return None 2274 return None
2268 2275
2269 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): 2276 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric):
2270 """Given known good and bad revisions, run a binary search on all 2277 """Given known good and bad revisions, run a binary search on all
2271 intermediate revisions to determine the CL where the performance regression 2278 intermediate revisions to determine the CL where the performance regression
2272 occurred. 2279 occurred.
2273 2280
2274 Args: 2281 Args:
2275 command_to_run: Specify the command to execute the performance test. 2282 command_to_run: Specify the command to execute the performance test.
2276 good_revision: Number/tag of the known good revision. 2283 good_revision: Number/tag of the known good revision.
2277 bad_revision: Number/tag of the known bad revision. 2284 bad_revision: Number/tag of the known bad revision.
2278 metric: The performance metric to monitor. 2285 metric: The performance metric to monitor.
2279 2286
2280 Returns: 2287 Returns:
2281 A dict with 2 members, 'revision_data' and 'error'. On success, 2288 A dict with 2 members, 'revision_data' and 'error'. On success,
2282 'revision_data' will contain a dict mapping revision ids to 2289 'revision_data' will contain a dict mapping revision ids to
2283 data about that revision. Each piece of revision data consists of a 2290 data about that revision. Each piece of revision data consists of a
2284 dict with the following keys: 2291 dict with the following keys:
2285 2292
2286 'passed': Represents whether the performance test was successful at 2293 'passed': Represents whether the performance test was successful at
2287 that revision. Possible values include: 1 (passed), 0 (failed), 2294 that revision. Possible values include: 1 (passed), 0 (failed),
2288 '?' (skipped), 'F' (build failed). 2295 '?' (skipped), 'F' (build failed).
2289 'depot': The depot that this revision is from (ie. WebKit) 2296 'depot': The depot that this revision is from (i.e. WebKit)
2290 'external': If the revision is a 'src' revision, 'external' contains 2297 'external': If the revision is a 'src' revision, 'external' contains
2291 the revisions of each of the external libraries. 2298 the revisions of each of the external libraries.
2292 'sort': A sort value for sorting the dict in order of commits. 2299 'sort': A sort value for sorting the dict in order of commits.
2293 2300
2294 For example: 2301 For example:
2295 { 2302 {
2296 'error':None, 2303 'error':None,
2297 'revision_data': 2304 'revision_data':
2298 { 2305 {
2299 'CL #1': 2306 'CL #1':
2300 { 2307 {
2301 'passed':False, 2308 'passed': False,
2302 'depot':'chromium', 2309 'depot': 'chromium',
2303 'external':None, 2310 'external': None,
2304 'sort':0 2311 'sort': 0
2305 } 2312 }
2306 } 2313 }
2307 } 2314 }
2308 2315
2309 If an error occurred, the 'error' field will contain the message and 2316 If an error occurred, the 'error' field will contain the message and
2310 'revision_data' will be empty. 2317 'revision_data' will be empty.
2311 """ 2318 """
2312 results = { 2319 results = {
2313 'revision_data' : {}, 2320 'revision_data' : {},
2314 'error' : None, 2321 'error' : None,
2315 } 2322 }
2316 2323
2317 # Choose depot to bisect first 2324 # Choose depot to bisect first
2318 target_depot = 'chromium' 2325 target_depot = 'chromium'
2319 if self.opts.target_platform == 'cros': 2326 if self.opts.target_platform == 'cros':
2320 target_depot = 'cros' 2327 target_depot = 'cros'
2321 elif self.opts.target_platform == 'android-chrome': 2328 elif self.opts.target_platform == 'android-chrome':
2322 target_depot = 'android-chrome' 2329 target_depot = 'android-chrome'
2323 2330
2324 cwd = os.getcwd() 2331 cwd = os.getcwd()
2325 self.ChangeToDepotWorkingDirectory(target_depot) 2332 self.ChangeToDepotWorkingDirectory(target_depot)
2326 2333
2327 # If they passed SVN CL's, etc... we can try match them to git SHA1's. 2334 # If they passed SVN revisions, we can try match them to git SHA1 hashes.
2328 bad_revision = self.source_control.ResolveToRevision( 2335 bad_revision = self.source_control.ResolveToRevision(
2329 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100) 2336 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100)
2330 good_revision = self.source_control.ResolveToRevision( 2337 good_revision = self.source_control.ResolveToRevision(
2331 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100) 2338 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100)
2332 2339
2333 os.chdir(cwd) 2340 os.chdir(cwd)
2334 2341
2335 if bad_revision is None: 2342 if bad_revision is None:
2336 results['error'] = 'Could\'t resolve [%s] to SHA1.' % (bad_revision_in,) 2343 results['error'] = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in
2337 return results 2344 return results
2338 2345
2339 if good_revision is None: 2346 if good_revision is None:
2340 results['error'] = 'Could\'t resolve [%s] to SHA1.' % (good_revision_in,) 2347 results['error'] = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in
2341 return results 2348 return results
2342 2349
2343 # Check that they didn't accidentally swap good and bad revisions. 2350 # Check that they didn't accidentally swap good and bad revisions.
2344 if not self.CheckIfRevisionsInProperOrder( 2351 if not self.CheckIfRevisionsInProperOrder(
2345 target_depot, good_revision, bad_revision): 2352 target_depot, good_revision, bad_revision):
2346 results['error'] = ('bad_revision < good_revision, did you swap these ' 2353 results['error'] = ('bad_revision < good_revision, did you swap these '
2347 'by mistake?') 2354 'by mistake?')
2348 return results 2355 return results
2349 2356
2350 bad_revision, good_revision = self.NudgeRevisionsIfDEPSChange( 2357 bad_revision, good_revision = self.NudgeRevisionsIfDEPSChange(
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
2615 return '' 2622 return ''
2616 2623
2617 def _PrintRevisionInfo(self, cl, info, depot=None): 2624 def _PrintRevisionInfo(self, cl, info, depot=None):
2618 email_info = '' 2625 email_info = ''
2619 if not info['email'].startswith(info['author']): 2626 if not info['email'].startswith(info['author']):
2620 email_info = '\nEmail : %s' % info['email'] 2627 email_info = '\nEmail : %s' % info['email']
2621 commit_link = self._GetViewVCLinkFromDepotAndHash(cl, depot) 2628 commit_link = self._GetViewVCLinkFromDepotAndHash(cl, depot)
2622 if commit_link: 2629 if commit_link:
2623 commit_info = '\nLink : %s' % commit_link 2630 commit_info = '\nLink : %s' % commit_link
2624 else: 2631 else:
2625 commit_info = ('\nFailed to parse svn revision from body:\n%s' % 2632 commit_info = ('\nFailed to parse SVN revision from body:\n%s' %
2626 info['body']) 2633 info['body'])
2627 print RESULTS_REVISION_INFO % { 2634 print RESULTS_REVISION_INFO % {
2628 'subject': info['subject'], 2635 'subject': info['subject'],
2629 'author': info['author'], 2636 'author': info['author'],
2630 'email_info': email_info, 2637 'email_info': email_info,
2631 'commit_info': commit_info, 2638 'commit_info': commit_info,
2632 'cl': cl, 2639 'cl': cl,
2633 'cl_date': info['date'] 2640 'cl_date': info['date']
2634 } 2641 }
2635 2642
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
3053 3060
3054 @staticmethod 3061 @staticmethod
3055 def _CreateCommandLineParser(): 3062 def _CreateCommandLineParser():
3056 """Creates a parser with bisect options. 3063 """Creates a parser with bisect options.
3057 3064
3058 Returns: 3065 Returns:
3059 An instance of optparse.OptionParser. 3066 An instance of optparse.OptionParser.
3060 """ 3067 """
3061 usage = ('%prog [options] [-- chromium-options]\n' 3068 usage = ('%prog [options] [-- chromium-options]\n'
3062 'Perform binary search on revision history to find a minimal ' 3069 'Perform binary search on revision history to find a minimal '
3063 'range of revisions where a peformance metric regressed.\n') 3070 'range of revisions where a performance metric regressed.\n')
3064 3071
3065 parser = optparse.OptionParser(usage=usage) 3072 parser = optparse.OptionParser(usage=usage)
3066 3073
3067 group = optparse.OptionGroup(parser, 'Bisect options') 3074 group = optparse.OptionGroup(parser, 'Bisect options')
3068 group.add_option('-c', '--command', 3075 group.add_option('-c', '--command',
3069 type='str', 3076 type='str',
3070 help='A command to execute your performance test at' + 3077 help='A command to execute your performance test at' +
3071 ' each point in the bisection.') 3078 ' each point in the bisection.')
3072 group.add_option('-b', '--bad_revision', 3079 group.add_option('-b', '--bad_revision',
3073 type='str', 3080 type='str',
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
3221 if not opts.bad_revision: 3228 if not opts.bad_revision:
3222 raise RuntimeError('missing required parameter: --bad_revision') 3229 raise RuntimeError('missing required parameter: --bad_revision')
3223 3230
3224 if not opts.metric and opts.bisect_mode != BISECT_MODE_RETURN_CODE: 3231 if not opts.metric and opts.bisect_mode != BISECT_MODE_RETURN_CODE:
3225 raise RuntimeError('missing required parameter: --metric') 3232 raise RuntimeError('missing required parameter: --metric')
3226 3233
3227 if opts.gs_bucket: 3234 if opts.gs_bucket:
3228 if not cloud_storage.List(opts.gs_bucket): 3235 if not cloud_storage.List(opts.gs_bucket):
3229 raise RuntimeError('Invalid Google Storage: gs://%s' % opts.gs_bucket) 3236 raise RuntimeError('Invalid Google Storage: gs://%s' % opts.gs_bucket)
3230 if not opts.builder_host: 3237 if not opts.builder_host:
3231 raise RuntimeError('Must specify try server hostname, when ' 3238 raise RuntimeError('Must specify try server host name using '
3232 'gs_bucket is used: --builder_host') 3239 '--builder_host when gs_bucket is used.')
3233 if not opts.builder_port: 3240 if not opts.builder_port:
3234 raise RuntimeError('Must specify try server port number, when ' 3241 raise RuntimeError('Must specify try server port number using '
3235 'gs_bucket is used: --builder_port') 3242 '--builder_port when gs_bucket is used.')
3236 if opts.target_platform == 'cros': 3243 if opts.target_platform == 'cros':
3237 # Run sudo up front to make sure credentials are cached for later. 3244 # Run sudo up front to make sure credentials are cached for later.
3238 print 'Sudo is required to build cros:' 3245 print 'Sudo is required to build cros:'
3239 print 3246 print
3240 bisect_utils.RunProcess(['sudo', 'true']) 3247 bisect_utils.RunProcess(['sudo', 'true'])
3241 3248
3242 if not opts.cros_board: 3249 if not opts.cros_board:
3243 raise RuntimeError('missing required parameter: --cros_board') 3250 raise RuntimeError('missing required parameter: --cros_board')
3244 3251
3245 if not opts.cros_remote_ip: 3252 if not opts.cros_remote_ip:
(...skipping 18 matching lines...) Expand all
3264 setattr(self, k, v) 3271 setattr(self, k, v)
3265 except RuntimeError, e: 3272 except RuntimeError, e:
3266 output_string = StringIO.StringIO() 3273 output_string = StringIO.StringIO()
3267 parser.print_help(file=output_string) 3274 parser.print_help(file=output_string)
3268 error_message = '%s\n\n%s' % (e.message, output_string.getvalue()) 3275 error_message = '%s\n\n%s' % (e.message, output_string.getvalue())
3269 output_string.close() 3276 output_string.close()
3270 raise RuntimeError(error_message) 3277 raise RuntimeError(error_message)
3271 3278
3272 @staticmethod 3279 @staticmethod
3273 def FromDict(values): 3280 def FromDict(values):
3274 """Creates an instance of BisectOptions with the values parsed from a 3281 """Creates an instance of BisectOptions from a dictionary.
3275 .cfg file.
3276 3282
3277 Args: 3283 Args:
3278 values: a dict containing options to set. 3284 values: a dict containing options to set.
3279 3285
3280 Returns: 3286 Returns:
3281 An instance of BisectOptions. 3287 An instance of BisectOptions.
3282 """ 3288 """
3283 opts = BisectOptions() 3289 opts = BisectOptions()
3284 for k, v in values.iteritems(): 3290 for k, v in values.iteritems():
3285 assert hasattr(opts, k), 'Invalid %s attribute in BisectOptions.' % k 3291 assert hasattr(opts, k), 'Invalid %s attribute in BisectOptions.' % k
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3356 # bugs. If you change this, please update the perf dashboard as well. 3362 # bugs. If you change this, please update the perf dashboard as well.
3357 bisect_utils.OutputAnnotationStepStart('Results') 3363 bisect_utils.OutputAnnotationStepStart('Results')
3358 print 'Error: %s' % e.message 3364 print 'Error: %s' % e.message
3359 if opts.output_buildbot_annotations: 3365 if opts.output_buildbot_annotations:
3360 bisect_utils.OutputAnnotationStepClosed() 3366 bisect_utils.OutputAnnotationStepClosed()
3361 return 1 3367 return 1
3362 3368
3363 3369
3364 if __name__ == '__main__': 3370 if __name__ == '__main__':
3365 sys.exit(main()) 3371 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/auto_bisect/source_control.py ('k') | tools/prepare-bisect-perf-regression.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698