diff options
author | fdeng@chromium.org <fdeng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-18 23:25:07 +0000 |
---|---|---|
committer | fdeng@chromium.org <fdeng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-18 23:25:07 +0000 |
commit | 9670b9ee7569b838f521b1a709daa7fe70df2e30 (patch) | |
tree | 1b6f5f34350225a600c1aa5c23cd6b840f98fd7f /chrome/test | |
parent | 459952967e22617117f51bc886d57ac9501023f7 (diff) | |
download | chromium_src-9670b9ee7569b838f521b1a709daa7fe70df2e30.zip chromium_src-9670b9ee7569b838f521b1a709daa7fe70df2e30.tar.gz chromium_src-9670b9ee7569b838f521b1a709daa7fe70df2e30.tar.bz2 |
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
Diffstat (limited to 'chrome/test')
-rwxr-xr-x | chrome/test/functional/perf/endure_server.py | 79 | ||||
-rwxr-xr-x | chrome/test/functional/perf/endure_setup.py | 337 |
2 files changed, 416 insertions, 0 deletions
diff --git a/chrome/test/functional/perf/endure_server.py b/chrome/test/functional/perf/endure_server.py new file mode 100755 index 0000000..ae4cd0f --- /dev/null +++ b/chrome/test/functional/perf/endure_server.py @@ -0,0 +1,79 @@ +#!/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:])) diff --git a/chrome/test/functional/perf/endure_setup.py b/chrome/test/functional/perf/endure_setup.py new file mode 100755 index 0000000..dba1df4 --- /dev/null +++ b/chrome/test/functional/perf/endure_setup.py @@ -0,0 +1,337 @@ +#!/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:])) |