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

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 optparse
7 import os
8 import platform
9 import shutil
10 import sys
11 import tempfile
12 import unittest
13 import urllib
14 import zipfile
15
16 import chrome_checkout
17
kkania 2012/06/14 17:20:33 no newline here, i think; check the style guide
nkang 2012/06/28 19:02:39 It's gone.
18 from chrome_installer import ChromeInstaller
19
20 os.sys.path.append(os.path.join(os.path.pardir, 'pyautolib'))
kkania 2012/06/14 17:20:33 os.sys? I thought it was just sys
nkang 2012/06/28 19:02:39 They are the same, but in order to use just sys, y
21 from fetch_prebuilt_pyauto import FetchPrebuilt
22
23 # Global var. to hold pyautolib locations. A global is needed because pyautolib
24 # files are downloaded only once at the beginning of the test. We cannot assign
25 # these locations to a member var. because each unittest creates a new instance
26 # of InstallTest, which means that while the first instance will know about the
27 # locations, subsequent instances will not. So a global is used because it will
28 # not go out of scope until the process exits.
29 _DOWNLOAD_DIR = []
30 # Flag that determines if its the first instance, and downloads pyautolib and
31 # other dependencies if it is. Its global for the same reason as above.
32 _B_FIRST_TIME = True
33
34 class InstallTest(unittest.TestCase):
35 """Test fixture for tests involving installing/updating Chrome.
36
37 Provides an interface to install or update chrome from within a testcase, and
38 allows users to run pyauto tests using the installed version. User and system
39 level installations are supported, and either one can be used for running the
40 pyauto tests. Pyautolib files are downloaded at runtime and a PyUITest object
41 is created when Chrome is installed or updated. Users can utilize that object
42 to run updater tests. All Updater tests should derive from this class.
43 """
44
45 def __init__(self, methodName='runTest'):
46 global _B_FIRST_TIME
47 unittest.TestCase.__init__(self, methodName)
48 self._pyauto = None
49 self._plat = self.GetPlatform()
50 self._source_dirs = ['functional', 'pyautolib', 'pyftpdlib', 'selenium',
51 'simplejson', 'testserver', 'tlslite']
52 self._ParseArgs()
53 self._dir_prefix = '__CHRBLD__'
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):
kkania 2012/06/14 17:20:33 move the global initialization stuff out to a main
nkang 2012/06/28 19:02:39 Done. Although, I hope you don't mind - since you
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)
kkania 2012/06/14 17:20:33 you use a bit too many abbreviations ('opts', 'bld
nkang 2012/06/28 19:02:39 Got rid of abbreviations wherever possible.
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 """
kkania 2012/06/14 17:20:33 i think we should uninstall first to make sure the
nkang 2012/06/28 19:02:39 Done, now if Chrome is already installed, we unins
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):
kkania 2012/06/14 17:20:33 check these, i don't think they're used
nkang 2012/06/28 19:02:39 Removed both of them.
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')
kkania 2012/06/14 17:20:33 i thought it was just sys.modules
nkang 2012/06/28 19:02:39 You can either call sys.modules or os.sys.modules,
135 os.sys.modules.pop('pyautolib')
136 os.sys.modules.pop('_pyautolib')
137 except KeyError, err:
138 print 'CBaseUpdater._Refresh: ', err
kkania 2012/06/14 17:20:33 when could this occur? I think we should just let
nkang 2012/06/28 19:02:39 This scenario, though unlikely, could occur if the
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 try:
147 import pyauto
148 self._pyauto = pyauto.PyUITest(methodName='runTest',
149 browser_path=os.path.dirname(
150 ret.GetChromeExePath()))
151 self._pyauto.suite_holder = pyauto.PyUITestSuite(['test.py'])
152 self._pyauto.setUp()
153 except ImportError, err:
154 print 'CBaseUpdater.InstallBuild: ', err
155 self._pyauto = None
156
157 def InstallBuild(self):
158 """Installs the first of the Chrome builds specified as command args."""
159 global _DOWNLOAD_DIR
160 if _DOWNLOAD_DIR[1] in os.sys.path:
kkania 2012/06/14 17:20:33 same here and many places in this file; i think al
nkang 2012/06/28 19:02:39 Done.
161 os.sys.path.remove(_DOWNLOAD_DIR[1])
162 if os.path.join(_DOWNLOAD_DIR[1], 'pyautolib') in os.sys.path:
163 os.sys.path.remove(os.path.join(_DOWNLOAD_DIR, 'pyautolib'))
164 os.sys.path.insert(0, _DOWNLOAD_DIR[0])
165 os.sys.path.insert(1, os.path.join(_DOWNLOAD_DIR[0], 'pyautolib'))
166 self._bld_counter += 1
167 self._Install()
168
169 def _Update(self):
170 """Updates Chrome by installing the second(higher) version of Chrome."""
171 global _DOWNLOAD_DIR
172 if _DOWNLOAD_DIR[0] in os.sys.path:
173 os.sys.path.remove(_DOWNLOAD_DIR[0])
174 if os.path.join(_DOWNLOAD_DIR[0], 'pyautolib') in os.sys.path:
175 os.sys.path.remove(os.path.join(_DOWNLOAD_DIR[0], 'pyautolib'))
176 os.sys.path.insert(0, _DOWNLOAD_DIR[1])
177 os.sys.path.insert(1, os.path.join(_DOWNLOAD_DIR[1], 'pyautolib'))
178 if self._bld_counter >= len(self._builds):
179 print 'No more builds left to install. The following builds have '\
kkania 2012/06/14 17:20:33 raise, not print
nkang 2012/06/28 19:02:39 Done.
180 'already been installed: %r' % self._builds
181 return None
182 if self._c_installer:
183 self._c_installer.SetBuild(self._builds[self._bld_counter])
184 self._Install()
185
186 def UpdateBuild(self):
187 if self._pyauto:
188 self._pyauto.TearDown()
189 self._Refresh()
190 self._Update()
191
192 def _SrcFilesExist(self, root, items):
193 """Checks if specified files/folders exist at specified 'root' folder.
194
195 Args:
196 root: Parent folder where all the source directories reside.
197 items: List of files/folders to be verified for existence in the root.
198
199 Returns:
200 Boolean, True if all sub-folders exist in the root, otherwise False.
201 """
202 return all(map(lambda p: os.path.exists(p) and True or False,
203 [os.path.join(root, path) for path in items]))
204
205 def _CheckoutSourceFiles(self, build, location):
206 # Checkout folder doesn't exist or is missing some data.
207 if(not os.path.isdir(location) or not
208 self._SrcFilesExist(location, self._source_dirs)):
209 return chrome_checkout.CheckOut(build, location)
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 self._CheckoutSourceFiles(build, download_dir)
237 return True
238 return False
239
240 def _DeleteBuild(self):
241 """Uninstalls Chrome"""
242 if self._bld_counter == None or self._bld_counter < 0:
243 return -1
244 cur_build = self._builds[self._bld_counter - 1]
245 if cur_build != self._c_installer.GetBuild():
246 self._c_installer.SetBuild(cur_build)
247 ret = self._c_installer.UninstallChrome()
248 if ret:
249 self._bld_counter = 0
250 return ret
251
252 def _DeleteDepFiles(self):
253 """Deletes Chrome related files that were downloaded for testing."""
254 global _DOWNLOAD_DIR
255 for path in _DOWNLOAD_DIR:
256 try:
257 shutil.rmtree(path)
258 except shutil.Error, err:
259 print 'CBaseUpdater._DeleteDepFiles: ', err
260 return -1
261 return 0
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698