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

Side by Side Diff: tools/telemetry/telemetry/page_runner.py

Issue 12278015: [Telemetry] Reorganize everything. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Re-add shebangs. Created 7 years, 10 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
OLDNEW
(Empty)
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 import codecs
5 import logging
6 import os
7 import time
8 import traceback
9 import urlparse
10 import random
11
12 from telemetry import browser_gone_exception
13 from telemetry import page_filter as page_filter_module
14 from telemetry import page_test
15 from telemetry import tab_crash_exception
16 from telemetry import util
17 from telemetry import wpr_modes
18
19 class PageState(object):
20 def __init__(self):
21 self.did_login = False
22
23 class _RunState(object):
24 def __init__(self):
25 self.first_browser = True
26 self.browser = None
27 self.tab = None
28 self.is_tracing = False
29
30 def Close(self):
31 self.is_tracing = False
32
33 if self.tab:
34 self.tab.Disconnect()
35 self.tab = None
36
37 if self.browser:
38 self.browser.Close()
39 self.browser = None
40
41 def _ShuffleAndFilterPageSet(page_set, options):
42 if options.pageset_shuffle_order_file and not options.pageset_shuffle:
43 raise Exception('--pageset-shuffle-order-file requires --pageset-shuffle.')
44
45 if options.pageset_shuffle_order_file:
46 return page_set.ReorderPageSet(options.pageset_shuffle_order_file)
47
48 page_filter = page_filter_module.PageFilter(options)
49 pages = [page for page in page_set.pages[:]
50 if not page.disabled and page_filter.IsSelected(page)]
51
52 if options.pageset_shuffle:
53 random.Random().shuffle(pages)
54 return [page
55 for _ in xrange(int(options.pageset_repeat))
56 for page in pages
57 for _ in xrange(int(options.page_repeat))]
58
59 class PageRunner(object):
60 """Runs a given test against a given test."""
61 def __init__(self, page_set):
62 self.page_set = page_set
63
64 def __enter__(self):
65 return self
66
67 def __exit__(self, *args):
68 self.Close()
69
70 def Run(self, options, possible_browser, test, results):
71 # Check if we can run against WPR.
72 for page in self.page_set.pages:
73 parsed_url = urlparse.urlparse(page.url)
74 if parsed_url.scheme == 'file':
75 continue
76 if not page.archive_path:
77 logging.warning("""
78 No page set archive provided for the page %s. Benchmarking against live sites!
79 Results won't be repeatable or comparable.
80 """, page.url)
81 elif options.wpr_mode != wpr_modes.WPR_RECORD:
82 # The page has an archive, and we're not recording.
83 if not os.path.isfile(page.archive_path):
84 logging.warning("""
85 The page set archive %s for page %s does not exist, benchmarking against live
86 sites! Results won't be repeatable or comparable.
87
88 To fix this, either add svn-internal to your .gclient using
89 http://goto/read-src-internal, or create a new archive using record_wpr.
90 """, os.path.relpath(page.archive_path), page.url)
91
92 # Verify credentials path.
93 credentials_path = None
94 if self.page_set.credentials_path:
95 credentials_path = os.path.join(os.path.dirname(self.page_set.file_path),
96 self.page_set.credentials_path)
97 if not os.path.exists(credentials_path):
98 credentials_path = None
99
100 # Set up user agent.
101 if self.page_set.user_agent_type:
102 options.browser_user_agent_type = self.page_set.user_agent_type
103
104 for page in self.page_set:
105 test.CustomizeBrowserOptionsForPage(page, possible_browser.options)
106
107 # Check tracing directory.
108 if options.trace_dir:
109 if not os.path.exists(options.trace_dir):
110 os.mkdir(options.trace_dir)
111 if not os.path.isdir(options.trace_dir):
112 raise Exception('--trace-dir isn\'t a directory: %s' %
113 options.trace_dir)
114 elif os.listdir(options.trace_dir):
115 raise Exception('Trace directory isn\'t empty: %s' % options.trace_dir)
116
117 # Reorder page set based on options.
118 pages = _ShuffleAndFilterPageSet(self.page_set, options)
119
120 state = _RunState()
121 last_archive_path = None
122 try:
123 for page in pages:
124 if options.wpr_mode != wpr_modes.WPR_RECORD:
125 if page.archive_path and os.path.isfile(page.archive_path):
126 possible_browser.options.wpr_mode = wpr_modes.WPR_REPLAY
127 else:
128 possible_browser.options.wpr_mode = wpr_modes.WPR_OFF
129 if last_archive_path != page.archive_path:
130 state.Close()
131 state = _RunState()
132 last_archive_path = page.archive_path
133 tries = 3
134 while tries:
135 try:
136 if not state.browser:
137 self._SetupBrowser(state, test, possible_browser,
138 credentials_path, page.archive_path)
139 if not state.tab:
140 if len(state.browser.tabs) == 0:
141 state.browser.tabs.New()
142 state.tab = state.browser.tabs[0]
143 if options.trace_dir:
144 self._SetupTracingTab(state)
145
146 try:
147 self._RunPage(options, page, state.tab, test, results)
148 except tab_crash_exception.TabCrashException:
149 stdout = ''
150 if not options.show_stdout:
151 stdout = state.browser.GetStandardOutput()
152 stdout = (('\nStandard Output:\n') +
153 ('*' * 80) +
154 '\n\t' + stdout.replace('\n', '\n\t') + '\n' +
155 ('*' * 80))
156 logging.warning('Tab crashed: %s%s', page.url, stdout)
157 state.Close()
158
159 if options.trace_dir:
160 self._EndTracing(state, options, page)
161
162 if test.needs_browser_restart_after_each_run:
163 state.Close()
164
165 break
166 except browser_gone_exception.BrowserGoneException:
167 logging.warning('Lost connection to browser. Retrying.')
168 state.Close()
169 tries -= 1
170 if not tries:
171 logging.error('Lost connection to browser 3 times. Failing.')
172 raise
173 finally:
174 state.Close()
175
176 def _RunPage(self, options, page, tab, test, results):
177 if not test.CanRunForPage(page):
178 logging.warning('Skiping test: it cannot run for %s', page.url)
179 results.AddSkippedPage(page, 'Test cannot run', '')
180 return
181
182 logging.info('Running %s' % page.url)
183
184 page_state = PageState()
185 try:
186 did_prepare = self._PreparePage(page, tab, page_state, test, results)
187 except util.TimeoutException, ex:
188 logging.warning('Timed out waiting for reply on %s. This is unusual.',
189 page.url)
190 results.AddFailure(page, ex, traceback.format_exc())
191 return
192 except tab_crash_exception.TabCrashException, ex:
193 results.AddFailure(page, ex, traceback.format_exc())
194 raise
195 except browser_gone_exception.BrowserGoneException:
196 raise
197 except Exception, ex:
198 logging.error('Unexpected failure while running %s: %s',
199 page.url, traceback.format_exc())
200 self._CleanUpPage(page, tab, page_state)
201 raise
202
203 if not did_prepare:
204 self._CleanUpPage(page, tab, page_state)
205 return
206
207 try:
208 test.Run(options, page, tab, results)
209 except page_test.Failure, ex:
210 logging.info('%s: %s', ex, page.url)
211 results.AddFailure(page, ex, traceback.format_exc())
212 return
213 except util.TimeoutException, ex:
214 logging.warning('Timed out while running %s', page.url)
215 results.AddFailure(page, ex, traceback.format_exc())
216 return
217 except tab_crash_exception.TabCrashException, ex:
218 results.AddFailure(page, ex, traceback.format_exc())
219 raise
220 except browser_gone_exception.BrowserGoneException:
221 raise
222 except Exception, ex:
223 logging.error('Unexpected failure while running %s: %s',
224 page.url, traceback.format_exc())
225 raise
226 finally:
227 self._CleanUpPage(page, tab, page_state)
228
229 results.AddSuccess(page)
230
231 def Close(self):
232 pass
233
234 def _SetupBrowser(self, state, test, possible_browser, credentials_path,
235 archive_path):
236 assert not state.tab
237 state.browser = possible_browser.Create()
238 state.browser.credentials.credentials_path = credentials_path
239 test.SetUpBrowser(state.browser)
240
241 if state.first_browser:
242 state.browser.credentials.WarnIfMissingCredentials(self.page_set)
243 state.first_browser = False
244
245 state.browser.SetReplayArchivePath(archive_path)
246
247 def _SetupTracingTab(self, state):
248 if state.browser.supports_tracing:
249 state.is_tracing = True
250 state.browser.StartTracing()
251
252 def _EndTracing(self, state, options, page):
253 if state.is_tracing:
254 assert state.browser
255 state.is_tracing = False
256 state.browser.StopTracing()
257 trace_result = state.browser.GetTraceResultAndReset()
258 logging.info('Processing trace...')
259
260 trace_file_base = os.path.join(
261 options.trace_dir, page.url_as_file_safe_name)
262
263 if options.page_repeat != 1 or options.pageset_repeat != 1:
264 trace_file_index = 0
265
266 while True:
267 trace_file = '%s_%03d.json' % (trace_file_base, trace_file_index)
268 if not os.path.exists(trace_file):
269 break
270 trace_file_index = trace_file_index + 1
271 else:
272 trace_file = '%s.json' % trace_file_base
273 with codecs.open(trace_file, 'w',
274 encoding='utf-8') as trace_file:
275 trace_result.Serialize(trace_file)
276 logging.info('Trace saved.')
277
278 def _PreparePage(self, page, tab, page_state, test, results):
279 parsed_url = urlparse.urlparse(page.url)
280 if parsed_url[0] == 'file':
281 dirname, filename = page.url_base_dir_and_file
282 tab.browser.SetHTTPServerDirectory(dirname)
283 target_side_url = tab.browser.http_server.UrlOf(filename)
284 else:
285 target_side_url = page.url
286
287 if page.credentials:
288 page_state.did_login = tab.browser.credentials.LoginNeeded(
289 tab, page.credentials)
290 if not page_state.did_login:
291 msg = 'Could not login to %s on %s' % (page.credentials,
292 target_side_url)
293 logging.info(msg)
294 results.AddFailure(page, msg, "")
295 return False
296
297 test.WillNavigateToPage(page, tab)
298 tab.Navigate(target_side_url)
299 test.DidNavigateToPage(page, tab)
300
301 # Wait for unpredictable redirects.
302 if page.wait_time_after_navigate:
303 time.sleep(page.wait_time_after_navigate)
304 page.WaitToLoad(tab, 60)
305 tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
306
307 return True
308
309 def _CleanUpPage(self, page, tab, page_state): # pylint: disable=R0201
310 if page.credentials and page_state.did_login:
311 tab.browser.credentials.LoginNoLongerNeeded(tab, page.credentials)
312 try:
313 tab.EvaluateJavaScript("""window.chrome && chrome.benchmarking &&
314 chrome.benchmarking.closeConnections()""")
315 except Exception:
316 pass
317
318 @staticmethod
319 def AddCommandLineOptions(parser):
320 page_filter_module.PageFilter.AddCommandLineOptions(parser)
OLDNEW
« no previous file with comments | « tools/telemetry/telemetry/page_filter.py ('k') | tools/telemetry/telemetry/page_runner_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698