| OLD | NEW |
| (Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """CBaseUpdater.py: Base updater test class. All updater tests will derive from |
| 7 this class. |
| 8 |
| 9 """ |
| 10 |
| 11 import os |
| 12 import sys |
| 13 import optparse |
| 14 import platform |
| 15 import unittest |
| 16 import tempfile |
| 17 import urllib |
| 18 import shutil |
| 19 import zipfile |
| 20 |
| 21 from chrome_installer import ChromeInstaller |
| 22 from fetch_prebuilt_pyauto import FetchPrebuilt |
| 23 |
| 24 # Global var. to hold pyautolib locations. A global is needed because pyautolib |
| 25 # files are downloaded only once at the beginning of the test. We cannot assign |
| 26 # these locations to a member var. because each unittest creates a new instance |
| 27 # of InstallTest, which means that while the first instance will know about the |
| 28 # locations, subsequent instances will not. So a global is used because it will |
| 29 # not go out of scope until the process exits. |
| 30 _DOWNLOAD_DIR = [] |
| 31 # Flag that determines if its the first instance, and downloads pyautolib and |
| 32 # other dependencies if it is. Its global for the same reason as above. |
| 33 _B_FIRST_TIME = True |
| 34 |
| 35 class InstallTest(unittest.TestCase): |
| 36 """Test fixture for tests involving installing/updating Chrome. |
| 37 |
| 38 Provides an interface to install or update chrome from within a testcase, and |
| 39 allows users to run pyauto tests using the installed version. User and system |
| 40 level installations are supported, and either one can be used for running the |
| 41 pyauto tests. Pyautolib files are downloaded at runtime and a PyUITest object |
| 42 is created when Chrome is installed or updated. Users can utilize that object |
| 43 to run updater tests. All Updater tests should derive from this class. |
| 44 """ |
| 45 |
| 46 def __init__(self, methodName='runTest'): |
| 47 global _B_FIRST_TIME |
| 48 unittest.TestCase.__init__(self, methodName) |
| 49 self._pyauto = None |
| 50 self._plat = self.GetPlatform() |
| 51 self._c_win32 = 'chrome-win32.test' |
| 52 self._deps = ['pyautolib.py', '_pyautolib.pyd'] |
| 53 self._ParseArgs() |
| 54 if self._builds: |
| 55 if _B_FIRST_TIME: |
| 56 for build in self._builds: |
| 57 if not self._DownloadDeps(build): |
| 58 print 'Couldn\'t download dependencies, aborting test...' |
| 59 sys.exit(-1) |
| 60 _B_FIRST_TIME = False |
| 61 |
| 62 def _ParseArgs(self): |
| 63 """Parses the command line arguments.""" |
| 64 parser = optparse.OptionParser() |
| 65 parser.add_option( |
| 66 '-b', '--builds', type='string', default='', dest='builds', |
| 67 help='Specifies the two (or more) builds needed for testing.') |
| 68 parser.add_option( |
| 69 '-u', '--url', type='string', default='', dest='url', |
| 70 help='Specifies the chrome-master2 url, without the build number.') |
| 71 parser.add_option( |
| 72 '-d', '--dir', type='string', default=os.getcwd(), |
| 73 help='Specifies directory where the installer will be downloaded.') |
| 74 parser.add_option( |
| 75 '-o', '--options', type='string', default='', |
| 76 help='Specifies any additional Chrome options (i.e. --system-level).') |
| 77 self.opts, self.args = parser.parse_args() |
| 78 self.dir = (lambda d: os.path.isdir(d) and d or os.getcwd())(self.opts.dir) |
| 79 self._builds = (lambda b: b.split(',') if b else [])(self.opts.builds) |
| 80 self._builds.sort() |
| 81 self._bld_counter = (lambda lst: 0 if len(lst) > 0 else None)(self._builds)
|
| 82 self._c_opts = ((lambda opts: opts.replace(',', ' ') if opts else '') |
| 83 (self.opts.options)) |
| 84 self._url = self.opts.url |
| 85 if self._url and not self._url.endswith('/'): |
| 86 self._url += '/' |
| 87 if self._builds: |
| 88 self._c_installer = ChromeInstaller(self._url, self._builds[0], |
| 89 dest=self.dir, opts=self._c_opts, |
| 90 clean=True) |
| 91 else: |
| 92 self._c_installer = None |
| 93 if not self._builds or not self._url: |
| 94 print 'Please specify a valid URL and at least two Chrome builds.' |
| 95 sys.exit(-1) |
| 96 |
| 97 def setUp(self): |
| 98 """Called before each unittest. It calls _Install, which installs the |
| 99 |
| 100 first Chrome build and creates a pyauto.PyUITest object. |
| 101 """ |
| 102 self.InstallBuild() |
| 103 self.failIf(self._pyauto == None) |
| 104 |
| 105 def tearDown(self): |
| 106 """Called at the end of each unittest. Clears the modules registry so |
| 107 |
| 108 pyautolib can be reloaded when the build is updated. |
| 109 """ |
| 110 self._Refresh() |
| 111 self._DeleteBuild() |
| 112 |
| 113 def GetPlatform(self): |
| 114 """Returns the platform name.""" |
| 115 return ({'Windows': 'win', 'Darwin': 'mac', |
| 116 'Linux': 'linux'}).get(platform.system()) |
| 117 |
| 118 def SetCurrentBuild(self, nVal): |
| 119 """Sets current Chrome build.""" |
| 120 self._bld_counter = (lambda n: n if(n > 0 and n <= 2) else 0)(nVal) |
| 121 |
| 122 def GetCurrentBuild(self): |
| 123 """Returns the current chrome build.""" |
| 124 return self._builds[self._bld_counter] |
| 125 |
| 126 def _Refresh(self): |
| 127 """Deletes the PyUITest object and clears the modules registry.""" |
| 128 try: |
| 129 del(self._pyauto) |
| 130 except NameError, err: |
| 131 print 'CBaseUpdater._Refresh: ', err |
| 132 pass |
| 133 try: |
| 134 os.sys.modules.pop('pyauto') |
| 135 os.sys.modules.pop('pyautolib') |
| 136 os.sys.modules.pop('_pyautolib') |
| 137 except KeyError, err: |
| 138 print 'CBaseUpdater._Refresh: ', err |
| 139 |
| 140 def _Install(self): |
| 141 """Installs chrome and creates a PyUITest object on completion.""" |
| 142 self._pyauto = None |
| 143 if isinstance(self._c_installer, ChromeInstaller): |
| 144 ret = self._c_installer.InstallChrome() |
| 145 if ret: |
| 146 os.sys.path.append(os.path.join(os.path.pardir, 'pyautolib')) |
| 147 try: |
| 148 import pyauto |
| 149 self._pyauto = pyauto.PyUITest(methodName='runTest', |
| 150 browser_path=os.path.dirname( |
| 151 ret.GetChromeExePath())) |
| 152 self._pyauto.suite_holder = pyauto.PyUITestSuite(['test.py']) |
| 153 self._pyauto.setUp() |
| 154 except ImportError, err: |
| 155 print 'CBaseUpdater.InstallBuild: ', err |
| 156 self._pyauto = None |
| 157 |
| 158 def InstallBuild(self): |
| 159 """Installs the first of the Chrome builds specified as command args.""" |
| 160 global _DOWNLOAD_DIR |
| 161 if os.path.join(os.path.pardir, 'pyautolib') not in os.sys.path: |
| 162 os.sys.path.append(os.path.join(os.path.pardir, 'pyautolib')) |
| 163 os.sys.path = list(frozenset(os.sys.path)) |
| 164 if _DOWNLOAD_DIR[1] in os.sys.path: |
| 165 os.sys.path.remove(_DOWNLOAD_DIR[1]) |
| 166 os.sys.path.insert(0, _DOWNLOAD_DIR[0]) |
| 167 self._bld_counter += 1 |
| 168 self._Install() |
| 169 |
| 170 def _Update(self): |
| 171 """Updates Chrome by installing the second(higher) version of Chrome.""" |
| 172 global _DOWNLOAD_DIR |
| 173 if _DOWNLOAD_DIR[0] in os.sys.path: |
| 174 os.sys.path.remove(_DOWNLOAD_DIR[0]) |
| 175 os.sys.path.insert(0, _DOWNLOAD_DIR[1]) |
| 176 if self._bld_counter >= len(self._builds): |
| 177 print 'No more builds left to install. The following builds have '\ |
| 178 'already been installed: %r' % (self._builds) |
| 179 return None |
| 180 if self._c_installer: |
| 181 self._c_installer.SetCurrentBuild(self._builds[self._bld_counter]) |
| 182 self._Install() |
| 183 |
| 184 def UpdateBuild(self): |
| 185 if self._pyauto: |
| 186 self._pyauto.TearDown() |
| 187 self._Refresh() |
| 188 self._Update() |
| 189 |
| 190 def _DownloadDeps(self, build): |
| 191 global _DOWNLOAD_DIR |
| 192 url = '%s%s/%s' % (self._url, build, self._plat) |
| 193 download_dir = tempfile.mkdtemp('', '__CHROME-DEPS__') |
| 194 _DOWNLOAD_DIR.append(download_dir) |
| 195 fpb = FetchPrebuilt(url, download_dir, self._plat) |
| 196 if fpb.DoesUrlExist(url): |
| 197 return fpb.Run() == 0 |
| 198 return False |
| 199 |
| 200 def _DeleteBuild(self): |
| 201 """Uninstalls Chrome""" |
| 202 if self._bld_counter == None or self._bld_counter < 0: |
| 203 return -1 |
| 204 cur_build = self._builds[self._bld_counter - 1] |
| 205 if cur_build != self._c_installer.build: |
| 206 self._c_installer.SetCurrentBuild(cur_build) |
| 207 ret = self._c_installer.UninstallChrome() |
| 208 if ret: |
| 209 self._bld_counter = 0 |
| 210 return ret |
| 211 |
| 212 def _DeleteDepFiles(self): |
| 213 """Deletes Chrome related files that were downloaded for testing.""" |
| 214 global _DOWNLOAD_DIR |
| 215 for path in _DOWNLOAD_DIR: |
| 216 try: |
| 217 shutil.rmtree(path) |
| 218 except shutil.Error, err: |
| 219 print 'CBaseUpdater._DeleteDepFiles: ', err |
| 220 return -1 |
| 221 return 0 |
| OLD | NEW |