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