page_runner.py revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import codecs 5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)import glob 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import logging 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import time 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import traceback 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import urlparse 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import random 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import util 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import wpr_modes 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import exceptions 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from telemetry.page import page_measurement_results 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.page import page_filter as page_filter_module 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.page import page_test 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PageState(object): 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self): 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.did_login = False 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class _RunState(object): 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self): 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.first_browser = True 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.browser = None 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.tab = None 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.is_tracing = False 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def Close(self): 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.is_tracing = False 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self.tab: 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.tab.Disconnect() 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.tab = None 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self.browser: 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.browser.Close() 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.browser = None 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _ShuffleAndFilterPageSet(page_set, options): 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.pageset_shuffle_order_file and not options.pageset_shuffle: 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise Exception('--pageset-shuffle-order-file requires --pageset-shuffle.') 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.pageset_shuffle_order_file: 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return page_set.ReorderPageSet(options.pageset_shuffle_order_file) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_filter = page_filter_module.PageFilter(options) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pages = [page for page in page_set.pages[:] 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not page.disabled and page_filter.IsSelected(page)] 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.pageset_shuffle: 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) random.Random().shuffle(pages) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return [page 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for _ in xrange(int(options.pageset_repeat)) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for page in pages 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for _ in xrange(int(options.page_repeat))] 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PageRunner(object): 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Runs a given test against a given test.""" 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self, page_set): 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.page_set = page_set 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) self.has_called_will_run_page_set = False 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __enter__(self): 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return self 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __exit__(self, *args): 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.Close() 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) def Run(self, options, possible_browser, test, out_results): 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Reorder page set based on options. 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pages = _ShuffleAndFilterPageSet(self.page_set, options) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Check if we can run against WPR. 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pages_without_archives = [] 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for page in pages: 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parsed_url = urlparse.urlparse(page.url) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if parsed_url.scheme == 'file': 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not page.archive_path: 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.allow_live_sites: 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning(""" 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) No page set archive provided for the page %s. Running against live sites! 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Results won't be repeatable or comparable. 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)""", page.url) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning(""" 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) No page set archive provided for the page %s. Not running the page. To run 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) against live sites, pass the flag --allow-live-sites. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)""", page.url) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out_results.AddFailure(page, 'Page set archive not defined', '') 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pages_without_archives.append(page) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif options.wpr_mode != wpr_modes.WPR_RECORD: 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # The page has an archive, and we're not recording. 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not os.path.isfile(page.archive_path): 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.allow_live_sites: 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning(""" 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) The page set archive %s for page %s does not exist, running against live 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sites! Results won't be repeatable or comparable. 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) To fix this, either add svn-internal to your .gclient using 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) http://goto/read-src-internal, or create a new archive using record_wpr. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """, os.path.relpath(page.archive_path), page.url) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning(""" 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) The page set archive %s for page %s does not exist. Not running the page. 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) To fix this, either add svn-internal to your .gclient using 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) http://goto/read-src-internal, or create a new archive using record_wpr. 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) To run against live sites, pass the flag --allow-live-sites. 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """, os.path.relpath(page.archive_path), page.url) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out_results.AddFailure(page, 'Page set archive doesn\'t exist', '') 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pages_without_archives.append(page) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pages = [page for page in pages if page not in pages_without_archives] 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Verify credentials path. 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credentials_path = None 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self.page_set.credentials_path: 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credentials_path = os.path.join(os.path.dirname(self.page_set.file_path), 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.page_set.credentials_path) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not os.path.exists(credentials_path): 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credentials_path = None 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Set up user agent. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self.page_set.user_agent_type: 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.browser_user_agent_type = self.page_set.user_agent_type 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for page in pages: 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test.CustomizeBrowserOptionsForPage(page, possible_browser.options) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._ValidateOrCreateEmptyDirectory('--trace-dir', options.trace_dir) 135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._ValidateOrCreateEmptyDirectory('--profiler-dir', options.profiler_dir) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state = _RunState() 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_archive_path = None 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) results_for_current_run = out_results 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for page in pages: 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.wpr_mode != wpr_modes.WPR_RECORD: 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if page.archive_path and os.path.isfile(page.archive_path): 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) possible_browser.options.wpr_mode = wpr_modes.WPR_REPLAY 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) possible_browser.options.wpr_mode = wpr_modes.WPR_OFF 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if last_archive_path != page.archive_path: 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.Close() 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state = _RunState() 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_archive_path = page.archive_path 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (test.discard_first_result and 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) not self.has_called_will_run_page_set): 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # If discarding results, substitute a dummy object. 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) results_for_current_run = ( 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) page_measurement_results.PageMeasurementResults()) 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else: 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) results_for_current_run = out_results 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tries = 3 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while tries: 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not state.browser: 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._SetupBrowser(state, test, possible_browser, 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credentials_path, page.archive_path) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not state.tab: 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if len(state.browser.tabs) == 0: 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser.tabs.New() 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.tab = state.browser.tabs[0] 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if state.browser.supports_tab_control: 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while len(state.browser.tabs) > 1: 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser.tabs[-1].Close() 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._WaitForThermalThrottlingIfNeeded(state.browser.platform) 175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.trace_dir: 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._SetupTracingTab(state) 178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if options.profiler_dir: 179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._SetupProfiling(state, options, page) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) self._RunPage(options, page, state.tab, test, 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) results_for_current_run) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._CheckThermalThrottling(state.browser.platform) 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except exceptions.TabCrashException: 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stdout = '' 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not options.show_stdout: 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stdout = state.browser.GetStandardOutput() 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stdout = (('\nStandard Output:\n') + 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ('*' * 80) + 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) '\n\t' + stdout.replace('\n', '\n\t') + '\n' + 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ('*' * 80)) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning('Tab crashed: %s%s', page.url, stdout) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.Close() 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.trace_dir: 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._EndTracing(state, options, page) 198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if options.profiler_dir: 199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self._EndProfiling(state) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if test.needs_browser_restart_after_each_run: 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.Close() 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except exceptions.BrowserGoneException: 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning('Lost connection to browser. Retrying.') 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.Close() 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tries -= 1 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not tries: 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.error('Lost connection to browser 3 times. Failing.') 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) test.DidRunPageSet(state.tab, results_for_current_run) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) finally: 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.Close() 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _RunPage(self, options, page, tab, test, results): 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not test.CanRunForPage(page): 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning('Skiping test: it cannot run for %s', page.url) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddSkippedPage(page, 'Test cannot run', '') 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.info('Running %s' % page.url) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_state = PageState() 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) did_prepare = self._PreparePage(page, tab, page_state, test, results) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except util.TimeoutException, ex: 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) logging.error(str(ex) + ' Timeout occurred during page %s', page.url) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddFailure(page, ex, traceback.format_exc()) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except exceptions.TabCrashException, ex: 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddFailure(page, ex, traceback.format_exc()) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except exceptions.BrowserGoneException: 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except Exception, ex: 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.error('Unexpected failure while running %s: %s', 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page.url, traceback.format_exc()) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._CleanUpPage(page, tab, page_state) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not did_prepare: 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._CleanUpPage(page, tab, page_state) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test.Run(options, page, tab, results) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except page_test.Failure, ex: 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.info('%s: %s', ex, page.url) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddFailure(page, ex, traceback.format_exc()) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except util.TimeoutException, ex: 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning('Timed out while running %s', page.url) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddFailure(page, ex, traceback.format_exc()) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except exceptions.TabCrashException, ex: 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddFailure(page, ex, traceback.format_exc()) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except exceptions.BrowserGoneException: 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except Exception, ex: 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.error('Unexpected failure while running %s: %s', 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page.url, traceback.format_exc()) 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) finally: 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._CleanUpPage(page, tab, page_state) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddSuccess(page) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def Close(self): 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pass 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def _GetSequentialFileName(self, base_name): 274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Returns the next sequential file name based on |base_name| and the 275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) existing files.""" 276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) index = 0 277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while True: 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) output_name = '%s_%03d' % (base_name, index) 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not glob.glob(output_name + '.*'): 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) index = index + 1 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return output_name 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def _ValidateOrCreateEmptyDirectory(self, name, path): 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not path: 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not os.path.exists(path): 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) os.mkdir(path) 289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if not os.path.isdir(path): 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) raise Exception('%s isn\'t a directory: %s' % (name, path)) 291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) elif os.listdir(path): 292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) raise Exception('%s isn\'t empty: %s' % (name, path)) 293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _SetupBrowser(self, state, test, possible_browser, credentials_path, 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) archive_path): 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert not state.tab 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser = possible_browser.Create() 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser.credentials.credentials_path = credentials_path 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test.SetUpBrowser(state.browser) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if state.first_browser: 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser.credentials.WarnIfMissingCredentials(self.page_set) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.first_browser = False 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser.SetReplayArchivePath(archive_path) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def _SetupProfiling(self, state, options, page): 308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) output_file = os.path.join(options.profiler_dir, page.url_as_file_safe_name) 309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if options.page_repeat != 1 or options.pageset_repeat != 1: 310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) output_file = self._GetSequentialFileName(output_file) 311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) state.browser.StartProfiling(options, output_file) 312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def _EndProfiling(self, state): 314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) state.browser.StopProfiling() 315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _SetupTracingTab(self, state): 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if state.browser.supports_tracing: 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.is_tracing = True 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser.StartTracing() 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _EndTracing(self, state, options, page): 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if state.is_tracing: 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert state.browser 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.is_tracing = False 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state.browser.StopTracing() 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trace_result = state.browser.GetTraceResultAndReset() 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.info('Processing trace...') 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) trace_file = os.path.join(options.trace_dir, page.url_as_file_safe_name) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if options.page_repeat != 1 or options.pageset_repeat != 1: 331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) trace_file = self._GetSequentialFileName(trace_file) 332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) trace_file += '.json' 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) with codecs.open(trace_file, 'w', 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) encoding='utf-8') as trace_file: 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trace_result.Serialize(trace_file) 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.info('Trace saved.') 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _PreparePage(self, page, tab, page_state, test, results): 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parsed_url = urlparse.urlparse(page.url) 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if parsed_url[0] == 'file': 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) serving_dirs, filename = page.serving_dirs_and_file 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab.browser.SetHTTPServerDirectories(serving_dirs) 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_side_url = tab.browser.http_server.UrlOf(filename) 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_side_url = page.url 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if page.credentials: 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_state.did_login = tab.browser.credentials.LoginNeeded( 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab, page.credentials) 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not page_state.did_login: 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg = 'Could not login to %s on %s' % (page.credentials, 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_side_url) 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.info(msg) 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.AddFailure(page, msg, "") 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return False 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not self.has_called_will_run_page_set: 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) self.has_called_will_run_page_set = True 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) test.WillRunPageSet(tab, results) 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test.WillNavigateToPage(page, tab) 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tab.Navigate(target_side_url, page.script_to_evaluate_on_commit) 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test.DidNavigateToPage(page, tab) 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page.WaitToLoad(tab, 60) 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return True 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _CleanUpPage(self, page, tab, page_state): # pylint: disable=R0201 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if page.credentials and page_state.did_login: 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab.browser.credentials.LoginNoLongerNeeded(tab, page.credentials) 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab.EvaluateJavaScript("""window.chrome && chrome.benchmarking && 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome.benchmarking.closeConnections()""") 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except Exception: 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pass 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _WaitForThermalThrottlingIfNeeded(self, platform): 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not platform.CanMonitorThermalThrottling(): 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thermal_throttling_retry = 0 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (platform.IsThermallyThrottled() and 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thermal_throttling_retry < 3): 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.warning('Thermally throttled, waiting (%d)...', 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thermal_throttling_retry) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thermal_throttling_retry += 1 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) time.sleep(thermal_throttling_retry * 2) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if platform.IsThermallyThrottled(): 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.error('Device is thermally throttled before running ' 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'performance tests, results will vary.') 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _CheckThermalThrottling(self, platform): 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not platform.CanMonitorThermalThrottling(): 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if platform.HasBeenThermallyThrottled(): 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.error('Device has been thermally throttled during ' 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'performance tests, results will vary.') 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @staticmethod 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def AddCommandLineOptions(parser): 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) page_filter_module.PageFilter.AddCommandLineOptions(parser) 405