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 os 7import shutil 8import tempfile 9import unittest 10 11from telemetry.core import exceptions 12from telemetry import decorators 13from telemetry.internal.browser import browser as browser_module 14from telemetry.internal.browser import browser_finder 15from telemetry.internal.platform import gpu_device 16from telemetry.internal.platform import gpu_info 17from telemetry.internal.platform import system_info 18from telemetry.internal.util import path 19from telemetry.testing import browser_test_case 20from telemetry.testing import options_for_unittests 21from telemetry.timeline import tracing_config 22 23import mock 24import py_utils 25 26class IntentionalException(Exception): 27 pass 28 29 30class BrowserTest(browser_test_case.BrowserTestCase): 31 def testBrowserCreation(self): 32 self.assertEquals(1, len(self._browser.tabs)) 33 34 # Different browsers boot up to different things. 35 assert self._browser.tabs[0].url 36 37 @decorators.Enabled('has tabs') 38 def testNewCloseTab(self): 39 existing_tab = self._browser.tabs[0] 40 self.assertEquals(1, len(self._browser.tabs)) 41 existing_tab_url = existing_tab.url 42 43 new_tab = self._browser.tabs.New() 44 self.assertEquals(2, len(self._browser.tabs)) 45 self.assertEquals(existing_tab.url, existing_tab_url) 46 self.assertEquals(new_tab.url, 'about:blank') 47 48 new_tab.Close() 49 self.assertEquals(1, len(self._browser.tabs)) 50 self.assertEquals(existing_tab.url, existing_tab_url) 51 52 def testMultipleTabCalls(self): 53 self._browser.tabs[0].Navigate(self.UrlOfUnittestFile('blank.html')) 54 self._browser.tabs[0].WaitForDocumentReadyStateToBeInteractiveOrBetter() 55 56 def testTabCallByReference(self): 57 tab = self._browser.tabs[0] 58 tab.Navigate(self.UrlOfUnittestFile('blank.html')) 59 self._browser.tabs[0].WaitForDocumentReadyStateToBeInteractiveOrBetter() 60 61 @decorators.Enabled('has tabs') 62 def testCloseReferencedTab(self): 63 self._browser.tabs.New() 64 tab = self._browser.tabs[0] 65 tab.Navigate(self.UrlOfUnittestFile('blank.html')) 66 tab.Close() 67 self.assertEquals(1, len(self._browser.tabs)) 68 69 @decorators.Enabled('has tabs') 70 def testForegroundTab(self): 71 # Should be only one tab at this stage, so that must be the foreground tab 72 original_tab = self._browser.tabs[0] 73 self.assertEqual(self._browser.foreground_tab, original_tab) 74 new_tab = self._browser.tabs.New() 75 # New tab shouls be foreground tab 76 self.assertEqual(self._browser.foreground_tab, new_tab) 77 # Make sure that activating the background tab makes it the foreground tab 78 original_tab.Activate() 79 self.assertEqual(self._browser.foreground_tab, original_tab) 80 # Closing the current foreground tab should switch the foreground tab to the 81 # other tab 82 original_tab.Close() 83 self.assertEqual(self._browser.foreground_tab, new_tab) 84 85 # This test uses the reference browser and doesn't have access to 86 # helper binaries like crashpad_database_util. 87 @decorators.Enabled('linux') 88 def testGetMinidumpPathOnCrash(self): 89 tab = self._browser.tabs[0] 90 with self.assertRaises(exceptions.AppCrashException): 91 tab.Navigate('chrome://crash', timeout=5) 92 crash_minidump_path = self._browser.GetMostRecentMinidumpPath() 93 self.assertIsNotNone(crash_minidump_path) 94 95 def testGetSystemInfo(self): 96 if not self._browser.supports_system_info: 97 logging.warning( 98 'Browser does not support getting system info, skipping test.') 99 return 100 101 info = self._browser.GetSystemInfo() 102 103 self.assertTrue(isinstance(info, system_info.SystemInfo)) 104 self.assertTrue(hasattr(info, 'model_name')) 105 self.assertTrue(hasattr(info, 'gpu')) 106 self.assertTrue(isinstance(info.gpu, gpu_info.GPUInfo)) 107 self.assertTrue(hasattr(info.gpu, 'devices')) 108 self.assertTrue(len(info.gpu.devices) > 0) 109 for g in info.gpu.devices: 110 self.assertTrue(isinstance(g, gpu_device.GPUDevice)) 111 112 def testGetSystemInfoNotCachedObject(self): 113 if not self._browser.supports_system_info: 114 logging.warning( 115 'Browser does not support getting system info, skipping test.') 116 return 117 118 info_a = self._browser.GetSystemInfo() 119 info_b = self._browser.GetSystemInfo() 120 self.assertFalse(info_a is info_b) 121 122 def testGetSystemTotalMemory(self): 123 self.assertTrue(self._browser.memory_stats['SystemTotalPhysicalMemory'] > 0) 124 125 126 # crbug.com/628836 (CrOS, where system-guest indicates ChromeOS guest) 127 # github.com/catapult-project/catapult/issues/3130 (Windows) 128 @decorators.Disabled('cros-chrome-guest', 'system-guest', 'chromeos', 'win') 129 def testIsTracingRunning(self): 130 tracing_controller = self._browser.platform.tracing_controller 131 if not tracing_controller.IsChromeTracingSupported(): 132 return 133 self.assertFalse(tracing_controller.is_tracing_running) 134 config = tracing_config.TracingConfig() 135 config.enable_chrome_trace = True 136 tracing_controller.StartTracing(config) 137 self.assertTrue(tracing_controller.is_tracing_running) 138 tracing_controller.StopTracing() 139 self.assertFalse(tracing_controller.is_tracing_running) 140 141 142class CommandLineBrowserTest(browser_test_case.BrowserTestCase): 143 @classmethod 144 def CustomizeBrowserOptions(cls, options): 145 options.AppendExtraBrowserArgs('--user-agent=telemetry') 146 147 def testCommandLineOverriding(self): 148 # This test starts the browser with --user-agent=telemetry. This tests 149 # whether the user agent is then set. 150 t = self._browser.tabs[0] 151 t.Navigate(self.UrlOfUnittestFile('blank.html')) 152 t.WaitForDocumentReadyStateToBeInteractiveOrBetter() 153 self.assertEquals(t.EvaluateJavaScript('navigator.userAgent'), 154 'telemetry') 155 156class DirtyProfileBrowserTest(browser_test_case.BrowserTestCase): 157 @classmethod 158 def CustomizeBrowserOptions(cls, options): 159 options.profile_type = 'small_profile' 160 161 @decorators.Disabled('chromeos') # crbug.com/243912 162 def testDirtyProfileCreation(self): 163 self.assertEquals(1, len(self._browser.tabs)) 164 165 166class BrowserLoggingTest(browser_test_case.BrowserTestCase): 167 @classmethod 168 def CustomizeBrowserOptions(cls, options): 169 options.logging_verbosity = options.VERBOSE_LOGGING 170 171 @decorators.Disabled('chromeos', 'android') 172 def testLogFileExist(self): 173 self.assertTrue( 174 os.path.isfile(self._browser._browser_backend.log_file_path)) 175 176 177def _GenerateBrowserProfile(number_of_tabs): 178 """ Generate a browser profile which browser had |number_of_tabs| number of 179 tabs opened before it was closed. 180 Returns: 181 profile_dir: the directory of profile. 182 """ 183 profile_dir = tempfile.mkdtemp() 184 options = options_for_unittests.GetCopy() 185 options.browser_options.output_profile_path = profile_dir 186 browser_to_create = browser_finder.FindBrowser(options) 187 browser_to_create.platform.network_controller.InitializeIfNeeded() 188 try: 189 with browser_to_create.Create(options) as browser: 190 browser.platform.SetHTTPServerDirectories(path.GetUnittestDataDir()) 191 blank_file_path = os.path.join(path.GetUnittestDataDir(), 'blank.html') 192 blank_url = browser.platform.http_server.UrlOf(blank_file_path) 193 browser.foreground_tab.Navigate(blank_url) 194 browser.foreground_tab.WaitForDocumentReadyStateToBeComplete() 195 for _ in xrange(number_of_tabs - 1): 196 tab = browser.tabs.New() 197 tab.Navigate(blank_url) 198 tab.WaitForDocumentReadyStateToBeComplete() 199 return profile_dir 200 finally: 201 browser_to_create.platform.network_controller.Close() 202 203 204class BrowserCreationTest(unittest.TestCase): 205 def setUp(self): 206 self.mock_browser_backend = mock.MagicMock() 207 self.mock_platform_backend = mock.MagicMock() 208 209 def testCleanedUpCalledWhenExceptionRaisedInBrowserCreation(self): 210 self.mock_platform_backend.platform.FlushDnsCache.side_effect = ( 211 IntentionalException('Boom!')) 212 with self.assertRaises(IntentionalException): 213 browser_module.Browser( 214 self.mock_browser_backend, self.mock_platform_backend, 215 credentials_path=None) 216 self.assertTrue(self.mock_platform_backend.WillCloseBrowser.called) 217 218 def testOriginalExceptionNotSwallow(self): 219 self.mock_platform_backend.platform.FlushDnsCache.side_effect = ( 220 IntentionalException('Boom!')) 221 self.mock_platform_backend.WillCloseBrowser.side_effect = ( 222 IntentionalException('Cannot close browser!')) 223 with self.assertRaises(IntentionalException) as context: 224 browser_module.Browser( 225 self.mock_browser_backend, self.mock_platform_backend, 226 credentials_path=None) 227 self.assertIn('Boom!', context.exception.message) 228 229 230class BrowserRestoreSessionTest(unittest.TestCase): 231 232 @classmethod 233 def setUpClass(cls): 234 cls._number_of_tabs = 4 235 cls._profile_dir = _GenerateBrowserProfile(cls._number_of_tabs) 236 cls._options = options_for_unittests.GetCopy() 237 cls._options.browser_options.AppendExtraBrowserArgs( 238 ['--restore-last-session']) 239 cls._options.browser_options.profile_dir = cls._profile_dir 240 cls._browser_to_create = browser_finder.FindBrowser(cls._options) 241 cls._browser_to_create.platform.network_controller.InitializeIfNeeded() 242 243 @decorators.Enabled('has tabs') 244 @decorators.Disabled('chromeos', 'win', 'mac') 245 # TODO(nednguyen): Enable this test on windowsn platform 246 def testRestoreBrowserWithMultipleTabs(self): 247 with self._browser_to_create.Create(self._options) as browser: 248 # The number of tabs will be self._number_of_tabs + 1 as it includes the 249 # old tabs and a new blank tab. 250 expected_number_of_tabs = self._number_of_tabs + 1 251 try: 252 py_utils.WaitFor( 253 lambda: len(browser.tabs) == expected_number_of_tabs, 10) 254 except: 255 logging.error('Number of tabs is %s' % len(browser.tabs)) 256 raise 257 self.assertEquals(expected_number_of_tabs, len(browser.tabs)) 258 259 @classmethod 260 def tearDownClass(cls): 261 cls._browser_to_create.platform.network_controller.Close() 262 shutil.rmtree(cls._profile_dir) 263 264 265class TestBrowserOperationDoNotLeakTempFiles(unittest.TestCase): 266 267 @decorators.Enabled('win', 'mac', 'linux') 268 @decorators.Isolated 269 def testBrowserNotLeakingTempFiles(self): 270 options = options_for_unittests.GetCopy() 271 browser_to_create = browser_finder.FindBrowser(options) 272 self.assertIsNotNone(browser_to_create) 273 before_browser_run_temp_dir_content = os.listdir(tempfile.tempdir) 274 browser_to_create.platform.network_controller.InitializeIfNeeded() 275 try: 276 with browser_to_create.Create(options) as browser: 277 tab = browser.tabs.New() 278 tab.Navigate('about:blank') 279 self.assertEquals(2, tab.EvaluateJavaScript('1 + 1')) 280 after_browser_run_temp_dir_content = os.listdir(tempfile.tempdir) 281 self.assertEqual(before_browser_run_temp_dir_content, 282 after_browser_run_temp_dir_content) 283 finally: 284 browser_to_create.platform.network_controller.Close() 285