Home | History | Annotate | Download | only in page
      1 # Copyright 2014 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import os
      6 import re
      7 import shutil
      8 import sys
      9 import StringIO
     10 import tempfile
     11 import unittest
     12 
     13 from telemetry import benchmark
     14 from telemetry import story
     15 from telemetry.core import exceptions
     16 from telemetry.core import util
     17 from telemetry import decorators
     18 from telemetry.internal.browser import browser_finder
     19 from telemetry.internal.browser import user_agent
     20 from telemetry.internal.results import results_options
     21 from telemetry.internal import story_runner
     22 from telemetry.internal.testing.page_sets import example_domain
     23 from telemetry.internal.util import exception_formatter
     24 from telemetry.page import page as page_module
     25 from telemetry.page import page_test
     26 from telemetry.page import shared_page_state
     27 from telemetry.util import image_util
     28 from telemetry.testing import fakes
     29 from telemetry.testing import options_for_unittests
     30 from telemetry.testing import system_stub
     31 
     32 
     33 SIMPLE_CREDENTIALS_STRING = """
     34 {
     35   "test": {
     36     "username": "example",
     37     "password": "asdf"
     38   }
     39 }
     40 """
     41 
     42 
     43 class DummyTest(page_test.PageTest):
     44 
     45   def ValidateAndMeasurePage(self, *_):
     46     pass
     47 
     48 
     49 def SetUpStoryRunnerArguments(options):
     50   parser = options.CreateParser()
     51   story_runner.AddCommandLineArgs(parser)
     52   options.MergeDefaultValues(parser.get_default_values())
     53   story_runner.ProcessCommandLineArgs(parser, options)
     54 
     55 
     56 class EmptyMetadataForTest(benchmark.BenchmarkMetadata):
     57 
     58   def __init__(self):
     59     super(EmptyMetadataForTest, self).__init__('')
     60 
     61 
     62 class StubCredentialsBackend(object):
     63 
     64   def __init__(self, login_return_value):
     65     self.did_get_login = False
     66     self.did_get_login_no_longer_needed = False
     67     self.login_return_value = login_return_value
     68 
     69   @property
     70   def credentials_type(self):
     71     return 'test'
     72 
     73   def LoginNeeded(self, *_):
     74     self.did_get_login = True
     75     return self.login_return_value
     76 
     77   def LoginNoLongerNeeded(self, _):
     78     self.did_get_login_no_longer_needed = True
     79 
     80 
     81 def GetSuccessfulPageRuns(results):
     82   return [run for run in results.all_page_runs if run.ok or run.skipped]
     83 
     84 
     85 def CaptureStderr(func, output_buffer):
     86   def wrapper(*args, **kwargs):
     87     original_stderr, sys.stderr = sys.stderr, output_buffer
     88     try:
     89       return func(*args, **kwargs)
     90     finally:
     91       sys.stderr = original_stderr
     92   return wrapper
     93 
     94 
     95 # TODO: remove test cases that use real browsers and replace with a
     96 # story_runner or shared_page_state unittest that tests the same logic.
     97 class ActualPageRunEndToEndTests(unittest.TestCase):
     98   # TODO(nduca): Move the basic "test failed, test succeeded" tests from
     99   # page_test_unittest to here.
    100 
    101   def setUp(self):
    102     self._story_runner_logging_stub = None
    103     self._formatted_exception_buffer = StringIO.StringIO()
    104     self._original_formatter = exception_formatter.PrintFormattedException
    105 
    106   def tearDown(self):
    107     self.RestoreExceptionFormatter()
    108 
    109   def CaptureFormattedException(self):
    110     exception_formatter.PrintFormattedException = CaptureStderr(
    111         exception_formatter.PrintFormattedException,
    112         self._formatted_exception_buffer)
    113     self._story_runner_logging_stub = system_stub.Override(
    114         story_runner, ['logging'])
    115 
    116   @property
    117   def formatted_exception(self):
    118     return self._formatted_exception_buffer.getvalue()
    119 
    120   def RestoreExceptionFormatter(self):
    121     exception_formatter.PrintFormattedException = self._original_formatter
    122     if self._story_runner_logging_stub:
    123       self._story_runner_logging_stub.Restore()
    124       self._story_runner_logging_stub = None
    125 
    126   def assertFormattedExceptionIsEmpty(self):
    127     self.longMessage = False
    128     self.assertEquals(
    129         '', self.formatted_exception,
    130         msg='Expected empty formatted exception: actual=%s' % '\n   > '.join(
    131             self.formatted_exception.split('\n')))
    132 
    133   def assertFormattedExceptionOnlyHas(self, expected_exception_name):
    134     self.longMessage = True
    135     actual_exception_names = re.findall(r'^Traceback.*?^(\w+)',
    136                                         self.formatted_exception,
    137                                         re.DOTALL | re.MULTILINE)
    138     self.assertEquals([expected_exception_name], actual_exception_names,
    139                       msg='Full formatted exception: %s' % '\n   > '.join(
    140                           self.formatted_exception.split('\n')))
    141 
    142   def testRaiseBrowserGoneExceptionFromRestartBrowserBeforeEachPage(self):
    143     self.CaptureFormattedException()
    144     story_set = story.StorySet()
    145     story_set.AddStory(page_module.Page(
    146         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()))
    147     story_set.AddStory(page_module.Page(
    148         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()))
    149     story_set.AddStory(page_module.Page(
    150         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()))
    151 
    152     class Test(page_test.PageTest):
    153 
    154       def __init__(self, *args):
    155         super(Test, self).__init__(
    156             *args, needs_browser_restart_after_each_page=True)
    157         self.run_count = 0
    158 
    159       def RestartBrowserBeforeEachPage(self):
    160         # This will only be called twice with 3 pages.
    161         old_run_count = self.run_count
    162         self.run_count += 1
    163         if old_run_count == 1:
    164           raise exceptions.BrowserGoneException(None)
    165         return self._needs_browser_restart_after_each_page
    166 
    167       def ValidateAndMeasurePage(self, page, tab, results):
    168         pass
    169 
    170     options = options_for_unittests.GetCopy()
    171     options.output_formats = ['none']
    172     options.suppress_gtest_report = True
    173     test = Test()
    174     SetUpStoryRunnerArguments(options)
    175     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    176     story_runner.Run(test, story_set, options, results)
    177     self.assertEquals(2, test.run_count)
    178     self.assertEquals(2, len(GetSuccessfulPageRuns(results)))
    179     self.assertEquals(1, len(results.failures))
    180     self.assertFormattedExceptionIsEmpty()
    181 
    182   def testNeedsBrowserRestartAfterEachPage(self):
    183     self.CaptureFormattedException()
    184     story_set = story.StorySet()
    185     story_set.AddStory(page_module.Page(
    186         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()))
    187     story_set.AddStory(page_module.Page(
    188         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()))
    189 
    190     class Test(page_test.PageTest):
    191 
    192       def __init__(self, *args, **kwargs):
    193         super(Test, self).__init__(*args, **kwargs)
    194         self.browser_starts = 0
    195 
    196       def DidStartBrowser(self, *args):
    197         super(Test, self).DidStartBrowser(*args)
    198         self.browser_starts += 1
    199 
    200       def ValidateAndMeasurePage(self, page, tab, results):
    201         pass
    202 
    203     options = options_for_unittests.GetCopy()
    204     options.output_formats = ['none']
    205     options.suppress_gtest_report = True
    206     test = Test(needs_browser_restart_after_each_page=True)
    207     SetUpStoryRunnerArguments(options)
    208     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    209     story_runner.Run(test, story_set, options, results)
    210     self.assertEquals(2, len(GetSuccessfulPageRuns(results)))
    211     self.assertEquals(2, test.browser_starts)
    212     self.assertFormattedExceptionIsEmpty()
    213 
    214   def testCredentialsWhenLoginFails(self):
    215     self.CaptureFormattedException()
    216     credentials_backend = StubCredentialsBackend(login_return_value=False)
    217     did_run = self.runCredentialsTest(credentials_backend)
    218     assert credentials_backend.did_get_login
    219     assert not credentials_backend.did_get_login_no_longer_needed
    220     assert not did_run
    221     self.assertFormattedExceptionIsEmpty()
    222 
    223   def testCredentialsWhenLoginSucceeds(self):
    224     credentials_backend = StubCredentialsBackend(login_return_value=True)
    225     did_run = self.runCredentialsTest(credentials_backend)
    226     assert credentials_backend.did_get_login
    227     assert credentials_backend.did_get_login_no_longer_needed
    228     assert did_run
    229 
    230   def runCredentialsTest(self, credentials_backend):
    231     story_set = story.StorySet()
    232     did_run = [False]
    233 
    234     try:
    235       with tempfile.NamedTemporaryFile(delete=False) as f:
    236         page = page_module.Page(
    237             'file://blank.html', story_set, base_dir=util.GetUnittestDataDir(),
    238             credentials_path=f.name)
    239         page.credentials = "test"
    240         story_set.AddStory(page)
    241 
    242         f.write(SIMPLE_CREDENTIALS_STRING)
    243 
    244       class TestThatInstallsCredentialsBackend(page_test.PageTest):
    245 
    246         def __init__(self, credentials_backend):
    247           super(TestThatInstallsCredentialsBackend, self).__init__()
    248           self._credentials_backend = credentials_backend
    249 
    250         def DidStartBrowser(self, browser):
    251           browser.credentials.AddBackend(self._credentials_backend)
    252 
    253         def ValidateAndMeasurePage(self, *_):
    254           did_run[0] = True
    255 
    256       test = TestThatInstallsCredentialsBackend(credentials_backend)
    257       options = options_for_unittests.GetCopy()
    258       options.output_formats = ['none']
    259       options.suppress_gtest_report = True
    260       SetUpStoryRunnerArguments(options)
    261       results = results_options.CreateResults(EmptyMetadataForTest(), options)
    262       story_runner.Run(test, story_set, options, results)
    263     finally:
    264       os.remove(f.name)
    265 
    266     return did_run[0]
    267 
    268   @decorators.Disabled('chromeos')  # crbug.com/483212
    269   def testUserAgent(self):
    270     story_set = story.StorySet()
    271     page = page_module.Page(
    272         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir(),
    273         shared_page_state_class=shared_page_state.SharedTabletPageState)
    274     story_set.AddStory(page)
    275 
    276     class TestUserAgent(page_test.PageTest):
    277       def ValidateAndMeasurePage(self, page, tab, results):
    278         del page, results  # unused
    279         actual_user_agent = tab.EvaluateJavaScript('window.navigator.userAgent')
    280         expected_user_agent = user_agent.UA_TYPE_MAPPING['tablet']
    281         assert actual_user_agent.strip() == expected_user_agent
    282 
    283         # This is so we can check later that the test actually made it into this
    284         # function. Previously it was timing out before even getting here, which
    285         # should fail, but since it skipped all the asserts, it slipped by.
    286         self.hasRun = True  # pylint: disable=attribute-defined-outside-init
    287 
    288     test = TestUserAgent()
    289     options = options_for_unittests.GetCopy()
    290     options.output_formats = ['none']
    291     options.suppress_gtest_report = True
    292     SetUpStoryRunnerArguments(options)
    293     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    294     story_runner.Run(test, story_set, options, results)
    295 
    296     self.assertTrue(hasattr(test, 'hasRun') and test.hasRun)
    297 
    298   # Ensure that story_runner forces exactly 1 tab before running a page.
    299   @decorators.Enabled('has tabs')
    300   def testOneTab(self):
    301     story_set = story.StorySet()
    302     page = page_module.Page(
    303         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())
    304     story_set.AddStory(page)
    305 
    306     class TestOneTab(page_test.PageTest):
    307 
    308       def DidStartBrowser(self, browser):
    309         browser.tabs.New()
    310 
    311       def ValidateAndMeasurePage(self, page, tab, results):
    312         del page, results  # unused
    313         assert len(tab.browser.tabs) == 1
    314 
    315     test = TestOneTab()
    316     options = options_for_unittests.GetCopy()
    317     options.output_formats = ['none']
    318     options.suppress_gtest_report = True
    319     SetUpStoryRunnerArguments(options)
    320     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    321     story_runner.Run(test, story_set, options, results)
    322 
    323   # Ensure that story_runner allows >1 tab for multi-tab test.
    324   @decorators.Enabled('has tabs')
    325   def testMultipleTabsOkayForMultiTabTest(self):
    326     story_set = story.StorySet()
    327     page = page_module.Page(
    328         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())
    329     story_set.AddStory(page)
    330 
    331     class TestMultiTabs(page_test.PageTest):
    332       def TabForPage(self, page, browser):
    333         del page  # unused
    334         return browser.tabs.New()
    335 
    336       def ValidateAndMeasurePage(self, page, tab, results):
    337         del page, results  # unused
    338         assert len(tab.browser.tabs) == 2
    339 
    340     test = TestMultiTabs()
    341     options = options_for_unittests.GetCopy()
    342     options.output_formats = ['none']
    343     options.suppress_gtest_report = True
    344     SetUpStoryRunnerArguments(options)
    345     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    346     story_runner.Run(test, story_set, options, results)
    347 
    348   # Ensure that story_runner allows the test to customize the browser
    349   # before it launches.
    350   def testBrowserBeforeLaunch(self):
    351     story_set = story.StorySet()
    352     page = page_module.Page(
    353         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())
    354     story_set.AddStory(page)
    355 
    356     class TestBeforeLaunch(page_test.PageTest):
    357 
    358       def __init__(self):
    359         super(TestBeforeLaunch, self).__init__()
    360         self._did_call_will_start = False
    361         self._did_call_did_start = False
    362 
    363       def WillStartBrowser(self, platform):
    364         self._did_call_will_start = True
    365         # TODO(simonjam): Test that the profile is available.
    366 
    367       def DidStartBrowser(self, browser):
    368         assert self._did_call_will_start
    369         self._did_call_did_start = True
    370 
    371       def ValidateAndMeasurePage(self, *_):
    372         assert self._did_call_did_start
    373 
    374     test = TestBeforeLaunch()
    375     options = options_for_unittests.GetCopy()
    376     options.output_formats = ['none']
    377     options.suppress_gtest_report = True
    378     SetUpStoryRunnerArguments(options)
    379     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    380     story_runner.Run(test, story_set, options, results)
    381 
    382   def testRunPageWithStartupUrl(self):
    383     num_times_browser_closed = [0]
    384 
    385     class TestSharedState(shared_page_state.SharedPageState):
    386 
    387       def _StopBrowser(self):
    388         super(TestSharedState, self)._StopBrowser()
    389         num_times_browser_closed[0] += 1
    390 
    391     story_set = story.StorySet()
    392     page = page_module.Page(
    393         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir(),
    394         startup_url='about:blank', shared_page_state_class=TestSharedState)
    395     story_set.AddStory(page)
    396 
    397     class Measurement(page_test.PageTest):
    398 
    399       def __init__(self):
    400         super(Measurement, self).__init__()
    401 
    402       def ValidateAndMeasurePage(self, page, tab, results):
    403         del page, tab, results  # not used
    404 
    405     options = options_for_unittests.GetCopy()
    406     options.page_repeat = 2
    407     options.output_formats = ['none']
    408     options.suppress_gtest_report = True
    409     if not browser_finder.FindBrowser(options):
    410       return
    411     test = Measurement()
    412     SetUpStoryRunnerArguments(options)
    413     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    414     story_runner.Run(test, story_set, options, results)
    415     self.assertEquals('about:blank', options.browser_options.startup_url)
    416     # _StopBrowser should be called 2 times:
    417     # 1. browser restarts after page 1 run
    418     # 2. in the TearDownState after all the pages have run.
    419     self.assertEquals(num_times_browser_closed[0], 2)
    420 
    421   # Ensure that story_runner calls cleanUp when a page run fails.
    422   def testCleanUpPage(self):
    423     story_set = story.StorySet()
    424     page = page_module.Page(
    425         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir())
    426     story_set.AddStory(page)
    427 
    428     class Test(page_test.PageTest):
    429 
    430       def __init__(self):
    431         super(Test, self).__init__()
    432         self.did_call_clean_up = False
    433 
    434       def ValidateAndMeasurePage(self, *_):
    435         raise page_test.Failure
    436 
    437       def DidRunPage(self, platform):
    438         del platform  # unused
    439         self.did_call_clean_up = True
    440 
    441     test = Test()
    442     options = options_for_unittests.GetCopy()
    443     options.output_formats = ['none']
    444     options.suppress_gtest_report = True
    445     SetUpStoryRunnerArguments(options)
    446     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    447     story_runner.Run(test, story_set, options, results)
    448     assert test.did_call_clean_up
    449 
    450   # Ensure skipping the test if shared state cannot be run on the browser.
    451   def testSharedPageStateCannotRunOnBrowser(self):
    452     story_set = story.StorySet()
    453 
    454     class UnrunnableSharedState(shared_page_state.SharedPageState):
    455       def CanRunOnBrowser(self, browser_info, page):
    456         del browser_info, page  # unused
    457         return False
    458 
    459       def ValidateAndMeasurePage(self, _):
    460         pass
    461 
    462     story_set.AddStory(page_module.Page(
    463         url='file://blank.html', page_set=story_set,
    464         base_dir=util.GetUnittestDataDir(),
    465         shared_page_state_class=UnrunnableSharedState))
    466 
    467     class Test(page_test.PageTest):
    468 
    469       def __init__(self, *args, **kwargs):
    470         super(Test, self).__init__(*args, **kwargs)
    471         self.will_navigate_to_page_called = False
    472 
    473       def ValidateAndMeasurePage(self, *args):
    474         del args  # unused
    475         raise Exception('Exception should not be thrown')
    476 
    477       def WillNavigateToPage(self, page, tab):
    478         del page, tab  # unused
    479         self.will_navigate_to_page_called = True
    480 
    481     test = Test()
    482     options = options_for_unittests.GetCopy()
    483     options.output_formats = ['none']
    484     options.suppress_gtest_report = True
    485     SetUpStoryRunnerArguments(options)
    486     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    487     story_runner.Run(test, story_set, options, results)
    488     self.assertFalse(test.will_navigate_to_page_called)
    489     self.assertEquals(1, len(GetSuccessfulPageRuns(results)))
    490     self.assertEquals(1, len(results.skipped_values))
    491     self.assertEquals(0, len(results.failures))
    492 
    493   def testRunPageWithProfilingFlag(self):
    494     story_set = story.StorySet()
    495     story_set.AddStory(page_module.Page(
    496         'file://blank.html', story_set, base_dir=util.GetUnittestDataDir()))
    497 
    498     class Measurement(page_test.PageTest):
    499 
    500       def ValidateAndMeasurePage(self, page, tab, results):
    501         pass
    502 
    503     options = options_for_unittests.GetCopy()
    504     options.output_formats = ['none']
    505     options.suppress_gtest_report = True
    506     options.reset_results = None
    507     options.upload_results = None
    508     options.results_label = None
    509     options.output_dir = tempfile.mkdtemp()
    510     options.profiler = 'trace'
    511     try:
    512       SetUpStoryRunnerArguments(options)
    513       results = results_options.CreateResults(EmptyMetadataForTest(), options)
    514       story_runner.Run(Measurement(), story_set, options, results)
    515       self.assertEquals(1, len(GetSuccessfulPageRuns(results)))
    516       self.assertEquals(0, len(results.failures))
    517       self.assertEquals(0, len(results.all_page_specific_values))
    518       self.assertTrue(os.path.isfile(
    519           os.path.join(options.output_dir, 'blank_html.zip')))
    520     finally:
    521       shutil.rmtree(options.output_dir)
    522 
    523   def _RunPageTestThatRaisesAppCrashException(self, test, max_failures):
    524     class TestPage(page_module.Page):
    525 
    526       def RunNavigateSteps(self, _):
    527         raise exceptions.AppCrashException
    528 
    529     story_set = story.StorySet()
    530     for _ in range(5):
    531       story_set.AddStory(
    532           TestPage('file://blank.html', story_set,
    533                    base_dir=util.GetUnittestDataDir()))
    534     options = options_for_unittests.GetCopy()
    535     options.output_formats = ['none']
    536     options.suppress_gtest_report = True
    537     SetUpStoryRunnerArguments(options)
    538     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    539     story_runner.Run(test, story_set, options, results,
    540                      max_failures=max_failures)
    541     return results
    542 
    543   def testSingleTabMeansCrashWillCauseFailureValue(self):
    544     self.CaptureFormattedException()
    545 
    546     class SingleTabTest(page_test.PageTest):
    547       # Test is not multi-tab because it does not override TabForPage.
    548 
    549       def ValidateAndMeasurePage(self, *_):
    550         pass
    551 
    552     test = SingleTabTest()
    553     results = self._RunPageTestThatRaisesAppCrashException(
    554         test, max_failures=1)
    555     self.assertEquals([], GetSuccessfulPageRuns(results))
    556     self.assertEquals(2, len(results.failures))  # max_failures + 1
    557     self.assertFormattedExceptionIsEmpty()
    558 
    559   @decorators.Enabled('has tabs')
    560   def testMultipleTabsMeansCrashRaises(self):
    561     self.CaptureFormattedException()
    562 
    563     class MultipleTabsTest(page_test.PageTest):
    564       # Test *is* multi-tab because it overrides TabForPage.
    565 
    566       def TabForPage(self, page, browser):
    567         return browser.tabs.New()
    568 
    569       def ValidateAndMeasurePage(self, *_):
    570         pass
    571 
    572     test = MultipleTabsTest()
    573     with self.assertRaises(page_test.MultiTabTestAppCrashError):
    574       self._RunPageTestThatRaisesAppCrashException(test, max_failures=1)
    575     self.assertFormattedExceptionOnlyHas('AppCrashException')
    576 
    577   def testWebPageReplay(self):
    578     story_set = example_domain.ExampleDomainPageSet()
    579     body = []
    580 
    581     class TestWpr(page_test.PageTest):
    582       def ValidateAndMeasurePage(self, page, tab, results):
    583         del page, results  # unused
    584         body.append(tab.EvaluateJavaScript('document.body.innerText'))
    585 
    586       def DidRunPage(self, platform):
    587         # Force the replay server to restart between pages; this verifies that
    588         # the restart mechanism works.
    589         platform.network_controller.StopReplay()
    590 
    591     test = TestWpr()
    592     options = options_for_unittests.GetCopy()
    593     options.output_formats = ['none']
    594     options.suppress_gtest_report = True
    595     SetUpStoryRunnerArguments(options)
    596     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    597 
    598     story_runner.Run(test, story_set, options, results)
    599 
    600     self.longMessage = True
    601     self.assertIn('Example Domain', body[0],
    602                   msg='URL: %s' % story_set.stories[0].url)
    603     self.assertIn('Example Domain', body[1],
    604                   msg='URL: %s' % story_set.stories[1].url)
    605 
    606     self.assertEquals(2, len(GetSuccessfulPageRuns(results)))
    607     self.assertEquals(0, len(results.failures))
    608 
    609   def testScreenShotTakenForFailedPage(self):
    610     self.CaptureFormattedException()
    611     platform_screenshot_supported = [False]
    612     tab_screenshot_supported = [False]
    613     chrome_version_screen_shot = [None]
    614 
    615     class FailingTestPage(page_module.Page):
    616 
    617       def RunNavigateSteps(self, action_runner):
    618         action_runner.Navigate(self._url)
    619         platform_screenshot_supported[0] = (
    620             action_runner.tab.browser.platform.CanTakeScreenshot)
    621         tab_screenshot_supported[0] = action_runner.tab.screenshot_supported
    622         if not platform_screenshot_supported[0] and tab_screenshot_supported[0]:
    623           chrome_version_screen_shot[0] = action_runner.tab.Screenshot()
    624         raise exceptions.AppCrashException
    625 
    626     story_set = story.StorySet()
    627     story_set.AddStory(page_module.Page('file://blank.html', story_set))
    628     failing_page = FailingTestPage('chrome://version', story_set)
    629     story_set.AddStory(failing_page)
    630     options = options_for_unittests.GetCopy()
    631     options.output_formats = ['none']
    632     options.browser_options.take_screenshot_for_failed_page = True
    633     options.suppress_gtest_report = True
    634     SetUpStoryRunnerArguments(options)
    635     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    636     story_runner.Run(DummyTest(), story_set, options, results,
    637                      max_failures=2)
    638     self.assertEquals(1, len(results.failures))
    639     if not platform_screenshot_supported[0] and tab_screenshot_supported[0]:
    640       self.assertEquals(1, len(results.pages_to_profiling_files))
    641       self.assertIn(failing_page,
    642                     results.pages_to_profiling_files)
    643       screenshot_file_path = (
    644           results.pages_to_profiling_files[failing_page][0].GetAbsPath())
    645       try:
    646         actual_screenshot = image_util.FromPngFile(screenshot_file_path)
    647         self.assertEquals(image_util.Pixels(chrome_version_screen_shot[0]),
    648                           image_util.Pixels(actual_screenshot))
    649       finally:  # Must clean up screenshot file if exists.
    650         os.remove(screenshot_file_path)
    651 
    652   def testNoProfilingFilesCreatedForPageByDefault(self):
    653     self.CaptureFormattedException()
    654 
    655     class FailingTestPage(page_module.Page):
    656 
    657       def RunNavigateSteps(self, action_runner):
    658         action_runner.Navigate(self._url)
    659         raise exceptions.AppCrashException
    660 
    661     story_set = story.StorySet()
    662     story_set.AddStory(page_module.Page('file://blank.html', story_set))
    663     failing_page = FailingTestPage('chrome://version', story_set)
    664     story_set.AddStory(failing_page)
    665     options = options_for_unittests.GetCopy()
    666     options.output_formats = ['none']
    667     options.suppress_gtest_report = True
    668     SetUpStoryRunnerArguments(options)
    669     results = results_options.CreateResults(EmptyMetadataForTest(), options)
    670     story_runner.Run(DummyTest(), story_set, options, results,
    671                      max_failures=2)
    672     self.assertEquals(1, len(results.failures))
    673     self.assertEquals(0, len(results.pages_to_profiling_files))
    674 
    675 
    676 class FakePageRunEndToEndTests(unittest.TestCase):
    677 
    678   def setUp(self):
    679     self.options = fakes.CreateBrowserFinderOptions()
    680     self.options.output_formats = ['none']
    681     self.options.suppress_gtest_report = True
    682     SetUpStoryRunnerArguments(self.options)
    683 
    684   def testNoScreenShotTakenForFailedPageDueToNoSupport(self):
    685     self.options.browser_options.take_screenshot_for_failed_page = True
    686 
    687     class FailingTestPage(page_module.Page):
    688 
    689       def RunNavigateSteps(self, action_runner):
    690         raise exceptions.AppCrashException
    691 
    692     story_set = story.StorySet()
    693     story_set.AddStory(page_module.Page('file://blank.html', story_set))
    694     failing_page = FailingTestPage('chrome://version', story_set)
    695     story_set.AddStory(failing_page)
    696     results = results_options.CreateResults(
    697         EmptyMetadataForTest(), self.options)
    698     story_runner.Run(DummyTest(), story_set, self.options, results,
    699                      max_failures=2)
    700     self.assertEquals(1, len(results.failures))
    701     self.assertEquals(0, len(results.pages_to_profiling_files))
    702 
    703   def testScreenShotTakenForFailedPageOnSupportedPlatform(self):
    704     fake_platform = self.options.fake_possible_browser.returned_browser.platform
    705     expected_png_base64 = """
    706  iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91
    707  JpzAAAAFklEQVR4Xg3EAQ0AAABAMP1LY3YI7l8l6A
    708  T8tgwbJAAAAABJRU5ErkJggg==
    709 """
    710     fake_platform.screenshot_png_data = expected_png_base64
    711     self.options.browser_options.take_screenshot_for_failed_page = True
    712 
    713     class FailingTestPage(page_module.Page):
    714 
    715       def RunNavigateSteps(self, action_runner):
    716         raise exceptions.AppCrashException
    717     story_set = story.StorySet()
    718     story_set.AddStory(page_module.Page('file://blank.html', story_set))
    719     failing_page = FailingTestPage('chrome://version', story_set)
    720     story_set.AddStory(failing_page)
    721 
    722     results = results_options.CreateResults(
    723         EmptyMetadataForTest(), self.options)
    724     story_runner.Run(DummyTest(), story_set, self.options, results,
    725                      max_failures=2)
    726     self.assertEquals(1, len(results.failures))
    727     self.assertEquals(1, len(results.pages_to_profiling_files))
    728     self.assertIn(failing_page,
    729                   results.pages_to_profiling_files)
    730     screenshot_file_path = (
    731         results.pages_to_profiling_files[failing_page][0].GetAbsPath())
    732     try:
    733       actual_screenshot_img = image_util.FromPngFile(screenshot_file_path)
    734       self.assertTrue(image_util.AreEqual(
    735                       image_util.FromBase64Png(expected_png_base64),
    736                       actual_screenshot_img))
    737     finally:  # Must clean up screenshot file if exists.
    738       os.remove(screenshot_file_path)
    739