page_runner.py revision a3f7b4e666c476898878fa745f637129375cd889
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.
4a3f7b4e666c476898878fa745f637129375cd889Ben Murdochimport collections
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)import glob
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import logging
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import sys
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochimport tempfile
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import time
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import traceback
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import urlparse
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import random
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)from telemetry.core import browser_finder
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)from telemetry.core import exceptions
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import util
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import wpr_modes
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.page import page_filter as page_filter_module
20a3f7b4e666c476898878fa745f637129375cd889Ben Murdochfrom telemetry.page import page_runner_repeat
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.page import page_test
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class _RunState(object):
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self):
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.browser = None
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.tab = None
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._append_to_existing_wpr = False
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._last_archive_path = None
317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._first_browser = True
32a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.first_page = collections.defaultdict(lambda: True)
33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.profiler_dir = None
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def StartBrowser(self, test, page_set, page, possible_browser,
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   credentials_path, archive_path):
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    # Create a browser.
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not self.browser:
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      assert not self.tab
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self.browser = possible_browser.Create()
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self.browser.credentials.credentials_path = credentials_path
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      test.SetUpBrowser(self.browser)
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if self._first_browser:
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self._first_browser = False
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self.browser.credentials.WarnIfMissingCredentials(page_set)
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Set up WPR path on the new browser.
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self.browser.SetReplayArchivePath(archive_path,
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        self._append_to_existing_wpr,
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        page_set.make_javascript_deterministic)
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self._last_archive_path = page.archive_path
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    else:
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Set up WPR path if it changed.
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if page.archive_path and self._last_archive_path != page.archive_path:
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        self.browser.SetReplayArchivePath(
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            page.archive_path,
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            self._append_to_existing_wpr,
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            page_set.make_javascript_deterministic)
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self._last_archive_path = page.archive_path
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if self.browser.supports_tab_control:
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Create a tab if there's none.
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if len(self.browser.tabs) == 0:
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self.browser.tabs.New()
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Ensure only one tab is open.
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      while len(self.browser.tabs) > 1:
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self.browser.tabs[-1].Close()
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not self.tab:
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self.tab = self.browser.tabs[0]
737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
74a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if self.first_page[page]:
75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      self.first_page[page] = False
767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def StopBrowser(self):
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if self.tab:
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.tab.Disconnect()
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.tab = None
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if self.browser:
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.browser.Close()
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.browser = None
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Restarting the state will also restart the wpr server. If we're
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # recording, we need to continue adding into the same wpr archive,
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # not overwrite it.
897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self._append_to_existing_wpr = True
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def StartProfiling(self, page, options):
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if not self.profiler_dir:
93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      self.profiler_dir = tempfile.mkdtemp()
94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    output_file = os.path.join(self.profiler_dir, page.url_as_file_safe_name)
95a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if options.repeat_options.IsRepeating():
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      output_file = _GetSequentialFileName(output_file)
97a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.browser.StartProfiling(options.profiler, output_file)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def StopProfiling(self):
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self.browser.StopProfiling()
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class PageState(object):
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def __init__(self):
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._did_login = False
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  def PreparePage(self, page, tab, test=None):
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parsed_url = urlparse.urlparse(page.url)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if parsed_url[0] == 'file':
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      serving_dirs, filename = page.serving_dirs_and_file
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if tab.browser.SetHTTPServerDirectories(serving_dirs) and test:
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        test.DidStartHTTPServer(tab)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      target_side_url = tab.browser.http_server.UrlOf(filename)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else:
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      target_side_url = page.url
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if page.credentials:
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if not tab.browser.credentials.LoginNeeded(tab, page.credentials):
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        raise page_test.Failure('Login as ' + page.credentials + ' failed')
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self._did_login = True
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if test:
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if test.clear_cache_before_each_run:
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        tab.ClearCache()
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      test.WillNavigateToPage(page, tab)
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    tab.Navigate(target_side_url, page.script_to_evaluate_on_commit)
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if test:
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      test.DidNavigateToPage(page, tab)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    page.WaitToLoad(tab, 60)
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def CleanUpPage(self, page, tab):
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if page.credentials and self._did_login:
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab.browser.credentials.LoginNoLongerNeeded(tab, page.credentials)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def AddCommandLineOptions(parser):
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  page_filter_module.PageFilter.AddCommandLineOptions(parser)
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochdef _LogStackTrace(title, browser):
143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  stack_trace = browser.GetStackTrace()
144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  stack_trace = (('\nStack Trace:\n') +
145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            ('*' * 80) +
146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            '\n\t' + stack_trace.replace('\n', '\n\t') + '\n' +
147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            ('*' * 80))
148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  logging.warning('%s%s', title, stack_trace)
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
151a3f7b4e666c476898878fa745f637129375cd889Ben Murdochdef _PrepareAndRunPage(test, page_set, expectations, options, page,
152a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                       credentials_path, possible_browser, results, state):
153a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if options.wpr_mode != wpr_modes.WPR_RECORD:
154a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if page.archive_path and os.path.isfile(page.archive_path):
155a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      possible_browser.options.wpr_mode = wpr_modes.WPR_REPLAY
156a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    else:
157a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      possible_browser.options.wpr_mode = wpr_modes.WPR_OFF
158a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  results_for_current_run = results
159a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if state.first_page[page] and test.discard_first_result:
160a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    # If discarding results, substitute a dummy object.
161a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    results_for_current_run = type(results)()
162a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  results_for_current_run.StartTest(page)
163a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  tries = 3
164a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  while tries:
165a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    try:
166a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      state.StartBrowser(test, page_set, page, possible_browser,
167a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                         credentials_path, page.archive_path)
168a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
169a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      _WaitForThermalThrottlingIfNeeded(state.browser.platform)
170a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
171a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      if options.profiler:
172a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        state.StartProfiling(page, options)
173a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
174a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      expectation = expectations.GetExpectationForPage(
175a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          state.browser.platform, page)
176a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
177a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      try:
178a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        _RunPage(test, page, state.tab, expectation,
179a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 results_for_current_run, options)
180a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        _CheckThermalThrottling(state.browser.platform)
181a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      except exceptions.TabCrashException:
182a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        _LogStackTrace('Tab crashed: %s' % page.url, state.browser)
183a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        state.StopBrowser()
184a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
185a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      if options.profiler:
186a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        state.StopProfiling()
187a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
188a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      if test.NeedsBrowserRestartAfterEachRun(state.tab):
189a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        state.StopBrowser()
190a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
191a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      break
192a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    except exceptions.BrowserGoneException:
193a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      _LogStackTrace('Browser crashed', state.browser)
194a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      logging.warning('Lost connection to browser. Retrying.')
195a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      state.StopBrowser()
196a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      tries -= 1
197a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      if not tries:
198a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        logging.error('Lost connection to browser 3 times. Failing.')
199a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        raise
200a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  results_for_current_run.StopTest(page)
201a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
202a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochdef Run(test, page_set, expectations, options):
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  """Runs a given test against a given page_set with the given options."""
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  results = test.PrepareResults(options)
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Create a possible_browser with the given options.
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test.CustomizeBrowserOptions(options)
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  possible_browser = browser_finder.FindBrowser(options)
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if not possible_browser:
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    raise Exception('No browser found.\n'
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        'Use --browser=list to figure out which are available.')
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Reorder page set based on options.
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pages = _ShuffleAndFilterPageSet(page_set, options)
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (not options.allow_live_sites and
2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      options.wpr_mode != wpr_modes.WPR_RECORD):
2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    pages = _CheckArchives(page_set, pages, results)
2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Verify credentials path.
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  credentials_path = None
2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if page_set.credentials_path:
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    credentials_path = os.path.join(os.path.dirname(page_set.file_path),
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    page_set.credentials_path)
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not os.path.exists(credentials_path):
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      credentials_path = None
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Set up user agent.
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if page_set.user_agent_type:
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    options.browser_user_agent_type = page_set.user_agent_type
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for page in pages:
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    test.CustomizeBrowserOptionsForPage(page, possible_browser.options)
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
236a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  for page in list(pages):
237a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if not test.CanRunForPage(page):
238a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      logging.warning('Skipping test: it cannot run for %s', page.url)
239a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      results.AddSkip(page, 'Test cannot run')
240a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      pages.remove(page)
241a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
242a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if not pages:
243a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return results
244a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  state = _RunState()
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # TODO(dtu): Move results creation and results_for_current_run into RunState.
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  try:
249a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    test.WillRunTest(state.tab)
250a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    repeat_state = page_runner_repeat.PageRunnerRepeatState(
251a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                       options.repeat_options)
252a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
253a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    repeat_state.WillRunPageSet()
254a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    while repeat_state.ShouldRepeatPageSet():
255a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      for page in pages:
256a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        repeat_state.WillRunPage()
257a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        while repeat_state.ShouldRepeatPage():
258a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          # execute test on page
259a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          _PrepareAndRunPage(test, page_set, expectations, options, page,
260a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                             credentials_path, possible_browser, results, state)
261a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          repeat_state.DidRunPage()
262a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      repeat_state.DidRunPageSet()
263a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
264a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    test.DidRunTest(state.tab, results)
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  finally:
2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    state.StopBrowser()
2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return results
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _ShuffleAndFilterPageSet(page_set, options):
2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if options.pageset_shuffle_order_file and not options.pageset_shuffle:
2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    raise Exception('--pageset-shuffle-order-file requires --pageset-shuffle.')
2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if options.pageset_shuffle_order_file:
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return page_set.ReorderPageSet(options.pageset_shuffle_order_file)
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  page_filter = page_filter_module.PageFilter(options)
2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pages = [page for page in page_set.pages[:]
2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           if not page.disabled and page_filter.IsSelected(page)]
2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if options.pageset_shuffle:
2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    random.Random().shuffle(pages)
284a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
285a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return pages
2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _CheckArchives(page_set, pages, results):
2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  """Returns a subset of pages that are local or have WPR archives.
2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Logs warnings if any are missing."""
2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  page_set_has_live_sites = False
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for page in pages:
2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    parsed_url = urlparse.urlparse(page.url)
2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if parsed_url.scheme != 'chrome' and parsed_url.scheme != 'file':
2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      page_set_has_live_sites = True
2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break
2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Potential problems with the entire page set.
3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if page_set_has_live_sites:
3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not page_set.archive_data_file:
3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      logging.warning('The page set is missing an "archive_data_file" '
3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      'property. Skipping any live sites. To include them, '
3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      'pass the flag --allow-live-sites.')
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not page_set.wpr_archive_info:
3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      logging.warning('The archive info file is missing. '
3077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      'To fix this, either add svn-internal to your '
3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      '.gclient using http://goto/read-src-internal, '
3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      'or create a new archive using record_wpr.')
3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Potential problems with individual pages.
3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pages_missing_archive_path = []
3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pages_missing_archive_data = []
3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for page in pages:
3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    parsed_url = urlparse.urlparse(page.url)
3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if parsed_url.scheme == 'chrome' or parsed_url.scheme == 'file':
3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue
3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not page.archive_path:
3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pages_missing_archive_path.append(page)
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    elif not os.path.isfile(page.archive_path):
3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pages_missing_archive_data.append(page)
3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if pages_missing_archive_path:
3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.warning('The page set archives for some pages do not exist. '
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'Skipping those pages. To fix this, record those pages '
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'using record_wpr. To ignore this warning and run '
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'against live sites, pass the flag --allow-live-sites.')
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if pages_missing_archive_data:
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.warning('The page set archives for some pages are missing. '
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'Someone forgot to check them in, or they were deleted. '
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'Skipping those pages. To fix this, record those pages '
3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'using record_wpr. To ignore this warning and run '
3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'against live sites, pass the flag --allow-live-sites.')
3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for page in pages_missing_archive_path + pages_missing_archive_data:
3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    results.StartTest(page)
3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    results.AddErrorMessage(page, 'Page set archive doesn\'t exist.')
3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    results.StopTest(page)
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return [page for page in pages if page not in
3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          pages_missing_archive_path + pages_missing_archive_data]
3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochdef _RunPage(test, page, tab, expectation, results, options):
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  logging.info('Running %s' % page.url)
3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  page_state = PageState()
3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  try:
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    page_state.PreparePage(page, tab, test)
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    test.Run(options, page, tab, results)
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    util.CloseConnections(tab)
3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  except page_test.Failure:
3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.warning('%s:\n%s', page.url, traceback.format_exc())
357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if expectation == 'fail':
358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      logging.info('Failure was expected\n')
359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      results.AddSuccess(page)
360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    else:
361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      results.AddFailure(page, sys.exc_info())
3627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  except (util.TimeoutException, exceptions.LoginException):
3637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.error('%s:\n%s', page.url, traceback.format_exc())
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    results.AddError(page, sys.exc_info())
3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  except (exceptions.TabCrashException, exceptions.BrowserGoneException):
3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.error('%s:\n%s', page.url, traceback.format_exc())
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    results.AddError(page, sys.exc_info())
3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    # Run() catches these exceptions to relaunch the tab/browser, so re-raise.
3697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    raise
3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  except Exception:
3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    raise
3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  else:
373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if expectation == 'fail':
374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      logging.warning('%s was expected to fail, but passed.\n', page.url)
3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    results.AddSuccess(page)
3767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  finally:
3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    page_state.CleanUpPage(page, tab)
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _GetSequentialFileName(base_name):
3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  """Returns the next sequential file name based on |base_name| and the
3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  existing files."""
3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  index = 0
3847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  while True:
3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    output_name = '%s_%03d' % (base_name, index)
3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not glob.glob(output_name + '.*'):
3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break
3887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    index = index + 1
3897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return output_name
3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _WaitForThermalThrottlingIfNeeded(platform):
3937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if not platform.CanMonitorThermalThrottling():
3947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return
3957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  thermal_throttling_retry = 0
3967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  while (platform.IsThermallyThrottled() and
3977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)         thermal_throttling_retry < 3):
3987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.warning('Thermally throttled, waiting (%d)...',
3997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    thermal_throttling_retry)
4007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    thermal_throttling_retry += 1
4017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    time.sleep(thermal_throttling_retry * 2)
4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if thermal_throttling_retry and platform.IsThermallyThrottled():
4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.error('Device is thermally throttled before running '
4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                  'performance tests, results will vary.')
4067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _CheckThermalThrottling(platform):
4097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if not platform.CanMonitorThermalThrottling():
4107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return
4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if platform.HasBeenThermallyThrottled():
4127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.error('Device has been thermally throttled during '
4137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                  'performance tests, results will vary.')
414