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

Side by Side 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, 6 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 unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(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 import os
7 import sys
8 import optparse
9 import platform
10 import unittest
11 import tempfile
12 import urllib
13 import shutil
14 import zipfile
15
16 from chrome_installer import ChromeInstaller
17 from chrome_checkout import ChromeCheckout
18
19 os.sys.path.append(os.path.join(os.path.pardir, 'pyautolib'))
20 from fetch_prebuilt_pyauto import FetchPrebuilt
21
22 # Global var. to hold pyautolib locations. A global is needed because pyautolib
23 # files are downloaded only once at the beginning of the test. We cannot assign
24 # these locations to a member var. because each unittest creates a new instance
25 # of InstallTest, which means that while the first instance will know about the
26 # locations, subsequent instances will not. So a global is used because it will
27 # not go out of scope until the process exits.
28 _DOWNLOAD_DIR = []
29 # Flag that determines if its the first instance, and downloads pyautolib and
30 # other dependencies if it is. Its global for the same reason as above.
31 _B_FIRST_TIME = True
32
33 class InstallTest(unittest.TestCase):
34 """Test fixture for tests involving installing/updating Chrome.
35
36 Provides an interface to install or update chrome from within a testcase, and
37 allows users to run pyauto tests using the installed version. User and system
38 level installations are supported, and either one can be used for running the
39 pyauto tests. Pyautolib files are downloaded at runtime and a PyUITest object
40 is created when Chrome is installed or updated. Users can utilize that object
41 to run updater tests. All Updater tests should derive from this class.
42 """
43
44 def __init__(self, methodName='runTest'):
45 global _B_FIRST_TIME
46 unittest.TestCase.__init__(self, methodName)
47 self._pyauto = None
48 self._plat = self.GetPlatform()
49 self._source_dirs = ['functional', 'pyautolib', 'pyftpdlib', 'selenium',
50 'simplejson', 'testserver', 'tlslite']
51 self._ParseArgs()
52 self._dir_prefix = '__CHRBLD__'
53 if self._builds:
54 if _B_FIRST_TIME:
55 for build in self._builds:
56 if not self._DownloadDeps(build):
57 print 'Couldn\'t download dependencies, aborting test...'
58 sys.exit(-1)
59 _B_FIRST_TIME = False
60
61 def _ParseArgs(self):
62 """Parses the command line arguments."""
63 parser = optparse.OptionParser()
64 parser.add_option(
65 '-b', '--builds', type='string', default='', dest='builds',
66 help='Specifies the two (or more) builds needed for testing.')
67 parser.add_option(
68 '-u', '--url', type='string', default='', dest='url',
69 help='Specifies the chrome-master2 url, without the build number.')
70 parser.add_option(
71 '-d', '--dir', type='string', default=os.getcwd(),
72 help='Specifies directory where the installer will be downloaded.')
73 parser.add_option(
74 '-o', '--options', type='string', default='',
75 help='Specifies any additional Chrome options (i.e. --system-level).')
76 self.opts, self.args = parser.parse_args()
77 self.dir = (lambda d: os.path.isdir(d) and d or os.getcwd())(self.opts.dir)
78 self._builds = (lambda b: b.split(',') if b else [])(self.opts.builds)
79 self._builds.sort()
80 self._bld_counter = (lambda lst: 0 if len(lst) > 0 else None)(self._builds)
81 self._c_opts = ((lambda opts: opts.replace(',', ' ') if opts else '')
82 (self.opts.options))
83 self._url = self.opts.url
84 if self._url and not self._url.endswith('/'):
85 self._url += '/'
86 if self._builds:
87 self._c_installer = ChromeInstaller(self._url, self._builds[0],
88 dest=self.dir, opts=self._c_opts,
89 clean=True)
90 else:
91 self._c_installer = None
92 if not self._builds or not self._url:
93 print 'Please specify a valid URL and at least two Chrome builds.'
94 sys.exit(-1)
95
96 def setUp(self):
97 """Called before each unittest. It calls _Install, which installs the
98
99 first Chrome build and creates a pyauto.PyUITest object.
100 """
101 self.InstallBuild()
102 self.failIf(self._pyauto == None)
103
104 def tearDown(self):
105 """Called at the end of each unittest. Clears the modules registry so
106
107 pyautolib can be reloaded when the build is updated.
108 """
109 self._Refresh()
110 self._DeleteBuild()
111
112 def GetPlatform(self):
113 """Returns the platform name."""
114 return ({'Windows': 'win', 'Darwin': 'mac',
115 'Linux': 'linux'}).get(platform.system())
116
117 def SetCurrentBuild(self, nVal):
118 """Sets current Chrome build."""
119 self._bld_counter = (lambda n: n if(n > 0 and n <= 2) else 0)(nVal)
120
121 def GetCurrentBuild(self):
122 """Returns the current chrome build."""
123 return self._builds[self._bld_counter]
124
125 def _Refresh(self):
126 """Deletes the PyUITest object and clears the modules registry."""
127 try:
128 del(self._pyauto)
129 except NameError, err:
130 print 'CBaseUpdater._Refresh: ', err
131 pass
132 try:
133 os.sys.modules.pop('pyauto')
134 os.sys.modules.pop('pyautolib')
135 os.sys.modules.pop('_pyautolib')
136 except KeyError, err:
137 print 'CBaseUpdater._Refresh: ', err
138
139 def _Install(self):
140 """Installs chrome and creates a PyUITest object on completion."""
141 self._pyauto = None
142 if isinstance(self._c_installer, ChromeInstaller):
143 ret = self._c_installer.InstallChrome()
144 if ret:
145 try:
146 import pyauto
147 self._pyauto = pyauto.PyUITest(methodName='runTest',
148 browser_path=os.path.dirname(
149 ret.GetChromeExePath()))
150 self._pyauto.suite_holder = pyauto.PyUITestSuite(['test.py'])
151 self._pyauto.setUp()
152 except ImportError, err:
153 print 'CBaseUpdater.InstallBuild: ', err
154 self._pyauto = None
155
156 def InstallBuild(self):
157 """Installs the first of the Chrome builds specified as command args."""
158 global _DOWNLOAD_DIR
159 if _DOWNLOAD_DIR[1] in os.sys.path:
160 os.sys.path.remove(_DOWNLOAD_DIR[1])
161 if os.path.join(_DOWNLOAD_DIR[1], 'pyautolib') in os.sys.path:
162 os.sys.path.remove(os.path.join(_DOWNLOAD_DIR, 'pyautolib'))
163 os.sys.path.insert(0, _DOWNLOAD_DIR[0])
164 os.sys.path.insert(1, os.path.join(_DOWNLOAD_DIR[0], 'pyautolib'))
165 self._bld_counter += 1
166 self._Install()
167
168 def _Update(self):
169 """Updates Chrome by installing the second(higher) version of Chrome."""
170 global _DOWNLOAD_DIR
171 if _DOWNLOAD_DIR[0] in os.sys.path:
172 os.sys.path.remove(_DOWNLOAD_DIR[0])
173 if os.path.join(_DOWNLOAD_DIR[0], 'pyautolib') in os.sys.path:
174 os.sys.path.remove(os.path.join(_DOWNLOAD_DIR[0], 'pyautolib'))
175 os.sys.path.insert(0, _DOWNLOAD_DIR[1])
176 os.sys.path.insert(1, os.path.join(_DOWNLOAD_DIR[1], 'pyautolib'))
177 if self._bld_counter >= len(self._builds):
178 print 'No more builds left to install. The following builds have '\
179 'already been installed: %r' % self._builds
180 return None
181 if self._c_installer:
182 self._c_installer.SetBuild(self._builds[self._bld_counter])
183 self._Install()
184
185 def UpdateBuild(self):
186 if self._pyauto:
187 self._pyauto.TearDown()
188 self._Refresh()
189 self._Update()
190
191 def _SrcFilesExist(self, root, items):
192 """Checks if specified files/folders exist at specified 'root' folder.
193
194 Args:
195 root: Parent folder where all the source directories reside.
196 items: List of files/folders to be verified for existence in the root.
197
198 Returns:
199 Boolean, True if all sub-folders exist in the root, otherwise False.
200 """
201 return all(map(lambda p: os.path.exists(p) and True or False,
202 [os.path.join(root, path) for path in items]))
203
204 def _CheckoutSourceFiles(self, build, location):
205 # Checkout folder doesn't exist or is missing some data.
206 if(not os.path.isdir(location) or not
207 self._SrcFilesExist(location, self._source_dirs)):
208 cc = ChromeCheckout(build, location)
209 return cc.CheckOut()
210 # Folder already exists, no need to do another checkout.
211 else:
212 return 0
213
214 def _DownloadDeps(self, build):
215 global _DOWNLOAD_DIR
216 ret = -1
217 url = '%s%s/%s' % (self._url, build, self._plat)
218 download_dir = os.path.join('%s', '%s%s') % (tempfile.gettempdir(),
219 self._dir_prefix, build)
220 _DOWNLOAD_DIR.append(download_dir)
221 if not os.path.isdir(download_dir):
222 try:
223 os.mkdir(download_dir)
224 except(OSError, IOError), err:
225 print 'InstallTest._DownloadDeps: %s' % err
226 return False
227 if not self._SrcFilesExist(download_dir, ['pyautolib.py',
228 '_pyautolib.pyd']):
229 fpb = FetchPrebuilt(url, download_dir, self._plat)
230 if fpb.DoesUrlExist(url):
231 ret = fpb.Run()
232 else:
233 ret = 0
234 # Check out source files.
235 if ret == 0:
236 return self._CheckoutSourceFiles(build, download_dir) == 0
237 return False
238
239 def _DeleteBuild(self):
240 """Uninstalls Chrome"""
241 if self._bld_counter == None or self._bld_counter < 0:
242 return -1
243 cur_build = self._builds[self._bld_counter - 1]
244 if cur_build != self._c_installer.GetBuild():
245 self._c_installer.SetBuild(cur_build)
246 ret = self._c_installer.UninstallChrome()
247 if ret:
248 self._bld_counter = 0
249 return ret
250
251 def _DeleteDepFiles(self):
252 """Deletes Chrome related files that were downloaded for testing."""
253 global _DOWNLOAD_DIR
254 for path in _DOWNLOAD_DIR:
255 try:
256 shutil.rmtree(path)
257 except shutil.Error, err:
258 print 'CBaseUpdater._DeleteDepFiles: ', err
259 return -1
260 return 0
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698