diff --git a/.eslintignore b/.eslintignore index 137ddad03d3a..15ca6febda18 100644 --- a/.eslintignore +++ b/.eslintignore @@ -291,6 +291,7 @@ testing/talos/talos/tests/v8_7/ testing/talos/talos/tests/kraken/ # Runing Talos may extract data here, see bug 1435677. testing/talos/talos/tests/tp5n/ +testing/talos/talos/fis/tp5n/ testing/web-platform/ testing/xpcshell/moz-http2/ diff --git a/.gitignore b/.gitignore index 3eac5f0130cf..2f1a8ea42885 100644 --- a/.gitignore +++ b/.gitignore @@ -135,7 +135,7 @@ node_modules/ # Ignore talos virtualenv and tp5n files. # The tp5n set is supposed to be decompressed at -# testing/talos/talos/page_load_test/tp5n in order to run tests like tps +# testing/talos/talos/fis|tests/tp5n in order to run tests like tps # locally. Similarly, running talos requires a Python package virtual # environment. Both the virtual environment and tp5n files end up littering # the status command, so we ignore them. @@ -143,6 +143,8 @@ testing/talos/.Python testing/talos/bin/ testing/talos/include/ testing/talos/lib/ +testing/talos/talos/fis/tp5n.zip +testing/talos/talos/fis/tp5n testing/talos/talos/tests/tp5n.zip testing/talos/talos/tests/tp5n testing/talos/talos/tests/devtools/damp.manifest.develop diff --git a/.hgignore b/.hgignore index c6867a20eb5c..952f7ae6459f 100644 --- a/.hgignore +++ b/.hgignore @@ -145,7 +145,7 @@ _OPT\.OBJ/ # Ignore talos virtualenv and tp5n files. # The tp5n set is supposed to be decompressed at -# testing/talos/talos/tests/tp5n in order to run tests like tps +# testing/talos/talos/fis|tests/tp5n in order to run tests like tps # locally. Similarly, running talos requires a Python package virtual # environment. Both the virtual environment and tp5n files end up littering # the status command, so we ignore them. @@ -153,6 +153,9 @@ _OPT\.OBJ/ ^testing/talos/bin/ ^testing/talos/include/ ^testing/talos/lib/ +^testing/talos/talos/fis/tp5n.zip +^testing/talos/talos/fis/tp5n.tar.gz +^testing/talos/talos/fis/tp5n ^testing/talos/talos/tests/tp5n.zip ^testing/talos/talos/tests/tp5n.tar.gz ^testing/talos/talos/tests/tp5n diff --git a/testing/mozharness/mozharness/mozilla/testing/talos.py b/testing/mozharness/mozharness/mozilla/testing/talos.py index db172e478d90..73a6cb263539 100755 --- a/testing/mozharness/mozharness/mozilla/testing/talos.py +++ b/testing/mozharness/mozharness/mozilla/testing/talos.py @@ -9,12 +9,14 @@ run talos tests in a virtualenv """ import argparse +import io import os import sys import pprint import copy import re import shutil +import string import subprocess import json @@ -250,6 +252,72 @@ class Talos(TestingMixin, MercurialScript, TooltoolMixin, self.info(pprint.pformat(self.talos_json_config)) return self.talos_json_config + def make_talos_domain(self, host): + return host + "-talos" + + def split_path(self, path): + result = [] + while True: + path, folder = os.path.split(path) + if folder: + result.append(folder) + continue + elif path: + result.append(path) + break + + result.reverse() + return result + + def merge_paths(self, lhs, rhs): + backtracks = 0 + for subdir in rhs: + if subdir == '..': + backtracks += 1 + else: + break + return lhs[:-backtracks] + rhs[backtracks:] + + def replace_relative_iframe_paths(self, directory, filename): + """This will find iframes with relative paths and replace them with + absolute paths containing domains derived from the original source's + domain. This helps us better simulate real-world cases for fission + """ + if not filename.endswith('.html'): + return + + directory_pieces = self.split_path(directory) + while directory_pieces and directory_pieces[0] != 'fis': + directory_pieces = directory_pieces[1:] + path = os.path.join(directory, filename) + + # XXX: ugh, is there a better way to account for multiple encodings than just + # trying each of them? + encodings = ['utf-8', 'latin-1'] + iframe_pattern = re.compile(r'(iframe.*")(\.\./.*\.html)"') + for encoding in encodings: + try: + with io.open(path, 'r', encoding=encoding) as f: + content = f.read() + + def replace_iframe_src(match): + src = match.group(2) + split = self.split_path(src) + merged = self.merge_paths(directory_pieces, split) + host = merged[3] + site_origin_hash = self.make_talos_domain(host) + new_url = 'http://%s/%s"' % (site_origin_hash, string.join(merged, '/')) + self.info("Replacing %s with %s in iframe inside %s" % + (match.group(2), new_url, path)) + return (match.group(1) + new_url) + + content = re.sub(iframe_pattern, replace_iframe_src, content) + with io.open(path, 'w', encoding=encoding) as f: + f.write(content) + break + except UnicodeDecodeError: + pass + def query_pagesets_name(self): """Certain suites require external pagesets to be downloaded and extracted. @@ -389,12 +457,24 @@ class Talos(TestingMixin, MercurialScript, TooltoolMixin, tooltool_artifacts = [] src_talos_pageset_dest = os.path.join(self.talos_path, 'talos', 'tests') + # unfortunately this path has to be short and can't be descriptive, because + # on Windows we tend to already push the boundaries of the max path length + # constraint. This will contain the tp5 pageset, but adjusted to have + # absolute URLs on iframes for the purposes of better modeling things for + # fission. + src_talos_pageset_multidomain_dest = os.path.join(self.talos_path, + 'talos', + 'fis') webextension_dest = os.path.join(self.talos_path, 'talos', 'webextensions') if self.query_pagesets_name(): tooltool_artifacts.append({'name': self.pagesets_name, 'manifest': self.pagesets_name_manifest, 'dest': src_talos_pageset_dest}) + tooltool_artifacts.append({'name': self.pagesets_name, + 'manifest': self.pagesets_name_manifest, + 'dest': src_talos_pageset_multidomain_dest, + 'postprocess': self.replace_relative_iframe_paths}) if self.query_benchmark_zip(): tooltool_artifacts.append({'name': self.benchmark_zip, @@ -412,19 +492,26 @@ class Talos(TestingMixin, MercurialScript, TooltoolMixin, if '--no-download' not in self.config.get('talos_extra_options', []): self.info("Downloading %s with tooltool..." % artifact) - if not os.path.exists(os.path.join(artifact['dest'], artifact['name'])): + archive = os.path.join(artifact['dest'], artifact['name']) + output_dir_path = re.sub(r'\.zip$', '', archive) + if not os.path.exists(archive): manifest_file = os.path.join(self.talos_path, artifact['manifest']) self.tooltool_fetch( manifest_file, output_dir=artifact['dest'], cache=self.config.get('tooltool_cache') ) - archive = os.path.join(artifact['dest'], artifact['name']) unzip = self.query_exe('unzip') unzip_cmd = [unzip, '-q', '-o', archive, '-d', artifact['dest']] self.run_command(unzip_cmd, halt_on_failure=True) + + if 'postprocess' in artifact: + for subdir, dirs, files in os.walk(output_dir_path): + for file in files: + artifact['postprocess'](subdir, file) else: self.info("%s already available" % artifact) + else: self.info("Not downloading %s because the no-download option was specified" % artifact) diff --git a/testing/talos/talos/tests/tabswitch/api.js b/testing/talos/talos/tests/tabswitch/api.js index 3ce54879b2ce..dda4b8e165f2 100644 --- a/testing/talos/talos/tests/tabswitch/api.js +++ b/testing/talos/talos/tests/tabswitch/api.js @@ -103,6 +103,7 @@ async function switchToTab(tab) { await switchDone; let finish = await finishPromise; + return finish - start; } @@ -318,6 +319,11 @@ async function test(window) { }); } +// This just has to match up with the make_talos_domain function in talos.py +function makeTalosDomain(host) { + return host + "-talos"; +} + function handleFile(win, file) { let localFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); localFile.initWithPath(file); @@ -327,17 +333,19 @@ function handleFile(win, file) { req.send(null); let testURLs = []; - let server = Services.prefs.getCharPref("addon.test.tabswitch.webserver"); let maxurls = Services.prefs.getIntPref("addon.test.tabswitch.maxurls"); - let parent = server + "/tests/"; let lines = req.responseText.split('