| Index: install_test/install_test.py
|
| ===================================================================
|
| --- install_test/install_test.py (revision 0)
|
| +++ install_test/install_test.py (revision 0)
|
| @@ -0,0 +1,260 @@
|
| +#!/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.
|
| +
|
| +import os
|
| +import sys
|
| +import optparse
|
| +import platform
|
| +import unittest
|
| +import tempfile
|
| +import urllib
|
| +import shutil
|
| +import zipfile
|
| +
|
| +from chrome_installer import ChromeInstaller
|
| +from chrome_checkout import ChromeCheckout
|
| +
|
| +os.sys.path.append(os.path.join(os.path.pardir, 'pyautolib'))
|
| +from fetch_prebuilt_pyauto import FetchPrebuilt
|
| +
|
| +# Global var. to hold pyautolib locations. A global is needed because pyautolib
|
| +# files are downloaded only once at the beginning of the test. We cannot assign
|
| +# these locations to a member var. because each unittest creates a new instance
|
| +# of InstallTest, which means that while the first instance will know about the
|
| +# locations, subsequent instances will not. So a global is used because it will
|
| +# not go out of scope until the process exits.
|
| +_DOWNLOAD_DIR = []
|
| +# Flag that determines if its the first instance, and downloads pyautolib and
|
| +# other dependencies if it is. Its global for the same reason as above.
|
| +_B_FIRST_TIME = True
|
| +
|
| +class InstallTest(unittest.TestCase):
|
| + """Test fixture for tests involving installing/updating Chrome.
|
| +
|
| + Provides an interface to install or update chrome from within a testcase, and
|
| + allows users to run pyauto tests using the installed version. User and system
|
| + level installations are supported, and either one can be used for running the
|
| + pyauto tests. Pyautolib files are downloaded at runtime and a PyUITest object
|
| + is created when Chrome is installed or updated. Users can utilize that object
|
| + to run updater tests. All Updater tests should derive from this class.
|
| + """
|
| +
|
| + def __init__(self, methodName='runTest'):
|
| + global _B_FIRST_TIME
|
| + unittest.TestCase.__init__(self, methodName)
|
| + self._pyauto = None
|
| + self._plat = self.GetPlatform()
|
| + self._source_dirs = ['functional', 'pyautolib', 'pyftpdlib', 'selenium',
|
| + 'simplejson', 'testserver', 'tlslite']
|
| + self._ParseArgs()
|
| + self._dir_prefix = '__CHRBLD__'
|
| + if self._builds:
|
| + if _B_FIRST_TIME:
|
| + for build in self._builds:
|
| + if not self._DownloadDeps(build):
|
| + print 'Couldn\'t download dependencies, aborting test...'
|
| + sys.exit(-1)
|
| + _B_FIRST_TIME = False
|
| +
|
| + def _ParseArgs(self):
|
| + """Parses the command line arguments."""
|
| + parser = optparse.OptionParser()
|
| + parser.add_option(
|
| + '-b', '--builds', type='string', default='', dest='builds',
|
| + help='Specifies the two (or more) builds needed for testing.')
|
| + parser.add_option(
|
| + '-u', '--url', type='string', default='', dest='url',
|
| + help='Specifies the chrome-master2 url, without the build number.')
|
| + parser.add_option(
|
| + '-d', '--dir', type='string', default=os.getcwd(),
|
| + help='Specifies directory where the installer will be downloaded.')
|
| + parser.add_option(
|
| + '-o', '--options', type='string', default='',
|
| + help='Specifies any additional Chrome options (i.e. --system-level).')
|
| + self.opts, self.args = parser.parse_args()
|
| + self.dir = (lambda d: os.path.isdir(d) and d or os.getcwd())(self.opts.dir)
|
| + self._builds = (lambda b: b.split(',') if b else [])(self.opts.builds)
|
| + self._builds.sort()
|
| + self._bld_counter = (lambda lst: 0 if len(lst) > 0 else None)(self._builds)
|
| + self._c_opts = ((lambda opts: opts.replace(',', ' ') if opts else '')
|
| + (self.opts.options))
|
| + self._url = self.opts.url
|
| + if self._url and not self._url.endswith('/'):
|
| + self._url += '/'
|
| + if self._builds:
|
| + self._c_installer = ChromeInstaller(self._url, self._builds[0],
|
| + dest=self.dir, opts=self._c_opts,
|
| + clean=True)
|
| + else:
|
| + self._c_installer = None
|
| + if not self._builds or not self._url:
|
| + print 'Please specify a valid URL and at least two Chrome builds.'
|
| + sys.exit(-1)
|
| +
|
| + def setUp(self):
|
| + """Called before each unittest. It calls _Install, which installs the
|
| +
|
| + first Chrome build and creates a pyauto.PyUITest object.
|
| + """
|
| + self.InstallBuild()
|
| + self.failIf(self._pyauto == None)
|
| +
|
| + def tearDown(self):
|
| + """Called at the end of each unittest. Clears the modules registry so
|
| +
|
| + pyautolib can be reloaded when the build is updated.
|
| + """
|
| + self._Refresh()
|
| + self._DeleteBuild()
|
| +
|
| + def GetPlatform(self):
|
| + """Returns the platform name."""
|
| + return ({'Windows': 'win', 'Darwin': 'mac',
|
| + 'Linux': 'linux'}).get(platform.system())
|
| +
|
| + def SetCurrentBuild(self, nVal):
|
| + """Sets current Chrome build."""
|
| + self._bld_counter = (lambda n: n if(n > 0 and n <= 2) else 0)(nVal)
|
| +
|
| + def GetCurrentBuild(self):
|
| + """Returns the current chrome build."""
|
| + return self._builds[self._bld_counter]
|
| +
|
| + def _Refresh(self):
|
| + """Deletes the PyUITest object and clears the modules registry."""
|
| + try:
|
| + del(self._pyauto)
|
| + except NameError, err:
|
| + print 'CBaseUpdater._Refresh: ', err
|
| + pass
|
| + try:
|
| + os.sys.modules.pop('pyauto')
|
| + os.sys.modules.pop('pyautolib')
|
| + os.sys.modules.pop('_pyautolib')
|
| + except KeyError, err:
|
| + print 'CBaseUpdater._Refresh: ', err
|
| +
|
| + def _Install(self):
|
| + """Installs chrome and creates a PyUITest object on completion."""
|
| + self._pyauto = None
|
| + if isinstance(self._c_installer, ChromeInstaller):
|
| + ret = self._c_installer.InstallChrome()
|
| + if ret:
|
| + try:
|
| + import pyauto
|
| + self._pyauto = pyauto.PyUITest(methodName='runTest',
|
| + browser_path=os.path.dirname(
|
| + ret.GetChromeExePath()))
|
| + self._pyauto.suite_holder = pyauto.PyUITestSuite(['test.py'])
|
| + self._pyauto.setUp()
|
| + except ImportError, err:
|
| + print 'CBaseUpdater.InstallBuild: ', err
|
| + self._pyauto = None
|
| +
|
| + def InstallBuild(self):
|
| + """Installs the first of the Chrome builds specified as command args."""
|
| + global _DOWNLOAD_DIR
|
| + if _DOWNLOAD_DIR[1] in os.sys.path:
|
| + os.sys.path.remove(_DOWNLOAD_DIR[1])
|
| + if os.path.join(_DOWNLOAD_DIR[1], 'pyautolib') in os.sys.path:
|
| + os.sys.path.remove(os.path.join(_DOWNLOAD_DIR, 'pyautolib'))
|
| + os.sys.path.insert(0, _DOWNLOAD_DIR[0])
|
| + os.sys.path.insert(1, os.path.join(_DOWNLOAD_DIR[0], 'pyautolib'))
|
| + self._bld_counter += 1
|
| + self._Install()
|
| +
|
| + def _Update(self):
|
| + """Updates Chrome by installing the second(higher) version of Chrome."""
|
| + global _DOWNLOAD_DIR
|
| + if _DOWNLOAD_DIR[0] in os.sys.path:
|
| + os.sys.path.remove(_DOWNLOAD_DIR[0])
|
| + if os.path.join(_DOWNLOAD_DIR[0], 'pyautolib') in os.sys.path:
|
| + os.sys.path.remove(os.path.join(_DOWNLOAD_DIR[0], 'pyautolib'))
|
| + os.sys.path.insert(0, _DOWNLOAD_DIR[1])
|
| + os.sys.path.insert(1, os.path.join(_DOWNLOAD_DIR[1], 'pyautolib'))
|
| + if self._bld_counter >= len(self._builds):
|
| + print 'No more builds left to install. The following builds have '\
|
| + 'already been installed: %r' % self._builds
|
| + return None
|
| + if self._c_installer:
|
| + self._c_installer.SetBuild(self._builds[self._bld_counter])
|
| + self._Install()
|
| +
|
| + def UpdateBuild(self):
|
| + if self._pyauto:
|
| + self._pyauto.TearDown()
|
| + self._Refresh()
|
| + self._Update()
|
| +
|
| + def _SrcFilesExist(self, root, items):
|
| + """Checks if specified files/folders exist at specified 'root' folder.
|
| +
|
| + Args:
|
| + root: Parent folder where all the source directories reside.
|
| + items: List of files/folders to be verified for existence in the root.
|
| +
|
| + Returns:
|
| + Boolean, True if all sub-folders exist in the root, otherwise False.
|
| + """
|
| + return all(map(lambda p: os.path.exists(p) and True or False,
|
| + [os.path.join(root, path) for path in items]))
|
| +
|
| + def _CheckoutSourceFiles(self, build, location):
|
| + # Checkout folder doesn't exist or is missing some data.
|
| + if(not os.path.isdir(location) or not
|
| + self._SrcFilesExist(location, self._source_dirs)):
|
| + cc = ChromeCheckout(build, location)
|
| + return cc.CheckOut()
|
| + # Folder already exists, no need to do another checkout.
|
| + else:
|
| + return 0
|
| +
|
| + def _DownloadDeps(self, build):
|
| + global _DOWNLOAD_DIR
|
| + ret = -1
|
| + url = '%s%s/%s' % (self._url, build, self._plat)
|
| + download_dir = os.path.join('%s', '%s%s') % (tempfile.gettempdir(),
|
| + self._dir_prefix, build)
|
| + _DOWNLOAD_DIR.append(download_dir)
|
| + if not os.path.isdir(download_dir):
|
| + try:
|
| + os.mkdir(download_dir)
|
| + except(OSError, IOError), err:
|
| + print 'InstallTest._DownloadDeps: %s' % err
|
| + return False
|
| + if not self._SrcFilesExist(download_dir, ['pyautolib.py',
|
| + '_pyautolib.pyd']):
|
| + fpb = FetchPrebuilt(url, download_dir, self._plat)
|
| + if fpb.DoesUrlExist(url):
|
| + ret = fpb.Run()
|
| + else:
|
| + ret = 0
|
| + # Check out source files.
|
| + if ret == 0:
|
| + return self._CheckoutSourceFiles(build, download_dir) == 0
|
| + return False
|
| +
|
| + def _DeleteBuild(self):
|
| + """Uninstalls Chrome"""
|
| + if self._bld_counter == None or self._bld_counter < 0:
|
| + return -1
|
| + cur_build = self._builds[self._bld_counter - 1]
|
| + if cur_build != self._c_installer.GetBuild():
|
| + self._c_installer.SetBuild(cur_build)
|
| + ret = self._c_installer.UninstallChrome()
|
| + if ret:
|
| + self._bld_counter = 0
|
| + return ret
|
| +
|
| + def _DeleteDepFiles(self):
|
| + """Deletes Chrome related files that were downloaded for testing."""
|
| + global _DOWNLOAD_DIR
|
| + for path in _DOWNLOAD_DIR:
|
| + try:
|
| + shutil.rmtree(path)
|
| + except shutil.Error, err:
|
| + print 'CBaseUpdater._DeleteDepFiles: ', err
|
| + return -1
|
| + return 0
|
|
|
| Property changes on: install_test\install_test.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|