Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 """Snapshot Build Bisect Tool | 6 """Snapshot Build Bisect Tool |
| 7 | 7 |
| 8 This script bisects a snapshot archive using binary search. It starts at | 8 This script bisects a snapshot archive using binary search. It starts at |
| 9 a bad revision (it will try to guess HEAD) and asks for a last known-good | 9 a bad revision (it will try to guess HEAD) and asks for a last known-good |
| 10 revision. It will then binary search across this revision range by downloading, | 10 revision. It will then binary search across this revision range by downloading, |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 | 293 |
| 294 download_url = context.GetDownloadURL(rev) | 294 download_url = context.GetDownloadURL(rev) |
| 295 try: | 295 try: |
| 296 urllib.urlretrieve(download_url, filename, ReportHook) | 296 urllib.urlretrieve(download_url, filename, ReportHook) |
| 297 if progress_event and progress_event.isSet(): | 297 if progress_event and progress_event.isSet(): |
| 298 print | 298 print |
| 299 except RuntimeError, e: | 299 except RuntimeError, e: |
| 300 pass | 300 pass |
| 301 | 301 |
| 302 | 302 |
| 303 def RunRevision(context, revision, zipfile, profile, num_runs, args): | 303 def RunRevision(context, revision, zipfile, num_runs, testargs, tempdir, |
| 304 outdir=None): | |
|
Ian Vollick
2012/09/18 17:46:32
Why is tempdir a parameter? It doesn't look like g
hartmanng
2012/09/19 02:17:55
Done.
| |
| 304 """Given a zipped revision, unzip it and run the test.""" | 305 """Given a zipped revision, unzip it and run the test.""" |
| 305 print "Trying revision %s..." % str(revision) | 306 print "Trying revision %s..." % str(revision) |
| 306 | 307 |
| 307 # Create a temp directory and unzip the revision into it. | |
| 308 cwd = os.getcwd() | |
| 309 tempdir = tempfile.mkdtemp(prefix='bisect_tmp') | |
| 310 UnzipFilenameToDir(zipfile, tempdir) | 308 UnzipFilenameToDir(zipfile, tempdir) |
| 311 os.chdir(tempdir) | |
| 312 | 309 |
| 313 # Run the build as many times as specified. | |
| 314 testargs = [context.GetLaunchPath(), '--user-data-dir=%s' % profile] + args | |
| 315 # The sandbox must be run as root on Official Chrome, so bypass it. | 310 # The sandbox must be run as root on Official Chrome, so bypass it. |
| 316 if context.is_official and (context.platform == 'linux' or | 311 if context.is_official and (context.platform == 'linux' or |
| 317 context.platform == 'linux64'): | 312 context.platform == 'linux64'): |
| 318 testargs.append('--no-sandbox') | 313 testargs.append('--no-sandbox') |
| 319 | 314 |
| 315 # Run the build as many times as specified. | |
| 320 for i in range(0, num_runs): | 316 for i in range(0, num_runs): |
| 321 subproc = subprocess.Popen(testargs, | 317 subproc = subprocess.Popen(testargs, |
| 322 bufsize=-1, | 318 bufsize=-1, |
| 323 stdout=subprocess.PIPE, | 319 stdout=subprocess.PIPE, |
| 324 stderr=subprocess.PIPE) | 320 stderr=subprocess.PIPE) |
| 325 (stdout, stderr) = subproc.communicate() | 321 (stdout, stderr) = subproc.communicate() |
| 326 | 322 |
| 327 os.chdir(cwd) | 323 if outdir is not None: |
| 328 try: | 324 if not os.path.isdir(outdir): |
| 329 shutil.rmtree(tempdir, True) | 325 os.mkdir(outdir) |
| 330 except Exception, e: | 326 |
| 331 pass | 327 fout = open(os.path.join(outdir, '%s_%s.out' % (str(revision), str(i))), |
| 328 'w') | |
| 329 fout.write(stdout) | |
| 330 fout.close() | |
| 331 ferr = open(os.path.join(outdir, '%s_%s.err' % (str(revision), str(i))), | |
| 332 'w') | |
| 333 ferr.write(stderr) | |
| 334 ferr.close() | |
|
Ian Vollick
2012/09/18 17:46:32
It looks like we shutil.rmtree after every call to
hartmanng
2012/09/19 02:17:55
Done.
| |
| 332 | 335 |
| 333 return (subproc.returncode, stdout, stderr) | 336 return (subproc.returncode, stdout, stderr) |
| 334 | 337 |
| 335 | 338 |
| 336 def AskIsGoodBuild(rev, official_builds, status, stdout, stderr): | 339 def AskIsGoodBuild(rev, official_builds, status, stdout, stderr): |
| 337 """Ask the user whether build |rev| is good or bad.""" | 340 """Ask the user whether build |rev| is good or bad.""" |
| 338 # Loop until we get a response that we can parse. | 341 # Loop until we get a response that we can parse. |
| 339 while True: | 342 while True: |
| 340 response = raw_input('Revision %s is [(g)ood/(b)ad/(u)nknown/(q)uit]: ' % | 343 response = raw_input('Revision %s is [(g)ood/(b)ad/(u)nknown/(q)uit]: ' % |
| 341 str(rev)) | 344 str(rev)) |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 | 472 |
| 470 up_pivot = int((bad - pivot) / 2) + pivot | 473 up_pivot = int((bad - pivot) / 2) + pivot |
| 471 up_fetch = None | 474 up_fetch = None |
| 472 if up_pivot != pivot and up_pivot != bad: | 475 if up_pivot != pivot and up_pivot != bad: |
| 473 up_rev = revlist[up_pivot] | 476 up_rev = revlist[up_pivot] |
| 474 up_fetch = DownloadJob(context, 'up_fetch', up_rev, | 477 up_fetch = DownloadJob(context, 'up_fetch', up_rev, |
| 475 _GetDownloadPath(up_rev)) | 478 _GetDownloadPath(up_rev)) |
| 476 up_fetch.Start() | 479 up_fetch.Start() |
| 477 | 480 |
| 478 # Run test on the pivot revision. | 481 # Run test on the pivot revision. |
| 482 tempdir = tempfile.mkdtemp(prefix='bisect_tmp') | |
| 483 testargs = [os.path.join(tempdir, context.GetLaunchPath()), | |
| 484 '--user-data-dir=%s' % profile] + try_args | |
| 479 (status, stdout, stderr) = RunRevision(context, | 485 (status, stdout, stderr) = RunRevision(context, |
| 480 rev, | 486 rev, |
| 481 zipfile, | 487 zipfile, |
| 482 profile, | |
| 483 num_runs, | 488 num_runs, |
| 484 try_args) | 489 testargs, |
| 490 tempdir) | |
| 491 try: | |
| 492 shutil.rmtree(tempdir, True) | |
| 493 except Exception, e: | |
| 494 pass | |
| 495 | |
| 485 os.unlink(zipfile) | 496 os.unlink(zipfile) |
| 486 zipfile = None | 497 zipfile = None |
| 487 | 498 |
| 488 # Call the evaluate function to see if the current revision is good or bad. | 499 # Call the evaluate function to see if the current revision is good or bad. |
| 489 # On that basis, kill one of the background downloads and complete the | 500 # On that basis, kill one of the background downloads and complete the |
| 490 # other, as described in the comments above. | 501 # other, as described in the comments above. |
| 491 try: | 502 try: |
| 492 answer = evaluate(rev, official_builds, status, stdout, stderr) | 503 answer = evaluate(rev, official_builds, status, stdout, stderr) |
| 493 if answer == 'g': | 504 if answer == 'g': |
| 494 good = pivot | 505 good = pivot |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 669 print ' ' + WEBKIT_CHANGELOG_URL % (first_known_bad_webkit_rev, | 680 print ' ' + WEBKIT_CHANGELOG_URL % (first_known_bad_webkit_rev, |
| 670 last_known_good_webkit_rev) | 681 last_known_good_webkit_rev) |
| 671 print 'CHANGELOG URL:' | 682 print 'CHANGELOG URL:' |
| 672 if opts.official_builds: | 683 if opts.official_builds: |
| 673 print OFFICIAL_CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev) | 684 print OFFICIAL_CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev) |
| 674 else: | 685 else: |
| 675 print ' ' + CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev) | 686 print ' ' + CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev) |
| 676 | 687 |
| 677 if __name__ == '__main__': | 688 if __name__ == '__main__': |
| 678 sys.exit(main()) | 689 sys.exit(main()) |
| OLD | NEW |