| Index: chrome/test/functional/perf/endure_setup.py
|
| diff --git a/chrome/test/functional/perf/endure_setup.py b/chrome/test/functional/perf/endure_setup.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..dba1df4375a1f68e01ea74f3e9e8b9ddfa533844
|
| --- /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:]))
|
|
|