summaryrefslogtreecommitdiffstats
path: root/testing/awsy/awsy/test_memory_usage.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/awsy/awsy/test_memory_usage.py')
-rw-r--r--testing/awsy/awsy/test_memory_usage.py238
1 files changed, 238 insertions, 0 deletions
diff --git a/testing/awsy/awsy/test_memory_usage.py b/testing/awsy/awsy/test_memory_usage.py
new file mode 100644
index 0000000000..e3daaf08dc
--- /dev/null
+++ b/testing/awsy/awsy/test_memory_usage.py
@@ -0,0 +1,238 @@
+# 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/.
+
+import os
+import sys
+
+import mozinfo
+import yaml
+from marionette_driver.errors import JavascriptException, ScriptTimeoutException
+from mozproxy import get_playback
+
+AWSY_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+if AWSY_PATH not in sys.path:
+ sys.path.append(AWSY_PATH)
+
+from awsy import process_perf_data, webservers
+from awsy.awsy_test_case import AwsyTestCase
+
+
+class TestMemoryUsage(AwsyTestCase):
+ """Provides a test that collects memory usage at various checkpoints:
+ - "Start" - Just after startup
+ - "StartSettled" - After an additional wait time
+ - "TabsOpen" - After opening all provided URLs
+ - "TabsOpenSettled" - After an additional wait time
+ - "TabsOpenForceGC" - After forcibly invoking garbage collection
+ - "TabsClosed" - After closing all tabs
+ - "TabsClosedSettled" - After an additional wait time
+ - "TabsClosedForceGC" - After forcibly invoking garbage collection
+ """
+
+ def urls(self):
+ return self._urls
+
+ def perf_suites(self):
+ return process_perf_data.PERF_SUITES
+
+ def perf_checkpoints(self):
+ return process_perf_data.CHECKPOINTS
+
+ def perf_extra_opts(self):
+ return self._extra_opts
+
+ def setupTp5(self):
+ urls = None
+ default_tp5n_manifest = os.path.join(
+ self._webroot_dir, "page_load_test", "tp5n", "tp5n.manifest"
+ )
+ tp5n_manifest = self.testvars.get("pageManifest", default_tp5n_manifest)
+ with open(tp5n_manifest) as fp:
+ urls = fp.readlines()
+ # pylint --py3k: W1636
+ urls = list(map(lambda x: x.replace("localhost", "localhost:{}"), urls))
+
+ # We haven't set self._urls yet, so this value might be zero if
+ # 'entities' wasn't specified.
+ to_load = self.pages_to_load()
+ if not to_load:
+ to_load = len(urls)
+ self._webservers = webservers.WebServers(
+ "localhost", 8001, self._webroot_dir, to_load
+ )
+ self._webservers.start()
+ for url, server in zip(urls, self._webservers.servers):
+ self._urls.append(url.strip().format(server.port))
+
+ def setupTp6(self):
+ # tp5n stores its manifest in the zip file that gets extracted, tp6
+ # doesn't so we just keep one in our project dir for now.
+ default_tp6_pages_manifest = os.path.join(AWSY_PATH, "conf", "tp6-pages.yml")
+ tp6_pages_manifest = self.testvars.get(
+ "pageManifest", default_tp6_pages_manifest
+ )
+ urls = []
+ with open(tp6_pages_manifest) as f:
+ d = yaml.safe_load(f)
+ for r in d:
+ url = r["url"]
+ if isinstance(url, list):
+ urls.extend(url)
+ else:
+ urls.append(url)
+
+ self._urls = urls
+
+ # Indicate that we're using tp6 in the perf data.
+ self._extra_opts = ["tp6"]
+
+ if self.marionette.get_pref("fission.autostart"):
+ self._extra_opts.append("fission")
+
+ # Now we setup the mitm proxy with our tp6 pageset.
+ tp6_pageset_manifest = os.path.join(AWSY_PATH, "tp6-pageset.manifest")
+ config = {
+ "playback_tool": "mitmproxy",
+ "playback_version": "5.1.1",
+ "playback_files": [tp6_pageset_manifest],
+ "platform": mozinfo.os,
+ "obj_path": self._webroot_dir,
+ "binary": self._binary,
+ "run_local": self._run_local,
+ "app": "firefox",
+ "host": "127.0.0.1",
+ "ignore_mitmdump_exit_failure": True,
+ }
+
+ self._playback = get_playback(config)
+ self._playback.start()
+
+ # We need to reload after the mitmproxy cert is installed
+ self.marionette.restart(in_app=False, clean=False)
+
+ # Setup WebDriver capabilities that we need
+ self.marionette.delete_session()
+ caps = {
+ "unhandledPromptBehavior": "dismiss", # Ignore page navigation warnings
+ }
+ self.marionette.start_session(caps)
+ self.marionette.set_context("chrome")
+
+ def setUp(self):
+ AwsyTestCase.setUp(self)
+ self.logger.info("setting up")
+ self._webroot_dir = self.testvars["webRootDir"]
+ self._urls = []
+ self._extra_opts = None
+
+ if self.testvars.get("tp6", False):
+ self.setupTp6()
+ else:
+ self.setupTp5()
+
+ self.logger.info(
+ "areweslimyet run by %d pages, %d iterations,"
+ " %d perTabPause, %d settleWaitTime"
+ % (
+ self._pages_to_load,
+ self._iterations,
+ self._perTabPause,
+ self._settleWaitTime,
+ )
+ )
+ self.logger.info("done setting up!")
+
+ def tearDown(self):
+ self.logger.info("tearing down!")
+
+ self.logger.info("tearing down webservers!")
+
+ if self.testvars.get("tp6", False):
+ self._playback.stop()
+ else:
+ self._webservers.stop()
+
+ AwsyTestCase.tearDown(self)
+
+ self.logger.info("done tearing down!")
+
+ def clear_preloaded_browser(self):
+ """
+ Clears out the preloaded browser.
+ """
+ self.logger.info("closing preloaded browser")
+ script = """
+ if (window.NewTabPagePreloading) {
+ return NewTabPagePreloading.removePreloadedBrowser(window);
+ }
+ return "NewTabPagePreloading.removePreloadedBrowser not available";
+ """
+ try:
+ result = self.marionette.execute_script(script, script_timeout=180000)
+ except JavascriptException as e:
+ self.logger.error("removePreloadedBrowser() JavaScript error: %s" % e)
+ except ScriptTimeoutException:
+ self.logger.error("removePreloadedBrowser() timed out")
+ except Exception:
+ self.logger.error(
+ "removePreloadedBrowser() Unexpected error: %s" % sys.exc_info()[0]
+ )
+ else:
+ if result:
+ self.logger.info(result)
+
+ def test_open_tabs(self):
+ """Marionette test entry that returns an array of checkpoint arrays.
+
+ This will generate a set of checkpoints for each iteration requested.
+ Upon successful completion the results will be stored in
+ |self.testvars["results"]| and accessible to the test runner via the
+ |testvars| object it passed in.
+ """
+ # setup the results array
+ results = [[] for _ in range(self.iterations())]
+
+ def create_checkpoint(name, iteration, minimize=False):
+ checkpoint = self.do_memory_report(name, iteration, minimize)
+ self.assertIsNotNone(checkpoint, "Checkpoint was recorded")
+ results[iteration].append(checkpoint)
+
+ # The first iteration gets Start and StartSettled entries before
+ # opening tabs
+ create_checkpoint("Start", 0)
+ self.settle()
+ create_checkpoint("StartSettled", 0)
+
+ for itr in range(self.iterations()):
+ self.open_pages()
+
+ create_checkpoint("TabsOpen", itr)
+ self.settle()
+ create_checkpoint("TabsOpenSettled", itr)
+ create_checkpoint("TabsOpenForceGC", itr, minimize=True)
+
+ # Close all tabs
+ self.reset_state()
+
+ with self.marionette.using_context("content"):
+ self.logger.info("navigating to about:blank")
+ self.marionette.navigate("about:blank")
+ self.logger.info("navigated to about:blank")
+ self.signal_user_active()
+
+ # Create checkpoint that may contain retained processes that will
+ # be reused.
+ create_checkpoint("TabsClosedExtraProcesses", itr)
+
+ # Clear out the retained processes and measure again.
+ self.clear_preloaded_browser()
+
+ create_checkpoint("TabsClosed", itr)
+ self.settle()
+ create_checkpoint("TabsClosedSettled", itr)
+ create_checkpoint("TabsClosedForceGC", itr, minimize=True)
+
+ # TODO(ER): Temporary hack until bug 1121139 lands
+ self.logger.info("setting results")
+ self.testvars["results"] = results