Bug 1470646 - Update Fxfn tests to use WebDriver conforming platformName. r=whimboo

MozReview-Commit-ID: 1GYS453pA5D

--HG--
extra : rebase_source : a8b5fb17e53c218621eddc03a0166c888bd9ca0e
This commit is contained in:
Andreas Tolfsen 2018-06-24 14:03:52 +01:00
Родитель adeb44c73e
Коммит 90fe6cc297
2 изменённых файлов: 287 добавлений и 287 удалений

Просмотреть файл

@ -1,285 +1,285 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from firefox_puppeteer import PuppeteerMixin
from marionette_harness import MarionetteTestCase
class SessionStoreTestCase(PuppeteerMixin, MarionetteTestCase):
def setUp(self, startup_page=1, include_private=True, no_auto_updates=True):
super(SessionStoreTestCase, self).setUp()
# Each list element represents a window of tabs loaded at
# some testing URL
self.test_windows = set([
# Window 1. Note the comma after the absolute_url call -
# this is Python's way of declaring a 1 item tuple.
(self.marionette.absolute_url('layout/mozilla.html'), ),
# Window 2
(self.marionette.absolute_url('layout/mozilla_organizations.html'),
self.marionette.absolute_url('layout/mozilla_community.html')),
# Window 3
(self.marionette.absolute_url('layout/mozilla_governance.html'),
self.marionette.absolute_url('layout/mozilla_grants.html')),
])
self.private_windows = set([
(self.marionette.absolute_url('layout/mozilla_mission.html'),
self.marionette.absolute_url('layout/mozilla_organizations.html')),
(self.marionette.absolute_url('layout/mozilla_projects.html'),
self.marionette.absolute_url('layout/mozilla_mission.html')),
])
self.marionette.enforce_gecko_prefs({
# Set browser restore previous session pref,
# depending on what the test requires.
'browser.startup.page': startup_page,
# Make the content load right away instead of waiting for
# the user to click on the background tabs
'browser.sessionstore.restore_on_demand': False,
# Avoid race conditions by having the content process never
# send us session updates unless the parent has explicitly asked
# for them via the TabStateFlusher.
'browser.sessionstore.debug.no_auto_updates': no_auto_updates,
})
self.all_windows = self.test_windows.copy()
self.open_windows(self.test_windows)
if include_private:
self.all_windows.update(self.private_windows)
self.open_windows(self.private_windows, is_private=True)
def tearDown(self):
try:
# Create a fresh profile for subsequent tests.
self.restart(clean=True)
finally:
super(SessionStoreTestCase, self).tearDown()
def open_windows(self, window_sets, is_private=False):
""" Opens a set of windows with tabs pointing at some
URLs.
@param window_sets (list)
A set of URL tuples. Each tuple within window_sets
represents a window, and each URL in the URL
tuples represents what will be loaded in a tab.
Note that if is_private is False, then the first
URL tuple will be opened in the current window, and
subequent tuples will be opened in new windows.
Example:
set(
(self.marionette.absolute_url('layout/mozilla_1.html'),
self.marionette.absolute_url('layout/mozilla_2.html')),
(self.marionette.absolute_url('layout/mozilla_3.html'),
self.marionette.absolute_url('layout/mozilla_4.html')),
)
This would take the currently open window, and load
mozilla_1.html and mozilla_2.html in new tabs. It would
then open a new, second window, and load tabs at
mozilla_3.html and mozilla_4.html.
@param is_private (boolean, optional)
Whether or not any new windows should be a private browsing
windows.
"""
if (is_private):
win = self.browser.open_browser(is_private=True)
win.switch_to()
else:
win = self.browser
for index, urls in enumerate(window_sets):
if index > 0:
win = self.browser.open_browser(is_private=is_private)
win.switch_to()
self.open_tabs(win, urls)
def open_tabs(self, win, urls):
""" Opens a set of URLs inside a window in new tabs.
@param win (browser window)
The browser window to load the tabs in.
@param urls (tuple)
A tuple of URLs to load in this window. The
first URL will be loaded in the currently selected
browser tab. Subsequent URLs will be loaded in
new tabs.
"""
# If there are any remaining URLs for this window,
# open some new tabs and navigate to them.
with self.marionette.using_context('content'):
if isinstance(urls, str):
self.marionette.navigate(urls)
else:
for index, url in enumerate(urls):
if index > 0:
with self.marionette.using_context('chrome'):
win.tabbar.open_tab()
self.marionette.navigate(url)
def convert_open_windows_to_set(self):
windows = self.puppeteer.windows.all
# There's no guarantee that Marionette will return us an
# iterator for the opened windows that will match the
# order within our window list. Instead, we'll convert
# the list of URLs within each open window to a set of
# tuples that will allow us to do a direct comparison
# while allowing the windows to be in any order.
opened_windows = set()
for win in windows:
urls = tuple()
for tab in win.tabbar.tabs:
urls = urls + tuple([tab.location])
opened_windows.add(urls)
return opened_windows
def simulate_os_shutdown(self):
""" Simulate an OS shutdown.
:raises: Exception: if not supported on the current platform
:raises: WindowsError: if a Windows API call failed
"""
if self.marionette.session_capabilities['platformName'] != 'windows_nt':
raise Exception('Unsupported platform for simulate_os_shutdown')
self._shutdown_with_windows_restart_manager(self.marionette.process_id)
def _shutdown_with_windows_restart_manager(self, pid):
""" Shut down a process using the Windows Restart Manager.
When Windows shuts down, it uses a protocol including the
WM_QUERYENDSESSION and WM_ENDSESSION messages to give
applications a chance to shut down safely. The best way to
simulate this is via the Restart Manager, which allows a process
(such as an installer) to use the same mechanism to shut down
any other processes which are using registered resources.
This function starts a Restart Manager session, registers the
process as a resource, and shuts down the process.
:param pid: The process id (int) of the process to shutdown
:raises: WindowsError: if a Windows API call fails
"""
import ctypes
from ctypes import Structure, POINTER, WINFUNCTYPE, windll, pointer, WinError
from ctypes.wintypes import HANDLE, DWORD, BOOL, WCHAR, UINT, ULONG, LPCWSTR
# set up Windows SDK types
OpenProcess = windll.kernel32.OpenProcess
OpenProcess.restype = HANDLE
OpenProcess.argtypes = [DWORD, # dwDesiredAccess
BOOL, # bInheritHandle
DWORD] # dwProcessId
PROCESS_QUERY_INFORMATION = 0x0400
class FILETIME(Structure):
_fields_ = [('dwLowDateTime', DWORD),
('dwHighDateTime', DWORD)]
LPFILETIME = POINTER(FILETIME)
GetProcessTimes = windll.kernel32.GetProcessTimes
GetProcessTimes.restype = BOOL
GetProcessTimes.argtypes = [HANDLE, # hProcess
LPFILETIME, # lpCreationTime
LPFILETIME, # lpExitTime
LPFILETIME, # lpKernelTime
LPFILETIME] # lpUserTime
ERROR_SUCCESS = 0
class RM_UNIQUE_PROCESS(Structure):
_fields_ = [('dwProcessId', DWORD),
('ProcessStartTime', FILETIME)]
RmStartSession = windll.rstrtmgr.RmStartSession
RmStartSession.restype = DWORD
RmStartSession.argtypes = [POINTER(DWORD), # pSessionHandle
DWORD, # dwSessionFlags
POINTER(WCHAR)] # strSessionKey
class GUID(ctypes.Structure):
_fields_ = [('Data1', ctypes.c_ulong),
('Data2', ctypes.c_ushort),
('Data3', ctypes.c_ushort),
('Data4', ctypes.c_ubyte * 8)]
CCH_RM_SESSION_KEY = ctypes.sizeof(GUID) * 2
RmRegisterResources = windll.rstrtmgr.RmRegisterResources
RmRegisterResources.restype = DWORD
RmRegisterResources.argtypes = [DWORD, # dwSessionHandle
UINT, # nFiles
POINTER(LPCWSTR), # rgsFilenames
UINT, # nApplications
POINTER(RM_UNIQUE_PROCESS), # rgApplications
UINT, # nServices
POINTER(LPCWSTR)] # rgsServiceNames
RM_WRITE_STATUS_CALLBACK = WINFUNCTYPE(None, UINT)
RmShutdown = windll.rstrtmgr.RmShutdown
RmShutdown.restype = DWORD
RmShutdown.argtypes = [DWORD, # dwSessionHandle
ULONG, # lActionFlags
RM_WRITE_STATUS_CALLBACK] # fnStatus
RmEndSession = windll.rstrtmgr.RmEndSession
RmEndSession.restype = DWORD
RmEndSession.argtypes = [DWORD] # dwSessionHandle
# Get the info needed to uniquely identify the process
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
if not hProc:
raise WinError()
creationTime = FILETIME()
exitTime = FILETIME()
kernelTime = FILETIME()
userTime = FILETIME()
if not GetProcessTimes(hProc,
pointer(creationTime),
pointer(exitTime),
pointer(kernelTime),
pointer(userTime)):
raise WinError()
# Start the Restart Manager Session
dwSessionHandle = DWORD()
sessionKeyType = WCHAR * (CCH_RM_SESSION_KEY + 1)
sessionKey = sessionKeyType()
if RmStartSession(pointer(dwSessionHandle), 0, sessionKey) != ERROR_SUCCESS:
raise WinError()
try:
UProcs_count = 1
UProcsArrayType = RM_UNIQUE_PROCESS * UProcs_count
UProcs = UProcsArrayType(RM_UNIQUE_PROCESS(pid, creationTime))
# Register the process as a resource
if RmRegisterResources(dwSessionHandle,
0, None,
UProcs_count, UProcs,
0, None) != ERROR_SUCCESS:
raise WinError()
# Shut down all processes using registered resources
if RmShutdown(dwSessionHandle, 0,
ctypes.cast(None, RM_WRITE_STATUS_CALLBACK)) != ERROR_SUCCESS:
raise WinError()
finally:
RmEndSession(dwSessionHandle)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from firefox_puppeteer import PuppeteerMixin
from marionette_harness import MarionetteTestCase
class SessionStoreTestCase(PuppeteerMixin, MarionetteTestCase):
def setUp(self, startup_page=1, include_private=True, no_auto_updates=True):
super(SessionStoreTestCase, self).setUp()
# Each list element represents a window of tabs loaded at
# some testing URL
self.test_windows = set([
# Window 1. Note the comma after the absolute_url call -
# this is Python's way of declaring a 1 item tuple.
(self.marionette.absolute_url('layout/mozilla.html'), ),
# Window 2
(self.marionette.absolute_url('layout/mozilla_organizations.html'),
self.marionette.absolute_url('layout/mozilla_community.html')),
# Window 3
(self.marionette.absolute_url('layout/mozilla_governance.html'),
self.marionette.absolute_url('layout/mozilla_grants.html')),
])
self.private_windows = set([
(self.marionette.absolute_url('layout/mozilla_mission.html'),
self.marionette.absolute_url('layout/mozilla_organizations.html')),
(self.marionette.absolute_url('layout/mozilla_projects.html'),
self.marionette.absolute_url('layout/mozilla_mission.html')),
])
self.marionette.enforce_gecko_prefs({
# Set browser restore previous session pref,
# depending on what the test requires.
'browser.startup.page': startup_page,
# Make the content load right away instead of waiting for
# the user to click on the background tabs
'browser.sessionstore.restore_on_demand': False,
# Avoid race conditions by having the content process never
# send us session updates unless the parent has explicitly asked
# for them via the TabStateFlusher.
'browser.sessionstore.debug.no_auto_updates': no_auto_updates,
})
self.all_windows = self.test_windows.copy()
self.open_windows(self.test_windows)
if include_private:
self.all_windows.update(self.private_windows)
self.open_windows(self.private_windows, is_private=True)
def tearDown(self):
try:
# Create a fresh profile for subsequent tests.
self.restart(clean=True)
finally:
super(SessionStoreTestCase, self).tearDown()
def open_windows(self, window_sets, is_private=False):
""" Opens a set of windows with tabs pointing at some
URLs.
@param window_sets (list)
A set of URL tuples. Each tuple within window_sets
represents a window, and each URL in the URL
tuples represents what will be loaded in a tab.
Note that if is_private is False, then the first
URL tuple will be opened in the current window, and
subequent tuples will be opened in new windows.
Example:
set(
(self.marionette.absolute_url('layout/mozilla_1.html'),
self.marionette.absolute_url('layout/mozilla_2.html')),
(self.marionette.absolute_url('layout/mozilla_3.html'),
self.marionette.absolute_url('layout/mozilla_4.html')),
)
This would take the currently open window, and load
mozilla_1.html and mozilla_2.html in new tabs. It would
then open a new, second window, and load tabs at
mozilla_3.html and mozilla_4.html.
@param is_private (boolean, optional)
Whether or not any new windows should be a private browsing
windows.
"""
if (is_private):
win = self.browser.open_browser(is_private=True)
win.switch_to()
else:
win = self.browser
for index, urls in enumerate(window_sets):
if index > 0:
win = self.browser.open_browser(is_private=is_private)
win.switch_to()
self.open_tabs(win, urls)
def open_tabs(self, win, urls):
""" Opens a set of URLs inside a window in new tabs.
@param win (browser window)
The browser window to load the tabs in.
@param urls (tuple)
A tuple of URLs to load in this window. The
first URL will be loaded in the currently selected
browser tab. Subsequent URLs will be loaded in
new tabs.
"""
# If there are any remaining URLs for this window,
# open some new tabs and navigate to them.
with self.marionette.using_context('content'):
if isinstance(urls, str):
self.marionette.navigate(urls)
else:
for index, url in enumerate(urls):
if index > 0:
with self.marionette.using_context('chrome'):
win.tabbar.open_tab()
self.marionette.navigate(url)
def convert_open_windows_to_set(self):
windows = self.puppeteer.windows.all
# There's no guarantee that Marionette will return us an
# iterator for the opened windows that will match the
# order within our window list. Instead, we'll convert
# the list of URLs within each open window to a set of
# tuples that will allow us to do a direct comparison
# while allowing the windows to be in any order.
opened_windows = set()
for win in windows:
urls = tuple()
for tab in win.tabbar.tabs:
urls = urls + tuple([tab.location])
opened_windows.add(urls)
return opened_windows
def simulate_os_shutdown(self):
""" Simulate an OS shutdown.
:raises: Exception: if not supported on the current platform
:raises: WindowsError: if a Windows API call failed
"""
if self.marionette.session_capabilities['platformName'] != 'windows':
raise Exception('Unsupported platform for simulate_os_shutdown')
self._shutdown_with_windows_restart_manager(self.marionette.process_id)
def _shutdown_with_windows_restart_manager(self, pid):
""" Shut down a process using the Windows Restart Manager.
When Windows shuts down, it uses a protocol including the
WM_QUERYENDSESSION and WM_ENDSESSION messages to give
applications a chance to shut down safely. The best way to
simulate this is via the Restart Manager, which allows a process
(such as an installer) to use the same mechanism to shut down
any other processes which are using registered resources.
This function starts a Restart Manager session, registers the
process as a resource, and shuts down the process.
:param pid: The process id (int) of the process to shutdown
:raises: WindowsError: if a Windows API call fails
"""
import ctypes
from ctypes import Structure, POINTER, WINFUNCTYPE, windll, pointer, WinError
from ctypes.wintypes import HANDLE, DWORD, BOOL, WCHAR, UINT, ULONG, LPCWSTR
# set up Windows SDK types
OpenProcess = windll.kernel32.OpenProcess
OpenProcess.restype = HANDLE
OpenProcess.argtypes = [DWORD, # dwDesiredAccess
BOOL, # bInheritHandle
DWORD] # dwProcessId
PROCESS_QUERY_INFORMATION = 0x0400
class FILETIME(Structure):
_fields_ = [('dwLowDateTime', DWORD),
('dwHighDateTime', DWORD)]
LPFILETIME = POINTER(FILETIME)
GetProcessTimes = windll.kernel32.GetProcessTimes
GetProcessTimes.restype = BOOL
GetProcessTimes.argtypes = [HANDLE, # hProcess
LPFILETIME, # lpCreationTime
LPFILETIME, # lpExitTime
LPFILETIME, # lpKernelTime
LPFILETIME] # lpUserTime
ERROR_SUCCESS = 0
class RM_UNIQUE_PROCESS(Structure):
_fields_ = [('dwProcessId', DWORD),
('ProcessStartTime', FILETIME)]
RmStartSession = windll.rstrtmgr.RmStartSession
RmStartSession.restype = DWORD
RmStartSession.argtypes = [POINTER(DWORD), # pSessionHandle
DWORD, # dwSessionFlags
POINTER(WCHAR)] # strSessionKey
class GUID(ctypes.Structure):
_fields_ = [('Data1', ctypes.c_ulong),
('Data2', ctypes.c_ushort),
('Data3', ctypes.c_ushort),
('Data4', ctypes.c_ubyte * 8)]
CCH_RM_SESSION_KEY = ctypes.sizeof(GUID) * 2
RmRegisterResources = windll.rstrtmgr.RmRegisterResources
RmRegisterResources.restype = DWORD
RmRegisterResources.argtypes = [DWORD, # dwSessionHandle
UINT, # nFiles
POINTER(LPCWSTR), # rgsFilenames
UINT, # nApplications
POINTER(RM_UNIQUE_PROCESS), # rgApplications
UINT, # nServices
POINTER(LPCWSTR)] # rgsServiceNames
RM_WRITE_STATUS_CALLBACK = WINFUNCTYPE(None, UINT)
RmShutdown = windll.rstrtmgr.RmShutdown
RmShutdown.restype = DWORD
RmShutdown.argtypes = [DWORD, # dwSessionHandle
ULONG, # lActionFlags
RM_WRITE_STATUS_CALLBACK] # fnStatus
RmEndSession = windll.rstrtmgr.RmEndSession
RmEndSession.restype = DWORD
RmEndSession.argtypes = [DWORD] # dwSessionHandle
# Get the info needed to uniquely identify the process
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, False, pid)
if not hProc:
raise WinError()
creationTime = FILETIME()
exitTime = FILETIME()
kernelTime = FILETIME()
userTime = FILETIME()
if not GetProcessTimes(hProc,
pointer(creationTime),
pointer(exitTime),
pointer(kernelTime),
pointer(userTime)):
raise WinError()
# Start the Restart Manager Session
dwSessionHandle = DWORD()
sessionKeyType = WCHAR * (CCH_RM_SESSION_KEY + 1)
sessionKey = sessionKeyType()
if RmStartSession(pointer(dwSessionHandle), 0, sessionKey) != ERROR_SUCCESS:
raise WinError()
try:
UProcs_count = 1
UProcsArrayType = RM_UNIQUE_PROCESS * UProcs_count
UProcs = UProcsArrayType(RM_UNIQUE_PROCESS(pid, creationTime))
# Register the process as a resource
if RmRegisterResources(dwSessionHandle,
0, None,
UProcs_count, UProcs,
0, None) != ERROR_SUCCESS:
raise WinError()
# Shut down all processes using registered resources
if RmShutdown(dwSessionHandle, 0,
ctypes.cast(None, RM_WRITE_STATUS_CALLBACK)) != ERROR_SUCCESS:
raise WinError()
finally:
RmEndSession(dwSessionHandle)

Просмотреть файл

@ -69,7 +69,7 @@ class TestPageInfoWindow(PuppeteerMixin, MarionetteTestCase):
platformName = self.marionette.session_capabilities['platformName']
for trigger in open_strategies:
if trigger == 'shortcut' and platformName == 'windows_nt':
if trigger == 'shortcut' and platformName == 'windows':
# The shortcut for page info window does not exist on windows.
self.assertRaises(ValueError, self.browser.open_page_info_window,
trigger=trigger)
@ -93,7 +93,7 @@ class TestPageInfoWindow(PuppeteerMixin, MarionetteTestCase):
platformName = self.marionette.session_capabilities['platformName']
for trigger in close_strategies:
# menu only works on OS X
if trigger == 'menu' and platformName != 'darwin':
if trigger == 'menu' and platformName != 'mac':
continue
page_info = self.browser.open_page_info_window()