| OLD | NEW |
| 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 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 import shlex | 45 import shlex |
| 46 import shutil | 46 import shutil |
| 47 import StringIO | 47 import StringIO |
| 48 import sys | 48 import sys |
| 49 import time | 49 import time |
| 50 import zipfile | 50 import zipfile |
| 51 | 51 |
| 52 sys.path.append(os.path.join(os.path.dirname(__file__), 'telemetry')) | 52 sys.path.append(os.path.join(os.path.dirname(__file__), 'telemetry')) |
| 53 | 53 |
| 54 from auto_bisect import bisect_utils | 54 from auto_bisect import bisect_utils |
| 55 from auto_bisect import builder |
| 55 from auto_bisect import math_utils | 56 from auto_bisect import math_utils |
| 56 from auto_bisect import post_perf_builder_job as bisect_builder | 57 from auto_bisect import post_perf_builder_job as bisect_builder |
| 57 from auto_bisect import source_control as source_control_module | 58 from auto_bisect import source_control as source_control_module |
| 58 from telemetry.util import cloud_storage | 59 from telemetry.util import cloud_storage |
| 59 | 60 |
| 60 # The additional repositories that might need to be bisected. | 61 # The additional repositories that might need to be bisected. |
| 61 # If the repository has any dependant repositories (such as skia/src needs | 62 # If the repository has any dependant repositories (such as skia/src needs |
| 62 # skia/include and skia/gyp to be updated), specify them in the 'depends' | 63 # skia/include and skia/gyp to be updated), specify them in the 'depends' |
| 63 # so that they're synced appropriately. | 64 # so that they're synced appropriately. |
| 64 # Format is: | 65 # Format is: |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 "svn" : "http://skia.googlecode.com/svn/trunk/gyp", | 138 "svn" : "http://skia.googlecode.com/svn/trunk/gyp", |
| 138 "depends" : None, | 139 "depends" : None, |
| 139 "from" : ['chromium'], | 140 "from" : ['chromium'], |
| 140 'viewvc': 'https://code.google.com/p/skia/source/detail?r=', | 141 'viewvc': 'https://code.google.com/p/skia/source/detail?r=', |
| 141 'deps_var': 'None' | 142 'deps_var': 'None' |
| 142 }, | 143 }, |
| 143 } | 144 } |
| 144 | 145 |
| 145 DEPOT_NAMES = DEPOT_DEPS_NAME.keys() | 146 DEPOT_NAMES = DEPOT_DEPS_NAME.keys() |
| 146 | 147 |
| 147 CROS_SDK_PATH = os.path.join('..', 'cros', 'chromite', 'bin', 'cros_sdk') | |
| 148 CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome' | 148 CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome' |
| 149 CROS_TEST_KEY_PATH = os.path.join('..', 'cros', 'chromite', 'ssh_keys', | |
| 150 'testing_rsa') | |
| 151 CROS_SCRIPT_KEY_PATH = os.path.join('..', 'cros', 'src', 'scripts', | |
| 152 'mod_for_test_scripts', 'ssh_keys', | |
| 153 'testing_rsa') | |
| 154 | 149 |
| 155 BUILD_RESULT_SUCCEED = 0 | 150 BUILD_RESULT_SUCCEED = 0 |
| 156 BUILD_RESULT_FAIL = 1 | 151 BUILD_RESULT_FAIL = 1 |
| 157 BUILD_RESULT_SKIPPED = 2 | 152 BUILD_RESULT_SKIPPED = 2 |
| 158 | 153 |
| 159 # Maximum time in seconds to wait after posting build request to tryserver. | 154 # Maximum time in seconds to wait after posting build request to tryserver. |
| 160 # TODO: Change these values based on the actual time taken by buildbots on | 155 # TODO: Change these values based on the actual time taken by buildbots on |
| 161 # the tryserver. | 156 # the tryserver. |
| 162 MAX_MAC_BUILD_TIME = 14400 | 157 MAX_MAC_BUILD_TIME = 14400 |
| 163 MAX_WIN_BUILD_TIME = 14400 | 158 MAX_WIN_BUILD_TIME = 14400 |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 for name in zf.namelist(): | 428 for name in zf.namelist(): |
| 434 if verbose: | 429 if verbose: |
| 435 print 'Extracting %s' % name | 430 print 'Extracting %s' % name |
| 436 zf.extract(name, output_dir) | 431 zf.extract(name, output_dir) |
| 437 if bisect_utils.IsMacHost(): | 432 if bisect_utils.IsMacHost(): |
| 438 # Restore permission bits. | 433 # Restore permission bits. |
| 439 os.chmod(os.path.join(output_dir, name), | 434 os.chmod(os.path.join(output_dir, name), |
| 440 zf.getinfo(name).external_attr >> 16L) | 435 zf.getinfo(name).external_attr >> 16L) |
| 441 | 436 |
| 442 | 437 |
| 443 | |
| 444 | |
| 445 def SetBuildSystemDefault(build_system, use_goma, goma_dir): | |
| 446 """Sets up any environment variables needed to build with the specified build | |
| 447 system. | |
| 448 | |
| 449 Args: | |
| 450 build_system: A string specifying build system. Currently only 'ninja' or | |
| 451 'make' are supported.""" | |
| 452 if build_system == 'ninja': | |
| 453 gyp_var = os.getenv('GYP_GENERATORS', default='') | |
| 454 | |
| 455 if not gyp_var or not 'ninja' in gyp_var: | |
| 456 if gyp_var: | |
| 457 os.environ['GYP_GENERATORS'] = gyp_var + ',ninja' | |
| 458 else: | |
| 459 os.environ['GYP_GENERATORS'] = 'ninja' | |
| 460 | |
| 461 if bisect_utils.IsWindowsHost(): | |
| 462 os.environ['GYP_DEFINES'] = 'component=shared_library '\ | |
| 463 'incremental_chrome_dll=1 disable_nacl=1 fastbuild=1 '\ | |
| 464 'chromium_win_pch=0' | |
| 465 | |
| 466 elif build_system == 'make': | |
| 467 os.environ['GYP_GENERATORS'] = 'make' | |
| 468 else: | |
| 469 raise RuntimeError('%s build not supported.' % build_system) | |
| 470 | |
| 471 if use_goma: | |
| 472 os.environ['GYP_DEFINES'] = '%s %s' % (os.getenv('GYP_DEFINES', default=''), | |
| 473 'use_goma=1') | |
| 474 if goma_dir: | |
| 475 os.environ['GYP_DEFINES'] += ' gomadir=%s' % goma_dir | |
| 476 | |
| 477 | |
| 478 def BuildWithMake(threads, targets, build_type='Release'): | |
| 479 cmd = ['make', 'BUILDTYPE=%s' % build_type] | |
| 480 | |
| 481 if threads: | |
| 482 cmd.append('-j%d' % threads) | |
| 483 | |
| 484 cmd += targets | |
| 485 | |
| 486 return_code = bisect_utils.RunProcess(cmd) | |
| 487 | |
| 488 return not return_code | |
| 489 | |
| 490 | |
| 491 def BuildWithNinja(threads, targets, build_type='Release'): | |
| 492 cmd = ['ninja', '-C', os.path.join('out', build_type)] | |
| 493 | |
| 494 if threads: | |
| 495 cmd.append('-j%d' % threads) | |
| 496 | |
| 497 cmd += targets | |
| 498 | |
| 499 return_code = bisect_utils.RunProcess(cmd) | |
| 500 | |
| 501 return not return_code | |
| 502 | |
| 503 | |
| 504 def BuildWithVisualStudio(targets, build_type='Release'): | |
| 505 path_to_devenv = os.path.abspath( | |
| 506 os.path.join(os.environ['VS100COMNTOOLS'], '..', 'IDE', 'devenv.com')) | |
| 507 path_to_sln = os.path.join(os.getcwd(), 'chrome', 'chrome.sln') | |
| 508 cmd = [path_to_devenv, '/build', build_type, path_to_sln] | |
| 509 | |
| 510 for t in targets: | |
| 511 cmd.extend(['/Project', t]) | |
| 512 | |
| 513 return_code = bisect_utils.RunProcess(cmd) | |
| 514 | |
| 515 return not return_code | |
| 516 | |
| 517 | |
| 518 def WriteStringToFile(text, file_name): | 438 def WriteStringToFile(text, file_name): |
| 519 try: | 439 try: |
| 520 with open(file_name, "wb") as f: | 440 with open(file_name, "wb") as f: |
| 521 f.write(text) | 441 f.write(text) |
| 522 except IOError as e: | 442 except IOError as e: |
| 523 raise RuntimeError('Error writing to file [%s]' % file_name ) | 443 raise RuntimeError('Error writing to file [%s]' % file_name ) |
| 524 | 444 |
| 525 | 445 |
| 526 def ReadStringFromFile(file_name): | 446 def ReadStringFromFile(file_name): |
| 527 try: | 447 try: |
| 528 with open(file_name) as f: | 448 with open(file_name) as f: |
| 529 return f.read() | 449 return f.read() |
| 530 except IOError as e: | 450 except IOError as e: |
| 531 raise RuntimeError('Error reading file [%s]' % file_name ) | 451 raise RuntimeError('Error reading file [%s]' % file_name ) |
| 532 | 452 |
| 533 | 453 |
| 534 def ChangeBackslashToSlashInPatch(diff_text): | 454 def ChangeBackslashToSlashInPatch(diff_text): |
| 535 """Formats file paths in the given text to unix-style paths.""" | 455 """Formats file paths in the given text to unix-style paths.""" |
| 536 if diff_text: | 456 if diff_text: |
| 537 diff_lines = diff_text.split('\n') | 457 diff_lines = diff_text.split('\n') |
| 538 for i in range(len(diff_lines)): | 458 for i in range(len(diff_lines)): |
| 539 if (diff_lines[i].startswith('--- ') or | 459 if (diff_lines[i].startswith('--- ') or |
| 540 diff_lines[i].startswith('+++ ')): | 460 diff_lines[i].startswith('+++ ')): |
| 541 diff_lines[i] = diff_lines[i].replace('\\', '/') | 461 diff_lines[i] = diff_lines[i].replace('\\', '/') |
| 542 return '\n'.join(diff_lines) | 462 return '\n'.join(diff_lines) |
| 543 return None | 463 return None |
| 544 | 464 |
| 545 | 465 |
| 546 class Builder(object): | |
| 547 """Builder is used by the bisect script to build relevant targets and deploy. | |
| 548 """ | |
| 549 def __init__(self, opts): | |
| 550 """Performs setup for building with target build system. | |
| 551 | |
| 552 Args: | |
| 553 opts: Options parsed from command line. | |
| 554 """ | |
| 555 if bisect_utils.IsWindowsHost(): | |
| 556 if not opts.build_preference: | |
| 557 opts.build_preference = 'msvs' | |
| 558 | |
| 559 if opts.build_preference == 'msvs': | |
| 560 if not os.getenv('VS100COMNTOOLS'): | |
| 561 raise RuntimeError( | |
| 562 'Path to visual studio could not be determined.') | |
| 563 else: | |
| 564 SetBuildSystemDefault(opts.build_preference, opts.use_goma, | |
| 565 opts.goma_dir) | |
| 566 else: | |
| 567 if not opts.build_preference: | |
| 568 if 'ninja' in os.getenv('GYP_GENERATORS', default=''): | |
| 569 opts.build_preference = 'ninja' | |
| 570 else: | |
| 571 opts.build_preference = 'make' | |
| 572 | |
| 573 SetBuildSystemDefault(opts.build_preference, opts.use_goma, opts.goma_dir) | |
| 574 | |
| 575 if not bisect_utils.SetupPlatformBuildEnvironment(opts): | |
| 576 raise RuntimeError('Failed to set platform environment.') | |
| 577 | |
| 578 @staticmethod | |
| 579 def FromOpts(opts): | |
| 580 builder = None | |
| 581 if opts.target_platform == 'cros': | |
| 582 builder = CrosBuilder(opts) | |
| 583 elif opts.target_platform == 'android': | |
| 584 builder = AndroidBuilder(opts) | |
| 585 elif opts.target_platform == 'android-chrome': | |
| 586 builder = AndroidChromeBuilder(opts) | |
| 587 else: | |
| 588 builder = DesktopBuilder(opts) | |
| 589 return builder | |
| 590 | |
| 591 def Build(self, depot, opts): | |
| 592 raise NotImplementedError() | |
| 593 | |
| 594 def GetBuildOutputDirectory(self, opts, src_dir=None): | |
| 595 """Returns the path to the build directory, relative to the checkout root. | |
| 596 | |
| 597 Assumes that the current working directory is the checkout root. | |
| 598 """ | |
| 599 src_dir = src_dir or 'src' | |
| 600 if opts.build_preference == 'ninja' or bisect_utils.IsLinuxHost(): | |
| 601 return os.path.join(src_dir, 'out') | |
| 602 if bisect_utils.IsMacHost(): | |
| 603 return os.path.join(src_dir, 'xcodebuild') | |
| 604 if bisect_utils.IsWindowsHost(): | |
| 605 return os.path.join(src_dir, 'build') | |
| 606 raise NotImplementedError('Unexpected platform %s' % sys.platform) | |
| 607 | |
| 608 | |
| 609 class DesktopBuilder(Builder): | |
| 610 """DesktopBuilder is used to build Chromium on linux/mac/windows.""" | |
| 611 def __init__(self, opts): | |
| 612 super(DesktopBuilder, self).__init__(opts) | |
| 613 | |
| 614 def Build(self, depot, opts): | |
| 615 """Builds chromium_builder_perf target using options passed into | |
| 616 the script. | |
| 617 | |
| 618 Args: | |
| 619 depot: Current depot being bisected. | |
| 620 opts: The options parsed from the command line. | |
| 621 | |
| 622 Returns: | |
| 623 True if build was successful. | |
| 624 """ | |
| 625 targets = ['chromium_builder_perf'] | |
| 626 | |
| 627 threads = None | |
| 628 if opts.use_goma: | |
| 629 threads = 64 | |
| 630 | |
| 631 build_success = False | |
| 632 if opts.build_preference == 'make': | |
| 633 build_success = BuildWithMake(threads, targets, opts.target_build_type) | |
| 634 elif opts.build_preference == 'ninja': | |
| 635 build_success = BuildWithNinja(threads, targets, opts.target_build_type) | |
| 636 elif opts.build_preference == 'msvs': | |
| 637 assert bisect_utils.IsWindowsHost(), 'msvs is only supported on Windows.' | |
| 638 build_success = BuildWithVisualStudio(targets, opts.target_build_type) | |
| 639 else: | |
| 640 assert False, 'No build system defined.' | |
| 641 return build_success | |
| 642 | |
| 643 | |
| 644 class AndroidBuilder(Builder): | |
| 645 """AndroidBuilder is used to build on android.""" | |
| 646 def __init__(self, opts): | |
| 647 super(AndroidBuilder, self).__init__(opts) | |
| 648 | |
| 649 def _GetTargets(self): | |
| 650 return ['chrome_shell_apk', 'cc_perftests_apk', 'android_tools'] | |
| 651 | |
| 652 def Build(self, depot, opts): | |
| 653 """Builds the android content shell and other necessary tools using options | |
| 654 passed into the script. | |
| 655 | |
| 656 Args: | |
| 657 depot: Current depot being bisected. | |
| 658 opts: The options parsed from the command line. | |
| 659 | |
| 660 Returns: | |
| 661 True if build was successful. | |
| 662 """ | |
| 663 threads = None | |
| 664 if opts.use_goma: | |
| 665 threads = 64 | |
| 666 | |
| 667 build_success = False | |
| 668 if opts.build_preference == 'ninja': | |
| 669 build_success = BuildWithNinja( | |
| 670 threads, self._GetTargets(), opts.target_build_type) | |
| 671 else: | |
| 672 assert False, 'No build system defined.' | |
| 673 | |
| 674 return build_success | |
| 675 | |
| 676 | |
| 677 class AndroidChromeBuilder(AndroidBuilder): | |
| 678 """AndroidBuilder is used to build on android's chrome.""" | |
| 679 def __init__(self, opts): | |
| 680 super(AndroidChromeBuilder, self).__init__(opts) | |
| 681 | |
| 682 def _GetTargets(self): | |
| 683 return AndroidBuilder._GetTargets(self) + ['chrome_apk'] | |
| 684 | |
| 685 | |
| 686 class CrosBuilder(Builder): | |
| 687 """CrosBuilder is used to build and image ChromeOS/Chromium when cros is the | |
| 688 target platform.""" | |
| 689 def __init__(self, opts): | |
| 690 super(CrosBuilder, self).__init__(opts) | |
| 691 | |
| 692 def ImageToTarget(self, opts): | |
| 693 """Installs latest image to target specified by opts.cros_remote_ip. | |
| 694 | |
| 695 Args: | |
| 696 opts: Program options containing cros_board and cros_remote_ip. | |
| 697 | |
| 698 Returns: | |
| 699 True if successful. | |
| 700 """ | |
| 701 try: | |
| 702 # Keys will most likely be set to 0640 after wiping the chroot. | |
| 703 os.chmod(CROS_SCRIPT_KEY_PATH, 0600) | |
| 704 os.chmod(CROS_TEST_KEY_PATH, 0600) | |
| 705 cmd = [CROS_SDK_PATH, '--', './bin/cros_image_to_target.py', | |
| 706 '--remote=%s' % opts.cros_remote_ip, | |
| 707 '--board=%s' % opts.cros_board, '--test', '--verbose'] | |
| 708 | |
| 709 return_code = bisect_utils.RunProcess(cmd) | |
| 710 return not return_code | |
| 711 except OSError, e: | |
| 712 return False | |
| 713 | |
| 714 def BuildPackages(self, opts, depot): | |
| 715 """Builds packages for cros. | |
| 716 | |
| 717 Args: | |
| 718 opts: Program options containing cros_board. | |
| 719 depot: The depot being bisected. | |
| 720 | |
| 721 Returns: | |
| 722 True if successful. | |
| 723 """ | |
| 724 cmd = [CROS_SDK_PATH] | |
| 725 | |
| 726 if depot != 'cros': | |
| 727 path_to_chrome = os.path.join(os.getcwd(), '..') | |
| 728 cmd += ['--chrome_root=%s' % path_to_chrome] | |
| 729 | |
| 730 cmd += ['--'] | |
| 731 | |
| 732 if depot != 'cros': | |
| 733 cmd += ['CHROME_ORIGIN=LOCAL_SOURCE'] | |
| 734 | |
| 735 cmd += ['BUILDTYPE=%s' % opts.target_build_type, './build_packages', | |
| 736 '--board=%s' % opts.cros_board] | |
| 737 return_code = bisect_utils.RunProcess(cmd) | |
| 738 | |
| 739 return not return_code | |
| 740 | |
| 741 def BuildImage(self, opts, depot): | |
| 742 """Builds test image for cros. | |
| 743 | |
| 744 Args: | |
| 745 opts: Program options containing cros_board. | |
| 746 depot: The depot being bisected. | |
| 747 | |
| 748 Returns: | |
| 749 True if successful. | |
| 750 """ | |
| 751 cmd = [CROS_SDK_PATH] | |
| 752 | |
| 753 if depot != 'cros': | |
| 754 path_to_chrome = os.path.join(os.getcwd(), '..') | |
| 755 cmd += ['--chrome_root=%s' % path_to_chrome] | |
| 756 | |
| 757 cmd += ['--'] | |
| 758 | |
| 759 if depot != 'cros': | |
| 760 cmd += ['CHROME_ORIGIN=LOCAL_SOURCE'] | |
| 761 | |
| 762 cmd += ['BUILDTYPE=%s' % opts.target_build_type, '--', './build_image', | |
| 763 '--board=%s' % opts.cros_board, 'test'] | |
| 764 | |
| 765 return_code = bisect_utils.RunProcess(cmd) | |
| 766 | |
| 767 return not return_code | |
| 768 | |
| 769 def Build(self, depot, opts): | |
| 770 """Builds targets using options passed into the script. | |
| 771 | |
| 772 Args: | |
| 773 depot: Current depot being bisected. | |
| 774 opts: The options parsed from the command line. | |
| 775 | |
| 776 Returns: | |
| 777 True if build was successful. | |
| 778 """ | |
| 779 if self.BuildPackages(opts, depot): | |
| 780 if self.BuildImage(opts, depot): | |
| 781 return self.ImageToTarget(opts) | |
| 782 return False | |
| 783 | |
| 784 | |
| 785 | |
| 786 | |
| 787 class BisectPerformanceMetrics(object): | 466 class BisectPerformanceMetrics(object): |
| 788 """This class contains functionality to perform a bisection of a range of | 467 """This class contains functionality to perform a bisection of a range of |
| 789 revisions to narrow down where performance regressions may have occurred. | 468 revisions to narrow down where performance regressions may have occurred. |
| 790 | 469 |
| 791 The main entry-point is the Run method. | 470 The main entry-point is the Run method. |
| 792 """ | 471 """ |
| 793 | 472 |
| 794 def __init__(self, source_control, opts): | 473 def __init__(self, source_control, opts): |
| 795 super(BisectPerformanceMetrics, self).__init__() | 474 super(BisectPerformanceMetrics, self).__init__() |
| 796 | 475 |
| 797 self.opts = opts | 476 self.opts = opts |
| 798 self.source_control = source_control | 477 self.source_control = source_control |
| 799 self.src_cwd = os.getcwd() | 478 self.src_cwd = os.getcwd() |
| 800 self.cros_cwd = os.path.join(os.getcwd(), '..', 'cros') | 479 self.cros_cwd = os.path.join(os.getcwd(), '..', 'cros') |
| 801 self.depot_cwd = {} | 480 self.depot_cwd = {} |
| 802 self.cleanup_commands = [] | 481 self.cleanup_commands = [] |
| 803 self.warnings = [] | 482 self.warnings = [] |
| 804 self.builder = Builder.FromOpts(opts) | 483 self.builder = builder.Builder.FromOpts(opts) |
| 805 | 484 |
| 806 # This always starts true since the script grabs latest first. | 485 # This always starts true since the script grabs latest first. |
| 807 self.was_blink = True | 486 self.was_blink = True |
| 808 | 487 |
| 809 for d in DEPOT_NAMES: | 488 for d in DEPOT_NAMES: |
| 810 # The working directory of each depot is just the path to the depot, but | 489 # The working directory of each depot is just the path to the depot, but |
| 811 # since we're already in 'src', we can skip that part. | 490 # since we're already in 'src', we can skip that part. |
| 812 | 491 |
| 813 self.depot_cwd[d] = os.path.join( | 492 self.depot_cwd[d] = os.path.join( |
| 814 self.src_cwd, DEPOT_DEPS_NAME[d]['src'][4:]) | 493 self.src_cwd, DEPOT_DEPS_NAME[d]['src'][4:]) |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 """ | 712 """ |
| 1034 cwd = os.getcwd() | 713 cwd = os.getcwd() |
| 1035 self.ChangeToDepotWorkingDirectory(depot) | 714 self.ChangeToDepotWorkingDirectory(depot) |
| 1036 | 715 |
| 1037 results = {} | 716 results = {} |
| 1038 | 717 |
| 1039 if depot == 'chromium' or depot == 'android-chrome': | 718 if depot == 'chromium' or depot == 'android-chrome': |
| 1040 results = self._ParseRevisionsFromDEPSFile(depot) | 719 results = self._ParseRevisionsFromDEPSFile(depot) |
| 1041 os.chdir(cwd) | 720 os.chdir(cwd) |
| 1042 elif depot == 'cros': | 721 elif depot == 'cros': |
| 1043 cmd = [CROS_SDK_PATH, '--', 'portageq-%s' % self.opts.cros_board, | 722 cmd = [ |
| 1044 'best_visible', '/build/%s' % self.opts.cros_board, 'ebuild', | 723 bisect_utils.CROS_SDK_PATH, |
| 1045 CROS_CHROMEOS_PATTERN] | 724 '--', |
| 725 'portageq-%s' % self.opts.cros_board, |
| 726 'best_visible', |
| 727 '/build/%s' % self.opts.cros_board, |
| 728 'ebuild', |
| 729 CROS_CHROMEOS_PATTERN |
| 730 ] |
| 1046 (output, return_code) = bisect_utils.RunProcessAndRetrieveOutput(cmd) | 731 (output, return_code) = bisect_utils.RunProcessAndRetrieveOutput(cmd) |
| 1047 | 732 |
| 1048 assert not return_code, 'An error occurred while running' \ | 733 assert not return_code, 'An error occurred while running' \ |
| 1049 ' "%s"' % ' '.join(cmd) | 734 ' "%s"' % ' '.join(cmd) |
| 1050 | 735 |
| 1051 if len(output) > CROS_CHROMEOS_PATTERN: | 736 if len(output) > CROS_CHROMEOS_PATTERN: |
| 1052 output = output[len(CROS_CHROMEOS_PATTERN):] | 737 output = output[len(CROS_CHROMEOS_PATTERN):] |
| 1053 | 738 |
| 1054 if len(output) > 1: | 739 if len(output) > 1: |
| 1055 output = output.split('_')[0] | 740 output = output.split('_')[0] |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1086 """Backs up or restores build output directory based on restore argument. | 771 """Backs up or restores build output directory based on restore argument. |
| 1087 | 772 |
| 1088 Args: | 773 Args: |
| 1089 restore: Indicates whether to restore or backup. Default is False(Backup) | 774 restore: Indicates whether to restore or backup. Default is False(Backup) |
| 1090 build_type: Target build type ('Release', 'Debug', 'Release_x64' etc.) | 775 build_type: Target build type ('Release', 'Debug', 'Release_x64' etc.) |
| 1091 | 776 |
| 1092 Returns: | 777 Returns: |
| 1093 Path to backup or restored location as string. otherwise None if it fails. | 778 Path to backup or restored location as string. otherwise None if it fails. |
| 1094 """ | 779 """ |
| 1095 build_dir = os.path.abspath( | 780 build_dir = os.path.abspath( |
| 1096 self.builder.GetBuildOutputDirectory(self.opts, self.src_cwd)) | 781 builder.GetBuildOutputDirectory(self.opts, self.src_cwd)) |
| 1097 source_dir = os.path.join(build_dir, build_type) | 782 source_dir = os.path.join(build_dir, build_type) |
| 1098 destination_dir = os.path.join(build_dir, '%s.bak' % build_type) | 783 destination_dir = os.path.join(build_dir, '%s.bak' % build_type) |
| 1099 if restore: | 784 if restore: |
| 1100 source_dir, destination_dir = destination_dir, source_dir | 785 source_dir, destination_dir = destination_dir, source_dir |
| 1101 if os.path.exists(source_dir): | 786 if os.path.exists(source_dir): |
| 1102 RmTreeAndMkDir(destination_dir, skip_makedir=True) | 787 RmTreeAndMkDir(destination_dir, skip_makedir=True) |
| 1103 shutil.move(source_dir, destination_dir) | 788 shutil.move(source_dir, destination_dir) |
| 1104 return destination_dir | 789 return destination_dir |
| 1105 return None | 790 return None |
| 1106 | 791 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 if patch: | 835 if patch: |
| 1151 # Get the SHA of the DEPS changes patch. | 836 # Get the SHA of the DEPS changes patch. |
| 1152 patch_sha = GetSHA1HexDigest(patch) | 837 patch_sha = GetSHA1HexDigest(patch) |
| 1153 | 838 |
| 1154 # Update the DEPS changes patch with a patch to create a new file named | 839 # Update the DEPS changes patch with a patch to create a new file named |
| 1155 # 'DEPS.sha' and add patch_sha evaluated above to it. | 840 # 'DEPS.sha' and add patch_sha evaluated above to it. |
| 1156 patch = '%s\n%s' % (patch, DEPS_SHA_PATCH % {'deps_sha': patch_sha}) | 841 patch = '%s\n%s' % (patch, DEPS_SHA_PATCH % {'deps_sha': patch_sha}) |
| 1157 | 842 |
| 1158 # Get Build output directory | 843 # Get Build output directory |
| 1159 abs_build_dir = os.path.abspath( | 844 abs_build_dir = os.path.abspath( |
| 1160 self.builder.GetBuildOutputDirectory(self.opts, self.src_cwd)) | 845 builder.GetBuildOutputDirectory(self.opts, self.src_cwd)) |
| 1161 | 846 |
| 1162 fetch_build_func = lambda: self.GetBuildArchiveForRevision( | 847 fetch_build_func = lambda: self.GetBuildArchiveForRevision( |
| 1163 revision, self.opts.gs_bucket, self.opts.target_arch, | 848 revision, self.opts.gs_bucket, self.opts.target_arch, |
| 1164 patch_sha, abs_build_dir) | 849 patch_sha, abs_build_dir) |
| 1165 | 850 |
| 1166 # Downloaded archive file path, downloads build archive for given revision. | 851 # Downloaded archive file path, downloads build archive for given revision. |
| 1167 downloaded_file = fetch_build_func() | 852 downloaded_file = fetch_build_func() |
| 1168 | 853 |
| 1169 # When build archive doesn't exists, post a build request to tryserver | 854 # When build archive doesn't exists, post a build request to tryserver |
| 1170 # and wait for the build to be produced. | 855 # and wait for the build to be produced. |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1791 | 1476 |
| 1792 if not self._GenerateProfileIfNecessary(args): | 1477 if not self._GenerateProfileIfNecessary(args): |
| 1793 err_text = 'Failed to generate profile for performance test.' | 1478 err_text = 'Failed to generate profile for performance test.' |
| 1794 return (err_text, failure_code) | 1479 return (err_text, failure_code) |
| 1795 | 1480 |
| 1796 # If running a Telemetry test for Chrome OS, insert the remote IP and | 1481 # If running a Telemetry test for Chrome OS, insert the remote IP and |
| 1797 # identity parameters. | 1482 # identity parameters. |
| 1798 is_telemetry = bisect_utils.IsTelemetryCommand(command_to_run) | 1483 is_telemetry = bisect_utils.IsTelemetryCommand(command_to_run) |
| 1799 if self.opts.target_platform == 'cros' and is_telemetry: | 1484 if self.opts.target_platform == 'cros' and is_telemetry: |
| 1800 args.append('--remote=%s' % self.opts.cros_remote_ip) | 1485 args.append('--remote=%s' % self.opts.cros_remote_ip) |
| 1801 args.append('--identity=%s' % CROS_TEST_KEY_PATH) | 1486 args.append('--identity=%s' % bisect_utils.CROS_TEST_KEY_PATH) |
| 1802 | 1487 |
| 1803 start_time = time.time() | 1488 start_time = time.time() |
| 1804 | 1489 |
| 1805 metric_values = [] | 1490 metric_values = [] |
| 1806 output_of_all_runs = '' | 1491 output_of_all_runs = '' |
| 1807 for i in xrange(self.opts.repeat_test_count): | 1492 for i in xrange(self.opts.repeat_test_count): |
| 1808 # Can ignore the return code since if the tests fail, it won't return 0. | 1493 # Can ignore the return code since if the tests fail, it won't return 0. |
| 1809 current_args = copy.copy(args) | 1494 current_args = copy.copy(args) |
| 1810 if is_telemetry: | 1495 if is_telemetry: |
| 1811 if i == 0 and reset_on_first_run: | 1496 if i == 0 and reset_on_first_run: |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1984 return True | 1669 return True |
| 1985 | 1670 |
| 1986 def PerformCrosChrootCleanup(self): | 1671 def PerformCrosChrootCleanup(self): |
| 1987 """Deletes the chroot. | 1672 """Deletes the chroot. |
| 1988 | 1673 |
| 1989 Returns: | 1674 Returns: |
| 1990 True if successful. | 1675 True if successful. |
| 1991 """ | 1676 """ |
| 1992 cwd = os.getcwd() | 1677 cwd = os.getcwd() |
| 1993 self.ChangeToDepotWorkingDirectory('cros') | 1678 self.ChangeToDepotWorkingDirectory('cros') |
| 1994 cmd = [CROS_SDK_PATH, '--delete'] | 1679 cmd = [bisect_utils.CROS_SDK_PATH, '--delete'] |
| 1995 return_code = bisect_utils.RunProcess(cmd) | 1680 return_code = bisect_utils.RunProcess(cmd) |
| 1996 os.chdir(cwd) | 1681 os.chdir(cwd) |
| 1997 return not return_code | 1682 return not return_code |
| 1998 | 1683 |
| 1999 def CreateCrosChroot(self): | 1684 def CreateCrosChroot(self): |
| 2000 """Creates a new chroot. | 1685 """Creates a new chroot. |
| 2001 | 1686 |
| 2002 Returns: | 1687 Returns: |
| 2003 True if successful. | 1688 True if successful. |
| 2004 """ | 1689 """ |
| 2005 cwd = os.getcwd() | 1690 cwd = os.getcwd() |
| 2006 self.ChangeToDepotWorkingDirectory('cros') | 1691 self.ChangeToDepotWorkingDirectory('cros') |
| 2007 cmd = [CROS_SDK_PATH, '--create'] | 1692 cmd = [bisect_utils.CROS_SDK_PATH, '--create'] |
| 2008 return_code = bisect_utils.RunProcess(cmd) | 1693 return_code = bisect_utils.RunProcess(cmd) |
| 2009 os.chdir(cwd) | 1694 os.chdir(cwd) |
| 2010 return not return_code | 1695 return not return_code |
| 2011 | 1696 |
| 2012 def PerformPreSyncCleanup(self, revision, depot): | 1697 def PerformPreSyncCleanup(self, revision, depot): |
| 2013 """Performs any necessary cleanup before syncing. | 1698 """Performs any necessary cleanup before syncing. |
| 2014 | 1699 |
| 2015 Returns: | 1700 Returns: |
| 2016 True if successful. | 1701 True if successful. |
| 2017 """ | 1702 """ |
| (...skipping 1640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3658 # bugs. If you change this, please update the perf dashboard as well. | 3343 # bugs. If you change this, please update the perf dashboard as well. |
| 3659 bisect_utils.OutputAnnotationStepStart('Results') | 3344 bisect_utils.OutputAnnotationStepStart('Results') |
| 3660 print 'Error: %s' % e.message | 3345 print 'Error: %s' % e.message |
| 3661 if opts.output_buildbot_annotations: | 3346 if opts.output_buildbot_annotations: |
| 3662 bisect_utils.OutputAnnotationStepClosed() | 3347 bisect_utils.OutputAnnotationStepClosed() |
| 3663 return 1 | 3348 return 1 |
| 3664 | 3349 |
| 3665 | 3350 |
| 3666 if __name__ == '__main__': | 3351 if __name__ == '__main__': |
| 3667 sys.exit(main()) | 3352 sys.exit(main()) |
| OLD | NEW |