| #!/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 utils import command_executer |
| from utils import logger |
| from 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 Exception("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) |