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 """Automate the setup process of Chrome Endure environment. | |
7 | |
8 Usage: | |
9 python endure_setup.py [option] | |
10 | |
11 We use <ENDURE_DIR> to refer to the root directory in which Chrome Endure | |
12 is set up. By default, <ENDURE_DIR> is the current working directory. | |
13 | |
14 First, run: | |
15 >python endure_setup.py | |
16 This command will automatically setup Chrome Endure in <ENDURE_DIR>. | |
17 | |
18 Next, run your first endure test by: | |
19 >TEST_LENGTH=30 LOCAL_PERF_DIR="<ENDURE_DIR>/chrome_graph" \\ | |
20 python <ENDURE_DIR>/src/chrome/test/functional/perf_endure.py \\ | |
21 perf_endure.ChromeEndureGmailTest.testGmailComposeDiscard \\ | |
22 The above commands runs a Chrome Endure test for 30 seconds and saves | |
23 the results to <ENDURE_DIR>/chrome_graph. | |
24 | |
25 Last, to view the graphs, run another script endure_server.py | |
26 within <ENDURE_DIR> to start a local HTTP server that serves | |
27 the graph directory, see endure_server.py for details. | |
28 | |
29 Use python endure_setup.py --help for more options. | |
30 | |
31 This script depends on the following modules | |
32 (which will be downloaded automatically): | |
33 depot_tools | |
34 src/chrome/test/pyautolib/fetch_prebuilt_pyauto.py | |
35 | |
36 Supported platforms: Linux and Linux_x64. | |
37 """ | |
38 | |
39 import logging | |
40 import optparse | |
41 import os | |
42 import platform | |
43 import shutil | |
44 import subprocess | |
45 import sys | |
46 import urllib | |
47 import urllib2 | |
48 import zipfile | |
49 | |
50 DESCRIPTION = ( | |
51 'Fetch Chrome Endure.\n\n' | |
52 'Usage:\n' | |
53 ' python endure_setup.py [options]\n\n' | |
54 'Examples:\n' | |
55 ' >python endure_setup.py\n' | |
56 ' Fetch the latest version of Chrome Endure to the current\n' | |
57 ' working directory.\n\n' | |
58 ' >python endure_setup.py --endure-dir=/home/user/endure_dir\n' | |
59 ' Fetch the latest version of Chrome Endure to /home/user/endure_dir.\n') | |
dennis_jeffrey
2012/08/17 00:55:03
It might be easier to format the above within """
fdeng1
2012/08/17 07:05:18
Done.
| |
60 URLS = {'depot_tools': ('http://src.chromium.org' | |
61 '/chrome/trunk/tools/depot_tools'), | |
62 'pyauto': ('https://src.chromium.org/' | |
63 'chrome/trunk/src/chrome/test/functional.DEPS'), | |
64 'binary': ('http://commondatastorage.googleapis.com/' | |
65 'chromium-browser-continuous/{os_type}/{revision}'), | |
66 } | |
67 | |
68 | |
69 class SetupError(Exception): | |
70 """Catch errors in setting up Chrome Endure.""" | |
71 pass | |
72 | |
73 | |
74 class HelpFormatter(optparse.IndentedHelpFormatter): | |
75 """Format the help message of this script.""" | |
76 | |
77 def format_description(self, description): | |
78 """Override to keep the original format of the description.""" | |
79 return description + '\n' if description else '' | |
80 | |
81 | |
82 def Main(argv): | |
83 """Setup Chrome Endure.""" | |
84 parser = optparse.OptionParser( | |
85 formatter=HelpFormatter(), | |
86 description=DESCRIPTION) | |
dennis_jeffrey
2012/08/17 00:55:03
probably can move this to the previous line
fdeng1
2012/08/17 07:05:18
Done.
| |
87 parser.add_option( | |
88 '-d', '--endure-dir', type='string', default=os.getcwd(), | |
89 help='Directory in which to setup or update. ' \ | |
90 'Default value is the current working directory.') | |
91 # TODO(fdeng): remove this option once the Chrome Endure | |
92 # graphing code is checked into chrome tree. | |
93 parser.add_option( | |
94 '-g', '--graph-zip-url', type='string', default=None, | |
95 help='URL to a zip file containing the chrome graphs.') | |
96 os_type = GetCurrentOSType() | |
97 if not os_type.startswith('Linux'): | |
98 raise SetupError('Only support Linux or Linux_x64, %s found' | |
99 % os_type) | |
100 options, _ = parser.parse_args(argv) | |
101 endure_dir = os.path.abspath(options.endure_dir) | |
102 depot_dir = os.path.join(endure_dir, 'depot_tools') | |
103 gclient = os.path.join(depot_dir, 'gclient') | |
104 fetch_py = os.path.join(endure_dir, 'src', 'chrome', | |
105 'test', 'pyautolib', | |
106 'fetch_prebuilt_pyauto.py') | |
107 binary_dir = os.path.join(endure_dir, 'src', 'out', 'Release') | |
108 graph_zip_url = options.graph_zip_url | |
109 graph_dir = os.path.join(endure_dir, 'chrome_graph') | |
110 | |
111 if not os.path.isdir(endure_dir): | |
112 os.makedirs(endure_dir) | |
113 | |
114 logging.info('Fetching depot tools...') | |
115 FetchDepot(depot_dir) | |
116 logging.info('Fetching PyAuto (python code)...') | |
117 FetchPyAuto(gclient, endure_dir) | |
118 logging.info('Fetching binaries(chrome, pyautolib, chrome driver)...') | |
119 FetchBinaries(fetch_py, binary_dir, os_type) | |
120 # TODO(fdeng): remove this after it is check into the chrome tree. | |
dennis_jeffrey
2012/08/17 00:55:03
check --> checked
fdeng1
2012/08/17 07:05:18
Done.
| |
121 logging.info('Fetching chrome graphing files...') | |
122 FetchGraph(graph_zip_url, graph_dir) | |
123 return 0 | |
124 | |
125 | |
126 def FetchDepot(depot_dir): | |
127 """Fetch depot_tools. | |
128 | |
129 Args: | |
130 depot_dir: The directory where depot_tools will be checked out. | |
131 | |
132 Raises: | |
133 SetupError: If fail. | |
134 """ | |
135 if subprocess.call(['svn', 'co', URLS['depot_tools'], depot_dir]) != 0: | |
136 raise SetupError('Error found when checking out depot_tools.') | |
137 if not CheckDepot(depot_dir): | |
138 raise SetupError('Could not get depot_tools.') | |
139 | |
140 | |
141 def CheckDepot(depot_dir): | |
142 """Check that some expected depot_tools files exist. | |
143 | |
144 Args: | |
145 depot_dir: The directory where depot_tools are checked out. | |
146 | |
147 Returns: | |
148 True if check passes otherwise False. | |
149 """ | |
150 gclient = os.path.join(depot_dir, 'gclient') | |
151 gclient_py = os.path.join(depot_dir, 'gclient.py') | |
152 files = [gclient, gclient_py] | |
153 for f in files: | |
154 if not os.path.exists(f): | |
155 return False | |
156 try: | |
157 subprocess.call([gclient, '--version']) | |
158 except OSError: | |
159 return False | |
160 return True | |
161 | |
162 | |
163 def FetchPyAuto(gclient, endure_dir): | |
164 """Use gclient to fetch python code. | |
165 | |
166 Args: | |
167 gclient: The path to the gclient executable. | |
168 endure_dir: Directory where Chrome Endure and | |
169 its dependencies will be checked out. | |
170 | |
171 Raises: | |
172 SetupError: if fails. | |
173 """ | |
174 cur_dir = os.getcwd() | |
175 os.chdir(endure_dir) | |
176 # gclient config | |
dennis_jeffrey
2012/08/17 00:55:03
probably don't need this comment. we can see in t
fdeng1
2012/08/17 07:05:18
Done.
| |
177 config_cmd = [gclient, 'config', URLS['pyauto']] | |
178 if subprocess.call(config_cmd) != 0: | |
179 raise SetupError('Running "%s" failed.' % ' '.join(config_cmd)) | |
180 # gclient sync | |
dennis_jeffrey
2012/08/17 00:55:03
similar comment as line 176 above
fdeng1
2012/08/17 07:05:18
Done.
| |
181 sync_cmd = [gclient, 'sync'] | |
182 if subprocess.call(sync_cmd) != 0: | |
183 raise SetupError('Running "%s" failed.' % ' '.join(sync_cmd)) | |
184 CheckPyAuto(endure_dir) | |
185 logging.info('Sync PyAuto python code done.') | |
186 os.chdir(cur_dir) | |
187 | |
188 | |
189 def CheckPyAuto(endure_dir): | |
190 """Sanity check for Chrome Endure code. | |
191 | |
192 Args: | |
193 endure_dir: Direcotry of Chrome Endure and its dependencies. | |
dennis_jeffrey
2012/08/17 00:55:03
Direcotry --> Directory
fdeng1
2012/08/17 07:05:18
Done.
| |
194 | |
195 Raises: | |
196 SetupError: If fails. | |
197 """ | |
198 fetch_py = os.path.join(endure_dir, 'src', 'chrome', | |
199 'test', 'pyautolib', | |
200 'fetch_prebuilt_pyauto.py') | |
201 pyauto_py = os.path.join(endure_dir, 'src', | |
202 'chrome', 'test', | |
203 'pyautolib', 'pyauto.py') | |
204 files = [fetch_py, pyauto_py] | |
205 for f in files: | |
206 if not os.path.exists(f): | |
207 raise SetupError('Checking %s failed.' % f) | |
208 | |
209 | |
210 def FetchBinaries(fetch_py, binary_dir, os_type): | |
211 """Get the prebuilt binaries from continuous build archive. | |
212 | |
213 Args: | |
214 fetch_py: Path to the script which fetches pre-built binaries. | |
215 binary_dir: Directory of the pre-built binaries. | |
216 os_type: 'Mac', 'Win', 'Linux', 'Linux_x64'. | |
217 | |
218 Raises: | |
219 SetupError: If fails. | |
220 """ | |
221 revision = GetLatestRevision(os_type) | |
222 logging.info('Cleaning %s', binary_dir) | |
223 if os.path.exists(binary_dir): | |
224 shutil.rmtree(binary_dir) | |
225 logging.info('Downloading binaries...') | |
226 cmd = [fetch_py, '-d', binary_dir, | |
227 URLS['binary'].format( | |
228 os_type=os_type, revision=revision)] | |
229 if subprocess.call(cmd) == 0: | |
230 logging.info('Binaries at revision %s', revision) | |
dennis_jeffrey
2012/08/17 00:55:03
before logging this, should we also make sure that
fdeng1
2012/08/17 07:05:18
Done.
| |
231 else: | |
232 raise SetupError('Running "%s" failed.' % ' '.join(cmd)) | |
233 | |
234 | |
235 def FetchGraph(graph_zip_url, graph_dir): | |
236 """Fetch graph code. | |
237 | |
238 Args: | |
239 graph_zip_url: The url to a zip file containing the chrome graphs. | |
240 graph_dir: Directory of the chrome graphs. | |
241 | |
242 Raises: | |
243 SetupError: if unable to retrive the zip file. | |
244 """ | |
245 # TODO(fdeng): remove this function once chrome graph | |
246 # is checked into chrome tree. | |
247 if not graph_zip_url: | |
248 logging.info( | |
249 'Skip fetching chrome graphs' + | |
250 ' since --graph-zip-url is not set.') | |
251 return | |
252 graph_zip = urllib.urlretrieve(graph_zip_url)[0] | |
253 if graph_zip is None or not os.path.exists(graph_zip): | |
254 raise SetupError('Unable to retrieve %s' % graph_zip_url) | |
255 if not os.path.exists(graph_dir): | |
256 os.mkdir(graph_dir) | |
257 UnzipFilenameToDir(graph_zip, graph_dir) | |
258 logging.info('Graph code is downloaded to %s', graph_dir) | |
259 | |
260 | |
261 def GetCurrentOSType(): | |
262 """Get a string representation for the current OS. | |
263 | |
264 Returns: | |
265 'Mac', 'Win', 'Linux', or 'Linux_64'. | |
266 | |
267 Raises: | |
268 RuntimeError: if OS can't be identified. | |
269 """ | |
270 if sys.platform == 'darwin': | |
271 os_type = 'Mac' | |
272 if sys.platform == 'win32': | |
273 os_type = 'Win' | |
274 if sys.platform.startswith('linux'): | |
275 os_type = 'Linux' | |
276 if platform.architecture()[0] == '64bit': | |
277 os_type += '_x64' | |
278 else: | |
279 raise RuntimeError('Unknown platform') | |
280 return os_type | |
281 | |
282 | |
283 def GetLatestRevision(os_type): | |
284 """Figure out the latest revision number of the prebuilt binary archive. | |
285 | |
286 Args: | |
287 os_type: 'Mac', 'Win', 'Linux', or 'Linux_64'. | |
288 | |
289 Returns: | |
290 A string of latest revision number. | |
291 | |
292 Raises: | |
293 SetupError: If unable to get the latest revision number. | |
294 """ | |
295 last_change_url = ('http://commondatastorage.googleapis.com/' | |
296 'chromium-browser-continuous/%s/LAST_CHANGE' % os_type) | |
297 response = urllib2.urlopen(last_change_url) | |
298 last_change = response.read() | |
299 if not last_change: | |
300 raise SetupError('Unable to get the latest revision number from %s' % | |
301 last_change_url) | |
302 return last_change | |
303 | |
304 | |
305 def UnzipFilenameToDir(filename, directory): | |
306 """Unzip |filename| to directory |directory|. | |
307 | |
308 This works with as low as python2.4 (used on win). | |
309 (Code is adapted from fetch_prebuilt_pyauto.py) | |
310 """ | |
311 # TODO(fdeng): remove this function as soon as the Chrome Endure | |
312 # graphing code is checked into the chrome tree. | |
313 zf = zipfile.ZipFile(filename) | |
314 pushd = os.getcwd() | |
315 if not os.path.isdir(directory): | |
316 os.mkdir(directory) | |
317 os.chdir(directory) | |
318 # Extract files. | |
319 for info in zf.infolist(): | |
320 name = info.filename | |
321 if name.endswith('/'): # dir | |
322 if not os.path.isdir(name): | |
323 os.makedirs(name) | |
324 else: # file | |
325 directory = os.path.dirname(name) | |
326 if directory and not os.path.isdir(directory): | |
327 os.makedirs(directory) | |
328 out = open(name, 'wb') | |
329 out.write(zf.read(name)) | |
330 out.close() | |
331 # Set permissions. Permission info in external_attr is shifted 16 bits. | |
332 os.chmod(name, info.external_attr >> 16L) | |
333 os.chdir(pushd) | |
334 | |
335 | |
336 if '__main__' == __name__: | |
337 logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.DEBUG) | |
338 sys.exit(Main(sys.argv[1:])) | |
OLD | NEW |