Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Unified Diff: install_test/install_test.py

Issue 10384104: Chrome updater test framework (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/test/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698