| Index: tools/telemetry/telemetry/page/page_runner.py
|
| diff --git a/tools/telemetry/telemetry/page/page_runner.py b/tools/telemetry/telemetry/page/page_runner.py
|
| index e80dc14cda6d5928aa93943f8b46d93e5a899ae0..8c1d9db751ca70ac5d16b849cd70ad2ba3879300 100644
|
| --- a/tools/telemetry/telemetry/page/page_runner.py
|
| +++ b/tools/telemetry/telemetry/page/page_runner.py
|
| @@ -11,25 +11,66 @@ import traceback
|
| import urlparse
|
| import random
|
|
|
| +from telemetry.core import browser_finder
|
| +from telemetry.core import exceptions
|
| from telemetry.core import util
|
| from telemetry.core import wpr_modes
|
| -from telemetry.core import exceptions
|
| from telemetry.page import page_filter as page_filter_module
|
| from telemetry.page import page_test
|
|
|
| -class PageState(object):
|
| - def __init__(self):
|
| - self.did_login = False
|
|
|
| class _RunState(object):
|
| def __init__(self):
|
| - self.first_browser = True
|
| self.browser = None
|
| self.tab = None
|
| - self.is_tracing = False
|
|
|
| - def Close(self):
|
| - self.is_tracing = False
|
| + self._append_to_existing_wpr = False
|
| + self._last_archive_path = None
|
| + self._is_tracing = False
|
| + self._first_browser = True
|
| + self.first_page = True
|
| +
|
| + def StartBrowser(self, test, page_set, page, possible_browser,
|
| + credentials_path, archive_path):
|
| + # Create a browser.
|
| + if not self.browser:
|
| + assert not self.tab
|
| + self.browser = possible_browser.Create()
|
| + self.browser.credentials.credentials_path = credentials_path
|
| + test.SetUpBrowser(self.browser)
|
| +
|
| + if self._first_browser:
|
| + self._first_browser = False
|
| + self.browser.credentials.WarnIfMissingCredentials(page_set)
|
| +
|
| + # Set up WPR path on the new browser.
|
| + self.browser.SetReplayArchivePath(archive_path,
|
| + self._append_to_existing_wpr)
|
| + self._last_archive_path = page.archive_path
|
| + else:
|
| + # Set up WPR path if it changed.
|
| + if self._last_archive_path != page.archive_path:
|
| + self.browser.SetReplayArchivePath(page.archive_path,
|
| + self._append_to_existing_wpr)
|
| + self._last_archive_path = page.archive_path
|
| +
|
| + if self.browser.supports_tab_control:
|
| + # Create a tab.
|
| + if not self.tab:
|
| + if len(self.browser.tabs) == 0:
|
| + self.browser.tabs.New()
|
| + self.tab = self.browser.tabs[0]
|
| +
|
| + # Ensure only one tab is open.
|
| + while len(self.browser.tabs) > 1:
|
| + self.browser.tabs[-1].Close()
|
| +
|
| + if self.first_page:
|
| + self.first_page = False
|
| + test.WillRunPageSet(self.tab)
|
| +
|
| + def StopBrowser(self):
|
| + self._is_tracing = False
|
|
|
| if self.tab:
|
| self.tab.Disconnect()
|
| @@ -39,315 +80,58 @@ class _RunState(object):
|
| self.browser.Close()
|
| self.browser = None
|
|
|
| -def _ShuffleAndFilterPageSet(page_set, options):
|
| - if options.pageset_shuffle_order_file and not options.pageset_shuffle:
|
| - raise Exception('--pageset-shuffle-order-file requires --pageset-shuffle.')
|
| -
|
| - if options.pageset_shuffle_order_file:
|
| - return page_set.ReorderPageSet(options.pageset_shuffle_order_file)
|
| -
|
| - page_filter = page_filter_module.PageFilter(options)
|
| - pages = [page for page in page_set.pages[:]
|
| - if not page.disabled and page_filter.IsSelected(page)]
|
| + # Restarting the state will also restart the wpr server. If we're
|
| + # recording, we need to continue adding into the same wpr archive,
|
| + # not overwrite it.
|
| + self._append_to_existing_wpr = True
|
|
|
| - if options.pageset_shuffle:
|
| - random.Random().shuffle(pages)
|
| - return [page
|
| - for _ in xrange(int(options.pageset_repeat))
|
| - for page in pages
|
| - for _ in xrange(int(options.page_repeat))]
|
| + def StartProfiling(self, page, options):
|
| + output_file = os.path.join(options.profiler_dir, page.url_as_file_safe_name)
|
| + if options.page_repeat != 1 or options.pageset_repeat != 1:
|
| + output_file = _GetSequentialFileName(output_file)
|
| + self.browser.StartProfiling(options, output_file)
|
|
|
| -class PageRunner(object):
|
| - """Runs a given test against a given test."""
|
| - def __init__(self, page_set):
|
| - self.page_set = page_set
|
| - self.has_called_will_run_page_set = False
|
| + def StopProfiling(self):
|
| + self.browser.StopProfiling()
|
|
|
| - def __enter__(self):
|
| - return self
|
| + def StartTracing(self):
|
| + if not self.browser.supports_tracing:
|
| + return
|
|
|
| - def __exit__(self, *args):
|
| - self.Close()
|
| + self._is_tracing = True
|
| + self.browser.StartTracing()
|
|
|
| - def Run(self, options, possible_browser, test, out_results):
|
| - # Reorder page set based on options.
|
| - pages = _ShuffleAndFilterPageSet(self.page_set, options)
|
| + def StopTracing(self, page, options):
|
| + if not self._is_tracing:
|
| + return
|
|
|
| - if (not options.allow_live_sites and
|
| - options.wpr_mode != wpr_modes.WPR_RECORD):
|
| - pages = self._CheckArchives(self.page_set, pages, out_results)
|
| + assert self.browser
|
| + self._is_tracing = False
|
| + self.browser.StopTracing()
|
| + trace_result = self.browser.GetTraceResultAndReset()
|
| + logging.info('Processing trace...')
|
|
|
| - # Verify credentials path.
|
| - credentials_path = None
|
| - if self.page_set.credentials_path:
|
| - credentials_path = os.path.join(os.path.dirname(self.page_set.file_path),
|
| - self.page_set.credentials_path)
|
| - if not os.path.exists(credentials_path):
|
| - credentials_path = None
|
| + trace_file = os.path.join(options.trace_dir, page.url_as_file_safe_name)
|
| + if options.page_repeat != 1 or options.pageset_repeat != 1:
|
| + trace_file = _GetSequentialFileName(trace_file)
|
| + trace_file += '.json'
|
|
|
| - # Set up user agent.
|
| - if self.page_set.user_agent_type:
|
| - options.browser_user_agent_type = self.page_set.user_agent_type
|
| + with codecs.open(trace_file, 'w',
|
| + encoding='utf-8') as trace_file:
|
| + trace_result.Serialize(trace_file)
|
| + logging.info('Trace saved.')
|
|
|
| - for page in pages:
|
| - test.CustomizeBrowserOptionsForPage(page, possible_browser.options)
|
| -
|
| - self._ValidateOrCreateEmptyDirectory('--trace-dir', options.trace_dir)
|
| - self._ValidateOrCreateEmptyDirectory('--profiler-dir', options.profiler_dir)
|
| -
|
| - state = _RunState()
|
| - last_archive_path = None
|
| - results_for_current_run = out_results
|
| - append_to_existing_wpr = False
|
| -
|
| - try:
|
| - for page in pages:
|
| - if options.wpr_mode != wpr_modes.WPR_RECORD:
|
| - if page.archive_path and os.path.isfile(page.archive_path):
|
| - possible_browser.options.wpr_mode = wpr_modes.WPR_REPLAY
|
| - else:
|
| - possible_browser.options.wpr_mode = wpr_modes.WPR_OFF
|
| - if last_archive_path != page.archive_path and state.browser:
|
| - state.browser.SetReplayArchivePath(page.archive_path)
|
| - last_archive_path = page.archive_path
|
| - if (test.discard_first_result and
|
| - not self.has_called_will_run_page_set):
|
| - # If discarding results, substitute a dummy object.
|
| - results_for_current_run = type(out_results)()
|
| - else:
|
| - results_for_current_run = out_results
|
| - results_for_current_run.StartTest(page)
|
| - tries = 3
|
| - while tries:
|
| - try:
|
| - if not state.browser:
|
| - self._SetupBrowser(state, test, possible_browser,
|
| - credentials_path, page.archive_path,
|
| - append_to_existing_wpr)
|
| - last_archive_path = page.archive_path
|
| - if not state.tab:
|
| - if len(state.browser.tabs) == 0:
|
| - state.browser.tabs.New()
|
| - state.tab = state.browser.tabs[0]
|
| -
|
| - if state.browser.supports_tab_control:
|
| - while len(state.browser.tabs) > 1:
|
| - state.browser.tabs[-1].Close()
|
| -
|
| - self._WaitForThermalThrottlingIfNeeded(state.browser.platform)
|
| -
|
| - if options.trace_dir:
|
| - self._SetupTracingTab(state)
|
| - if options.profiler_dir:
|
| - self._SetupProfiling(state, options, page)
|
| -
|
| - try:
|
| - self._RunPage(options, page, state.tab, test,
|
| - results_for_current_run)
|
| - self._CheckThermalThrottling(state.browser.platform)
|
| - except exceptions.TabCrashException:
|
| - stdout = ''
|
| - if not options.show_stdout:
|
| - stdout = state.browser.GetStandardOutput()
|
| - stdout = (('\nStandard Output:\n') +
|
| - ('*' * 80) +
|
| - '\n\t' + stdout.replace('\n', '\n\t') + '\n' +
|
| - ('*' * 80))
|
| - logging.warning('Tab crashed: %s%s', page.url, stdout)
|
| - state.Close()
|
| - # Restarting the state will also restart the wpr server. If we're
|
| - # recording, we need to continue adding into the same wpr archive,
|
| - # not overwrite it.
|
| - append_to_existing_wpr = True
|
| -
|
| - if options.trace_dir:
|
| - self._EndTracing(state, options, page)
|
| - if options.profiler_dir:
|
| - self._EndProfiling(state)
|
| -
|
| - if test.NeedsBrowserRestartAfterEachRun(state.tab):
|
| - state.Close()
|
| -
|
| - break
|
| - except exceptions.BrowserGoneException:
|
| - logging.warning('Lost connection to browser. Retrying.')
|
| - state.Close()
|
| - # Restarting the state will also restart the wpr server. If we're
|
| - # recording, we need to continue adding into the same wpr archive,
|
| - # not overwrite it.
|
| - append_to_existing_wpr = True
|
| - tries -= 1
|
| - if not tries:
|
| - logging.error('Lost connection to browser 3 times. Failing.')
|
| - raise
|
| - results_for_current_run.StopTest(page)
|
| - test.DidRunPageSet(state.tab, results_for_current_run)
|
| - finally:
|
| - state.Close()
|
| -
|
| - def _CheckArchives(self, page_set, pages, out_results):
|
| - """Returns a subset of pages that are local or have WPR archives.
|
| -
|
| - Logs warnings if any are missing."""
|
| - page_set_has_live_sites = False
|
| - for page in pages:
|
| - parsed_url = urlparse.urlparse(page.url)
|
| - if parsed_url.scheme != 'chrome' and parsed_url.scheme != 'file':
|
| - page_set_has_live_sites = True
|
| - break
|
| -
|
| - # Potential problems with the entire page set.
|
| - if page_set_has_live_sites:
|
| - if not page_set.archive_data_file:
|
| - logging.warning('The page set is missing an "archive_data_file" '
|
| - 'property. Skipping any live sites. To include them, '
|
| - 'pass the flag --allow-live-sites.')
|
| - if not page_set.wpr_archive_info:
|
| - logging.warning('The archive info file is missing. '
|
| - 'To fix this, either add svn-internal to your '
|
| - '.gclient using http://goto/read-src-internal, '
|
| - 'or create a new archive using record_wpr.')
|
| -
|
| - # Potential problems with individual pages.
|
| - pages_missing_archive_path = []
|
| - pages_missing_archive_data = []
|
|
|
| - for page in pages:
|
| - parsed_url = urlparse.urlparse(page.url)
|
| - if parsed_url.scheme == 'chrome' or parsed_url.scheme == 'file':
|
| - continue
|
| -
|
| - if not page.archive_path:
|
| - pages_missing_archive_path.append(page)
|
| - if not os.path.isfile(page.archive_path):
|
| - pages_missing_archive_data.append(page)
|
| -
|
| - if pages_missing_archive_path:
|
| - logging.warning('The page set archives for some pages do not exist. '
|
| - 'Skipping those pages. To fix this, record those pages '
|
| - 'using record_wpr. To ignore this warning and run '
|
| - 'against live sites, pass the flag --allow-live-sites.')
|
| - if pages_missing_archive_data:
|
| - logging.warning('The page set archives for some pages are missing. '
|
| - 'Someone forgot to check them in, or they were deleted. '
|
| - 'Skipping those pages. To fix this, record those pages '
|
| - 'using record_wpr. To ignore this warning and run '
|
| - 'against live sites, pass the flag --allow-live-sites.')
|
| -
|
| - for page in pages_missing_archive_path + pages_missing_archive_data:
|
| - out_results.StartTest(page)
|
| - out_results.AddErrorMessage(page, 'Page set archive doesn\'t exist.')
|
| - out_results.StopTest(page)
|
| -
|
| - return [page for page in pages if page not in
|
| - pages_missing_archive_path + pages_missing_archive_data]
|
| -
|
| - def _RunPage(self, options, page, tab, test, results):
|
| - if not test.CanRunForPage(page):
|
| - logging.warning('Skipping test: it cannot run for %s', page.url)
|
| - results.AddSkip(page, 'Test cannot run')
|
| - return
|
| +class PageState(object):
|
| + def __init__(self):
|
| + self._did_login = False
|
|
|
| - logging.info('Running %s' % page.url)
|
| -
|
| - page_state = PageState()
|
| -
|
| - try:
|
| - self._PreparePage(page, tab, page_state, test, results)
|
| - test.Run(options, page, tab, results)
|
| - util.CloseConnections(tab)
|
| - except page_test.Failure:
|
| - logging.warning('%s:\n%s', page.url, traceback.format_exc())
|
| - results.AddFailure(page, sys.exc_info())
|
| - except (util.TimeoutException, exceptions.LoginException):
|
| - logging.error('%s:\n%s', page.url, traceback.format_exc())
|
| - results.AddError(page, sys.exc_info())
|
| - except (exceptions.TabCrashException, exceptions.BrowserGoneException):
|
| - logging.error('%s:\n%s', page.url, traceback.format_exc())
|
| - results.AddError(page, sys.exc_info())
|
| - # Run() catches these exceptions to relaunch the tab/browser, so re-raise.
|
| - raise
|
| - except Exception:
|
| - raise
|
| - else:
|
| - results.AddSuccess(page)
|
| - finally:
|
| - self._CleanUpPage(page, tab, page_state)
|
| -
|
| - def Close(self):
|
| - pass
|
| -
|
| - def _GetSequentialFileName(self, base_name):
|
| - """Returns the next sequential file name based on |base_name| and the
|
| - existing files."""
|
| - index = 0
|
| - while True:
|
| - output_name = '%s_%03d' % (base_name, index)
|
| - if not glob.glob(output_name + '.*'):
|
| - break
|
| - index = index + 1
|
| - return output_name
|
| -
|
| - def _ValidateOrCreateEmptyDirectory(self, name, path):
|
| - if not path:
|
| - return
|
| - if not os.path.exists(path):
|
| - os.mkdir(path)
|
| - if not os.path.isdir(path):
|
| - raise Exception('%s isn\'t a directory: %s' % (name, path))
|
| - elif os.listdir(path):
|
| - raise Exception('%s isn\'t empty: %s' % (name, path))
|
| -
|
| - def _SetupBrowser(self, state, test, possible_browser, credentials_path,
|
| - archive_path, append_to_existing_wpr):
|
| - assert not state.tab
|
| - state.browser = possible_browser.Create()
|
| - state.browser.credentials.credentials_path = credentials_path
|
| - test.SetUpBrowser(state.browser)
|
| -
|
| - if state.first_browser:
|
| - state.browser.credentials.WarnIfMissingCredentials(self.page_set)
|
| - state.first_browser = False
|
| -
|
| - state.browser.SetReplayArchivePath(archive_path, append_to_existing_wpr)
|
| -
|
| - def _SetupProfiling(self, state, options, page):
|
| - output_file = os.path.join(options.profiler_dir, page.url_as_file_safe_name)
|
| - if options.page_repeat != 1 or options.pageset_repeat != 1:
|
| - output_file = self._GetSequentialFileName(output_file)
|
| - state.browser.StartProfiling(options, output_file)
|
| -
|
| - def _EndProfiling(self, state):
|
| - state.browser.StopProfiling()
|
| -
|
| - def _SetupTracingTab(self, state):
|
| - if state.browser.supports_tracing:
|
| - state.is_tracing = True
|
| - state.browser.StartTracing()
|
| -
|
| - def _EndTracing(self, state, options, page):
|
| - if state.is_tracing:
|
| - assert state.browser
|
| - state.is_tracing = False
|
| - state.browser.StopTracing()
|
| - trace_result = state.browser.GetTraceResultAndReset()
|
| - logging.info('Processing trace...')
|
| -
|
| - trace_file = os.path.join(options.trace_dir, page.url_as_file_safe_name)
|
| - if options.page_repeat != 1 or options.pageset_repeat != 1:
|
| - trace_file = self._GetSequentialFileName(trace_file)
|
| - trace_file += '.json'
|
| -
|
| - with codecs.open(trace_file, 'w',
|
| - encoding='utf-8') as trace_file:
|
| - trace_result.Serialize(trace_file)
|
| - logging.info('Trace saved.')
|
| -
|
| - def _PreparePage(self, page, tab, page_state, test, results):
|
| + def PreparePage(self, test, page, tab):
|
| parsed_url = urlparse.urlparse(page.url)
|
| if parsed_url[0] == 'file':
|
| serving_dirs, filename = page.serving_dirs_and_file
|
| - tab.browser.SetHTTPServerDirectories(serving_dirs)
|
| + if tab.browser.SetHTTPServerDirectories(serving_dirs):
|
| + test.DidStartHTTPServer(tab)
|
| target_side_url = tab.browser.http_server.UrlOf(filename)
|
| else:
|
| target_side_url = page.url
|
| @@ -355,11 +139,7 @@ class PageRunner(object):
|
| if page.credentials:
|
| if not tab.browser.credentials.LoginNeeded(tab, page.credentials):
|
| raise page_test.Failure('Login as ' + page.credentials + ' failed')
|
| - page_state.did_login = True
|
| -
|
| - if not self.has_called_will_run_page_set:
|
| - self.has_called_will_run_page_set = True
|
| - test.WillRunPageSet(tab, results)
|
| + self._did_login = True
|
|
|
| test.WillNavigateToPage(page, tab)
|
| tab.Navigate(target_side_url, page.script_to_evaluate_on_commit)
|
| @@ -368,32 +148,270 @@ class PageRunner(object):
|
| page.WaitToLoad(tab, 60)
|
| tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
|
|
|
| - def _CleanUpPage(self, page, tab, page_state): # pylint: disable=R0201
|
| - if page.credentials and page_state.did_login:
|
| + def CleanUpPage(self, page, tab):
|
| + if page.credentials and self._did_login:
|
| tab.browser.credentials.LoginNoLongerNeeded(tab, page.credentials)
|
|
|
| - def _WaitForThermalThrottlingIfNeeded(self, platform):
|
| - if not platform.CanMonitorThermalThrottling():
|
| - return
|
| - thermal_throttling_retry = 0
|
| - while (platform.IsThermallyThrottled() and
|
| - thermal_throttling_retry < 3):
|
| - logging.warning('Thermally throttled, waiting (%d)...',
|
| - thermal_throttling_retry)
|
| - thermal_throttling_retry += 1
|
| - time.sleep(thermal_throttling_retry * 2)
|
| -
|
| - if platform.IsThermallyThrottled():
|
| - logging.error('Device is thermally throttled before running '
|
| - 'performance tests, results will vary.')
|
| -
|
| - def _CheckThermalThrottling(self, platform):
|
| - if not platform.CanMonitorThermalThrottling():
|
| - return
|
| - if platform.HasBeenThermallyThrottled():
|
| - logging.error('Device has been thermally throttled during '
|
| - 'performance tests, results will vary.')
|
|
|
| - @staticmethod
|
| - def AddCommandLineOptions(parser):
|
| - page_filter_module.PageFilter.AddCommandLineOptions(parser)
|
| +def AddCommandLineOptions(parser):
|
| + page_filter_module.PageFilter.AddCommandLineOptions(parser)
|
| +
|
| +
|
| +def Run(test, page_set, options):
|
| + """Runs a given test against a given page_set with the given options."""
|
| + results = test.PrepareResults(options)
|
| +
|
| + # Create a possible_browser with the given options.
|
| + test.CustomizeBrowserOptions(options)
|
| + possible_browser = browser_finder.FindBrowser(options)
|
| + if not possible_browser:
|
| + raise Exception('No browser found.\n'
|
| + 'Use --browser=list to figure out which are available.')
|
| +
|
| + # Reorder page set based on options.
|
| + pages = _ShuffleAndFilterPageSet(page_set, options)
|
| +
|
| + if (not options.allow_live_sites and
|
| + options.wpr_mode != wpr_modes.WPR_RECORD):
|
| + pages = _CheckArchives(page_set, pages, results)
|
| +
|
| + # Verify credentials path.
|
| + credentials_path = None
|
| + if page_set.credentials_path:
|
| + credentials_path = os.path.join(os.path.dirname(page_set.file_path),
|
| + page_set.credentials_path)
|
| + if not os.path.exists(credentials_path):
|
| + credentials_path = None
|
| +
|
| + # Set up user agent.
|
| + if page_set.user_agent_type:
|
| + options.browser_user_agent_type = page_set.user_agent_type
|
| +
|
| + for page in pages:
|
| + test.CustomizeBrowserOptionsForPage(page, possible_browser.options)
|
| +
|
| + _ValidateOrCreateEmptyDirectory('--trace-dir', options.trace_dir)
|
| + _ValidateOrCreateEmptyDirectory('--profiler-dir', options.profiler_dir)
|
| +
|
| + state = _RunState()
|
| + # TODO(dtu): Move results creation and results_for_current_run into RunState.
|
| + results_for_current_run = results
|
| +
|
| + try:
|
| + for page in pages:
|
| + if options.wpr_mode != wpr_modes.WPR_RECORD:
|
| + if page.archive_path and os.path.isfile(page.archive_path):
|
| + possible_browser.options.wpr_mode = wpr_modes.WPR_REPLAY
|
| + else:
|
| + possible_browser.options.wpr_mode = wpr_modes.WPR_OFF
|
| + results_for_current_run = results
|
| + if state.first_page and test.discard_first_result:
|
| + # If discarding results, substitute a dummy object.
|
| + results_for_current_run = type(results)()
|
| + results_for_current_run.StartTest(page)
|
| + tries = 3
|
| + while tries:
|
| + try:
|
| + state.StartBrowser(test, page_set, page, possible_browser,
|
| + credentials_path, page.archive_path)
|
| +
|
| + _WaitForThermalThrottlingIfNeeded(state.browser.platform)
|
| +
|
| + if options.trace_dir:
|
| + state.StartTracing()
|
| + if options.profiler_dir:
|
| + state.StartProfiling(page, options)
|
| +
|
| + try:
|
| + _RunPage(test, page, state.tab, results_for_current_run, options)
|
| + _CheckThermalThrottling(state.browser.platform)
|
| + except exceptions.TabCrashException:
|
| + stdout = ''
|
| + if not options.show_stdout:
|
| + stdout = state.browser.GetStandardOutput()
|
| + stdout = (('\nStandard Output:\n') +
|
| + ('*' * 80) +
|
| + '\n\t' + stdout.replace('\n', '\n\t') + '\n' +
|
| + ('*' * 80))
|
| + logging.warning('Tab crashed: %s%s', page.url, stdout)
|
| + state.StopBrowser()
|
| +
|
| + if options.trace_dir:
|
| + state.StopTracing(page, options)
|
| + if options.profiler_dir:
|
| + state.StopProfiling()
|
| +
|
| + if test.NeedsBrowserRestartAfterEachRun(state.tab):
|
| + state.StopBrowser()
|
| +
|
| + break
|
| + except exceptions.BrowserGoneException:
|
| + logging.warning('Lost connection to browser. Retrying.')
|
| + state.StopBrowser()
|
| + tries -= 1
|
| + if not tries:
|
| + logging.error('Lost connection to browser 3 times. Failing.')
|
| + raise
|
| + results_for_current_run.StopTest(page)
|
| + test.DidRunPageSet(state.tab, results_for_current_run)
|
| + finally:
|
| + state.StopBrowser()
|
| +
|
| + return results
|
| +
|
| +
|
| +def _ShuffleAndFilterPageSet(page_set, options):
|
| + if options.pageset_shuffle_order_file and not options.pageset_shuffle:
|
| + raise Exception('--pageset-shuffle-order-file requires --pageset-shuffle.')
|
| +
|
| + if options.pageset_shuffle_order_file:
|
| + return page_set.ReorderPageSet(options.pageset_shuffle_order_file)
|
| +
|
| + page_filter = page_filter_module.PageFilter(options)
|
| + pages = [page for page in page_set.pages[:]
|
| + if not page.disabled and page_filter.IsSelected(page)]
|
| +
|
| + if options.pageset_shuffle:
|
| + random.Random().shuffle(pages)
|
| + return [page
|
| + for _ in xrange(int(options.pageset_repeat))
|
| + for page in pages
|
| + for _ in xrange(int(options.page_repeat))]
|
| +
|
| +
|
| +def _CheckArchives(page_set, pages, results):
|
| + """Returns a subset of pages that are local or have WPR archives.
|
| +
|
| + Logs warnings if any are missing."""
|
| + page_set_has_live_sites = False
|
| + for page in pages:
|
| + parsed_url = urlparse.urlparse(page.url)
|
| + if parsed_url.scheme != 'chrome' and parsed_url.scheme != 'file':
|
| + page_set_has_live_sites = True
|
| + break
|
| +
|
| + # Potential problems with the entire page set.
|
| + if page_set_has_live_sites:
|
| + if not page_set.archive_data_file:
|
| + logging.warning('The page set is missing an "archive_data_file" '
|
| + 'property. Skipping any live sites. To include them, '
|
| + 'pass the flag --allow-live-sites.')
|
| + if not page_set.wpr_archive_info:
|
| + logging.warning('The archive info file is missing. '
|
| + 'To fix this, either add svn-internal to your '
|
| + '.gclient using http://goto/read-src-internal, '
|
| + 'or create a new archive using record_wpr.')
|
| +
|
| + # Potential problems with individual pages.
|
| + pages_missing_archive_path = []
|
| + pages_missing_archive_data = []
|
| +
|
| + for page in pages:
|
| + parsed_url = urlparse.urlparse(page.url)
|
| + if parsed_url.scheme == 'chrome' or parsed_url.scheme == 'file':
|
| + continue
|
| +
|
| + if not page.archive_path:
|
| + pages_missing_archive_path.append(page)
|
| + if not os.path.isfile(page.archive_path):
|
| + pages_missing_archive_data.append(page)
|
| +
|
| + if pages_missing_archive_path:
|
| + logging.warning('The page set archives for some pages do not exist. '
|
| + 'Skipping those pages. To fix this, record those pages '
|
| + 'using record_wpr. To ignore this warning and run '
|
| + 'against live sites, pass the flag --allow-live-sites.')
|
| + if pages_missing_archive_data:
|
| + logging.warning('The page set archives for some pages are missing. '
|
| + 'Someone forgot to check them in, or they were deleted. '
|
| + 'Skipping those pages. To fix this, record those pages '
|
| + 'using record_wpr. To ignore this warning and run '
|
| + 'against live sites, pass the flag --allow-live-sites.')
|
| +
|
| + for page in pages_missing_archive_path + pages_missing_archive_data:
|
| + results.StartTest(page)
|
| + results.AddErrorMessage(page, 'Page set archive doesn\'t exist.')
|
| + results.StopTest(page)
|
| +
|
| + return [page for page in pages if page not in
|
| + pages_missing_archive_path + pages_missing_archive_data]
|
| +
|
| +
|
| +def _RunPage(test, page, tab, results, options):
|
| + if not test.CanRunForPage(page):
|
| + logging.warning('Skipping test: it cannot run for %s', page.url)
|
| + results.AddSkip(page, 'Test cannot run')
|
| + return
|
| +
|
| + logging.info('Running %s' % page.url)
|
| +
|
| + page_state = PageState()
|
| +
|
| + try:
|
| + page_state.PreparePage(test, page, tab)
|
| + test.Run(options, page, tab, results)
|
| + util.CloseConnections(tab)
|
| + except page_test.Failure:
|
| + logging.warning('%s:\n%s', page.url, traceback.format_exc())
|
| + results.AddFailure(page, sys.exc_info())
|
| + except (util.TimeoutException, exceptions.LoginException):
|
| + logging.error('%s:\n%s', page.url, traceback.format_exc())
|
| + results.AddError(page, sys.exc_info())
|
| + except (exceptions.TabCrashException, exceptions.BrowserGoneException):
|
| + logging.error('%s:\n%s', page.url, traceback.format_exc())
|
| + results.AddError(page, sys.exc_info())
|
| + # Run() catches these exceptions to relaunch the tab/browser, so re-raise.
|
| + raise
|
| + except Exception:
|
| + raise
|
| + else:
|
| + results.AddSuccess(page)
|
| + finally:
|
| + page_state.CleanUpPage(page, tab)
|
| +
|
| +
|
| +def _GetSequentialFileName(base_name):
|
| + """Returns the next sequential file name based on |base_name| and the
|
| + existing files."""
|
| + index = 0
|
| + while True:
|
| + output_name = '%s_%03d' % (base_name, index)
|
| + if not glob.glob(output_name + '.*'):
|
| + break
|
| + index = index + 1
|
| + return output_name
|
| +
|
| +
|
| +def _ValidateOrCreateEmptyDirectory(name, path):
|
| + if not path:
|
| + return
|
| + if not os.path.exists(path):
|
| + os.mkdir(path)
|
| + if not os.path.isdir(path):
|
| + raise Exception('%s isn\'t a directory: %s' % (name, path))
|
| + elif os.listdir(path):
|
| + raise Exception('%s isn\'t empty: %s' % (name, path))
|
| +
|
| +
|
| +def _WaitForThermalThrottlingIfNeeded(platform):
|
| + if not platform.CanMonitorThermalThrottling():
|
| + return
|
| + thermal_throttling_retry = 0
|
| + while (platform.IsThermallyThrottled() and
|
| + thermal_throttling_retry < 3):
|
| + logging.warning('Thermally throttled, waiting (%d)...',
|
| + thermal_throttling_retry)
|
| + thermal_throttling_retry += 1
|
| + time.sleep(thermal_throttling_retry * 2)
|
| +
|
| + if platform.IsThermallyThrottled():
|
| + logging.error('Device is thermally throttled before running '
|
| + 'performance tests, results will vary.')
|
| +
|
| +
|
| +def _CheckThermalThrottling(platform):
|
| + if not platform.CanMonitorThermalThrottling():
|
| + return
|
| + if platform.HasBeenThermallyThrottled():
|
| + logging.error('Device has been thermally throttled during '
|
| + 'performance tests, results will vary.')
|
|
|