Commit 9670b9ee authored by fdeng@chromium.org's avatar fdeng@chromium.org

Automate Chrome Endure setup process.

This script automates Chrome Endure setup process and
starts a local Http server to serve the results.

This CL is to re-commit the CL that got reverted due
to check_perms failures. Solve the failures by
add 'x' permission to endure_setup.py and endure_server.py

The original CL:
https://chromiumcodereview.appspot.com/10837114/

The CL that reverted the above CL:
https://chromiumcodereview.appspot.com/10860020/

BUG=None
TEST=Ran the script on two Linux_x64 machines. Ran python src/tools/checkperms/checkperms.py --root src


Review URL: https://chromiumcodereview.appspot.com/10829400

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152262 0039d316-1c4b-4281-b951-d872f2087c98
parent 45995296
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Start an HTTP server which serves Chrome Endure graphs.
Usage:
python endure_server.py [options]
To view Chrome Endure graphs from a browser,
run this script to start a local HTTP server that serves the directory
where graph code and test results are located. A port will be automatically
picked. You can then view the graphs via http://localhost:<GIVEN_PORT>.
Examples:
>python endure_server.py
Start a server which serves the default location
<CURRENT_WORKING_DIR>/chrome_graph.
>python endure_server.py --graph-dir=/home/user/Document/graph_dir
Start a server which serves /home/user/Document/graph_dir which
is where your graph code and test results are.
"""
import BaseHTTPServer
import logging
import optparse
import os
import SimpleHTTPServer
import sys
class HelpFormatter(optparse.IndentedHelpFormatter):
"""Format the help message of this script."""
def format_description(self, description):
"""Override to keep original format of the description."""
return description + '\n' if description else ''
def _ParseArgs(argv):
parser = optparse.OptionParser(
usage='%prog [options]',
formatter=HelpFormatter(),
description=__doc__)
parser.add_option(
'-g', '--graph-dir', type='string',
default=os.path.join(os.getcwd(), 'chrome_graph'),
help='The directory that contains graph code ' \
'and data files of test results. Default value is ' \
'<CURRENT_WORKING_DIR>/chrome_graph')
return parser.parse_args(argv)
def Run(argv):
"""Start an HTTP server which serves Chrome Endure graphs."""
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.DEBUG)
options, _ = _ParseArgs(argv)
graph_dir = os.path.abspath(options.graph_dir)
cur_dir = os.getcwd()
os.chdir(graph_dir)
httpd = BaseHTTPServer.HTTPServer(
('', 0), SimpleHTTPServer.SimpleHTTPRequestHandler)
try:
logging.info('Serving %s at port %d', graph_dir, httpd.server_port)
logging.info('View graphs at http://localhost:%d', httpd.server_port)
logging.info('Press Ctrl-C to stop the server.')
httpd.serve_forever()
except KeyboardInterrupt:
logging.info('Shutting down ...')
httpd.shutdown()
finally:
os.chdir(cur_dir)
return 0
if '__main__' == __name__:
sys.exit(Run(sys.argv[1:]))
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Automate the setup process of Chrome Endure environment.
Usage:
python endure_setup.py [option]
We use <ENDURE_DIR> to refer to the root directory in which Chrome Endure
is set up. By default, <ENDURE_DIR> is the current working directory.
First, run:
>python endure_setup.py
This command will automatically setup Chrome Endure in <ENDURE_DIR>.
Next, run your first endure test by:
>TEST_LENGTH=30 LOCAL_PERF_DIR="<ENDURE_DIR>/chrome_graph" \\
python <ENDURE_DIR>/src/chrome/test/functional/perf_endure.py \\
perf_endure.ChromeEndureGmailTest.testGmailComposeDiscard \\
The above commands runs a Chrome Endure test for 30 seconds and saves
the results to <ENDURE_DIR>/chrome_graph.
Last, to view the graphs, run another script endure_server.py
within <ENDURE_DIR> to start a local HTTP server that serves
the graph directory, see endure_server.py for details.
Use python endure_setup.py --help for more options.
This script depends on the following modules
(which will be downloaded automatically):
depot_tools
src/chrome/test/pyautolib/fetch_prebuilt_pyauto.py
Supported platforms: Linux and Linux_x64.
"""
import logging
import optparse
import os
import platform
import shutil
import subprocess
import sys
import urllib
import urllib2
import zipfile
URLS = {'depot_tools': ('http://src.chromium.org'
'/chrome/trunk/tools/depot_tools'),
'pyauto': ('https://src.chromium.org/'
'chrome/trunk/src/chrome/test/functional.DEPS'),
'binary': ('http://commondatastorage.googleapis.com/'
'chromium-browser-continuous/{os_type}/{revision}'),
}
class SetupError(Exception):
"""Catch errors in setting up Chrome Endure."""
pass
class HelpFormatter(optparse.IndentedHelpFormatter):
"""Format the help message of this script."""
def format_description(self, description):
"""Override to keep the original format of the description."""
return description + '\n' if description else ''
def Main(argv):
"""Fetch Chrome Endure.
Usage:
python endure_setup.py [options]
Examples:
>python endure_setup.py
Fetch the latest version of Chrome Endure to the current
working directory.
>python endure_setup.py --endure-dir=/home/user/endure_dir
Fetch the latest version of Chrome Endure to /home/user/endure_dir.
"""
parser = optparse.OptionParser(
formatter=HelpFormatter(), description=Main.__doc__)
parser.add_option(
'-d', '--endure-dir', type='string', default=os.getcwd(),
help='Directory in which to setup or update. ' \
'Default value is the current working directory.')
# TODO(fdeng): remove this option once the Chrome Endure
# graphing code is checked into chrome tree.
parser.add_option(
'-g', '--graph-zip-url', type='string', default=None,
help='URL to a zip file containing the chrome graphs.')
os_type = GetCurrentOSType()
if not os_type.startswith('Linux'):
raise SetupError('Only support Linux or Linux_x64, %s found'
% os_type)
options, _ = parser.parse_args(argv)
endure_dir = os.path.abspath(options.endure_dir)
depot_dir = os.path.join(endure_dir, 'depot_tools')
gclient = os.path.join(depot_dir, 'gclient')
fetch_py = os.path.join(endure_dir, 'src', 'chrome',
'test', 'pyautolib',
'fetch_prebuilt_pyauto.py')
binary_dir = os.path.join(endure_dir, 'src', 'out', 'Release')
graph_zip_url = options.graph_zip_url
graph_dir = os.path.join(endure_dir, 'chrome_graph')
if not os.path.isdir(endure_dir):
os.makedirs(endure_dir)
logging.info('Fetching depot tools...')
FetchDepot(depot_dir)
logging.info('Fetching PyAuto (python code)...')
FetchPyAuto(gclient, endure_dir)
logging.info('Fetching binaries(chrome, pyautolib, chrome driver)...')
FetchBinaries(fetch_py, binary_dir, os_type)
# TODO(fdeng): remove this after it is checked into the chrome tree.
logging.info('Fetching chrome graphing files...')
FetchGraph(graph_zip_url, graph_dir)
return 0
def FetchDepot(depot_dir):
"""Fetch depot_tools.
Args:
depot_dir: The directory where depot_tools will be checked out.
Raises:
SetupError: If fail.
"""
if subprocess.call(['svn', 'co', URLS['depot_tools'], depot_dir]) != 0:
raise SetupError('Error found when checking out depot_tools.')
if not CheckDepot(depot_dir):
raise SetupError('Could not get depot_tools.')
def CheckDepot(depot_dir):
"""Check that some expected depot_tools files exist.
Args:
depot_dir: The directory where depot_tools are checked out.
Returns:
True if check passes otherwise False.
"""
gclient = os.path.join(depot_dir, 'gclient')
gclient_py = os.path.join(depot_dir, 'gclient.py')
files = [gclient, gclient_py]
for f in files:
if not os.path.exists(f):
return False
try:
subprocess.call([gclient, '--version'])
except OSError:
return False
return True
def FetchPyAuto(gclient, endure_dir):
"""Use gclient to fetch python code.
Args:
gclient: The path to the gclient executable.
endure_dir: Directory where Chrome Endure and
its dependencies will be checked out.
Raises:
SetupError: if fails.
"""
cur_dir = os.getcwd()
os.chdir(endure_dir)
config_cmd = [gclient, 'config', URLS['pyauto']]
if subprocess.call(config_cmd) != 0:
raise SetupError('Running "%s" failed.' % ' '.join(config_cmd))
sync_cmd = [gclient, 'sync']
if subprocess.call(sync_cmd) != 0:
raise SetupError('Running "%s" failed.' % ' '.join(sync_cmd))
CheckPyAuto(endure_dir)
logging.info('Sync PyAuto python code done.')
os.chdir(cur_dir)
def CheckPyAuto(endure_dir):
"""Sanity check for Chrome Endure code.
Args:
endure_dir: Directory of Chrome Endure and its dependencies.
Raises:
SetupError: If fails.
"""
fetch_py = os.path.join(endure_dir, 'src', 'chrome',
'test', 'pyautolib',
'fetch_prebuilt_pyauto.py')
pyauto_py = os.path.join(endure_dir, 'src',
'chrome', 'test',
'pyautolib', 'pyauto.py')
files = [fetch_py, pyauto_py]
for f in files:
if not os.path.exists(f):
raise SetupError('Checking %s failed.' % f)
def FetchBinaries(fetch_py, binary_dir, os_type):
"""Get the prebuilt binaries from continuous build archive.
Args:
fetch_py: Path to the script which fetches pre-built binaries.
binary_dir: Directory of the pre-built binaries.
os_type: 'Mac', 'Win', 'Linux', 'Linux_x64'.
Raises:
SetupError: If fails.
"""
revision = GetLatestRevision(os_type)
logging.info('Cleaning %s', binary_dir)
if os.path.exists(binary_dir):
shutil.rmtree(binary_dir)
logging.info('Downloading binaries...')
cmd = [fetch_py, '-d', binary_dir,
URLS['binary'].format(
os_type=os_type, revision=revision)]
if subprocess.call(cmd) == 0 and os.path.exists(binary_dir):
logging.info('Binaries at revision %s', revision)
else:
raise SetupError('Running "%s" failed.' % ' '.join(cmd))
def FetchGraph(graph_zip_url, graph_dir):
"""Fetch graph code.
Args:
graph_zip_url: The url to a zip file containing the chrome graphs.
graph_dir: Directory of the chrome graphs.
Raises:
SetupError: if unable to retrive the zip file.
"""
# TODO(fdeng): remove this function once chrome graph
# is checked into chrome tree.
if not graph_zip_url:
logging.info(
'Skip fetching chrome graphs' +
' since --graph-zip-url is not set.')
return
graph_zip = urllib.urlretrieve(graph_zip_url)[0]
if graph_zip is None or not os.path.exists(graph_zip):
raise SetupError('Unable to retrieve %s' % graph_zip_url)
if not os.path.exists(graph_dir):
os.mkdir(graph_dir)
UnzipFilenameToDir(graph_zip, graph_dir)
logging.info('Graph code is downloaded to %s', graph_dir)
def GetCurrentOSType():
"""Get a string representation for the current OS.
Returns:
'Mac', 'Win', 'Linux', or 'Linux_64'.
Raises:
RuntimeError: if OS can't be identified.
"""
if sys.platform == 'darwin':
os_type = 'Mac'
if sys.platform == 'win32':
os_type = 'Win'
if sys.platform.startswith('linux'):
os_type = 'Linux'
if platform.architecture()[0] == '64bit':
os_type += '_x64'
else:
raise RuntimeError('Unknown platform')
return os_type
def GetLatestRevision(os_type):
"""Figure out the latest revision number of the prebuilt binary archive.
Args:
os_type: 'Mac', 'Win', 'Linux', or 'Linux_64'.
Returns:
A string of latest revision number.
Raises:
SetupError: If unable to get the latest revision number.
"""
last_change_url = ('http://commondatastorage.googleapis.com/'
'chromium-browser-continuous/%s/LAST_CHANGE' % os_type)
response = urllib2.urlopen(last_change_url)
last_change = response.read()
if not last_change:
raise SetupError('Unable to get the latest revision number from %s' %
last_change_url)
return last_change
def UnzipFilenameToDir(filename, directory):
"""Unzip |filename| to directory |directory|.
This works with as low as python2.4 (used on win).
(Code is adapted from fetch_prebuilt_pyauto.py)
"""
# TODO(fdeng): remove this function as soon as the Chrome Endure
# graphing code is checked into the chrome tree.
zf = zipfile.ZipFile(filename)
pushd = os.getcwd()
if not os.path.isdir(directory):
os.mkdir(directory)
os.chdir(directory)
# Extract files.
for info in zf.infolist():
name = info.filename
if name.endswith('/'): # dir
if not os.path.isdir(name):
os.makedirs(name)
else: # file
directory = os.path.dirname(name)
if directory and not os.path.isdir(directory):
os.makedirs(directory)
out = open(name, 'wb')
out.write(zf.read(name))
out.close()
# Set permissions. Permission info in external_attr is shifted 16 bits.
os.chmod(name, info.external_attr >> 16L)
os.chdir(pushd)
if '__main__' == __name__:
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.DEBUG)
sys.exit(Main(sys.argv[1:]))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment