page_runner.py revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Copyright 2014 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.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5a3f7b4e666c476898878fa745f637129375cd889Ben Murdochimport collections
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import logging
7a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochimport optparse
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import random
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import sys
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochimport tempfile
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import time
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from telemetry import decorators
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)from telemetry.core import browser_finder
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from telemetry.core import browser_info
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)from telemetry.core import exceptions
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import util
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import wpr_modes
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)from telemetry.core.platform.profiler import profiler_finder
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)from telemetry.page import page_filter
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.page import page_test
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)from telemetry.page.actions import navigate
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from telemetry.page.actions import page_action
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)from telemetry.results import results_options
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfrom telemetry.util import cloud_storage
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochfrom telemetry.util import exception_formatter
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from telemetry.value import failure
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from telemetry.value import skip
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class _RunState(object):
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self):
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.browser = None
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._append_to_existing_wpr = False
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._last_archive_path = None
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._first_browser = True
39a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    self.first_page = collections.defaultdict(lambda: True)
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    self.profiler_dir = None
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  def StartBrowserIfNeeded(self, test, page_set, page, possible_browser,
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           credentials_path, archive_path, finder_options):
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    started_browser = not self.browser
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    # Create a browser.
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not self.browser:
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      test.CustomizeBrowserOptionsForSinglePage(page, finder_options)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self.browser = possible_browser.Create()
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self.browser.credentials.credentials_path = credentials_path
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      # Set up WPR path on the new browser.
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self.browser.SetReplayArchivePath(archive_path,
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        self._append_to_existing_wpr,
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        page_set.make_javascript_deterministic)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      self._last_archive_path = page.archive_path
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      test.WillStartBrowser(self.browser)
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      self.browser.Start()
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      test.DidStartBrowser(self.browser)
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if self._first_browser:
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self._first_browser = False
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self.browser.credentials.WarnIfMissingCredentials(page_set)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        logging.info('OS: %s %s',
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     self.browser.platform.GetOSName(),
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     self.browser.platform.GetOSVersionName())
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if self.browser.supports_system_info:
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          system_info = self.browser.GetSystemInfo()
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if system_info.model_name:
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            logging.info('Model: %s', system_info.model_name)
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if system_info.gpu:
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            for i, device in enumerate(system_info.gpu.devices):
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              logging.info('GPU device %d: %s', i, device)
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            if system_info.gpu.aux_attributes:
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              logging.info('GPU Attributes:')
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              for k, v in sorted(system_info.gpu.aux_attributes.iteritems()):
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                logging.info('  %-20s: %s', k, v)
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            if system_info.gpu.feature_status:
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              logging.info('Feature Status:')
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              for k, v in sorted(system_info.gpu.feature_status.iteritems()):
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                logging.info('  %-20s: %s', k, v)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if system_info.gpu.driver_bug_workarounds:
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              logging.info('Driver Bug Workarounds:')
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              for workaround in system_info.gpu.driver_bug_workarounds:
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                logging.info('  %s', workaround)
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          else:
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            logging.info('No GPU devices')
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        else:
8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          logging.warning('System info not supported')
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    else:
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Set up WPR path if it changed.
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if page.archive_path and self._last_archive_path != page.archive_path:
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        self.browser.SetReplayArchivePath(
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            page.archive_path,
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            self._append_to_existing_wpr,
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            page_set.make_javascript_deterministic)
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self._last_archive_path = page.archive_path
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if self.browser.supports_tab_control and test.close_tabs_before_run:
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Create a tab if there's none.
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if len(self.browser.tabs) == 0:
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        self.browser.tabs.New()
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      # Ensure only one tab is open, unless the test is a multi-tab test.
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if not test.is_multi_tab_test:
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        while len(self.browser.tabs) > 1:
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          self.browser.tabs[-1].Close()
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      # Must wait for tab to commit otherwise it can commit after the next
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      # navigation has begun and RenderFrameHostManager::DidNavigateMainFrame()
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      # will cancel the next navigation because it's pending. This manifests as
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      # the first navigation in a PageSet freezing indefinitly because the
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      # navigation was silently cancelled when |self.browser.tabs[0]| was
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      # committed. Only do this when we just started the browser, otherwise
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      # there are cases where previous pages in a PageSet never complete
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      # loading so we'll wait forever.
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if started_browser:
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        self.browser.tabs[0].WaitForDocumentReadyStateToBeComplete()
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def StopBrowser(self):
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if self.browser:
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.browser.Close()
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.browser = None
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # Restarting the state will also restart the wpr server. If we're
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # recording, we need to continue adding into the same wpr archive,
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      # not overwrite it.
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self._append_to_existing_wpr = True
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  def StartProfiling(self, page, finder_options):
131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if not self.profiler_dir:
132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      self.profiler_dir = tempfile.mkdtemp()
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    output_file = os.path.join(self.profiler_dir, page.file_safe_name)
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    is_repeating = (finder_options.page_repeat != 1 or
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                    finder_options.pageset_repeat != 1)
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if is_repeating:
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      output_file = util.GetSequentialFileName(output_file)
138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    self.browser.StartProfiling(finder_options.profiler, output_file)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  def StopProfiling(self):
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if self.browser:
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      self.browser.StopProfiling()
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class PageState(object):
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def __init__(self, page, tab):
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.page = page
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.tab = tab
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self._did_login = False
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def PreparePage(self, test=None):
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if self.page.is_file:
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      server_started = self.tab.browser.SetHTTPServerDirectories(
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        self.page.page_set.serving_dirs | set([self.page.serving_dir]))
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if server_started and test:
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        test.DidStartHTTPServer(self.tab)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if self.page.credentials:
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if not self.tab.browser.credentials.LoginNeeded(
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          self.tab, self.page.credentials):
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        raise page_test.Failure('Login as ' + self.page.credentials + ' failed')
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      self._did_login = True
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if test:
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if test.clear_cache_before_each_run:
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        self.tab.ClearCache(force=True)
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def ImplicitPageNavigation(self, test=None):
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    """Executes the implicit navigation that occurs for every page iteration.
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    This function will be called once per page before any actions are executed.
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    """
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if test:
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      test.WillNavigateToPage(self.page, self.tab)
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      test.RunNavigateSteps(self.page, self.tab)
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      test.DidNavigateToPage(self.page, self.tab)
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    else:
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      i = navigate.NavigateAction()
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      i.RunAction(self.page, self.tab, None)
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  def CleanUpPage(self, test):
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    test.CleanUpAfterPage(self.page, self.tab)
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if self.page.credentials and self._did_login:
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      self.tab.browser.credentials.LoginNoLongerNeeded(
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          self.tab, self.page.credentials)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def AddCommandLineArgs(parser):
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  page_filter.PageFilter.AddCommandLineArgs(parser)
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  results_options.AddResultsOptions(parser)
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  # Page set options
194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  group = optparse.OptionGroup(parser, 'Page set ordering and repeat options')
195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  group.add_option('--pageset-shuffle', action='store_true',
196a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      dest='pageset_shuffle',
197a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      help='Shuffle the order of pages within a pageset.')
198a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  group.add_option('--pageset-shuffle-order-file',
199a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      dest='pageset_shuffle_order_file', default=None,
200a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      help='Filename of an output of a previously run test on the current '
201a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      'pageset. The tests will run in the same order again, overriding '
202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      'what is specified by --page-repeat and --pageset-repeat.')
203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  group.add_option('--page-repeat', default=1, type='int',
204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   help='Number of times to repeat each individual page '
205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   'before proceeding with the next page in the pageset.')
206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  group.add_option('--pageset-repeat', default=1, type='int',
207a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   help='Number of times to repeat the entire pageset.')
208a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  parser.add_option_group(group)
209a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
210a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  # WPR options
211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  group = optparse.OptionGroup(parser, 'Web Page Replay options')
2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  group.add_option('--use-live-sites',
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      dest='use_live_sites', action='store_true',
2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      help='Run against live sites and ignore the Web Page Replay archives.')
215a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  parser.add_option_group(group)
216a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  parser.add_option('-d', '--also-run-disabled-tests',
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    dest='run_disabled_tests',
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    action='store_true', default=False,
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    help='Ignore @Disabled and @Enabled restrictions.')
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def ProcessCommandLineArgs(parser, args):
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  page_filter.PageFilter.ProcessCommandLineArgs(parser, args)
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
225a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  # Page set options
226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if args.pageset_shuffle_order_file and not args.pageset_shuffle:
227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    parser.error('--pageset-shuffle-order-file requires --pageset-shuffle.')
228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if args.page_repeat < 1:
230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    parser.error('--page-repeat must be a positive integer.')
231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if args.pageset_repeat < 1:
232a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    parser.error('--pageset-repeat must be a positive integer.')
233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)def _PrepareAndRunPage(test, page_set, expectations, finder_options,
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       browser_options, page, credentials_path,
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       possible_browser, results, state):
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if finder_options.use_live_sites:
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    browser_options.wpr_mode = wpr_modes.WPR_OFF
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  elif browser_options.wpr_mode != wpr_modes.WPR_RECORD:
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    browser_options.wpr_mode = (
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        wpr_modes.WPR_REPLAY
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if page.archive_path and os.path.isfile(page.archive_path)
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        else wpr_modes.WPR_OFF)
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  max_attempts = test.attempts
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  attempt_num = 0
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while attempt_num < max_attempts:
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    attempt_num = attempt_num + 1
250a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    try:
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      results.WillAttemptPageRun(attempt_num, max_attempts)
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if test.RestartBrowserBeforeEachPage() or page.startup_url:
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state.StopBrowser()
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # If we are restarting the browser for each page customize the per page
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # options for just the current page before starting the browser.
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      state.StartBrowserIfNeeded(test, page_set, page, possible_browser,
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 credentials_path, page.archive_path,
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 finder_options)
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if not page.CanRunOnBrowser(browser_info.BrowserInfo(state.browser)):
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        logging.info('Skip test for page %s because browser is not supported.'
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     % page.url)
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return
264a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      expectation = expectations.GetExpectationForPage(state.browser, page)
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
267a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      _WaitForThermalThrottlingIfNeeded(state.browser.platform)
268a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if finder_options.profiler:
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        state.StartProfiling(page, finder_options)
271a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
272a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      try:
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        _RunPage(test, page, state, expectation, results)
274a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        _CheckThermalThrottling(state.browser.platform)
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      except exceptions.TabCrashException as e:
2768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if test.is_multi_tab_test:
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          logging.error('Aborting multi-tab test after tab %s crashed',
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        page.url)
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          raise
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        logging.warning(str(e))
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        state.StopBrowser()
282a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if finder_options.profiler:
284a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        state.StopProfiling()
285a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (test.StopBrowserAfterPage(state.browser, page)):
287a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        state.StopBrowser()
288a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    except exceptions.BrowserGoneException as e:
291a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      state.StopBrowser()
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if attempt_num == max_attempts:
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        logging.error('Aborting after too many retries')
294a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        raise
2958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if test.is_multi_tab_test:
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        logging.error('Aborting multi-tab test after browser crashed')
2978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        raise
298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      logging.warning(str(e))
299a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
300a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)@decorators.Cache
3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochdef _UpdatePageSetArchivesIfChanged(page_set):
3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  # Attempt to download the credentials file.
3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if page_set.credentials_path:
3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    try:
3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      cloud_storage.GetIfChanged(
3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          os.path.join(page_set.base_dir, page_set.credentials_path))
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    except (cloud_storage.CredentialsError, cloud_storage.PermissionError,
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            cloud_storage.CloudStorageError) as e:
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      logging.warning('Cannot retrieve credential file %s due to cloud storage '
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      'error %s', page_set.credentials_path, str(e))
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  # Scan every serving directory for .sha1 files
3140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  # and download them from Cloud Storage. Assume all data is public.
3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  all_serving_dirs = page_set.serving_dirs.copy()
3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  # Add individual page dirs to all serving dirs.
3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for page in page_set:
3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if page.is_file:
3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      all_serving_dirs.add(page.serving_dir)
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  # Scan all serving dirs.
3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for serving_dir in all_serving_dirs:
3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if os.path.splitdrive(serving_dir)[1] == '/':
3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      raise ValueError('Trying to serve root directory from HTTP server.')
3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    for dirpath, _, filenames in os.walk(serving_dir):
3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      for filename in filenames:
3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        path, extension = os.path.splitext(
3270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            os.path.join(dirpath, filename))
3280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        if extension != '.sha1':
3290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          continue
330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        cloud_storage.GetIfChanged(path, page_set.bucket)
3310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def Run(test, page_set, expectations, finder_options, results):
3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  """Runs a given test against a given page_set with the given options."""
3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  test.ValidatePageSet(page_set)
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Create a possible_browser with the given options.
338bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  try:
339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    possible_browser = browser_finder.FindBrowser(finder_options)
340bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  except browser_finder.BrowserTypeRequiredException, e:
341bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    sys.stderr.write(str(e) + '\n')
342c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    sys.exit(-1)
3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if not possible_browser:
344bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    sys.stderr.write(
345bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        'No browser found. Available browsers:\n' +
346424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        '\n'.join(browser_finder.GetAllAvailableBrowserTypes(finder_options)) +
347424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        '\n')
348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    sys.exit(-1)
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  browser_options = possible_browser.finder_options.browser_options
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  browser_options.browser_type = possible_browser.browser_type
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test.CustomizeBrowserOptions(browser_options)
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  should_run = decorators.IsEnabled(test, possible_browser)
355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  should_run = should_run or finder_options.run_disabled_tests
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if not should_run:
359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    logging.warning('You are trying to run a disabled test.')
360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    logging.warning('Pass --also-run-disabled-tests to squelch this message.')
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
36303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if possible_browser.IsRemote():
36403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    possible_browser.RunRemote()
36503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    sys.exit(0)
36603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Reorder page set based on options.
368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  pages = _ShuffleAndFilterPageSet(page_set, finder_options)
3697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (not finder_options.use_live_sites and
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      browser_options.wpr_mode != wpr_modes.WPR_RECORD):
3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    _UpdatePageSetArchivesIfChanged(page_set)
3737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    pages = _CheckArchives(page_set, pages, results)
3747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Verify credentials path.
3767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  credentials_path = None
3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if page_set.credentials_path:
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    credentials_path = os.path.join(os.path.dirname(page_set.file_path),
3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    page_set.credentials_path)
3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not os.path.exists(credentials_path):
3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      credentials_path = None
3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Set up user agent.
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  browser_options.browser_user_agent_type = page_set.user_agent_type or None
3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if finder_options.profiler:
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    profiler_class = profiler_finder.FindProfiler(finder_options.profiler)
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    profiler_class.CustomizeBrowserOptions(browser_options.browser_type,
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                           finder_options)
3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
391a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  for page in list(pages):
392a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if not test.CanRunForPage(page):
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      results.WillRunPage(page)
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      logging.debug('Skipping test: it cannot run for %s', page.url)
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      results.AddValue(skip.SkipValue(page, 'Test cannot run'))
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      results.DidRunPage(page)
397a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      pages.remove(page)
398a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
399a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if not pages:
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return
401a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  state = _RunState()
4037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # TODO(dtu): Move results creation and results_for_current_run into RunState.
4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  try:
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    test.WillRunTest(finder_options)
4076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    for _ in xrange(0, finder_options.pageset_repeat):
408a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      for page in pages:
4096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if test.IsExiting():
4106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          break
4116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        test.WillRunPageRepeats(page)
4136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        for _ in xrange(0, finder_options.page_repeat):
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          results.WillRunPage(page)
415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          try:
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            _PrepareAndRunPage(
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                test, page_set, expectations, finder_options, browser_options,
418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                page, credentials_path, possible_browser, results, state)
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          finally:
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            discard_run = False
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if state.first_page[page]:
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              state.first_page[page] = False
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              if test.discard_first_result:
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                discard_run = True
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            results.DidRunPage(page, discard_run=discard_run)
4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        test.DidRunPageRepeats(page)
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (not test.max_failures is None and
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            len(results.failures) > test.max_failures):
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          logging.error('Too many failures. Aborting.')
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          test.RequestExit()
431a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
4327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  finally:
4336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    test.DidRunTest(state.browser, results)
4347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    state.StopBrowser()
4357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return
4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)def _ShuffleAndFilterPageSet(page_set, finder_options):
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if finder_options.pageset_shuffle_order_file:
441424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return page_set.ReorderPageSet(finder_options.pageset_shuffle_order_file)
4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pages = [page for page in page_set.pages[:]
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           if not page.disabled and page_filter.PageFilter.IsSelected(page)]
4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if finder_options.pageset_shuffle:
4477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    random.Random().shuffle(pages)
448a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
449a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return pages
4507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _CheckArchives(page_set, pages, results):
4537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  """Returns a subset of pages that are local or have WPR archives.
4547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Logs warnings if any are missing."""
4567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  page_set_has_live_sites = False
4577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for page in pages:
458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if not page.is_local:
4597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      page_set_has_live_sites = True
4607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break
4617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Potential problems with the entire page set.
4637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if page_set_has_live_sites:
4647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not page_set.archive_data_file:
4657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      logging.warning('The page set is missing an "archive_data_file" '
4667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      'property. Skipping any live sites. To include them, '
4670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                      'pass the flag --use-live-sites.')
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not page_set.wpr_archive_info:
4697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      logging.warning('The archive info file is missing. '
4707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      'To fix this, either add svn-internal to your '
4717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      '.gclient using http://goto/read-src-internal, '
4727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      'or create a new archive using record_wpr.')
4737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  # Potential problems with individual pages.
4757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pages_missing_archive_path = []
4767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pages_missing_archive_data = []
4777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for page in pages:
479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if page.is_local:
4807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue
4817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if not page.archive_path:
4837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pages_missing_archive_path.append(page)
484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    elif not os.path.isfile(page.archive_path):
4857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pages_missing_archive_data.append(page)
4867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if pages_missing_archive_path:
4887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.warning('The page set archives for some pages do not exist. '
4897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'Skipping those pages. To fix this, record those pages '
4907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'using record_wpr. To ignore this warning and run '
4910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    'against live sites, pass the flag --use-live-sites.')
4927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if pages_missing_archive_data:
4937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.warning('The page set archives for some pages are missing. '
4947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'Someone forgot to check them in, or they were deleted. '
4957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'Skipping those pages. To fix this, record those pages '
4967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    'using record_wpr. To ignore this warning and run '
4970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    'against live sites, pass the flag --use-live-sites.')
4987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for page in pages_missing_archive_path + pages_missing_archive_data:
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    results.WillRunPage(page)
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    results.AddValue(failure.FailureValue.FromMessage(
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        page, 'Page set archive doesn\'t exist.'))
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    results.DidRunPage(page)
5047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return [page for page in pages if page not in
5067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          pages_missing_archive_path + pages_missing_archive_data]
5077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)def _RunPage(test, page, state, expectation, results):
510424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if expectation == 'skip':
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    logging.debug('Skipping test: Skip expectation for %s', page.url)
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    results.AddValue(skip.SkipValue(page, 'Skipped by test expectations'))
513424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return
514424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  logging.info('Running %s', page.url)
5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  page_state = PageState(page, test.TabForPage(page, state.browser))
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  def ProcessError():
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if expectation == 'fail':
521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      msg = 'Expected exception while running %s' % page.url
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    else:
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      msg = 'Exception while running %s' % page.url
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      results.AddValue(failure.FailureValue(page, sys.exc_info()))
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    exception_formatter.PrintFormattedException(msg=msg)
5267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  try:
5281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    page_state.PreparePage(test)
5296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    page_state.ImplicitPageNavigation(test)
53023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    test.RunPage(page, page_state.tab, results)
5311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    util.CloseConnections(page_state.tab)
5324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  except page_test.TestNotSupportedOnPlatformFailure:
5334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    raise
5347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  except page_test.Failure:
535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if expectation == 'fail':
536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      exception_formatter.PrintFormattedException(
537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          msg='Expected failure while running %s' % page.url)
538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    else:
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      exception_formatter.PrintFormattedException(
540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          msg='Failure while running %s' % page.url)
5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      results.AddValue(failure.FailureValue(page, sys.exc_info()))
542558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  except (util.TimeoutException, exceptions.LoginException,
543558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          exceptions.ProfilingException):
5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ProcessError()
5457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  except (exceptions.TabCrashException, exceptions.BrowserGoneException):
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ProcessError()
5477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    # Run() catches these exceptions to relaunch the tab/browser, so re-raise.
5487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    raise
549a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  except page_action.PageActionNotSupported as e:
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    results.AddValue(skip.SkipValue(page, 'Unsupported page action: %s' % e))
5517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  except Exception:
552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    exception_formatter.PrintFormattedException(
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        msg='Unhandled exception while running %s' % page.url)
5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    results.AddValue(failure.FailureValue(page, sys.exc_info()))
5557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  else:
556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if expectation == 'fail':
557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      logging.warning('%s was expected to fail, but passed.\n', page.url)
5587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  finally:
559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    page_state.CleanUpPage(test)
5607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _WaitForThermalThrottlingIfNeeded(platform):
5637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if not platform.CanMonitorThermalThrottling():
5647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return
5657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  thermal_throttling_retry = 0
5667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  while (platform.IsThermallyThrottled() and
5677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)         thermal_throttling_retry < 3):
5687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    logging.warning('Thermally throttled, waiting (%d)...',
5697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    thermal_throttling_retry)
5707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    thermal_throttling_retry += 1
5717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    time.sleep(thermal_throttling_retry * 2)
5727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if thermal_throttling_retry and platform.IsThermallyThrottled():
574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    logging.warning('Device is thermally throttled before running '
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    'performance tests, results will vary.')
5767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def _CheckThermalThrottling(platform):
5797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if not platform.CanMonitorThermalThrottling():
5807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return
5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if platform.HasBeenThermallyThrottled():
582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    logging.warning('Device has been thermally throttled during '
583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    'performance tests, results will vary.')
584