blob: 5270d7e9e293804f4e6bc27f003c6a01abeabbfc [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import re
import types
import pyauto_functional # Must be imported before pyauto
import pyauto
class BrowserTest(pyauto.PyUITest):
"""TestCase for Browser info."""
def Debug(self):
"""Test method for experimentation.
This method will not run automatically.
"""
import pprint
pp = pprint.PrettyPrinter(indent=2)
while True:
raw_input('Hit <enter> to dump info.. ')
info = self.GetBrowserInfo()
pp.pprint(info)
def setUp(self):
pyauto.PyUITest.setUp(self)
self._flash_plugin_type = 'Plug-in'
if (self.IsChromeOS() and
self.GetBrowserInfo()['properties']['branding'] == 'Google Chrome'):
self._flash_plugin_type = 'Pepper Plugin'
def _GetUniqProcesses(self, total_tabs, renderer_processes):
""" Returns a count of uniq processes of opened tabs
Args:
total_tabs: opened tabs count
renderer_processes: opened renderers info data dictionary
"""
pid_list = []
for tab_index in range(total_tabs):
pid = renderer_processes[tab_index]['renderer_pid']
if pid not in pid_list:
pid_list.append(pid)
return len(pid_list)
def _VerifyUniqueRendererProcesses(self, browser_info):
"""Verify that each tab has a unique renderer process.
This cannot be used for large number of renderers since there actually is
a cap, depending on memory on the machine.
Args:
browser_info: browser info data dictionary as returned by GetBrowserInfo()
"""
seen_pids = {} # lookup table of PIDs we've seen
for window in browser_info['windows']:
for tab in window['tabs']:
renderer_pid = tab['renderer_pid']
self.assertEqual(types.IntType, type(renderer_pid))
# Verify unique renderer pid
self.assertFalse(renderer_pid in seen_pids, 'renderer pid not unique')
seen_pids[renderer_pid] = True
def testBasics(self):
"""Verify basic browser info at startup."""
url = self.GetFileURLForDataPath('title2.html')
self.NavigateToURL(url)
info = self.GetBrowserInfo()
# Verify valid version string
version_string = info['properties']['ChromeVersion']
self.assertTrue(re.match('\d+\.\d+\.\d+.\.\d+', version_string))
# Verify browser process
self.assertEqual(types.IntType, type(info['browser_pid']))
self.assertEqual(1, len(info['windows'])) # one window
self.assertEqual(1, len(info['windows'][0]['tabs'])) # one tab
self.assertEqual(0, info['windows'][0]['selected_tab']) # 1st tab selected
self.assertEqual(url, info['windows'][0]['tabs'][0]['url'])
self.assertFalse(info['windows'][0]['fullscreen']) # not fullscreen
self._VerifyUniqueRendererProcesses(info)
def testProcessesForMultipleWindowsAndTabs(self):
"""Verify processes for multiple windows and tabs"""
url = self.GetFileURLForDataPath('title2.html')
self.NavigateToURL(url)
for _ in range(2):
self.AppendTab(pyauto.GURL(url))
for windex in range(1, 3): # 2 new windows
self.OpenNewBrowserWindow(True)
self.NavigateToURL(url, windex, 0)
self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) # incognito window
self.NavigateToURL(url, 3, 0)
self._VerifyUniqueRendererProcesses(self.GetBrowserInfo())
def testWindowResize(self):
"""Verify window resizing and persistence after restart."""
def _VerifySize(x, y, width, height):
info = self.GetBrowserInfo()
self.assertEqual(x, info['windows'][0]['x'],
msg='Window x value should be %d, but was %d.' % (
x, info['windows'][0]['x']))
self.assertEqual(y, info['windows'][0]['y'],
msg='Window y value should be %d, but was %d.' % (
y, info['windows'][0]['y']))
self.assertEqual(width, info['windows'][0]['width'],
msg='Window width value should be %d, but was %d.' % (
width, info['windows'][0]['width']))
self.assertEqual(height, info['windows'][0]['height'],
msg='Window height value should be %d, but was %d.' % (
height, info['windows'][0]['height']))
self.SetWindowDimensions(x=20, y=40, width=600, height=300)
_VerifySize(20, 40, 600, 300)
self.RestartBrowser(clear_profile=False)
_VerifySize(20, 40, 600, 300)
def testMaxProcess(self):
"""Verify that opening 100 tabs doesn't create 100 child processes"""
total_tabs = 100
test_url = self.GetFileURLForDataPath('english_page.html')
# Opening tabs
for tab_index in range(total_tabs - 1):
self.AppendTab(pyauto.GURL(test_url))
tabs = self.GetBrowserInfo()['windows'][0]['tabs']
# For the first time we have 2 tabs opened, so sending the tab_index as +2
unique_renderers = self._GetUniqProcesses(len(tabs), tabs)
# We verify that opening a new tab should not create a new process after
# Chrome reaches to a maximum process limit.
if len(tabs) > unique_renderers:
return
# In case if we create 100 processes for 100 tabs, then we are failing.
self.fail(msg='Got 100 renderer processes')
def testKillAndReloadRenderer(self):
"""Verify that reloading of renderer is possible,
after renderer is killed"""
test_url = self.GetFileURLForDataPath('english_page.html')
self.NavigateToURL(test_url)
pid1 = self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid']
self.KillRendererProcess(pid1)
self.ReloadActiveTab()
pid2 = self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid']
self.assertNotEqual(pid1, pid2)
def testPopupSharesProcess(self):
"""Verify that parent tab and popup share a process."""
file_url = self.GetFileURLForDataPath(
'popup_blocker', 'popup-window-open.html')
self.NavigateToURL(file_url)
blocked_popups = self.GetBlockedPopupsInfo()
self.assertEqual(1, len(blocked_popups), msg='Popup not blocked')
self.UnblockAndLaunchBlockedPopup(0)
self.assertEquals(2, self.GetBrowserWindowCount())
parent_pid = self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid']
popup_pid = self.GetBrowserInfo()['windows'][1]['tabs'][0]['renderer_pid']
self.assertEquals(popup_pid, parent_pid,
msg='Parent and popup are not sharing a process.')
def testPopupSharesSameProcessInIncognito(self):
"""Verify parent incognito and popup share same process id"""
self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW)
file_url = self.GetFileURLForDataPath('popup_blocker',
'popup-window-open.html')
self.NavigateToURL(file_url, 1, 0)
self.UnblockAndLaunchBlockedPopup(0, tab_index=0, windex=1)
self.assertEquals(
self.GetBrowserInfo()['windows'][1]['tabs'][0]['renderer_pid'],
self.GetBrowserInfo()['windows'][2]['tabs'][0]['renderer_pid'],
msg='Incognito window and popup are not sharing a process id.')
def testKillAndReloadSharedProcess(self):
"""Verify that killing a shared process kills all associated renderers.
In this case we are killing a process shared by a parent and
its popup process. Reloading both should share a process again.
"""
file_url = self.GetFileURLForDataPath(
'popup_blocker', 'popup-window-open.html')
self.NavigateToURL(file_url)
blocked_popups = self.GetBlockedPopupsInfo()
self.assertEqual(1, len(blocked_popups), msg='Popup not blocked')
self.UnblockAndLaunchBlockedPopup(0)
self.assertEquals(2, self.GetBrowserWindowCount())
# Check that the renderers are alive.
self.assertEquals(1, self.FindInPage('pop-up')['match_count'])
self.assertEquals(1,
self.FindInPage('popup', tab_index=0, windex=1)['match_count'])
# Check if they are sharing a process id.
self.assertEquals(
self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid'],
self.GetBrowserInfo()['windows'][1]['tabs'][0]['renderer_pid'])
shared_pid = self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid']
# This method would fail if the renderers are not killed.
self.KillRendererProcess(shared_pid)
# Reload the parent and popup windows.
self.GetBrowserWindow(0).GetTab(0).Reload()
self.GetBrowserWindow(1).GetTab(0).Reload()
# Check if both are sharing a process id.
self.assertEquals(
self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid'],
self.GetBrowserInfo()['windows'][1]['tabs'][0]['renderer_pid'])
# The shared process id should be different from the previous one.
self.assertNotEqual(shared_pid,
self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid'])
if __name__ == '__main__':
pyauto_functional.Main()