#!/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)