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