| #!/usr/bin/python |
| # |
| # Copyright 2011 Google Inc. All Rights Reserved. |
| """Script to profile a page cycler, and get it back to the host.""" |
| |
| import copy |
| import optparse |
| import os |
| import pickle |
| import re |
| import sys |
| import tempfile |
| import time |
| |
| import build_chrome_browser |
| import cros_login |
| import lock_machine |
| import run_tests |
| from cros_utils import command_executer |
| from cros_utils import logger |
| from cros_utils import misc |
| |
| |
| class CyclerProfiler: |
| REMOTE_TMP_DIR = '/tmp' |
| |
| def __init__(self, chromeos_root, board, cycler, profile_dir, remote): |
| self._chromeos_root = chromeos_root |
| self._cycler = cycler |
| self._profile_dir = profile_dir |
| self._remote = remote |
| self._board = board |
| self._ce = command_executer.GetCommandExecuter() |
| self._l = logger.GetLogger() |
| |
| self._gcov_prefix = os.path.join(self.REMOTE_TMP_DIR, self._GetProfileDir()) |
| |
| def _GetProfileDir(self): |
| return misc.GetCtargetFromBoard(self._board, self._chromeos_root) |
| |
| def _CopyTestData(self): |
| page_cycler_dir = os.path.join(self._chromeos_root, 'distfiles', 'target', |
| 'chrome-src-internal', 'src', 'data', |
| 'page_cycler') |
| if not os.path.isdir(page_cycler_dir): |
| raise RuntimeError('Page cycler dir %s not found!' % page_cycler_dir) |
| self._ce.CopyFiles(page_cycler_dir, |
| os.path.join(self.REMOTE_TMP_DIR, 'page_cycler'), |
| dest_machine=self._remote, |
| chromeos_root=self._chromeos_root, |
| recursive=True, |
| dest_cros=True) |
| |
| def _PrepareTestData(self): |
| # chmod files so everyone can read them. |
| command = ('cd %s && find page_cycler -type f | xargs chmod a+r' % |
| self.REMOTE_TMP_DIR) |
| self._ce.CrosRunCommand(command, |
| chromeos_root=self._chromeos_root, |
| machine=self._remote) |
| command = ('cd %s && find page_cycler -type d | xargs chmod a+rx' % |
| self.REMOTE_TMP_DIR) |
| self._ce.CrosRunCommand(command, |
| chromeos_root=self._chromeos_root, |
| machine=self._remote) |
| |
| def _CopyProfileToHost(self): |
| dest_dir = os.path.join(self._profile_dir, |
| os.path.basename(self._gcov_prefix)) |
| # First remove the dir if it exists already |
| if os.path.exists(dest_dir): |
| command = 'rm -rf %s' % dest_dir |
| self._ce.RunCommand(command) |
| |
| # Strip out the initial prefix for the Chrome directory before doing the |
| # copy. |
| chrome_dir_prefix = misc.GetChromeSrcDir() |
| |
| command = 'mkdir -p %s' % dest_dir |
| self._ce.RunCommand(command) |
| self._ce.CopyFiles(self._gcov_prefix, |
| dest_dir, |
| src_machine=self._remote, |
| chromeos_root=self._chromeos_root, |
| recursive=True, |
| src_cros=True) |
| |
| def _RemoveRemoteProfileDir(self): |
| command = 'rm -rf %s' % self._gcov_prefix |
| self._ce.CrosRunCommand(command, |
| chromeos_root=self._chromeos_root, |
| machine=self._remote) |
| |
| def _LaunchCycler(self, cycler): |
| command = ( |
| 'DISPLAY=:0 ' |
| 'XAUTHORITY=/home/chronos/.Xauthority ' |
| 'GCOV_PREFIX=%s ' |
| 'GCOV_PREFIX_STRIP=3 ' |
| '/opt/google/chrome/chrome ' |
| '--no-sandbox ' |
| '--renderer-clean-exit ' |
| '--user-data-dir=$(mktemp -d) ' |
| "--url \"file:///%s/page_cycler/%s/start.html?iterations=10&auto=1\" " |
| '--enable-file-cookies ' |
| '--no-first-run ' |
| '--js-flags=expose_gc &' % (self._gcov_prefix, self.REMOTE_TMP_DIR, |
| cycler)) |
| |
| self._ce.CrosRunCommand(command, |
| chromeos_root=self._chromeos_root, |
| machine=self._remote, |
| command_timeout=60) |
| |
| def _PkillChrome(self, signal='9'): |
| command = 'pkill -%s chrome' % signal |
| self._ce.CrosRunCommand(command, |
| chromeos_root=self._chromeos_root, |
| machine=self._remote) |
| |
| def DoProfile(self): |
| # Copy the page cycler data to the remote |
| self._CopyTestData() |
| self._PrepareTestData() |
| self._RemoveRemoteProfileDir() |
| |
| for cycler in self._cycler.split(','): |
| self._ProfileOneCycler(cycler) |
| |
| # Copy the profile back |
| self._CopyProfileToHost() |
| |
| def _ProfileOneCycler(self, cycler): |
| # With aura, all that's needed is a stop/start ui. |
| self._PkillChrome() |
| cros_login.RestartUI(self._remote, self._chromeos_root, login=False) |
| # Run the cycler |
| self._LaunchCycler(cycler) |
| self._PkillChrome(signal='INT') |
| # Let libgcov dump the profile. |
| # TODO(asharif): There is a race condition here. Fix it later. |
| time.sleep(30) |
| |
| |
| def Main(argv): |
| """The main function.""" |
| # Common initializations |
| ### command_executer.InitCommandExecuter(True) |
| command_executer.InitCommandExecuter() |
| l = logger.GetLogger() |
| ce = command_executer.GetCommandExecuter() |
| parser = optparse.OptionParser() |
| parser.add_option('--cycler', |
| dest='cycler', |
| default='alexa_us', |
| help=('Comma-separated cyclers to profile. ' |
| 'Example: alexa_us,moz,moz2' |
| 'Use all to profile all cyclers.')) |
| parser.add_option('--chromeos_root', |
| dest='chromeos_root', |
| default='../../', |
| help='Output profile directory.') |
| parser.add_option('--board', |
| dest='board', |
| default='x86-zgb', |
| help='The target board.') |
| parser.add_option('--remote', |
| dest='remote', |
| help=('The remote chromeos machine that' |
| ' has the profile image.')) |
| parser.add_option('--profile_dir', |
| dest='profile_dir', |
| default='profile_dir', |
| help='Store profiles in this directory.') |
| |
| options, _ = parser.parse_args(argv) |
| |
| all_cyclers = ['alexa_us', 'bloat', 'dhtml', 'dom', 'intl1', 'intl2', |
| 'morejs', 'morejsnp', 'moz', 'moz2'] |
| |
| if options.cycler == 'all': |
| options.cycler = ','.join(all_cyclers) |
| |
| try: |
| cp = CyclerProfiler(options.chromeos_root, options.board, options.cycler, |
| options.profile_dir, options.remote) |
| cp.DoProfile() |
| retval = 0 |
| except Exception as e: |
| retval = 1 |
| print e |
| finally: |
| print 'Exiting...' |
| return retval |
| |
| |
| if __name__ == '__main__': |
| retval = Main(sys.argv) |
| sys.exit(retval) |