1# Copyright 2012 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 5import logging 6import tempfile 7import time 8 9from telemetry.core import exceptions 10from telemetry.core import util 11from telemetry import decorators 12from telemetry.internal.image_processing import video 13from telemetry.page import action_runner 14from telemetry.testing import tab_test_case 15from telemetry.timeline import model 16from telemetry.timeline import tracing_config 17from telemetry.util import image_util 18from telemetry.util import rgba_color 19 20 21def _IsDocumentVisible(tab): 22 return not tab.EvaluateJavaScript('document.hidden || document.webkitHidden') 23 24 25class FakePlatformBackend(object): 26 def __init__(self): 27 self.platform = FakePlatform() 28 29 def DidStartBrowser(self, _, _2): 30 pass 31 32 def WillCloseBrowser(self, _, _2): 33 pass 34 35 36class FakePlatform(object): 37 def __init__(self): 38 self._is_video_capture_running = False 39 40 #pylint: disable=unused-argument 41 def StartVideoCapture(self, min_bitrate_mbps): 42 self._is_video_capture_running = True 43 44 def StopVideoCapture(self): 45 self._is_video_capture_running = False 46 return video.Video(tempfile.NamedTemporaryFile()) 47 48 @property 49 def is_video_capture_running(self): 50 return self._is_video_capture_running 51 52 53class TabTest(tab_test_case.TabTestCase): 54 def testNavigateAndWaitForCompleteState(self): 55 self._tab.Navigate(self.UrlOfUnittestFile('blank.html')) 56 self._tab.WaitForDocumentReadyStateToBeComplete() 57 58 def testNavigateAndWaitForInteractiveState(self): 59 self._tab.Navigate(self.UrlOfUnittestFile('blank.html')) 60 self._tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() 61 62 def testTabBrowserIsRightBrowser(self): 63 self.assertEquals(self._tab.browser, self._browser) 64 65 def testRendererCrash(self): 66 self.assertRaises(exceptions.DevtoolsTargetCrashException, 67 lambda: self._tab.Navigate('chrome://crash', 68 timeout=30)) 69 70 def testTimeoutExceptionIncludeConsoleMessage(self): 71 self._tab.EvaluateJavaScript(""" 72 window.__set_timeout_called = false; 73 function buggyReference() { 74 window.__set_timeout_called = true; 75 if (window.__one.not_defined === undefined) 76 window.__one = 1; 77 } 78 setTimeout(buggyReference, 200);""") 79 self._tab.WaitForJavaScriptExpression( 80 'window.__set_timeout_called === true', 5) 81 with self.assertRaises(exceptions.TimeoutException) as context: 82 self._tab.WaitForJavaScriptExpression( 83 'window.__one === 1', 1) 84 self.assertIn( 85 ("(error) :5: Uncaught TypeError: Cannot read property 'not_defined' " 86 'of undefined\n'), 87 context.exception.message) 88 89 @decorators.Enabled('has tabs') 90 def testActivateTab(self): 91 util.WaitFor(lambda: _IsDocumentVisible(self._tab), timeout=5) 92 new_tab = self._browser.tabs.New() 93 new_tab.Navigate('about:blank') 94 util.WaitFor(lambda: _IsDocumentVisible(new_tab), timeout=5) 95 self.assertFalse(_IsDocumentVisible(self._tab)) 96 self._tab.Activate() 97 util.WaitFor(lambda: _IsDocumentVisible(self._tab), timeout=5) 98 self.assertFalse(_IsDocumentVisible(new_tab)) 99 100 def testTabUrl(self): 101 self.assertEquals(self._tab.url, 'about:blank') 102 url = self.UrlOfUnittestFile('blank.html') 103 self._tab.Navigate(url) 104 self.assertEquals(self._tab.url, url) 105 106 #pylint: disable=protected-access 107 def testIsVideoCaptureRunning(self): 108 original_platform_backend = self._tab.browser._platform_backend 109 try: 110 self._tab.browser._platform_backend = FakePlatformBackend() 111 self.assertFalse(self._tab.is_video_capture_running) 112 self._tab.StartVideoCapture(min_bitrate_mbps=2) 113 self.assertTrue(self._tab.is_video_capture_running) 114 self.assertIsNotNone(self._tab.StopVideoCapture()) 115 self.assertFalse(self._tab.is_video_capture_running) 116 finally: 117 self._tab.browser._platform_backend = original_platform_backend 118 119 # Test failing on android: http://crbug.com/437057 120 # and mac: http://crbug.com/468675 121 @decorators.Disabled('android', 'chromeos', 'mac') 122 @decorators.Disabled('win') # crbug.com/570955 123 def testHighlight(self): 124 self.assertEquals(self._tab.url, 'about:blank') 125 config = tracing_config.TracingConfig() 126 config.SetNoOverheadFilter() 127 config.enable_chrome_trace = True 128 self._browser.platform.tracing_controller.StartTracing(config) 129 self._tab.Highlight(rgba_color.WEB_PAGE_TEST_ORANGE) 130 self._tab.ClearHighlight(rgba_color.WEB_PAGE_TEST_ORANGE) 131 trace_data = self._browser.platform.tracing_controller.StopTracing() 132 timeline_model = model.TimelineModel(trace_data) 133 renderer_thread = timeline_model.GetRendererThreadFromTabId( 134 self._tab.id) 135 found_video_start_event = False 136 for event in renderer_thread.async_slices: 137 if event.name == '__ClearHighlight.video_capture_start': 138 found_video_start_event = True 139 break 140 self.assertTrue(found_video_start_event) 141 142 @decorators.Enabled('has tabs') 143 @decorators.Disabled('mac', 'linux') # crbug.com/499207. 144 @decorators.Disabled('win') # crbug.com/570955. 145 def testGetRendererThreadFromTabId(self): 146 self.assertEquals(self._tab.url, 'about:blank') 147 # Create 3 tabs. The third tab is closed before we call 148 # tracing_controller.StartTracing. 149 first_tab = self._tab 150 second_tab = self._browser.tabs.New() 151 second_tab.Navigate('about:blank') 152 second_tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() 153 third_tab = self._browser.tabs.New() 154 third_tab.Navigate('about:blank') 155 third_tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() 156 third_tab.Close() 157 config = tracing_config.TracingConfig() 158 config.SetNoOverheadFilter() 159 config.enable_chrome_trace = True 160 self._browser.platform.tracing_controller.StartTracing(config) 161 first_tab.ExecuteJavaScript('console.time("first-tab-marker");') 162 first_tab.ExecuteJavaScript('console.timeEnd("first-tab-marker");') 163 second_tab.ExecuteJavaScript('console.time("second-tab-marker");') 164 second_tab.ExecuteJavaScript('console.timeEnd("second-tab-marker");') 165 trace_data = self._browser.platform.tracing_controller.StopTracing() 166 timeline_model = model.TimelineModel(trace_data) 167 168 # Assert that the renderer_thread of the first tab contains 169 # 'first-tab-marker'. 170 renderer_thread = timeline_model.GetRendererThreadFromTabId( 171 first_tab.id) 172 first_tab_markers = [ 173 renderer_thread.IterAllSlicesOfName('first-tab-marker')] 174 self.assertEquals(1, len(first_tab_markers)) 175 176 # Close second tab and assert that the renderer_thread of the second tab 177 # contains 'second-tab-marker'. 178 second_tab.Close() 179 renderer_thread = timeline_model.GetRendererThreadFromTabId( 180 second_tab.id) 181 second_tab_markers = [ 182 renderer_thread.IterAllSlicesOfName('second-tab-marker')] 183 self.assertEquals(1, len(second_tab_markers)) 184 185 # Third tab wasn't available when we start tracing, so there is no 186 # renderer_thread corresponding to it in the the trace. 187 self.assertIs(None, timeline_model.GetRendererThreadFromTabId(third_tab.id)) 188 189 @decorators.Disabled('android') # https://crbug.com/463933 190 def testTabIsAlive(self): 191 self.assertEquals(self._tab.url, 'about:blank') 192 self.assertTrue(self._tab.IsAlive()) 193 194 self._tab.Navigate(self.UrlOfUnittestFile('blank.html')) 195 self.assertTrue(self._tab.IsAlive()) 196 197 self.assertRaises(exceptions.DevtoolsTargetCrashException, 198 lambda: self._tab.Navigate(self.UrlOfUnittestFile('chrome://crash'))) 199 self.assertFalse(self._tab.IsAlive()) 200 201 202class GpuTabTest(tab_test_case.TabTestCase): 203 @classmethod 204 def CustomizeBrowserOptions(cls, options): 205 options.AppendExtraBrowserArgs('--enable-gpu-benchmarking') 206 207 # Test flaky on mac: crbug.com/358664, chromeos: crbug.com/483212. 208 @decorators.Disabled('android', 'mac', 'chromeos') 209 def testScreenshot(self): 210 if not self._tab.screenshot_supported: 211 logging.warning('Browser does not support screenshots, skipping test.') 212 return 213 214 self.Navigate('green_rect.html') 215 pixel_ratio = self._tab.EvaluateJavaScript('window.devicePixelRatio || 1') 216 217 screenshot = self._tab.Screenshot(5) 218 assert screenshot is not None 219 image_util.GetPixelColor( 220 screenshot, 0 * pixel_ratio, 0 * pixel_ratio).AssertIsRGB( 221 0, 255, 0, tolerance=2) 222 image_util.GetPixelColor( 223 screenshot, 31 * pixel_ratio, 31 * pixel_ratio).AssertIsRGB( 224 0, 255, 0, tolerance=2) 225 image_util.GetPixelColor( 226 screenshot, 32 * pixel_ratio, 32 * pixel_ratio).AssertIsRGB( 227 255, 255, 255, tolerance=2) 228 229 230class MediaRouterDialogTabTest(tab_test_case.TabTestCase): 231 @classmethod 232 def CustomizeBrowserOptions(cls, options): 233 options.AppendExtraBrowserArgs('--media-router=1') 234 235 # There is no media router dialog on android/chromeos, it is a desktop-only 236 # feature. 237 @decorators.Disabled('android', 'chromeos') 238 def testMediaRouterDialog(self): 239 self._tab.Navigate(self.UrlOfUnittestFile('cast.html')) 240 self._tab.WaitForDocumentReadyStateToBeComplete() 241 runner = action_runner.ActionRunner(self._tab) 242 runner.TapElement(selector='#start_session_button') 243 # Wait for media router dialog 244 start_time = time.time() 245 while (time.time() - start_time < 5 and 246 len(self.tabs) != 2): 247 time.sleep(1) 248 self.assertEquals(len(self.tabs), 2) 249 self.assertEquals(self.tabs[1].url, 'chrome://media-router/') 250