Bug 1228120 - Add tests to ensure SessionStore saves and restores windows and tabs properly after a restart. r=whimboo
authorMike Conley <mconley@mozilla.com>
Fri, 29 Jul 2016 09:29:34 -0400
changeset 349501 474c03c87e8c80a313be0af14c56049b298027bb
parent 349500 f3d6887279f8175b0d1e3835d1ca2a152bc4453f
child 349502 6284dacc7718052ba6e7d91f45a48110be7c49af
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswhimboo
bugs1228120, 1228446
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1228120 - Add tests to ensure SessionStore saves and restores windows and tabs properly after a restart. r=whimboo Now that the Firefox UI tests are in the tree, this is possible and less of a pain. Unfortunately, due to bug 1228446, this test is disabled for e10s. MozReview-Commit-ID: A16EVJ8eYyB
testing/firefox-ui/tests/functional/manifest.ini
testing/firefox-ui/tests/functional/sessionstore/manifest.ini
testing/firefox-ui/tests/functional/sessionstore/test_restore_windows_after_restart.py
--- a/testing/firefox-ui/tests/functional/manifest.ini
+++ b/testing/firefox-ui/tests/functional/manifest.ini
@@ -1,4 +1,5 @@
 [include:keyboard_shortcuts/manifest.ini]
 [include:locationbar/manifest.ini]
 [include:private_browsing/manifest.ini]
 [include:security/manifest.ini]
+[include:sessionstore/manifest.ini]
new file mode 100644
--- /dev/null
+++ b/testing/firefox-ui/tests/functional/sessionstore/manifest.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+tags = local
+
+[test_restore_windows_after_restart.py]
+skip-if = e10s # Bug 1228446
new file mode 100644
--- /dev/null
+++ b/testing/firefox-ui/tests/functional/sessionstore/test_restore_windows_after_restart.py
@@ -0,0 +1,150 @@
+# 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_ui_harness.testcases import FirefoxTestCase
+
+
+class TestRestoreWindowsAfterRestart(FirefoxTestCase):
+
+    def setUp(self):
+        FirefoxTestCase.setUp(self)
+
+        # 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 to restore previous session
+            'browser.startup.page': 3,
+            # 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': True,
+        })
+
+    def tearDown(self):
+        try:
+            # Create a fresh profile for subsequent tests.
+            self.restart(clean=True)
+        finally:
+            FirefoxTestCase.tearDown(self)
+
+    def test_with_variety(self):
+        """ Opens a set of windows, both standard and private, with
+        some number of tabs in them. Once the tabs have loaded, restarts
+        the browser, and then ensures that the standard tabs have been
+        restored, and that the private ones have not.
+        """
+        self.open_windows(self.test_windows)
+        self.open_windows(self.private_windows, is_private=True)
+
+        self.restart()
+
+        windows = self.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)
+
+        self.assertEqual(opened_windows, self.test_windows)
+
+    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)