summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/tools/blinkpy
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-05-24 11:40:17 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-05-24 12:42:11 +0000
commit5d87695f37678f96492b258bbab36486c59866b4 (patch)
treebe9783bbaf04fb930c4d74ca9c00b5e7954c8bc6 /chromium/third_party/blink/tools/blinkpy
parent6c11fb357ec39bf087b8b632e2b1e375aef1b38b (diff)
downloadqtwebengine-chromium-5d87695f37678f96492b258bbab36486c59866b4.tar.gz
BASELINE: Update Chromium to 75.0.3770.56
Change-Id: I86d2007fd27a45d5797eee06f4c9369b8b50ac4f Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/third_party/blink/tools/blinkpy')
-rw-r--r--chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py24
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/config/builders.json8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/host_mock.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py17
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/path_finder.py18
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/path_finder_unittest.py22
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py4
-rwxr-xr-xchromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py59
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py13
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/README.chromium2
-rwxr-xr-xchromium/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/chromium.patch4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py24
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py218
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py156
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py223
-rwxr-xr-xchromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/update.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/utils.py7
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py62
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/client.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/transport.py6
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py221
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py52
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py14
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/utils.py5
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/virtualenv.py69
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py23
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/config.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/handlers.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/request.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py81
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py10
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py40
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py98
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py37
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py15
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py11
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py9
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py179
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py145
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py30
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py48
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/factory.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py21
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/linux.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/mac.py9
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/mac_unittest.py7
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py8
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py4
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py3
57 files changed, 1423 insertions, 651 deletions
diff --git a/chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py b/chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py
index 8e7a42a56d4..6db448d87f2 100644
--- a/chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py
+++ b/chromium/third_party/blink/tools/blinkpy/bindings/bindings_tests.py
@@ -34,6 +34,7 @@ from blinkpy.common.system.executive import Executive
from blinkpy.common import path_finder
path_finder.add_bindings_scripts_dir_to_sys_path()
+path_finder.add_build_scripts_dir_to_sys_path()
from code_generator_v8 import CodeGeneratorDictionaryImpl
from code_generator_v8 import CodeGeneratorV8
@@ -47,6 +48,7 @@ from idl_compiler import (generate_bindings,
generate_union_type_containers,
generate_dictionary_impl,
generate_callback_function_impl)
+from json5_generator import Json5File
from utilities import ComponentInfoProviderCore
from utilities import ComponentInfoProviderModules
from utilities import get_file_contents
@@ -68,9 +70,9 @@ TBR=someone in third_party/blink/renderer/bindings/OWNERS or WATCHLISTS:bindings
SOURCE_PATH = path_finder.get_source_dir()
DEPENDENCY_IDL_FILES = frozenset([
- 'test_implements.idl',
- 'test_implements_2.idl',
- 'test_implements_3.idl',
+ 'test_interface_mixin.idl',
+ 'test_interface_mixin_2.idl',
+ 'test_interface_mixin_3.idl',
'test_interface_partial.idl',
'test_interface_partial_2.idl',
'test_interface_partial_3.idl',
@@ -103,7 +105,7 @@ def TemporaryDirectory():
shutil.rmtree(name)
-def generate_interface_dependencies():
+def generate_interface_dependencies(runtime_enabled_features):
def idl_paths_recursive(directory):
# This is slow, especially on Windows, due to os.walk making
# excess stat() calls. Faster versions may appear in Python 3.5 or
@@ -137,7 +139,7 @@ def generate_interface_dependencies():
# To avoid this issue, we need to clear relative_dir here.
for value in info['interfaces_info'].itervalues():
value['relative_dir'] = ''
- component_info = info_collector.get_component_info_as_dict()
+ component_info = info_collector.get_component_info_as_dict(runtime_enabled_features)
return info, component_info
# We compute interfaces info for *all* IDL files, not just test IDL
@@ -275,8 +277,18 @@ def bindings_tests(output_directory, verbose, suppress_diff):
return False
return True
+ def make_runtime_features_dict():
+ input_filename = os.path.join(TEST_INPUT_DIRECTORY, 'runtime_enabled_features.json5')
+ json5_file = Json5File.load_from_files([input_filename])
+ features_map = {}
+ for feature in json5_file.name_dictionaries:
+ features_map[str(feature['name'])] = {
+ 'in_origin_trial': feature['in_origin_trial']
+ }
+ return features_map
+
try:
- generate_interface_dependencies()
+ generate_interface_dependencies(make_runtime_features_dict())
for component in COMPONENT_DIRECTORY:
output_dir = os.path.join(output_directory, component)
if not os.path.exists(output_dir):
diff --git a/chromium/third_party/blink/tools/blinkpy/common/config/builders.json b/chromium/third_party/blink/tools/blinkpy/common/config/builders.json
index 5c3e7c6016a..c38cd6bc555 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/config/builders.json
+++ b/chromium/third_party/blink/tools/blinkpy/common/config/builders.json
@@ -51,6 +51,14 @@
"port_name": "win-win7",
"specifiers": ["Win7", "Debug"]
},
+ "Win10 Tests x64": {
+ "port_name": "win-win10",
+ "specifiers": ["Win10", "Release"]
+ },
+ "Win10 Tests x64 (dbg)": {
+ "port_name": "win-win10",
+ "specifiers": ["Win10", "Debug"]
+ },
"linux-blink-rel": {
"port_name": "linux-trusty",
"specifiers": ["Trusty", "Release"],
diff --git a/chromium/third_party/blink/tools/blinkpy/common/host_mock.py b/chromium/third_party/blink/tools/blinkpy/common/host_mock.py
index 2131a01952a..ee20fed59a3 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/host_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/host_mock.py
@@ -36,6 +36,7 @@ from blinkpy.common.system.system_host_mock import MockSystemHost
from blinkpy.web_tests.builder_list import BuilderList
from blinkpy.web_tests.port.factory import PortFactory
from blinkpy.web_tests.port.test import add_unit_tests_to_mock_filesystem
+from blinkpy.w3c.wpt_manifest import BASE_MANIFEST_NAME
class MockHost(MockSystemHost):
@@ -116,6 +117,5 @@ class MockHost(MockSystemHost):
external_dir = path_finder.path_from_web_tests('external')
filesystem.maybe_make_directory(filesystem.join(external_dir, 'wpt'))
- # This filename should match the constant BASE_MANIFEST_NAME.
- manifest_base_path = filesystem.join(external_dir, 'WPT_BASE_MANIFEST_5.json')
+ manifest_base_path = filesystem.join(external_dir, BASE_MANIFEST_NAME)
filesystem.files[manifest_base_path] = '{"manifest": "base"}'
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py
index 6b6fcbca004..0491eaaee89 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py
@@ -52,12 +52,22 @@ class GitCL(object):
self._cwd = cwd
self._git_executable_name = Git.find_executable_name(host.executive, host.platform)
- def run(self, args):
- """Runs git-cl with the given arguments and returns the output."""
+ def run(self, args, return_stderr=False):
+ """Runs git-cl with the given arguments and returns the output.
+
+ Args:
+ args: A list of arguments passed to `git cl`.
+ return_stderr: Whether to include stderr in the returned output (the
+ default is False because git-cl will show a warning when running
+ on Swarming bots with local git cache).
+
+ Returns:
+ A string (the output from git-cl).
+ """
command = [self._git_executable_name, 'cl'] + args
if self._auth_refresh_token_json and args[0] in _COMMANDS_THAT_TAKE_REFRESH_TOKEN:
command += ['--auth-refresh-token-json', self._auth_refresh_token_json]
- return self._host.executive.run_command(command, cwd=self._cwd)
+ return self._host.executive.run_command(command, cwd=self._cwd, return_stderr=return_stderr)
def trigger_try_jobs(self, builders, bucket=None):
"""Triggers try jobs on the given builders.
@@ -136,6 +146,7 @@ class GitCL(object):
def closed_status_or_none():
status = self._get_cl_status()
+ _log.debug('CL status is: %s', status)
if status == 'closed':
self._host.print_('CL is closed.')
return status
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py
index 6e302cbcde5..4567df12a29 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_mock.py
@@ -3,6 +3,7 @@
# found in the LICENSE file.
from blinkpy.common.net.git_cl import CLStatus, GitCL
+from blinkpy.common.system.executive import ScriptError
# pylint: disable=unused-argument
@@ -10,7 +11,7 @@ class MockGitCL(object):
def __init__(
self, host, try_job_results=None, status='closed',
- issue_number='1234', time_out=False):
+ issue_number='1234', time_out=False, git_error_output=None):
"""Constructs a fake GitCL with canned return values.
Args:
@@ -19,16 +20,21 @@ class MockGitCL(object):
status: CL status string.
issue_number: CL issue number as a string.
time_out: Whether to simulate timing out while waiting.
+ git_error_output: A dict of git-cl args to exception output.
"""
self._builders = host.builders.all_try_builder_names()
self._status = status
self._try_job_results = try_job_results
self._issue_number = issue_number
self._time_out = time_out
+ self._git_error_output = git_error_output
self.calls = []
def run(self, args):
self.calls.append(['git', 'cl'] + args)
+ arg_key = "".join(args)
+ if self._git_error_output and arg_key in self._git_error_output.keys():
+ raise ScriptError(output=self._git_error_output[arg_key])
return 'mock output'
def trigger_try_jobs(self, builders, bucket=None):
diff --git a/chromium/third_party/blink/tools/blinkpy/common/path_finder.py b/chromium/third_party/blink/tools/blinkpy/common/path_finder.py
index 904b5c4f218..c829a09ba0c 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/path_finder.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/path_finder.py
@@ -44,6 +44,12 @@ def add_bindings_scripts_dir_to_sys_path():
sys.path.insert(0, path_to_bindings_scripts)
+def add_build_scripts_dir_to_sys_path():
+ path_to_build_scripts = os.path.join(get_source_dir(), 'build', 'scripts')
+ if path_to_build_scripts not in sys.path:
+ sys.path.insert(0, path_to_build_scripts)
+
+
def add_blinkpy_thirdparty_dir_to_sys_path():
path = get_blinkpy_thirdparty_dir()
if path not in sys.path:
@@ -148,6 +154,18 @@ class PathFinder(object):
def path_from_web_tests(self, *comps):
return self._filesystem.join(self.web_tests_dir(), *comps)
+ def strip_web_tests_path(self, wpt_test_abs_path):
+ web_tests_path = self.path_from_web_tests('')
+ if wpt_test_abs_path.startswith(web_tests_path):
+ return wpt_test_abs_path[len(web_tests_path):]
+ return wpt_test_abs_path
+
+ def strip_webdriver_tests_path(self, wpt_webdriver_test_path):
+ webdriver_prefix = self._filesystem.join('external', 'wpt', 'webdriver', '')
+ if wpt_webdriver_test_path.startswith(webdriver_prefix):
+ return wpt_webdriver_test_path[len(webdriver_prefix):]
+ return wpt_webdriver_test_path
+
@memoized
def depot_tools_base(self):
"""Returns the path to depot_tools, or None if not found.
diff --git a/chromium/third_party/blink/tools/blinkpy/common/path_finder_unittest.py b/chromium/third_party/blink/tools/blinkpy/common/path_finder_unittest.py
index 13baca96746..e2b96d3f87e 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/path_finder_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/path_finder_unittest.py
@@ -67,3 +67,25 @@ class TestPathFinder(unittest.TestCase):
finder = PathFinder(filesystem)
self.assertEqual(
finder.depot_tools_base(), '/checkout/third_party/depot_tools')
+
+ def test_strip_web_tests_path(self):
+ finder = PathFinder(MockFileSystem())
+ path_with_web_tests = '/mock-checkout/' + RELATIVE_WEB_TESTS + 'external/wpt'
+ self.assertEqual(
+ finder.strip_web_tests_path(path_with_web_tests),
+ 'external/wpt')
+ path_without_web_tests = '/checkout/' + RELATIVE_WEB_TESTS + 'external/wpt'
+ self.assertEqual(
+ finder.strip_web_tests_path(path_without_web_tests),
+ path_without_web_tests)
+
+ def test_strip_webdriver_tests_path(self):
+ finder = PathFinder(MockFileSystem())
+ path_with_webdriver_prefix = 'external/wpt/webdriver/' + 'foo/bar.py::test'
+ self.assertEqual(
+ finder.strip_webdriver_tests_path(path_with_webdriver_prefix),
+ 'foo/bar.py::test')
+ path_without_webdriver_prefix = 'external/wpt' + 'bar/foo.py::test'
+ self.assertEqual(
+ finder.strip_webdriver_tests_path(path_without_webdriver_prefix),
+ path_without_webdriver_prefix)
diff --git a/chromium/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py b/chromium/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py
index 7b728fa7c06..232bd655751 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py
@@ -30,8 +30,8 @@ class TestFileDiff(unittest.TestCase):
'similarity index 100%',
'rename from platform/modules/offscreencanvas/OWNERS',
'rename to platform/modules/frame_sinks/OWNERS',
- 'diff --git a/platform/modules/frame_sinks/embedded_frame_sink.mojom ' +
- 'b/platform/modules/frame_sinks/embedded_frame_sink.mojom']
+ 'diff --git a/mojom/frame_sinks/embedded_frame_sink.mojom ' +
+ 'b/mojom/frame_sinks/embedded_frame_sink.mojom']
diff, remaining_lines = DiffFile.parse(lines)
self.assertIsNotNone(diff)
self.assertEquals(remaining_lines[0], lines[4])
diff --git a/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index ceb6c930d55..81c8a26a81c 100755
--- a/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/chromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -32,6 +32,7 @@ _CONFIG = [
# //base constructs that are allowed everywhere
'base::AdoptRef',
'base::AutoReset',
+ 'base::CreateSequencedTaskRunnerWithTraits',
'base::ElapsedTimer',
'base::File',
'base::FilePath',
@@ -40,10 +41,10 @@ _CONFIG = [
'base::MakeRefCounted',
'base::Optional',
'base::OptionalOrNullptr',
+ 'base::PlatformThread',
'base::PlatformThreadId',
'base::RefCountedData',
'base::RunLoop',
- 'base::CreateSequencedTaskRunnerWithTraits',
'base::ReadOnlySharedMemoryMapping',
'base::ReadOnlySharedMemoryRegion',
'base::SequencedTaskRunner',
@@ -56,6 +57,11 @@ _CONFIG = [
'base::TimeDelta',
'base::TimeTicks',
'base::ThreadTicks',
+ 'base::trace_event::MemoryAllocatorDump',
+ 'base::trace_event::MemoryDumpArgs',
+ 'base::trace_event::MemoryDumpManager',
+ 'base::trace_event::MemoryDumpProvider',
+ 'base::trace_event::ProcessMemoryDump',
'base::UnguessableToken',
'base::UnguessableTokenHash',
'base::UnsafeSharedMemoryRegion',
@@ -86,6 +92,12 @@ _CONFIG = [
'base::RepeatingCallback',
'base::RepeatingClosure',
+ # //base/mac/scoped_nsobject.h
+ 'base::scoped_nsobject',
+
+ # //base/memory/scoped_policy.h
+ 'base::scoped_policy::RETAIN',
+
# //base/memory/ptr_util.h.
'base::WrapUnique',
@@ -95,6 +107,9 @@ _CONFIG = [
# //base/metrics/histogram_functions.h
'base::UmaHistogram.+',
+ # //base/metrics/histogram.h
+ 'base::LinearHistogram',
+
# //base/metrics/field_trial_params.h.
'base::GetFieldTrialParamValueByFeature',
'base::GetFieldTrialParamByFeatureAsBool',
@@ -139,6 +154,11 @@ _CONFIG = [
'base::CheckOr',
'base::CheckXor',
+ # //base/numerics/clamped_math.h.
+ 'base::ClampAdd',
+ 'base::ClampSub',
+ 'base::MakeClampedNum',
+
# Debugging helpers from //base/debug are allowed everywhere.
'base::debug::.+',
@@ -346,6 +366,11 @@ _CONFIG = [
# Permit using crash keys inside Blink without jumping through
# hoops.
'crash_reporter::.*CrashKey.*',
+
+ # Useful for platform-specific code.
+ 'base::mac::(CFToNSCast|NSToCFCast)',
+ 'base::mac::Is(AtMost|AtLeast)?OS.+',
+ 'base::(scoped_nsobject|ScopedCFTypeRef)',
],
'disallowed': [
'.+',
@@ -358,6 +383,16 @@ _CONFIG = [
'allowed': ['gin::.+'],
},
{
+ 'paths': ['third_party/blink/renderer/bindings/core/v8/script_streamer.cc'],
+ 'allowed': [
+ # For the script streaming to be able to block when reading from a
+ # mojo datapipe.
+ 'base::ScopedAllowBaseSyncPrimitives',
+ 'base::ScopedBlockingCall',
+ 'base::BlockingType',
+ ],
+ },
+ {
'paths': ['third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc'],
'allowed': [
# For memory reduction histogram.
@@ -371,6 +406,12 @@ _CONFIG = [
],
},
{
+ 'paths': ['third_party/blink/renderer/controller/user_level_memory_pressure_signal_generator.cc'],
+ 'allowed': [
+ 'base::MemoryPressureListener',
+ ],
+ },
+ {
'paths': ['third_party/blink/renderer/core/animation'],
'allowed': [
'[a-z_]+_functions::.+',
@@ -621,6 +662,22 @@ _CONFIG = [
'base::OnTaskRunnerDeleter',
'sigslot::.+',
],
+ },
+ # TODO(https://crbug.com/704441) : Added temporarily.
+ {
+ 'paths': ['third_party/blink/renderer/modules/exported/web_manifest_parser.cc'],
+ 'allowed': [
+ 'base::StringPiece',
+ 'GURL',
+ ],
+ },
+ {
+ 'paths': ['third_party/blink/renderer/modules/manifest/'],
+ 'allowed': [
+ 'base::.+',
+ 'net::ParseMimeTypeWithoutParameter',
+ 'GURL',
+ ],
}
]
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py
index 7d3936cfd92..e7ab3a76032 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp.py
@@ -1866,7 +1866,7 @@ def check_language(filename, clean_lines, line_number, file_extension, include_s
# FIXME: figure out if they're using default arguments in fn proto.
# Check if they're using a precise-width integer type.
- matched = search(r'\b((un)?signed\s+)?short\b', line)
+ matched = search(r'\b((un)?signed\s+)?(short|(long\s+)?long)\b', line)
if matched:
error(line_number, 'runtime/int', 1,
'Use a precise-width integer type from <stdint.h> or <cstdint>'
diff --git a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
index 36d83532abc..2ac8cc0ff4e 100644
--- a/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
@@ -463,6 +463,18 @@ class CppStyleTest(CppStyleTestBase):
self.assert_lint('uint16_t unsignedshort = 1', '')
self.assert_lint('signed short a = 1', errmsg % 'signed short [runtime/int] [1]')
self.assert_lint('short a = 1', errmsg % 'short [runtime/int] [1]')
+ self.assert_lint('unsigned long long a = 1', errmsg % 'unsigned long long [runtime/int] [1]')
+ self.assert_lint('signed long long a = 1', errmsg % 'signed long long [runtime/int] [1]')
+ self.assert_lint('long long a = 1', errmsg % 'long long [runtime/int] [1]')
+ self.assert_lint('uint64_t longlong = 1', '')
+ self.assert_lint('unsigned long a = 1', errmsg % 'unsigned long [runtime/int] [1]')
+ self.assert_lint('signed long a = 1', errmsg % 'signed long [runtime/int] [1]')
+ self.assert_lint('long a = 1', errmsg % 'long [runtime/int] [1]')
+ self.assert_lint('signed int long a = 1', errmsg % 'long [runtime/int] [1]')
+ self.assert_lint('unsigned long int a = 1', errmsg % 'unsigned long [runtime/int] [1]')
+ self.assert_lint('unsigned longlong = 1', '')
+ self.assert_lint('signed int a = 1', '')
+ self.assert_lint('int a = 1', '')
# Test C-style cast cases.
def test_cstyle_cast(self):
@@ -1511,7 +1523,6 @@ class CppStyleTest(CppStyleTestBase):
self.assert_lint('int a : 30;', errmsg)
self.assert_lint('mutable int a : 14;', errmsg)
self.assert_lint('const char a : 6;', errmsg)
- self.assert_lint('long int a : 30;', errmsg)
self.assert_lint('int a = 1 ? 0 : 30;', '')
# Bitfields which are not declared unsigned or bool will generate a warning.
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/README.chromium b/chromium/third_party/blink/tools/blinkpy/third_party/README.chromium
index ff596681578..fb6c057dff5 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/README.chromium
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/README.chromium
@@ -32,7 +32,7 @@ Local Modifications: None
Name: web-platform-tests - Test Suites for Web Platform specifications
Short Name: wpt
URL: https://github.com/web-platform-tests/wpt/
-Version: f759f0b3a8cb7457adbf30dc0734d3a158ce4990
+Version: 3d27143b5c6cbce8a9acc476b10c416aecd42a2d
License: LICENSES FOR W3C TEST SUITES (http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html)
License File: wpt/wpt/LICENSE.md
Security Critical: no
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
index d927f1844d1..59555adc3ea 100755
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
@@ -9,7 +9,7 @@ cd $DIR
TARGET_DIR=$DIR/wpt
REMOTE_REPO="https://chromium.googlesource.com/external/github.com/web-platform-tests/wpt.git"
-WPT_HEAD=f759f0b3a8cb7457adbf30dc0734d3a158ce4990
+WPT_HEAD=3d27143b5c6cbce8a9acc476b10c416aecd42a2d
function clone {
# Remove existing repo if already exists.
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/chromium.patch b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/chromium.patch
index 11fe8345bbb..ea26cc3c8b2 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/chromium.patch
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/chromium.patch
@@ -38,8 +38,10 @@ diff --git a/tools/wpt/paths b/tools/wpt/paths
index 0ef13c96e3..93c97dc02b 100644
--- a/tools/wpt/paths
+++ b/tools/wpt/paths
-@@ -1,4 +1,3 @@
+@@ -1,6 +1,4 @@
-tools/ci/
tools/lint/
tools/manifest/
tools/serve/
+-tools/taskcluster/
+ tools/wpt/
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json
index 3a674155c52..5715de520da 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json
@@ -20,6 +20,10 @@
},
"aliases": [
{
+ "url-path": "/wpt_internal/",
+ "local-dir": "../../../../../web_tests/wpt_internal"
+ },
+ {
"url-path": "/wpt_automation/",
"local-dir": "../../../../../web_tests/external/wpt_automation"
},
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py
index 03f0ecc7780..bcf08d9be9c 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py
@@ -134,6 +134,28 @@ def check_worker_collision(repo_root, path):
return []
+def check_gitignore_file(repo_root, path):
+ if not path.endswith(".gitignore"):
+ return []
+
+ path_parts = path.split(os.path.sep)
+ if len(path_parts) == 1:
+ return []
+
+ if path_parts[-1] != ".gitignore":
+ return []
+
+ if (path_parts[0] in ["tools", "docs"] or
+ path_parts[:2] == ["resources", "webidl2"] or
+ path_parts[:3] == ["css", "tools", "apiclient"]):
+ return []
+
+ return [("GITIGNORE",
+ ".gitignore found outside the root",
+ path,
+ None)]
+
+
def check_ahem_copy(repo_root, path):
lpath = path.lower()
if "ahem" in lpath and lpath.endswith(".ttf"):
@@ -914,7 +936,7 @@ def lint(repo_root, paths, output_format, ignore_glob):
logger.info(line)
return sum(itervalues(error_count))
-path_lints = [check_path_length, check_worker_collision, check_ahem_copy]
+path_lints = [check_path_length, check_worker_collision, check_ahem_copy, check_gitignore_file]
all_paths_lints = [check_css_globally_unique]
file_lints = [check_regexp_line, check_parsed, check_python_ast, check_script_metadata]
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py
index 2bbdf0d5a5b..b6d33e8452c 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py
@@ -1,24 +1,8 @@
+from copy import copy
+from six import iteritems
from six.moves.urllib.parse import urljoin, urlparse
from abc import ABCMeta, abstractproperty
-
-class SourceFileCache(object):
- def __init__(self):
- self.source_files = {}
-
- def make_new(self, tests_root, path, url_base):
- from .sourcefile import SourceFile
-
- return SourceFile(tests_root, path, url_base)
-
- def get(self, tests_root, manifest, path):
-
- if path not in self.source_files:
- self.source_files[path] = self.make_new(tests_root, path, manifest.url_base)
-
- return self.source_files[path]
-
-
item_types = {}
@@ -38,48 +22,30 @@ class ManifestItemMeta(ABCMeta):
class ManifestItem(object):
__metaclass__ = ManifestItemMeta
- item_type = None
+ __slots__ = ("_tests_root", "path")
- source_file_cache = SourceFileCache()
+ item_type = None
- def __init__(self, source_file, manifest=None):
- self.source_file = source_file
+ def __init__(self, tests_root=None, path=None):
+ self._tests_root = tests_root
+ self.path = path
@abstractproperty
def id(self):
"""The test's id (usually its url)"""
pass
- @property
- def meta_flags(self):
- return set(self.source_file.meta_flags)
-
- @property
- def path(self):
- """The test path relative to the test_root"""
- return self.source_file.rel_path
-
- @property
- def https(self):
- flags = self.meta_flags
- return ("https" in flags or "serviceworker" in flags)
-
def key(self):
"""A unique identifier for the test"""
return (self.item_type, self.id)
- def meta_key(self):
- """Extra metadata that doesn't form part of the test identity, but for
- which changes mean regenerating the manifest (e.g. the test timeout."""
- return ()
-
def __eq__(self, other):
if not hasattr(other, "key"):
return False
return self.key() == other.key()
def __hash__(self):
- return hash(self.key() + self.meta_key())
+ return hash(self.key())
def __repr__(self):
return "<%s.%s id=%s, path=%s>" % (self.__module__, self.__class__.__name__, self.id, self.path)
@@ -88,99 +54,117 @@ class ManifestItem(object):
return [{}]
@classmethod
- def from_json(cls, manifest, tests_root, path, obj):
- source_file = cls.source_file_cache.get(tests_root, manifest, path)
- return cls(source_file,
- manifest=manifest)
+ def from_json(cls, manifest, path, obj):
+ return cls(manifest.tests_root, path)
class URLManifestItem(ManifestItem):
- def __init__(self, source_file, url, url_base="/", manifest=None):
- ManifestItem.__init__(self, source_file, manifest=manifest)
- self._url = url
+ __slots__ = ("url_base", "_url", "_extras")
+
+ def __init__(self, tests_root, path, url_base, url, **extras):
+ super(URLManifestItem, self).__init__(tests_root, path)
+ assert url_base[0] == "/"
self.url_base = url_base
+ assert url[0] != "/"
+ self._url = url
+ self._extras = extras
@property
def id(self):
return self.url
@property
- def meta_flags(self):
- return set(urlparse(self.url).path.rsplit("/", 1)[1].split(".")[1:-1])
-
- @property
def url(self):
+ # we can outperform urljoin, because we know we just have path relative URLs
+ if self.url_base == "/":
+ return "/" + self._url
return urljoin(self.url_base, self._url)
+ @property
+ def https(self):
+ flags = set(urlparse(self.url).path.rsplit("/", 1)[1].split(".")[1:-1])
+ return ("https" in flags or "serviceworker" in flags)
+
def to_json(self):
rv = [self._url, {}]
return rv
@classmethod
- def from_json(cls, manifest, tests_root, path, obj):
- source_file = cls.source_file_cache.get(tests_root, manifest, path)
+ def from_json(cls, manifest, path, obj):
url, extras = obj
- return cls(source_file,
+ return cls(manifest.tests_root,
+ path,
+ manifest.url_base,
url,
- url_base=manifest.url_base,
- manifest=manifest)
+ **extras)
class TestharnessTest(URLManifestItem):
item_type = "testharness"
- def __init__(self, source_file, url, url_base="/", timeout=None, testdriver=False, jsshell=False, manifest=None):
- URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest)
- self.timeout = timeout
- self.testdriver = testdriver
- self.jsshell = jsshell
+ @property
+ def timeout(self):
+ return self._extras.get("timeout")
+
+ @property
+ def testdriver(self):
+ return self._extras.get("testdriver")
- def meta_key(self):
- return (self.timeout, self.testdriver)
+ @property
+ def jsshell(self):
+ return self._extras.get("jsshell")
+
+ @property
+ def script_metadata(self):
+ return self._extras.get("script_metadata")
def to_json(self):
- rv = URLManifestItem.to_json(self)
+ rv = super(TestharnessTest, self).to_json()
if self.timeout is not None:
rv[-1]["timeout"] = self.timeout
if self.testdriver:
rv[-1]["testdriver"] = self.testdriver
if self.jsshell:
rv[-1]["jsshell"] = True
+ if self.script_metadata:
+ rv[-1]["script_metadata"] = self.script_metadata
return rv
- @classmethod
- def from_json(cls, manifest, tests_root, path, obj):
- source_file = cls.source_file_cache.get(tests_root, manifest, path)
- url, extras = obj
- return cls(source_file,
- url,
- url_base=manifest.url_base,
- timeout=extras.get("timeout"),
- testdriver=bool(extras.get("testdriver")),
- jsshell=bool(extras.get("jsshell")),
- manifest=manifest)
+class RefTestBase(URLManifestItem):
+ __slots__ = ("references",)
+ item_type = "reftest_base"
-class RefTestNode(URLManifestItem):
- item_type = "reftest_node"
+ def __init__(self, tests_root, path, url_base, url, references=None, **extras):
+ super(RefTestBase, self).__init__(tests_root, path, url_base, url, **extras)
+ if references is None:
+ self.references = []
+ else:
+ self.references = references
- def __init__(self, source_file, url, references, url_base="/", timeout=None,
- viewport_size=None, dpi=None, manifest=None):
- URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest)
- for _, ref_type in references:
- if ref_type not in ["==", "!="]:
- raise ValueError("Unrecognised ref_type %s" % ref_type)
- self.references = tuple(references)
- self.timeout = timeout
- self.viewport_size = viewport_size
- self.dpi = dpi
+ @property
+ def timeout(self):
+ return self._extras.get("timeout")
- def meta_key(self):
- return (self.timeout, self.viewport_size, self.dpi)
+ @property
+ def viewport_size(self):
+ return self._extras.get("viewport_size")
+
+ @property
+ def dpi(self):
+ return self._extras.get("dpi")
+
+ @property
+ def fuzzy(self):
+ rv = self._extras.get("fuzzy", [])
+ if isinstance(rv, list):
+ return {tuple(item[0]): item[1]
+ for item in self._extras.get("fuzzy", [])}
+ return rv
def to_json(self):
- rv = [self.url, self.references, {}]
+ rv = [self._url, self.references, {}]
extras = rv[-1]
if self.timeout is not None:
extras["timeout"] = self.timeout
@@ -188,37 +172,40 @@ class RefTestNode(URLManifestItem):
extras["viewport_size"] = self.viewport_size
if self.dpi is not None:
extras["dpi"] = self.dpi
+ if self.fuzzy:
+ extras["fuzzy"] = list(iteritems(self.fuzzy))
return rv
@classmethod
- def from_json(cls, manifest, tests_root, path, obj):
- source_file = cls.source_file_cache.get(tests_root, manifest, path)
+ def from_json(cls, manifest, path, obj):
url, references, extras = obj
- return cls(source_file,
+ return cls(manifest.tests_root,
+ path,
+ manifest.url_base,
url,
references,
- url_base=manifest.url_base,
- timeout=extras.get("timeout"),
- viewport_size=extras.get("viewport_size"),
- dpi=extras.get("dpi"),
- manifest=manifest)
+ **extras)
def to_RefTest(self):
if type(self) == RefTest:
return self
- rv = RefTest.__new__(RefTest)
- rv.__dict__.update(self.__dict__)
+ rv = copy(self)
+ rv.__class__ = RefTest
return rv
def to_RefTestNode(self):
if type(self) == RefTestNode:
return self
- rv = RefTestNode.__new__(RefTestNode)
- rv.__dict__.update(self.__dict__)
+ rv = copy(self)
+ rv.__class__ = RefTestNode
return rv
-class RefTest(RefTestNode):
+class RefTestNode(RefTestBase):
+ item_type = "reftest_node"
+
+
+class RefTest(RefTestBase):
item_type = "reftest"
@@ -241,31 +228,20 @@ class Stub(URLManifestItem):
class WebDriverSpecTest(URLManifestItem):
item_type = "wdspec"
- def __init__(self, source_file, url, url_base="/", timeout=None, manifest=None):
- URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest)
- self.timeout = timeout
+ @property
+ def timeout(self):
+ return self._extras.get("timeout")
def to_json(self):
- rv = URLManifestItem.to_json(self)
+ rv = super(WebDriverSpecTest, self).to_json()
if self.timeout is not None:
rv[-1]["timeout"] = self.timeout
return rv
- @classmethod
- def from_json(cls, manifest, tests_root, path, obj):
- source_file = cls.source_file_cache.get(tests_root, manifest, path)
-
- url, extras = obj
- return cls(source_file,
- url,
- url_base=manifest.url_base,
- timeout=extras.get("timeout"),
- manifest=manifest)
-
class SupportFile(ManifestItem):
item_type = "support"
@property
def id(self):
- return self.source_file.rel_path
+ return self.path
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py
index 127d45dbc66..bfe57c7823b 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py
@@ -1,4 +1,5 @@
import itertools
+import json
import os
from collections import defaultdict
from six import iteritems, iterkeys, itervalues, string_types
@@ -10,13 +11,11 @@ from .log import get_logger
from .utils import from_os_path, to_os_path
try:
- import ujson as json
- JSON_LIBRARY = 'ujson'
+ import ujson as fast_json
except ImportError:
- import json
- JSON_LIBRARY = 'json'
+ fast_json = json
-CURRENT_VERSION = 5
+CURRENT_VERSION = 6
class ManifestError(Exception):
@@ -69,8 +68,8 @@ class TypeData(object):
self.load(key)
return self.data[key]
- def __bool__(self):
- return bool(self.data)
+ def __nonzero__(self):
+ return bool(self.data) or bool(self.json_data)
def __len__(self):
rv = len(self.data)
@@ -87,6 +86,10 @@ class TypeData(object):
raise KeyError
def __setitem__(self, key, value):
+ if self.json_data is not None:
+ path = from_os_path(key)
+ if path in self.json_data:
+ del self.json_data[path]
self.data[key] = value
def __contains__(self, key):
@@ -132,10 +135,7 @@ class TypeData(object):
data = set()
path = from_os_path(key)
for test in iterfilter(self.meta_filters, self.json_data.get(path, [])):
- manifest_item = self.type_cls.from_json(self.manifest,
- self.tests_root,
- path,
- test)
+ manifest_item = self.type_cls.from_json(self.manifest, path, test)
data.add(manifest_item)
try:
del self.json_data[path]
@@ -154,10 +154,7 @@ class TypeData(object):
continue
data = set()
for test in iterfilter(self.meta_filters, self.json_data.get(path, [])):
- manifest_item = self.type_cls.from_json(self.manifest,
- self.tests_root,
- path,
- test)
+ manifest_item = self.type_cls.from_json(self.manifest, path, test)
data.add(manifest_item)
self.data[key] = data
self.json_data = None
@@ -168,6 +165,21 @@ class TypeData(object):
self.tests_root = tests_root
self.json_data = data
+ def to_json(self):
+ data = {
+ from_os_path(path):
+ [t for t in sorted(test.to_json() for test in tests)]
+ for path, tests in iteritems(self.data)
+ }
+
+ if self.json_data is not None:
+ if not data:
+ # avoid copying if there's nothing here yet
+ return self.json_data
+ data.update(self.json_data)
+
+ return data
+
def paths(self):
"""Get a list of all paths containing items of this type,
without actually constructing all the items"""
@@ -202,11 +214,12 @@ class ManifestData(dict):
class Manifest(object):
- def __init__(self, url_base="/", meta_filters=None):
+ def __init__(self, tests_root=None, url_base="/", meta_filters=None):
assert url_base is not None
self._path_hash = {}
self._data = ManifestData(self, meta_filters)
self._reftest_nodes_by_url = None
+ self.tests_root = tests_root
self.url_base = url_base
def __iter__(self):
@@ -262,7 +275,12 @@ class Manifest(object):
changed = False
reftest_changes = False
- prev_files = self._data.paths()
+ # Create local variable references to these dicts so we avoid the
+ # attribute access in the hot loop below
+ path_hash = self._path_hash
+ data = self._data
+
+ prev_files = data.paths()
reftest_types = ("reftest", "reftest_node")
@@ -270,74 +288,77 @@ class Manifest(object):
if not update:
rel_path = source_file
seen_files.add(rel_path)
+ assert rel_path in path_hash
+ old_hash, old_type = path_hash[rel_path]
+ if old_type in reftest_types:
+ manifest_items = data[old_type][rel_path]
+ reftest_nodes.extend((item, old_hash) for item in manifest_items)
else:
rel_path = source_file.rel_path
seen_files.add(rel_path)
file_hash = source_file.hash
- is_new = rel_path not in self._path_hash
+ is_new = rel_path not in path_hash
hash_changed = False
if not is_new:
- old_hash, old_type = self._path_hash[rel_path]
+ old_hash, old_type = path_hash[rel_path]
if old_hash != file_hash:
new_type, manifest_items = source_file.manifest_items()
hash_changed = True
if new_type != old_type:
- try:
- del self._data[old_type][rel_path]
- except KeyError:
- pass
+ del data[old_type][rel_path]
+ if old_type in reftest_types:
+ reftest_changes = True
else:
- new_type, manifest_items = old_type, self._data[old_type][rel_path]
- if old_type in reftest_types and new_type != old_type:
- reftest_changes = True
+ new_type = old_type
+ if old_type in reftest_types:
+ manifest_items = data[old_type][rel_path]
else:
new_type, manifest_items = source_file.manifest_items()
- if new_type in ("reftest", "reftest_node"):
- reftest_nodes.extend(manifest_items)
+ if new_type in reftest_types:
+ reftest_nodes.extend((item, file_hash) for item in manifest_items)
if is_new or hash_changed:
reftest_changes = True
- elif new_type:
- self._data[new_type][rel_path] = set(manifest_items)
-
- self._path_hash[rel_path] = (file_hash, new_type)
+ elif is_new or hash_changed:
+ data[new_type][rel_path] = set(manifest_items)
if is_new or hash_changed:
+ path_hash[rel_path] = (file_hash, new_type)
changed = True
deleted = prev_files - seen_files
if deleted:
changed = True
for rel_path in deleted:
- if rel_path in self._path_hash:
- _, old_type = self._path_hash[rel_path]
+ if rel_path in path_hash:
+ _, old_type = path_hash[rel_path]
if old_type in reftest_types:
reftest_changes = True
- del self._path_hash[rel_path]
+ del path_hash[rel_path]
try:
- del self._data[old_type][rel_path]
+ del data[old_type][rel_path]
except KeyError:
pass
else:
- for test_data in itervalues(self._data):
+ for test_data in itervalues(data):
if rel_path in test_data:
del test_data[rel_path]
if reftest_changes:
reftests, reftest_nodes, changed_hashes = self._compute_reftests(reftest_nodes)
- self._data["reftest"].data = reftests
- self._data["reftest_node"].data = reftest_nodes
- self._path_hash.update(changed_hashes)
+ data["reftest"].data = reftests
+ data["reftest_node"].data = reftest_nodes
+ path_hash.update(changed_hashes)
return changed
def _compute_reftests(self, reftest_nodes):
self._reftest_nodes_by_url = {}
has_inbound = set()
- for item in reftest_nodes:
+ for item, _ in reftest_nodes:
for ref_url, ref_type in item.references:
has_inbound.add(ref_url)
@@ -345,31 +366,27 @@ class Manifest(object):
references = defaultdict(set)
changed_hashes = {}
- for item in reftest_nodes:
+ for item, file_hash in reftest_nodes:
if item.url in has_inbound:
# This is a reference
if isinstance(item, RefTest):
item = item.to_RefTestNode()
- changed_hashes[item.source_file.rel_path] = (item.source_file.hash,
- item.item_type)
- references[item.source_file.rel_path].add(item)
+ changed_hashes[item.path] = (file_hash,
+ item.item_type)
+ references[item.path].add(item)
else:
if isinstance(item, RefTestNode):
item = item.to_RefTest()
- changed_hashes[item.source_file.rel_path] = (item.source_file.hash,
- item.item_type)
- reftests[item.source_file.rel_path].add(item)
+ changed_hashes[item.path] = (file_hash,
+ item.item_type)
+ reftests[item.path].add(item)
self._reftest_nodes_by_url[item.url] = item
return reftests, references, changed_hashes
def to_json(self):
out_items = {
- test_type: {
- from_os_path(path):
- [t for t in sorted(test.to_json() for test in tests)]
- for path, tests in iteritems(type_paths)
- }
+ test_type: type_paths.to_json()
for test_type, type_paths in iteritems(self._data) if type_paths
}
rv = {"url_base": self.url_base,
@@ -384,7 +401,7 @@ class Manifest(object):
if version != CURRENT_VERSION:
raise ManifestVersionMismatch
- self = cls(url_base=obj.get("url_base", "/"), meta_filters=meta_filters)
+ self = cls(tests_root, url_base=obj.get("url_base", "/"), meta_filters=meta_filters)
if not hasattr(obj, "items") and hasattr(obj, "paths"):
raise ManifestError
@@ -412,11 +429,11 @@ def load(tests_root, manifest, types=None, meta_filters=None):
__load_cache = {}
-def _load(logger, tests_root, manifest, types=None, meta_filters=None):
+def _load(logger, tests_root, manifest, types=None, meta_filters=None, allow_cached=True):
# "manifest" is a path or file-like object.
manifest_path = (manifest if isinstance(manifest, string_types)
else manifest.name)
- if manifest_path in __load_cache:
+ if allow_cached and manifest_path in __load_cache:
return __load_cache[manifest_path]
if isinstance(manifest, string_types):
@@ -427,7 +444,7 @@ def _load(logger, tests_root, manifest, types=None, meta_filters=None):
try:
with open(manifest) as f:
rv = Manifest.from_json(tests_root,
- json.load(f),
+ fast_json.load(f),
types=types,
meta_filters=meta_filters)
except IOError:
@@ -437,11 +454,12 @@ def _load(logger, tests_root, manifest, types=None, meta_filters=None):
return None
else:
rv = Manifest.from_json(tests_root,
- json.load(manifest),
+ fast_json.load(manifest),
types=types,
meta_filters=meta_filters)
- __load_cache[manifest_path] = rv
+ if allow_cached:
+ __load_cache[manifest_path] = rv
return rv
@@ -455,7 +473,8 @@ def load_and_update(tests_root,
working_copy=False,
types=None,
meta_filters=None,
- write_manifest=True):
+ write_manifest=True,
+ allow_cached=True):
logger = get_logger()
manifest = None
@@ -465,7 +484,8 @@ def load_and_update(tests_root,
tests_root,
manifest_path,
types=types,
- meta_filters=meta_filters)
+ meta_filters=meta_filters,
+ allow_cached=allow_cached)
except ManifestVersionMismatch:
logger.info("Manifest version changed, rebuilding")
@@ -473,7 +493,7 @@ def load_and_update(tests_root,
logger.info("Manifest url base did not match, rebuilding")
if manifest is None:
- manifest = Manifest(url_base, meta_filters=meta_filters)
+ manifest = Manifest(tests_root, url_base, meta_filters=meta_filters)
update = True
if update:
@@ -492,12 +512,8 @@ def write(manifest, manifest_path):
if not os.path.exists(dir_name):
os.makedirs(dir_name)
with open(manifest_path, "wb") as f:
- if JSON_LIBRARY == 'ujson':
- # ujson does not support the separators flag.
- json.dump(manifest.to_json(), f, sort_keys=True, indent=1)
- else:
- # Use ',' instead of the default ', ' separator to prevent trailing
- # spaces: https://docs.python.org/2/library/json.html#json.dump
- json.dump(manifest.to_json(), f,
- sort_keys=True, indent=1, separators=(',', ': '))
+ # Use ',' instead of the default ', ' separator to prevent trailing
+ # spaces: https://docs.python.org/2/library/json.html#json.dump
+ json.dump(manifest.to_json(), f,
+ sort_keys=True, indent=1, separators=(',', ': '))
f.write("\n")
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py
index d2e5df85526..97fe89bbda8 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py
@@ -1,6 +1,7 @@
import hashlib
import re
import os
+from collections import deque
from six import binary_type
from six.moves.urllib.parse import urljoin
from fnmatch import fnmatch
@@ -13,7 +14,7 @@ import html5lib
from . import XMLParser
from .item import Stub, ManualTest, WebDriverSpecTest, RefTestNode, TestharnessTest, SupportFile, ConformanceCheckerTest, VisualTest
-from .utils import rel_path_to_url, ContextManagerBytesIO, cached_property
+from .utils import ContextManagerBytesIO, cached_property
wd_pattern = "*.py"
js_meta_re = re.compile(b"//\s*META:\s*(\w*)=(.*)$")
@@ -233,8 +234,13 @@ class SourceFile(object):
return os.path.join(self.tests_root, self.rel_path)
@cached_property
+ def rel_url(self):
+ assert not os.path.isabs(self.rel_path), self.rel_path
+ return self.rel_path.replace(os.sep, "/")
+
+ @cached_property
def url(self):
- return rel_path_to_url(self.rel_path, self.url_base)
+ return urljoin(self.url_base, self.rel_url)
@cached_property
def hash(self):
@@ -335,7 +341,7 @@ class SourceFile(object):
def name_is_reference(self):
"""Check if the file name matches the conditions for the file to
be a reference file (not a reftest)"""
- return "/reference/" in self.url or "/reftest/" in self.url or bool(reference_file_re.search(self.name))
+ return "/reference/" in self.url or bool(reference_file_re.search(self.name))
@property
def markup_type(self):
@@ -448,6 +454,79 @@ class SourceFile(object):
return self.dpi_nodes[0].attrib.get("content", None)
@cached_property
+ def fuzzy_nodes(self):
+ """List of ElementTree Elements corresponding to nodes in a test that
+ specify reftest fuzziness"""
+ return self.root.findall(".//{http://www.w3.org/1999/xhtml}meta[@name='fuzzy']")
+
+ @cached_property
+ def fuzzy(self):
+ rv = {}
+ if self.root is None:
+ return rv
+
+ if not self.fuzzy_nodes:
+ return rv
+
+ args = ["maxDifference", "totalPixels"]
+
+ for node in self.fuzzy_nodes:
+ item = node.attrib.get("content", "")
+
+ parts = item.rsplit(":", 1)
+ if len(parts) == 1:
+ key = None
+ value = parts[0]
+ else:
+ key = urljoin(self.url, parts[0])
+ reftype = None
+ for ref in self.references:
+ if ref[0] == key:
+ reftype = ref[1]
+ break
+ if reftype not in ("==", "!="):
+ raise ValueError("Fuzzy key %s doesn't correspond to a references" % key)
+ key = (self.url, key, reftype)
+ value = parts[1]
+ ranges = value.split(";")
+ if len(ranges) != 2:
+ raise ValueError("Malformed fuzzy value %s" % item)
+ arg_values = {None: deque()}
+ for range_str_value in ranges:
+ if "=" in range_str_value:
+ name, range_str_value = [part.strip()
+ for part in range_str_value.split("=", 1)]
+ if name not in args:
+ raise ValueError("%s is not a valid fuzzy property" % name)
+ if arg_values.get(name):
+ raise ValueError("Got multiple values for argument %s" % name)
+ else:
+ name = None
+ if "-" in range_str_value:
+ range_min, range_max = range_str_value.split("-")
+ else:
+ range_min = range_str_value
+ range_max = range_str_value
+ try:
+ range_value = [int(x.strip()) for x in (range_min, range_max)]
+ except ValueError:
+ raise ValueError("Fuzzy value %s must be a range of integers" %
+ range_str_value)
+ if name is None:
+ arg_values[None].append(range_value)
+ else:
+ arg_values[name] = range_value
+ rv[key] = []
+ for arg_name in args:
+ if arg_values.get(arg_name):
+ value = arg_values.pop(arg_name)
+ else:
+ value = arg_values[None].popleft()
+ rv[key].append(value)
+ assert list(arg_values.keys()) == [None] and len(arg_values[None]) == 0
+ return rv
+
+ @cached_property
def testharness_nodes(self):
"""List of ElementTree Elements corresponding to nodes representing a
testharness.js script"""
@@ -599,22 +678,54 @@ class SourceFile(object):
return self.items_cache
if self.name_is_non_test:
- rv = "support", [SupportFile(self)]
+ rv = "support", [
+ SupportFile(
+ self.tests_root,
+ self.rel_path
+ )]
elif self.name_is_stub:
- rv = Stub.item_type, [Stub(self, self.url)]
+ rv = Stub.item_type, [
+ Stub(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url
+ )]
elif self.name_is_manual:
- rv = ManualTest.item_type, [ManualTest(self, self.url)]
+ rv = ManualTest.item_type, [
+ ManualTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url
+ )]
elif self.name_is_conformance:
- rv = ConformanceCheckerTest.item_type, [ConformanceCheckerTest(self, self.url)]
+ rv = ConformanceCheckerTest.item_type, [
+ ConformanceCheckerTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url
+ )]
elif self.name_is_conformance_support:
- rv = "support", [SupportFile(self)]
+ rv = "support", [
+ SupportFile(
+ self.tests_root,
+ self.rel_path
+ )]
elif self.name_is_visual:
- rv = VisualTest.item_type, [VisualTest(self, self.url)]
+ rv = VisualTest.item_type, [
+ VisualTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url
+ )]
elif self.name_is_multi_global:
globals = b""
@@ -624,53 +735,115 @@ class SourceFile(object):
break
tests = [
- TestharnessTest(self, global_variant_url(self.url, suffix) + variant, timeout=self.timeout,
- jsshell=jsshell)
+ TestharnessTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ global_variant_url(self.rel_url, suffix) + variant,
+ timeout=self.timeout,
+ jsshell=jsshell,
+ script_metadata=self.script_metadata
+ )
for (suffix, jsshell) in sorted(global_suffixes(globals))
for variant in self.test_variants
]
rv = TestharnessTest.item_type, tests
elif self.name_is_worker:
- test_url = replace_end(self.url, ".worker.js", ".worker.html")
+ test_url = replace_end(self.rel_url, ".worker.js", ".worker.html")
tests = [
- TestharnessTest(self, test_url + variant, timeout=self.timeout)
+ TestharnessTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ test_url + variant,
+ timeout=self.timeout,
+ script_metadata=self.script_metadata
+ )
for variant in self.test_variants
]
rv = TestharnessTest.item_type, tests
elif self.name_is_window:
- test_url = replace_end(self.url, ".window.js", ".window.html")
+ test_url = replace_end(self.rel_url, ".window.js", ".window.html")
tests = [
- TestharnessTest(self, test_url + variant, timeout=self.timeout)
+ TestharnessTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ test_url + variant,
+ timeout=self.timeout,
+ script_metadata=self.script_metadata
+ )
for variant in self.test_variants
]
rv = TestharnessTest.item_type, tests
elif self.name_is_webdriver:
- rv = WebDriverSpecTest.item_type, [WebDriverSpecTest(self, self.url,
- timeout=self.timeout)]
+ rv = WebDriverSpecTest.item_type, [
+ WebDriverSpecTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url,
+ timeout=self.timeout
+ )]
elif self.content_is_css_manual and not self.name_is_reference:
- rv = ManualTest.item_type, [ManualTest(self, self.url)]
+ rv = ManualTest.item_type, [
+ ManualTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url
+ )]
elif self.content_is_testharness:
rv = TestharnessTest.item_type, []
testdriver = self.has_testdriver
for variant in self.test_variants:
- url = self.url + variant
- rv[1].append(TestharnessTest(self, url, timeout=self.timeout, testdriver=testdriver))
+ url = self.rel_url + variant
+ rv[1].append(TestharnessTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ url,
+ timeout=self.timeout,
+ testdriver=testdriver,
+ script_metadata=self.script_metadata
+ ))
elif self.content_is_ref_node:
- rv = (RefTestNode.item_type,
- [RefTestNode(self, self.url, self.references, timeout=self.timeout,
- viewport_size=self.viewport_size, dpi=self.dpi)])
+ rv = RefTestNode.item_type, [
+ RefTestNode(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url,
+ references=self.references,
+ timeout=self.timeout,
+ viewport_size=self.viewport_size,
+ dpi=self.dpi,
+ fuzzy=self.fuzzy
+ )]
elif self.content_is_css_visual and not self.name_is_reference:
- rv = VisualTest.item_type, [VisualTest(self, self.url)]
+ rv = VisualTest.item_type, [
+ VisualTest(
+ self.tests_root,
+ self.rel_path,
+ self.url_base,
+ self.rel_url
+ )]
else:
- rv = "support", [SupportFile(self)]
+ rv = "support", [
+ SupportFile(
+ self.tests_root,
+ self.rel_path
+ )]
+
+ assert len(rv[1]) == len(set(rv[1]))
self.items_cache = rv
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/update.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/update.py
index 217d767cece..321cfebe2a6 100755
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/update.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/update.py
@@ -33,7 +33,7 @@ def update_from_cli(**kwargs):
path = kwargs["path"]
assert tests_root is not None
- if kwargs["download"]:
+ if not kwargs["rebuild"] and kwargs["download"]:
download_from_github(path, tests_root)
manifest.load_and_update(tests_root,
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/utils.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/utils.py
index 9da79f6deb4..a097ad5090e 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/utils.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/utils.py
@@ -14,7 +14,10 @@ def rel_path_to_url(rel_path, url_base="/"):
def from_os_path(path):
assert os.path.sep == "/" or platform.system() == "Windows"
- rv = path.replace(os.path.sep, "/")
+ if "/" == os.path.sep:
+ rv = path
+ else:
+ rv = path.replace(os.path.sep, "/")
if "\\" in rv:
raise ValueError("path contains \\ when separator is %s" % os.path.sep)
return rv
@@ -24,6 +27,8 @@ def to_os_path(path):
assert os.path.sep == "/" or platform.system() == "Windows"
if "\\" in path:
raise ValueError("normalised path contains \\")
+ if "/" == os.path.sep:
+ return path
return path.replace("/", os.path.sep)
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py
index 69eb9ab8ecb..676e53f6785 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py
@@ -50,8 +50,8 @@ class Git(object):
return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT)
except Exception as e:
if platform.uname()[0] == "Windows" and isinstance(e, WindowsError):
- full_cmd[0] = "git.bat"
- return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT)
+ full_cmd[0] = "git.bat"
+ return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT)
else:
raise
return git
@@ -60,31 +60,32 @@ class Git(object):
def for_path(cls, path, url_base, cache_path, manifest_path=None, rebuild=False):
git = Git.get_func(path)
try:
- return cls(git("rev-parse", "--show-toplevel").rstrip(), url_base, cache_path,
- manifest_path=manifest_path, rebuild=rebuild)
+ # this needs to be a command that fails if we aren't in a git repo
+ git("rev-parse", "--show-toplevel")
except (subprocess.CalledProcessError, OSError):
return None
+ else:
+ return cls(path, url_base, cache_path,
+ manifest_path=manifest_path, rebuild=rebuild)
def _local_changes(self):
- changes = {}
+ """get a set of files which have changed between HEAD and working copy"""
+ changes = set()
+
cmd = ["status", "-z", "--ignore-submodules=all"]
data = self.git(*cmd)
- if data == "":
- return changes
-
- rename_data = None
- for entry in data.split("\0")[:-1]:
- if rename_data is not None:
- status, rel_path = entry.split(" ")
- if status[0] == "R":
- rename_data = (rel_path, status)
- else:
- changes[rel_path] = (status, None)
+ in_rename = False
+ for line in data.split(b"\0")[:-1]:
+ if in_rename:
+ changes.add(line)
+ in_rename = False
else:
- rel_path = entry
- changes[rel_path] = rename_data
- rename_data = None
+ status = line[:2]
+ if b"R" in status or b"C" in status:
+ in_rename = True
+ changes.add(line[3:])
+
return changes
def _show_file(self, path):
@@ -95,18 +96,17 @@ class Git(object):
cmd = ["ls-tree", "-r", "-z", "HEAD"]
local_changes = self._local_changes()
for result in self.git(*cmd).split("\0")[:-1]:
- rel_path = result.split("\t")[-1]
- hash = result.split()[2]
- if not os.path.isdir(os.path.join(self.root, rel_path)):
- if rel_path in local_changes:
- contents = self._show_file(rel_path)
- else:
- contents = None
- yield SourceFile(self.root,
- rel_path,
- self.url_base,
- hash,
- contents=contents), True
+ data, rel_path = result.rsplit("\t", 1)
+ hash = data.split(" ", 3)[2]
+ if rel_path in local_changes:
+ contents = self._show_file(rel_path)
+ else:
+ contents = None
+ yield SourceFile(self.root,
+ rel_path,
+ self.url_base,
+ hash,
+ contents=contents), True
def dump_caches(self):
pass
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py
index 4eee732443b..53f81457be1 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py
@@ -16,6 +16,7 @@ import traceback
from six.moves import urllib
import uuid
from collections import defaultdict, OrderedDict
+from itertools import chain, product
from multiprocessing import Process, Event
from localpaths import repo_root
@@ -720,6 +721,9 @@ def build_config(override_path=None, **kwargs):
return rv
+def _make_subdomains_product(s, depth=2):
+ return set(u".".join(x) for x in chain(*(product(s, repeat=i) for i in range(1, depth+1))))
+
_subdomains = {u"www",
u"www1",
u"www2",
@@ -728,6 +732,10 @@ _subdomains = {u"www",
_not_subdomains = {u"nonexistent"}
+_subdomains = _make_subdomains_product(_subdomains)
+
+_not_subdomains = _make_subdomains_product(_not_subdomains)
+
class ConfigBuilder(config.ConfigBuilder):
"""serve config
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/client.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/client.py
index 29be09bb3c9..52ebc95e84a 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/client.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/client.py
@@ -356,7 +356,7 @@ class UserPrompt(object):
@text.setter
@command
def text(self, value):
- body = {"value": list(value)}
+ body = {"text": value}
self.session.send_session_command("POST", "alert/text", body=body)
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/transport.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/transport.py
index 881002ad117..c6786b9ed05 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/transport.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/webdriver/webdriver/transport.py
@@ -16,9 +16,10 @@ class Response(object):
body has been read and parsed as appropriate.
"""
- def __init__(self, status, body):
+ def __init__(self, status, body, headers):
self.status = status
self.body = body
+ self.headers = headers
def __repr__(self):
cls_name = self.__class__.__name__
@@ -39,11 +40,12 @@ class Response(object):
def from_http(cls, http_response, decoder=json.JSONDecoder, **kwargs):
try:
body = json.load(http_response, cls=decoder, **kwargs)
+ headers = dict(http_response.getheaders())
except ValueError:
raise ValueError("Failed to decode response body as JSON:\n" +
http_response.read())
- return cls(http_response.status, body)
+ return cls(http_response.status, body, headers)
class HTTPWireProtocol(object):
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py
index 71d1e61918a..52157bca4e7 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py
@@ -5,10 +5,13 @@ import shutil
import stat
import subprocess
import tempfile
+import urlparse
from abc import ABCMeta, abstractmethod
from datetime import datetime, timedelta
from distutils.spawn import find_executable
+import requests
+
from utils import call, get, untar, unzip
uname = platform.uname()
@@ -26,7 +29,7 @@ class Browser(object):
return NotImplemented
@abstractmethod
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
"""Install the WebDriver implementation for this browser."""
return NotImplemented
@@ -93,30 +96,28 @@ class Firefox(Browser):
def install(self, dest=None, channel="nightly"):
"""Install Firefox."""
- branch = {
- "nightly": "mozilla-central",
- "beta": "mozilla-beta",
- "stable": "mozilla-stable"
- }
- scraper = {
- "nightly": "daily",
- "beta": "release",
- "stable": "release"
+ import mozinstall
+
+ product = {
+ "nightly": "firefox-nightly-latest-ssl",
+ "beta": "firefox-beta-latest-ssl",
+ "stable": "firefox-latest-ssl"
}
- version = {
- "stable": "latest",
- "beta": "latest-beta",
- "nightly": "latest"
+
+ os_builds = {
+ ("linux", "x86"): "linux",
+ ("linux", "x86_64"): "linux64",
+ ("win", "x86"): "win",
+ ("win", "x86_64"): "win64",
+ ("macos", "x86_64"): "osx",
}
+ os_key = (self.platform, uname[4])
- if channel not in branch:
+ if channel not in product:
raise ValueError("Unrecognised release channel: %s" % channel)
- from mozdownload import FactoryScraper
- import mozinstall
-
- if self.platform is None:
- raise ValueError("Unable to construct a valid Firefox package name for current platform")
+ if os_key not in os_builds:
+ raise ValueError("Unsupported platform: %s %s" % os_key)
if dest is None:
# os.getcwd() doesn't include the venv path
@@ -124,17 +125,35 @@ class Firefox(Browser):
dest = os.path.join(dest, "browsers", channel)
- scraper = FactoryScraper(scraper[channel],
- branch=branch[channel],
- version=version[channel],
- destination=dest)
+ if not os.path.exists(dest):
+ os.makedirs(dest)
+
+ url = "https://download.mozilla.org/?product=%s&os=%s&lang=en-US" % (product[channel],
+ os_builds[os_key])
+ self.logger.info("Downloading Firefox from %s" % url)
+ resp = requests.get(url)
+
+ filename = None
+
+ content_disposition = resp.headers.get('content-disposition')
+ if content_disposition:
+ filenames = re.findall("filename=(.+)", content_disposition)
+ if filenames:
+ filename = filenames[0]
+
+ if not filename:
+ filename = urlparse.urlsplit(resp.url).path.rsplit("/", 1)[1]
+
+ if not filename:
+ filename = "firefox.tar.bz2"
- self.logger.info("Downloading Firefox from %s" % scraper.url)
+ installer_path = os.path.join(dest, filename)
- filename = scraper.download()
+ with open(installer_path, "w") as f:
+ f.write(resp.content)
try:
- mozinstall.install(filename, dest)
+ mozinstall.install(installer_path, dest)
except mozinstall.mozinstall.InstallError:
if self.platform == "macos" and os.path.exists(os.path.join(dest, self.application_name.get(channel, "Firefox Nightly.app"))):
# mozinstall will fail if nightly is already installed in the venv because
@@ -144,14 +163,14 @@ class Firefox(Browser):
else:
raise
- os.remove(filename)
+ os.remove(installer_path)
return self.find_binary_path(dest)
- def find_binary_path(self,path=None, channel="nightly"):
+ def find_binary_path(self, path=None, channel="nightly"):
"""Looks for the firefox binary in the virtual environment"""
if path is None:
- #os.getcwd() doesn't include the venv path
+ # os.getcwd() doesn't include the venv path
path = os.path.join(os.getcwd(), "_venv", "browsers", channel)
binary = None
@@ -226,13 +245,10 @@ class Firefox(Browser):
tag = "tip"
else:
repo = "https://hg.mozilla.org/mozilla-central"
- if channel == "beta":
- tag = "FIREFOX_%s_BETA" % version.split(".", 1)[0]
- else:
- # Always use tip as the tag for nightly; this isn't quite right
- # but to do better we need the actual build revision, which we
- # can get if we have an application.ini file
- tag = "tip"
+ # Always use tip as the tag for nightly; this isn't quite right
+ # but to do better we need the actual build revision, which we
+ # can get if we have an application.ini file
+ tag = "tip"
return "%s/archive/%s.zip/testing/profiles/" % (repo, tag)
@@ -251,7 +267,7 @@ class Firefox(Browser):
if version:
dest = os.path.join(dest, version)
have_cache = False
- if os.path.exists(dest):
+ if os.path.exists(dest) and len(os.listdir(dest)) > 0:
if channel != "nightly":
have_cache = True
else:
@@ -299,7 +315,7 @@ class Firefox(Browser):
assert latest_release != 0
return "v%s.%s.%s" % tuple(str(item) for item in latest_release)
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
"""Install latest Geckodriver."""
if dest is None:
dest = os.getcwd()
@@ -376,7 +392,7 @@ class Fennec(Browser):
def find_webdriver(self, channel=None):
raise NotImplementedError
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
raise NotImplementedError
def version(self, binary=None, webdriver_binary=None):
@@ -424,24 +440,66 @@ class Chrome(Browser):
return "%s%s" % (platform, bits)
+ def chromium_platform_string(self):
+ platform = {
+ "Linux": "Linux",
+ "Windows": "Win",
+ "Darwin": "Mac"
+ }.get(uname[0])
+
+ if platform is None:
+ raise ValueError("Unable to construct a valid Chromium package name for current platform")
+
+ if (platform == "Linux" or platform == "Win") and uname[4] == "x86_64":
+ platform += "_x64"
+
+ return platform
+
def find_binary(self, venv_path=None, channel=None):
raise NotImplementedError
def find_webdriver(self, channel=None):
return find_executable("chromedriver")
- def install_webdriver(self, dest=None, channel=None):
+ def _latest_chromedriver_url(self, browser_binary=None):
+ latest = None
+ chrome_version = self.version(browser_binary)
+ if chrome_version is not None:
+ parts = chrome_version.split(".")
+ if len(parts) == 4:
+ latest_url = "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_%s.%s.%s" % (
+ parts[0], parts[1], parts[2])
+ try:
+ latest = get(latest_url).text.strip()
+ except requests.RequestException:
+ latest_url = "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_%s" % parts[0]
+ try:
+ latest = get(latest_url).text.strip()
+ except requests.RequestException:
+ pass
+ if latest is None:
+ # Fall back to the tip-of-tree *Chromium* build.
+ latest_url = "https://storage.googleapis.com/chromium-browser-snapshots/%s/LAST_CHANGE" % (
+ self.chromium_platform_string())
+ latest = get(latest_url).text.strip()
+ url = "https://storage.googleapis.com/chromium-browser-snapshots/%s/%s/chromedriver_%s.zip" % (
+ self.chromium_platform_string(), latest, self.platform_string())
+ else:
+ url = "https://chromedriver.storage.googleapis.com/%s/chromedriver_%s.zip" % (
+ latest, self.platform_string())
+ return url
+
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
if dest is None:
dest = os.pwd
- latest = get("http://chromedriver.storage.googleapis.com/LATEST_RELEASE").text.strip()
- url = "http://chromedriver.storage.googleapis.com/%s/chromedriver_%s.zip" % (latest,
- self.platform_string())
+ url = self._latest_chromedriver_url(browser_binary)
+ self.logger.info("Downloading ChromeDriver from %s" % url)
unzip(get(url).raw, dest)
-
- path = find_executable("chromedriver", dest)
- st = os.stat(path)
- os.chmod(path, st.st_mode | stat.S_IEXEC)
- return path
+ chromedriver_dir = os.path.join(dest, 'chromedriver_%s' % self.platform_string())
+ if os.path.isfile(os.path.join(chromedriver_dir, "chromedriver")):
+ shutil.move(os.path.join(chromedriver_dir, "chromedriver"), dest)
+ shutil.rmtree(chromedriver_dir)
+ return find_executable("chromedriver", dest)
def version(self, binary=None, webdriver_binary=None):
binary = binary or self.binary
@@ -449,11 +507,11 @@ class Chrome(Browser):
try:
version_string = call(binary, "--version").strip()
except subprocess.CalledProcessError:
- self.logger.warning("Failed to call %s", binary)
+ self.logger.warning("Failed to call %s" % binary)
return None
- m = re.match(r"Google Chrome (.*)", version_string)
+ m = re.match(r"(?:Google Chrome|Chromium) (.*)", version_string)
if not m:
- self.logger.warning("Failed to extract version from: s%", version_string)
+ self.logger.warning("Failed to extract version from: %s" % version_string)
return None
return m.group(1)
self.logger.warning("Unable to extract version from binary on Windows.")
@@ -478,13 +536,14 @@ class ChromeAndroid(Browser):
def find_webdriver(self, channel=None):
return find_executable("chromedriver")
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
chrome = Chrome()
return chrome.install_webdriver(dest, channel)
def version(self, binary=None, webdriver_binary=None):
return None
+
class Opera(Browser):
"""Opera-specific interface.
@@ -530,7 +589,7 @@ class Opera(Browser):
def find_webdriver(self, channel=None):
return find_executable("operadriver")
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
if dest is None:
dest = os.pwd
latest = get("https://api.github.com/repos/operasoftware/operachromiumdriver/releases/latest").json()["tag_name"]
@@ -553,7 +612,7 @@ class Opera(Browser):
try:
output = call(binary, "--version")
except subprocess.CalledProcessError:
- self.logger.warning("Failed to call %s", binary)
+ self.logger.warning("Failed to call %s" % binary)
return None
m = re.search(r"[0-9\.]+( [a-z]+)?$", output.strip())
if m:
@@ -575,11 +634,16 @@ class Edge(Browser):
def find_webdriver(self, channel=None):
return find_executable("MicrosoftWebDriver")
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
raise NotImplementedError
def version(self, binary=None, webdriver_binary=None):
- return None
+ command = "(Get-AppxPackage Microsoft.MicrosoftEdge).Version"
+ try:
+ return call("powershell.exe", command).strip()
+ except (subprocess.CalledProcessError, OSError):
+ self.logger.warning("Failed to call %s in PowerShell" % command)
+ return None
class EdgeWebDriver(Edge):
@@ -601,7 +665,7 @@ class InternetExplorer(Browser):
def find_webdriver(self, channel=None):
return find_executable("IEDriverServer.exe")
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
raise NotImplementedError
def version(self, binary=None, webdriver_binary=None):
@@ -629,7 +693,7 @@ class Safari(Browser):
path = "/Applications/Safari Technology Preview.app/Contents/MacOS"
return find_executable("safaridriver", path)
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
raise NotImplementedError
def version(self, binary=None, webdriver_binary=None):
@@ -643,11 +707,11 @@ class Safari(Browser):
try:
version_string = call(webdriver_binary, "--version").strip()
except subprocess.CalledProcessError:
- self.logger.warning("Failed to call %s --version", webdriver_binary)
+ self.logger.warning("Failed to call %s --version" % webdriver_binary)
return None
m = re.match(r"Included with Safari (.*)", version_string)
if not m:
- self.logger.warning("Failed to extract version from: s%", version_string)
+ self.logger.warning("Failed to extract version from: %s" % version_string)
return None
return m.group(1)
@@ -701,7 +765,7 @@ class Servo(Browser):
def find_webdriver(self, channel=None):
return None
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
raise NotImplementedError
def version(self, binary=None, webdriver_binary=None):
@@ -731,7 +795,7 @@ class Sauce(Browser):
def find_webdriver(self, channel=None):
raise NotImplementedError
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
raise NotImplementedError
def version(self, binary=None, webdriver_binary=None):
@@ -753,8 +817,37 @@ class WebKit(Browser):
def find_webdriver(self, channel=None):
return None
- def install_webdriver(self, dest=None, channel=None):
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
+ raise NotImplementedError
+
+ def version(self, binary=None, webdriver_binary=None):
+ return None
+
+
+class Epiphany(Browser):
+ """Epiphany-specific interface."""
+
+ product = "epiphany"
+ requirements = "requirements_epiphany.txt"
+
+ def install(self, dest=None, channel=None):
+ raise NotImplementedError
+
+ def find_binary(self, venv_path=None, channel=None):
+ return find_executable("epiphany")
+
+ def find_webdriver(self, channel=None):
+ return find_executable("WebKitWebDriver")
+
+ def install_webdriver(self, dest=None, channel=None, browser_binary=None):
raise NotImplementedError
def version(self, binary=None, webdriver_binary=None):
+ if binary is None:
+ return None
+ output = call(binary, "--version")
+ if output:
+ # Stable release output looks like: "Web 3.30.2"
+ # Tech Preview output looks like "Web 3.31.3-88-g97db4f40f"
+ return output.split()[1]
return None
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py
index 44cf3137d41..ffdd8efa946 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py
@@ -106,7 +106,7 @@ otherwise install OpenSSL and ensure that it's on your $PATH.""")
def check_environ(product):
- if product not in ("firefox", "servo"):
+ if product not in ("chrome", "firefox", "servo"):
config_builder = serve.build_config(os.path.join(wpt_root, "config.json"))
# Override the ports to avoid looking for free ports
config_builder.ssl = {"type": "none"}
@@ -171,7 +171,8 @@ class BrowserSetup(object):
return self.browser.install(venv.path, channel)
def install_requirements(self):
- self.venv.install_requirements(os.path.join(wpt_root, "tools", "wptrunner", self.browser.requirements))
+ if not self.venv.skip_virtualenv_setup:
+ self.venv.install_requirements(os.path.join(wpt_root, "tools", "wptrunner", self.browser.requirements))
def setup(self, kwargs):
self.setup_kwargs(kwargs)
@@ -265,7 +266,7 @@ class Chrome(BrowserSetup):
if install:
logger.info("Downloading chromedriver")
- webdriver_binary = self.browser.install_webdriver(dest=self.venv.bin_path)
+ webdriver_binary = self.browser.install_webdriver(dest=self.venv.bin_path, browser_binary=kwargs["binary"])
else:
logger.info("Using webdriver binary %s" % webdriver_binary)
@@ -276,14 +277,6 @@ class Chrome(BrowserSetup):
if kwargs["browser_channel"] == "dev":
logger.info("Automatically turning on experimental features for Chrome Dev")
kwargs["binary_args"].append("--enable-experimental-web-platform-features")
- # TODO(foolip): remove after unified plan is enabled on Chrome stable
- kwargs["binary_args"].append("--enable-features=RTCUnifiedPlanByDefault")
-
- # Allow audio autoplay without a user gesture.
- kwargs["binary_args"].append("--autoplay-policy=no-user-gesture-required")
-
- # Allow WebRTC tests to call getUserMedia.
- kwargs["binary_args"] += ["--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream"]
class ChromeAndroid(BrowserSetup):
@@ -422,7 +415,7 @@ class Servo(BrowserSetup):
binary = self.browser.find_binary(self.venv.path, None)
if binary is None:
- raise WptrunError("Unable to find servo binary on the PATH")
+ raise WptrunError("Unable to find servo binary in PATH")
kwargs["binary"] = binary
@@ -442,6 +435,29 @@ class WebKit(BrowserSetup):
pass
+class Epiphany(BrowserSetup):
+ name = "epiphany"
+ browser_cls = browser.Epiphany
+
+ def install(self, venv, channel=None):
+ raise NotImplementedError
+
+ def setup_kwargs(self, kwargs):
+ if kwargs["binary"] is None:
+ binary = self.browser.find_binary()
+
+ if binary is None:
+ raise WptrunError("Unable to find epiphany in PATH")
+ kwargs["binary"] = binary
+
+ if kwargs["webdriver_binary"] is None:
+ webdriver_binary = self.browser.find_webdriver()
+
+ if webdriver_binary is None:
+ raise WptrunError("Unable to find WebKitWebDriver in PATH")
+ kwargs["webdriver_binary"] = webdriver_binary
+
+
product_setup = {
"fennec": Fennec,
"firefox": Firefox,
@@ -456,6 +472,7 @@ product_setup = {
"sauce": Sauce,
"opera": Opera,
"webkit": WebKit,
+ "epiphany": Epiphany,
}
@@ -539,10 +556,15 @@ def setup_wptrunner(venv, prompt=True, install_browser=False, **kwargs):
wptrunner_path = os.path.join(wpt_root, "tools", "wptrunner")
- venv.install_requirements(os.path.join(wptrunner_path, "requirements.txt"))
+ if not venv.skip_virtualenv_setup:
+ venv.install_requirements(os.path.join(wptrunner_path, "requirements.txt"))
+
+ # Only update browser_version if it was not given as a command line
+ # argument, so that it can be overridden on the command line.
+ if not kwargs["browser_version"]:
+ kwargs["browser_version"] = setup_cls.browser.version(binary=kwargs.get("binary"),
+ webdriver_binary=kwargs.get("webdriver_binary"))
- kwargs['browser_version'] = setup_cls.browser.version(binary=kwargs.get("binary"),
- webdriver_binary=kwargs.get("webdriver_binary"))
return kwargs
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py
index 70e695aa010..006e4a22d0b 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/testfiles.py
@@ -34,15 +34,15 @@ def display_branch_point():
def branch_point():
git = get_git_cmd(wpt_root)
- if (os.environ.get("TRAVIS_PULL_REQUEST", "false") == "false" and
- os.environ.get("TRAVIS_BRANCH") == "master"):
+ if (os.environ.get("GITHUB_PULL_REQUEST", "false") == "false" and
+ os.environ.get("GITHUB_BRANCH") == "master"):
# For builds on the master branch just return the HEAD commit
return git("rev-parse", "HEAD")
- elif os.environ.get("TRAVIS_PULL_REQUEST", "false") != "false":
- # This is a PR, so the base branch is in TRAVIS_BRANCH
- travis_branch = os.environ.get("TRAVIS_BRANCH")
- assert travis_branch, "TRAVIS_BRANCH environment variable is defined"
- branch_point = git("merge-base", "HEAD", travis_branch)
+ elif os.environ.get("GITHUB_PULL_REQUEST", "false") != "false":
+ # This is a PR, so the base branch is in GITHUB_BRANCH
+ base_branch = os.environ.get("GITHUB_BRANCH")
+ assert base_branch, "GITHUB_BRANCH environment variable is defined"
+ branch_point = git("merge-base", "HEAD", base_branch)
else:
# Otherwise we aren't on a PR, so we try to find commits that are only in the
# current branch c.f.
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/utils.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/utils.py
index fa60230389d..f98687feb51 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/utils.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/utils.py
@@ -5,6 +5,11 @@ import tarfile
import zipfile
from io import BytesIO
+try:
+ from typing import Any
+except ImportError:
+ pass
+
logger = logging.getLogger(__name__)
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/virtualenv.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/virtualenv.py
index 0ce7054ae22..b99d15d1f6a 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/virtualenv.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/virtualenv.py
@@ -4,16 +4,21 @@ import sys
import logging
from distutils.spawn import find_executable
+import pkg_resources
+
from tools.wpt.utils import call
logger = logging.getLogger(__name__)
class Virtualenv(object):
- def __init__(self, path):
+ def __init__(self, path, skip_virtualenv_setup):
self.path = path
- self.virtualenv = find_executable("virtualenv")
- if not self.virtualenv:
- raise ValueError("virtualenv must be installed and on the PATH")
+ self.skip_virtualenv_setup = skip_virtualenv_setup
+ if not skip_virtualenv_setup:
+ self.virtualenv = find_executable("virtualenv")
+ if not self.virtualenv:
+ raise ValueError("virtualenv must be installed and on the PATH")
+ self._working_set = None
@property
def exists(self):
@@ -22,6 +27,7 @@ class Virtualenv(object):
def create(self):
if os.path.exists(self.path):
shutil.rmtree(self.path)
+ self._working_set = None
call(self.virtualenv, self.path, "-p", sys.executable)
@property
@@ -37,6 +43,36 @@ class Virtualenv(object):
raise ValueError("pip not found")
return path
+ @property
+ def lib_path(self):
+ base = self.path
+
+ # this block is literally taken from virtualenv 16.4.3
+ IS_PYPY = hasattr(sys, "pypy_version_info")
+ IS_JYTHON = sys.platform.startswith("java")
+ if IS_JYTHON:
+ site_packages = os.path.join(base, "Lib", "site-packages")
+ elif IS_PYPY:
+ site_packages = os.path.join(base, "site-packages")
+ else:
+ IS_WIN = sys.platform == "win32"
+ if IS_WIN:
+ site_packages = os.path.join(base, "Lib", "site-packages")
+ else:
+ site_packages = os.path.join(base, "lib", "python{}".format(sys.version[:3]), "site-packages")
+
+ return site_packages
+
+ @property
+ def working_set(self):
+ if not self.exists:
+ raise ValueError("trying to read working_set when venv doesn't exist")
+
+ if self._working_set is None:
+ self._working_set = pkg_resources.WorkingSet((self.lib_path,))
+
+ return self._working_set
+
def activate(self):
path = os.path.join(self.bin_path, "activate_this.py")
execfile(path, {"__file__": path}) # noqa: F821
@@ -47,7 +83,28 @@ class Virtualenv(object):
self.activate()
def install(self, *requirements):
- call(self.pip_path, "install", *requirements)
+ try:
+ self.working_set.require(*requirements)
+ except pkg_resources.ResolutionError:
+ pass
+ else:
+ return
+
+ # `--prefer-binary` guards against race conditions when installation
+ # occurs while packages are in the process of being published.
+ call(self.pip_path, "install", "--prefer-binary", *requirements)
def install_requirements(self, requirements_path):
- call(self.pip_path, "install", "-r", requirements_path)
+ with open(requirements_path) as f:
+ try:
+ self.working_set.require(f.read())
+ except pkg_resources.ResolutionError:
+ pass
+ else:
+ return
+
+ # `--prefer-binary` guards against race conditions when installation
+ # occurs while packages are in the process of being published.
+ call(
+ self.pip_path, "install", "--prefer-binary", "-r", requirements_path
+ )
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py
index 55802461553..909d435b648 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py
@@ -43,6 +43,9 @@ def load_commands():
def parse_args(argv, commands):
parser = argparse.ArgumentParser()
parser.add_argument("--venv", action="store", help="Path to an existing virtualenv to use")
+ parser.add_argument("--skip-venv-setup", action="store_true",
+ dest="skip_venv_setup",
+ help="Whether to use the virtualenv as-is. Must set --venv as well")
parser.add_argument("--debug", action="store_true", help="Run the debugger in case of an exception")
subparsers = parser.add_subparsers(dest="command")
for command, props in iteritems(commands):
@@ -77,15 +80,19 @@ def import_command(prog, command, props):
return script, parser
-def setup_virtualenv(path, props):
+def setup_virtualenv(path, skip_venv_setup, props):
+ if skip_venv_setup and path is None:
+ raise ValueError("Must set --venv when --skip-venv-setup is used")
+ should_skip_setup = path is not None and skip_venv_setup
if path is None:
path = os.path.join(wpt_root, "_venv")
- venv = virtualenv.Virtualenv(path)
- venv.start()
- for name in props["install"]:
- venv.install(name)
- for path in props["requirements"]:
- venv.install_requirements(path)
+ venv = virtualenv.Virtualenv(path, should_skip_setup)
+ if not should_skip_setup:
+ venv.start()
+ for name in props["install"]:
+ venv.install(name)
+ for path in props["requirements"]:
+ venv.install_requirements(path)
return venv
@@ -105,7 +112,7 @@ def main(prog=None, argv=None):
props = commands[command]
venv = None
if props["virtualenv"]:
- venv = setup_virtualenv(main_args.venv, props)
+ venv = setup_virtualenv(main_args.venv, main_args.skip_venv_setup, props)
script, parser = import_command(prog, command, props)
if parser:
if props["parse_known"]:
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/config.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/config.py
index aadcbb9b5a6..e11cae137b9 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/config.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/config.py
@@ -75,7 +75,9 @@ def json_types(obj):
return {key: json_types(value) for key, value in iteritems(obj)}
if (isinstance(obj, string_types) or
isinstance(obj, integer_types) or
- isinstance(obj, float)):
+ isinstance(obj, float) or
+ isinstance(obj, bool) or
+ obj is None):
return obj
if isinstance(obj, list) or hasattr(obj, "__iter__"):
return [json_types(value) for value in obj]
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/handlers.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/handlers.py
index 2dd01e29338..e846ff807a6 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/handlers.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/handlers.py
@@ -159,8 +159,8 @@ class FileHandler(object):
rv = (self.load_headers(request, os.path.join(os.path.split(path)[0], "__dir__")) +
self.load_headers(request, path))
- if not any(key.lower() == "content-type" for (key, _) in rv):
- rv.insert(0, ("Content-Type", guess_content_type(path)))
+ if not any(key.lower() == b"content-type" for (key, _) in rv):
+ rv.insert(0, (b"Content-Type", guess_content_type(path).encode("ascii")))
return rv
@@ -173,14 +173,14 @@ class FileHandler(object):
use_sub = False
try:
- with open(headers_path) as headers_file:
+ with open(headers_path, "rb") as headers_file:
data = headers_file.read()
except IOError:
return []
else:
if use_sub:
data = template(request, data, escape_type="none")
- return [tuple(item.strip() for item in line.split(":", 1))
+ return [tuple(item.strip() for item in line.split(b":", 1))
for line in data.splitlines() if line]
def get_data(self, response, path, byte_ranges):
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/request.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/request.py
index aa6306a533e..1b1061ba7b7 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/request.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/request.py
@@ -593,9 +593,7 @@ class MultiDict(dict):
values = [values]
for value in values:
- if value.filename:
- value = value
- else:
+ if not value.filename:
value = value.value
self.add(key, value)
return self
diff --git a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py
index 00a609b2950..efc65ef1801 100644
--- a/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py
+++ b/chromium/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptserve/wptserve/response.py
@@ -8,7 +8,7 @@ from .constants import response_codes, h2_headers
from .logger import get_logger
from io import BytesIO
-from six import binary_type, text_type, itervalues
+from six import binary_type, text_type, integer_types, itervalues, PY3
from hyperframe.frame import HeadersFrame, DataFrame, ContinuationFrame
from hpack.struct import HeaderTuple
@@ -157,6 +157,8 @@ class Response(object):
cookies = self.headers.get("Set-Cookie")
parser = BaseCookie()
for cookie in cookies:
+ if PY3:
+ cookie = cookie.decode("iso-8859-1")
parser.load(cookie)
if name in parser.keys():
@@ -237,18 +239,18 @@ class MultipartContent(object):
def __init__(self, boundary=None, default_content_type=None):
self.items = []
if boundary is None:
- boundary = str(uuid.uuid4())
+ boundary = text_type(uuid.uuid4())
self.boundary = boundary
self.default_content_type = default_content_type
def __call__(self):
- boundary = "--" + self.boundary
- rv = ["", boundary]
+ boundary = b"--" + self.boundary.encode("ascii")
+ rv = [b"", boundary]
for item in self.items:
- rv.append(str(item))
+ rv.append(item.to_bytes())
rv.append(boundary)
- rv[-1] += "--"
- return "\r\n".join(rv)
+ rv[-1] += b"--"
+ return b"\r\n".join(rv)
def append_part(self, data, content_type=None, headers=None):
if content_type is None:
@@ -265,6 +267,7 @@ class MultipartContent(object):
class MultipartPart(object):
def __init__(self, data, content_type=None, headers=None):
+ assert isinstance(data, binary_type), data
self.headers = ResponseHeaders()
if content_type is not None:
@@ -272,7 +275,7 @@ class MultipartPart(object):
if headers is not None:
for name, value in headers:
- if name.lower() == "content-type":
+ if name.lower() == b"content-type":
func = self.headers.set
else:
func = self.headers.append
@@ -280,13 +283,36 @@ class MultipartPart(object):
self.data = data
- def __str__(self):
+ def to_bytes(self):
rv = []
- for item in self.headers:
- rv.append("%s: %s" % item)
- rv.append("")
+ for key, value in self.headers:
+ assert isinstance(key, binary_type)
+ assert isinstance(value, binary_type)
+ rv.append(b"%s: %s" % (key, value))
+ rv.append(b"")
rv.append(self.data)
- return "\r\n".join(rv)
+ return b"\r\n".join(rv)
+
+
+def _maybe_encode(s):
+ """Encodes a text-type string into binary data using iso-8859-1.
+
+ Returns `str` in Python 2 and `bytes` in Python 3. The function is a no-op
+ if the argument already has a binary type.
+ """
+ if isinstance(s, binary_type):
+ return s
+
+ # Python 3 assumes iso-8859-1 when parsing headers, which will garble text
+ # with non ASCII characters. We try to encode the text back to binary.
+ # https://github.com/python/cpython/blob/273fc220b25933e443c82af6888eb1871d032fb8/Lib/http/client.py#L213
+ if isinstance(s, text_type):
+ return s.encode("iso-8859-1")
+
+ if isinstance(s, integer_types):
+ return b"%i" % (s,)
+
+ raise TypeError("Unexpected value in ResponseHeaders: %r" % s)
class ResponseHeaders(object):
@@ -301,6 +327,8 @@ class ResponseHeaders(object):
:param key: Name of the header to set
:param value: Value to set the header to
"""
+ key = _maybe_encode(key)
+ value = _maybe_encode(value)
self.data[key.lower()] = (key, [value])
def append(self, key, value):
@@ -310,6 +338,8 @@ class ResponseHeaders(object):
:param key: Name of the header to add
:param value: Value to set for the header
"""
+ key = _maybe_encode(key)
+ value = _maybe_encode(value)
if key.lower() in self.data:
self.data[key.lower()][1].append(value)
else:
@@ -317,6 +347,7 @@ class ResponseHeaders(object):
def get(self, key, default=missing):
"""Get the set values for a particular header."""
+ key = _maybe_encode(key)
try:
return self[key]
except KeyError:
@@ -328,12 +359,15 @@ class ResponseHeaders(object):
"""Get a list of values for a particular header
"""
+ key = _maybe_encode(key)
return self.data[key.lower()][1]
def __delitem__(self, key):
+ key = _maybe_encode(key)
del self.data[key.lower()]
def __contains__(self, key):
+ key = _maybe_encode(key)
return key.lower() in self.data
def __setitem__(self, key, value):
@@ -623,6 +657,9 @@ class ResponseWriter(object):
self.file_chunk_size = 32 * 1024
self.default_status = 200
+ def _seen_header(self, name):
+ return self.encode(name.lower()) in self._headers_seen
+
def write_status(self, code, message=None):
"""Write out the status line of a response.
@@ -648,19 +685,25 @@ class ResponseWriter(object):
"""
if not self._status_written:
self.write_status(self.default_status)
- self._headers_seen.add(name.lower())
- self.write("%s: %s\r\n" % (name, value))
+ self._headers_seen.add(self.encode(name.lower()))
+ self.write(name)
+ self.write(b": ")
+ if isinstance(value, int):
+ self.write(text_type(value))
+ else:
+ self.write(value)
+ self.write(b"\r\n")
if not self._response.explicit_flush:
self.flush()
def write_default_headers(self):
for name, f in [("Server", self._handler.version_string),
("Date", self._handler.date_time_string)]:
- if name.lower() not in self._headers_seen:
+ if not self._seen_header(name):
self.write_header(name, f())
if (isinstance(self._response.content, (binary_type, text_type)) and
- "content-length" not in self._headers_seen):
+ not self._seen_header("content-length")):
#Would be nice to avoid double-encoding here
self.write_header("Content-Length", len(self.encode(self._response.content)))
@@ -675,7 +718,7 @@ class ResponseWriter(object):
self.write_default_headers()
self.write("\r\n")
- if "content-length" not in self._headers_seen:
+ if not self._seen_header("content-length"):
self._response.close_connection = True
if not self._response.explicit_flush:
self.flush()
@@ -735,7 +778,7 @@ class ResponseWriter(object):
elif isinstance(data, text_type):
return data.encode(self._response.encoding)
else:
- raise ValueError
+ raise ValueError("data %r should be text or binary, but is %s" % (data, type(data)))
def flush(self):
"""Flush the output. Returns False if the flush failed due to
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py
index e4676e4d0ec..de02c959e26 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -21,6 +21,7 @@ from blinkpy.common.net.buildbot import current_build_link
from blinkpy.common.net.git_cl import GitCL
from blinkpy.common.net.network_transaction import NetworkTimeout
from blinkpy.common.path_finder import PathFinder
+from blinkpy.common.system.executive import ScriptError
from blinkpy.common.system.log_utils import configure_logging
from blinkpy.w3c.chromium_exportable_commits import exportable_commits_over_last_n_commits
from blinkpy.w3c.common import read_credentials, is_testharness_baseline, is_file_exportable, WPT_GH_URL
@@ -262,7 +263,14 @@ class TestImporter(object):
return True
_log.error('Cannot submit CL; aborting.')
- self.git_cl.run(['set-close'])
+ try:
+ self.git_cl.run(['set-close'])
+ except ScriptError as e:
+ if e.output and 'Conflict: change is merged' in e.output:
+ _log.error('CL is already merged; treating as success.')
+ return True
+ else:
+ raise e
return False
def blink_try_bots(self):
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
index 31647c56477..59279294328 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -188,6 +188,45 @@ class TestImporterTest(LoggingTestCase):
importer.git_cl.calls,
[['git', 'cl', 'try'], ['git', 'cl', 'set-close']])
+ def test_submit_cl_timeout_and_already_merged(self):
+ # Here we simulate a case where we timeout waiting for the CQ to submit a
+ # CL because we miss the notification that it was merged. We then get an
+ # error when trying to close the CL because it's already been merged.
+ host = MockHost()
+ host.filesystem.write_text_file(MOCK_WEB_TESTS + 'W3CImportExpectations', '')
+ importer = TestImporter(host)
+ # Define some error text that looks like a typical ScriptError.
+ git_error_text = (
+ 'This is a git Script Error\n'
+ '...there is usually a stack trace here with some calls\n'
+ '...and maybe other calls\n'
+ 'And finally, there is the exception:\n'
+ 'GerritError: Conflict: change is merged\n'
+ )
+ importer.git_cl = MockGitCL(
+ host, status='lgtm', git_error_output={'set-close': git_error_text},
+ # Only the latest job for each builder is counted.
+ try_job_results={
+ Build('cq-builder-a', 120): TryJobStatus('COMPLETED', 'FAILURE'),
+ Build('cq-builder-a', 123): TryJobStatus('COMPLETED', 'SUCCESS')})
+ importer.git_cl.wait_for_closed_status = lambda: False
+ success = importer.run_commit_queue_for_cl()
+ # Since the CL is already merged, we absorb the error and treat it as success.
+ self.assertTrue(success)
+ self.assertLog([
+ 'INFO: Triggering CQ try jobs.\n',
+ 'INFO: All jobs finished.\n',
+ 'INFO: CQ appears to have passed; trying to commit.\n',
+ 'ERROR: Cannot submit CL; aborting.\n',
+ 'ERROR: CL is already merged; treating as success.\n',
+ ])
+ self.assertEqual(importer.git_cl.calls, [
+ ['git', 'cl', 'try'],
+ ['git', 'cl', 'upload', '-f', '--send-mail'],
+ ['git', 'cl', 'set-commit'],
+ ['git', 'cl', 'set-close'],
+ ])
+
def test_apply_exportable_commits_locally(self):
# TODO(robertma): Consider using MockLocalWPT.
host = MockHost()
@@ -460,6 +499,7 @@ class TestImporterTest(LoggingTestCase):
'/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
'manifest',
'--work',
+ '--no-download',
'--tests-root',
MOCK_WEB_TESTS + 'external/wpt',
]
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py
index 7e18f3b3712..4dc48e7dd23 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py
@@ -7,6 +7,12 @@
The MANIFEST.json file contains metadata about files in web-platform-tests,
such as what tests exist, and extra information about each test, including
test type, options, URLs to use, and reference file paths if applicable.
+
+Naming conventions:
+* A (file) path is a relative file system path from the root of WPT.
+* A (test) URL is the path (with an optional query string) to the test on
+ wptserve relative to url_base.
+Neither has a leading slash.
"""
import json
@@ -17,14 +23,16 @@ from blinkpy.common.path_finder import PathFinder
_log = logging.getLogger(__file__)
-
+# The default filename of manifest expected by `wpt`.
+MANIFEST_NAME = 'MANIFEST.json'
# The filename used for the base manifest includes the version as a
# workaround for trouble landing huge changes to the base manifest when
# the version changes. See https://crbug.com/876717.
-BASE_MANIFEST_NAME = 'WPT_BASE_MANIFEST_5.json'
+BASE_MANIFEST_NAME = 'WPT_BASE_MANIFEST_6.json'
# TODO(robertma): Use the official wpt.manifest module.
+
class WPTManifest(object):
"""A simple abstraction of WPT MANIFEST.json.
@@ -53,8 +61,6 @@ class WPTManifest(object):
[[reference_url1, "=="], [reference_url2, "!="], ...]
"""
-
-
def __init__(self, json_content):
self.raw_dict = json.loads(json_content)
self.test_types = ('manual', 'reftest', 'testharness')
@@ -63,15 +69,15 @@ class WPTManifest(object):
"""Finds manifest items for the given WPT path.
Args:
- path_in_wpt: A file path relative to the root of WPT. Note that this
- is different from a WPT URL; a file path does not have a leading
- slash or a query string.
+ path_in_wpt: A file path relative to the root of WPT.
Returns:
A list of manifest items, or None if not found.
"""
items = self.raw_dict['items']
for test_type in self.test_types:
+ if test_type not in items:
+ continue
if path_in_wpt in items[test_type]:
return items[test_type][path_in_wpt]
return None
@@ -80,7 +86,7 @@ class WPTManifest(object):
"""Finds the manifest item for the given WPT URL.
Args:
- url: A WPT URL (with the leading slash).
+ url: A WPT URL.
Returns:
A manifest item, or None if not found.
@@ -112,8 +118,11 @@ class WPTManifest(object):
url_items = {}
if 'items' not in self.raw_dict:
return url_items
+ items = self.raw_dict['items']
for test_type in self.test_types:
- for records in self.raw_dict['items'][test_type].itervalues():
+ if test_type not in items:
+ continue
+ for records in items[test_type].itervalues():
for item in filter(self._is_not_jsshell, records):
url_items[self._get_url_from_item(item)] = item
return url_items
@@ -124,29 +133,20 @@ class WPTManifest(object):
return frozenset(self.all_url_items().keys())
def is_test_file(self, path_in_wpt):
+ """Checks if path_in_wpt is a test file according to the manifest."""
+ assert not path_in_wpt.startswith('/')
return self._items_for_file_path(path_in_wpt) is not None
def is_test_url(self, url):
- """Checks if url is a valid test in the manifest.
-
- The url must be the WPT test name with a leading slash (/).
- """
- if url[0] != '/':
- raise Exception('Test url missing leading /: %s' % url)
+ """Checks if url is a valid test in the manifest."""
+ assert not url.startswith('/')
return url in self.all_urls()
- def file_path_to_url_paths(self, path_in_wpt):
- manifest_items = self._items_for_file_path(path_in_wpt)
- assert manifest_items is not None
- # Remove the leading slashes when returning.
- return [self._get_url_from_item(item)[1:]
- for item in manifest_items if self._is_not_jsshell(item)]
-
def is_slow_test(self, url):
"""Checks if a WPT is slow (long timeout) according to the manifest.
Args:
- url: A WPT URL (with the leading slash).
+ url: A WPT URL.
Returns:
True if the test is found and is slow, False otherwise.
@@ -165,38 +165,50 @@ class WPTManifest(object):
The return value is a list of (match/not-match, reference path in wpt)
pairs, like:
- [("==", "foo/bar/baz-match.html"),
- ("!=", "foo/bar/baz-mismatch.html")]
+ [("==", "/foo/bar/baz-match.html"),
+ ("!=", "/foo/bar/baz-mismatch.html")]
"""
- all_items = self.raw_dict['items']
- if path_in_wpt not in all_items['reftest']:
+ items = self.raw_dict['items']
+ if path_in_wpt not in items.get('reftest', {}):
return []
reftest_list = []
- for item in all_items['reftest'][path_in_wpt]:
+ for item in items['reftest'][path_in_wpt]:
for ref_path_in_wpt, expectation in item[1]:
+ # Ref URLs in MANIFEST should be absolute, but we double check
+ # just in case.
+ if not ref_path_in_wpt.startswith('/'):
+ ref_path_in_wpt = '/' + ref_path_in_wpt
reftest_list.append((expectation, ref_path_in_wpt))
return reftest_list
@staticmethod
- def ensure_manifest(host):
- """Updates the MANIFEST.json file, or generates if it does not exist."""
- finder = PathFinder(host.filesystem)
- manifest_path = finder.path_from_web_tests('external', 'wpt', 'MANIFEST.json')
- base_manifest_path = finder.path_from_web_tests('external', BASE_MANIFEST_NAME)
+ def ensure_manifest(host, path=None):
+ """Updates the MANIFEST.json file, or generates if it does not exist.
- if not host.filesystem.exists(base_manifest_path):
- _log.error('Manifest base not found at "%s".', base_manifest_path)
- host.filesystem.write_text_file(base_manifest_path, '{}')
+ Args:
+ path: The path to a WPT root (relative to web_tests, optional).
+ """
+ if path is None:
+ path = host.filesystem.join('external', 'wpt')
+ finder = PathFinder(host.filesystem)
+ wpt_path = finder.path_from_web_tests(path)
+ manifest_path = host.filesystem.join(wpt_path, MANIFEST_NAME)
- # Unconditionally replace MANIFEST.json with the base manifest even if
- # the former exists, to avoid regenerating the manifest from scratch
- # when the manifest version changes. Remove the destination first as
- # copyfile will fail if the two files are hardlinked or symlinked.
+ # Unconditionally delete local MANIFEST.json to avoid regenerating the
+ # manifest from scratch (when version is bumped) or invalid/out-of-date
+ # local manifest breaking the runner.
if host.filesystem.exists(manifest_path):
host.filesystem.remove(manifest_path)
- host.filesystem.copyfile(base_manifest_path, manifest_path)
- wpt_path = finder.path_from_web_tests('external', 'wpt')
+ # TODO(crbug.com/853815): perhaps also cache the manifest for wpt_internal.
+ if 'external' in path:
+ base_manifest_path = finder.path_from_web_tests('external', BASE_MANIFEST_NAME)
+ if not host.filesystem.exists(base_manifest_path):
+ _log.error('Manifest base not found at "%s".', base_manifest_path)
+ host.filesystem.write_text_file(base_manifest_path, '{}')
+
+ host.filesystem.copyfile(base_manifest_path, manifest_path)
+
WPTManifest.generate_manifest(host, wpt_path)
_log.debug('Manifest generation completed.')
@@ -206,7 +218,7 @@ class WPTManifest(object):
"""Generates MANIFEST.json on the specified directory."""
finder = PathFinder(host.filesystem)
wpt_exec_path = finder.path_from_blink_tools('blinkpy', 'third_party', 'wpt', 'wpt', 'wpt')
- cmd = ['python', wpt_exec_path, 'manifest', '--work', '--tests-root', dest_path]
+ cmd = ['python', wpt_exec_path, 'manifest', '--work', '--no-download', '--tests-root', dest_path]
# ScriptError will be raised if the command fails.
host.executive.run_command(
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py
index ae3155bd9f3..eb9a5be65e5 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py
@@ -32,6 +32,7 @@ class WPTManifestUnitTest(unittest.TestCase):
'/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
'manifest',
'--work',
+ '--no-download',
'--tests-root',
MOCK_WEB_TESTS + 'external/wpt',
]
@@ -57,6 +58,7 @@ class WPTManifestUnitTest(unittest.TestCase):
'/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
'manifest',
'--work',
+ '--no-download',
'--tests-root',
MOCK_WEB_TESTS + 'external/wpt',
]
@@ -70,26 +72,43 @@ class WPTManifestUnitTest(unittest.TestCase):
with self.assertRaises(ScriptError):
WPTManifest.ensure_manifest(host)
- def test_all_url_items_skips_jsshell_tests(self):
+ def test_ensure_manifest_takes_optional_dest(self):
+ host = MockHost()
+ WPTManifest.ensure_manifest(host, 'wpt_internal')
+ self.assertEqual(
+ host.executive.calls,
+ [
+ [
+ 'python',
+ '/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
+ 'manifest',
+ '--work',
+ '--no-download',
+ '--tests-root',
+ MOCK_WEB_TESTS + 'wpt_internal',
+ ]
+ ]
+ )
+
+ def test_does_not_throw_when_missing_some_test_types(self):
manifest_json = '''
{
"items": {
- "manual": {},
- "reftest": {},
"testharness": {
"test.any.js": [
- ["/test.any.html", {}],
- ["/test.any.js", {"jsshell": true}]
+ ["/test.any.html", {}]
]
}
}
}
'''
manifest = WPTManifest(manifest_json)
+ self.assertTrue(manifest.is_test_file('test.any.js'))
self.assertEqual(manifest.all_url_items(),
{u'/test.any.html': [u'/test.any.html', {}]})
+ self.assertEqual(manifest.extract_reference_list('/foo/bar.html'), [])
- def test_file_path_to_url_paths(self):
+ def test_all_url_items_skips_jsshell_tests(self):
manifest_json = '''
{
"items": {
@@ -105,7 +124,5 @@ class WPTManifestUnitTest(unittest.TestCase):
}
'''
manifest = WPTManifest(manifest_json)
- # Leading slashes should be stripped; and jsshell tests shouldn't be
- # included.
- self.assertEqual(manifest.file_path_to_url_paths('test.any.js'),
- [u'test.any.html'])
+ self.assertEqual(manifest.all_url_items(),
+ {u'/test.any.html': [u'/test.any.html', {}]})
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
index 661ccdbdce7..5b5eb403769 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
@@ -99,10 +99,17 @@ class Manager(object):
self._printer.write_update('Collecting tests ...')
running_all_tests = False
- if self._options.manifest_update and (not args or any('external' in path for path in args)):
- self._printer.write_update('Generating MANIFEST.json for web-platform-tests ...')
- WPTManifest.ensure_manifest(self._port.host)
- self._printer.write_update('Completed generating manifest.')
+ if self._options.manifest_update:
+ # TODO(robertma): Consolidate the two cases to `for wpt_path in
+ # WPT_DIRS` when external/wpt is moved to wpt.
+ if not args or any('external' in path for path in args):
+ self._printer.write_update('Generating MANIFEST.json for external/wpt...')
+ WPTManifest.ensure_manifest(self._port.host)
+ self._printer.write_update('Completed generating manifest.')
+ if not args or any('wpt_internal' in path for path in args):
+ self._printer.write_update('Generating MANIFEST.json for wpt_internal...')
+ WPTManifest.ensure_manifest(self._port.host, 'wpt_internal')
+ self._printer.write_update('Completed generating manifest.')
self._printer.write_update('Collecting tests ...')
try:
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
index fd4774ce253..76e5ff6065c 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
@@ -461,6 +461,10 @@ class SingleTestRunner(object):
def _compare_image(self, expected_driver_output, driver_output):
if not expected_driver_output.image or not expected_driver_output.image_hash:
return []
+ # The presence of an expected image, but a lack of an outputted image
+ # does not signify an error. content::BlinkTestController checks the
+ # image_hash, and upon a match simply skips recording the outputted
+ # image. This even occurs when results_directory is set.
if not driver_output.image or not driver_output.image_hash:
return []
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
index cd64e3e4e07..200a5964370 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
@@ -117,7 +117,7 @@ class TestExpectationParser(object):
line_number = 0
for line in expectations_string.split('\n'):
line_number += 1
- test_expectation = TestExpectationLine.tokenize_line(filename, line, line_number)
+ test_expectation = TestExpectationLine.tokenize_line(filename, line, line_number, self._port)
self._parse_line(test_expectation)
expectation_lines.append(test_expectation)
@@ -326,7 +326,7 @@ class TestExpectationLine(object):
[('TEXT', 'Failure'), ('IMAGE', 'Failure'), ('IMAGE+TEXT', 'Failure'), ('AUDIO', 'Failure')])
@classmethod
- def tokenize_line(cls, filename, expectation_string, line_number):
+ def tokenize_line(cls, filename, expectation_string, line_number, port):
"""Tokenizes a line from TestExpectations and returns an unparsed TestExpectationLine instance using the old format.
The new format for a test expectation line is:
@@ -447,6 +447,11 @@ class TestExpectationLine(object):
if 'NeverFixTests' in filename and expectations != ['WONTFIX', 'SKIP']:
warnings.append('Only WONTFIX expectations are allowed in NeverFixTests')
+ if 'SlowTests' in filename and port.is_wpt_test(name):
+ warnings.append(
+ 'WPT should not be added to SlowTests; they should be marked as '
+ 'slow inside the test (see https://web-platform-tests.org/writing-tests/testharness-api.html#harness-timeout)')
+
if 'SlowTests' in filename and expectations != ['SLOW']:
warnings.append('Only SLOW expectations are allowed in SlowTests')
@@ -714,7 +719,7 @@ class TestExpectationsModel(object):
def get_expectations_string(self, test):
"""Returns the expectations for the given test as an uppercase string.
- If there are no expectations for the test, then "PASS" is returned.
+ If there are no expectations for the test, KeyError is raised.
"""
if self.get_expectation_line(test).is_extra_skipped_test:
return 'NOTRUN'
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
index 8331deaa53f..9409dd63c9f 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
@@ -354,7 +354,9 @@ class ExpectationSyntaxTests(Base):
expectations = expectations or []
warnings = warnings or []
line_number = '1'
- expectation_line = TestExpectationLine.tokenize_line(filename, line, line_number)
+ host = MockHost()
+ expectation_line = TestExpectationLine.tokenize_line(
+ filename, line, line_number, host.port_factory.get('test-win-win7', None))
self.assertEqual(expectation_line.warnings, warnings)
self.assertEqual(expectation_line.name, name)
self.assertEqual(expectation_line.filename, filename)
@@ -386,6 +388,8 @@ class ExpectationSyntaxTests(Base):
self.assert_tokenize_exp('foo.html [ Slow ]', specifiers=[], expectations=['SLOW'], filename='SlowTests')
self.assert_tokenize_exp('foo.html [ Timeout Slow ]', specifiers=[], expectations=['SKIP', 'TIMEOUT'], warnings=[
'Only SLOW expectations are allowed in SlowTests'], filename='SlowTests')
+ self.assert_tokenize_exp('external/wpt/foo.html [ Slow ]', name='external/wpt/foo.html', specifiers=[], expectations=['SLOW'], warnings=[
+ 'WPT should not be added to SlowTests; they should be marked as slow inside the test (see https://web-platform-tests.org/writing-tests/testharness-api.html#harness-timeout)'], filename='SlowTests')
def test_wontfix(self):
self.assert_tokenize_exp(
@@ -778,7 +782,8 @@ class TestExpectationSerializationTests(unittest.TestCase):
unittest.TestCase.__init__(self, testFunc)
def _tokenize(self, line):
- return TestExpectationLine.tokenize_line('path', line, 0)
+ host = MockHost()
+ return TestExpectationLine.tokenize_line('path', line, 0, host.port_factory.get('test-win-win7', None))
def assert_round_trip(self, in_string, expected_string=None):
expectation = self._tokenize(in_string)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py
index d890cefeaa8..d5c57ac31c7 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -46,7 +46,7 @@ from blinkpy.common import read_checksum_from_png
from blinkpy.common.memoized import memoized
from blinkpy.common.path_finder import PathFinder
from blinkpy.common.system.path import abspath_to_uri
-from blinkpy.w3c.wpt_manifest import WPTManifest
+from blinkpy.w3c.wpt_manifest import WPTManifest, MANIFEST_NAME
from blinkpy.web_tests.layout_package.bot_test_expectations import BotTestExpectationsFactory
from blinkpy.web_tests.models.test_configuration import TestConfiguration
from blinkpy.web_tests.models.test_expectations import TestExpectationParser
@@ -102,6 +102,7 @@ SXG_FINGERPRINT = '55qC1nKu2A88ESbFmk5sTPQS/ScG+8DD7P+2bgFA9iM='
# And one for external/wpt/signed-exchange/resources/127.0.0.1.sxg.pem
SXG_WPT_FINGERPRINT = '0Rt4mT6SJXojEMHTnKnlJ/hBKMBcI4kteBlhR1eTTdk='
+
class Port(object):
"""Abstract class for Port-specific hooks for the web_test package."""
@@ -173,6 +174,22 @@ class Port(object):
FLAG_EXPECTATIONS_PREFIX = 'FlagExpectations'
+ # The following is used for concetenating WebDriver test names.
+ WEBDRIVER_SUBTEST_SEPARATOR = '>>'
+
+ # The following two constants must match. When adding a new WPT root, also
+ # remember to add an alias rule to third_party/wpt/wpt.config.json.
+ # WPT_DIRS maps WPT roots on the file system to URL prefixes on wptserve.
+ # The order matters: '/' MUST be the last URL prefix.
+ WPT_DIRS = collections.OrderedDict([
+ ('wpt_internal', '/wpt_internal/'),
+ ('external/wpt', '/'),
+ ])
+ # WPT_REGEX captures: 1. the root directory of WPT relative to web_tests
+ # (without a trailing slash), 2. the path of the test within WPT (without a
+ # leading slash).
+ WPT_REGEX = re.compile(r'^(?:virtual/[^/]+/)?(external/wpt|wpt_internal)/(.*)$')
+
# Because this is an abstract base class, arguments to functions may be
# unused in this class - pylint: disable=unused-argument
@@ -399,8 +416,8 @@ class Port(object):
_log.error('httpd seems broken. Cannot run http tests.')
return False
return True
- except OSError:
- pass
+ except OSError as e:
+ _log.error('httpd launch error: ' + repr(e))
_log.error('No httpd found. Cannot run http tests.')
return False
@@ -437,6 +454,11 @@ class Port(object):
executable = self._path_to_image_diff()
# Although we are handed 'old', 'new', image_diff wants 'new', 'old'.
command = [executable, '--diff', actual_filename, expected_filename, diff_filename]
+ # Notifies image_diff to allow a tolerance when calculating the pixel
+ # diff. To account for variances when the tests are ran on an actual
+ # GPU.
+ if self.get_option('fuzzy_diff'):
+ command.append('--fuzzy-diff')
result = None
err_str = None
@@ -687,15 +709,13 @@ class Port(object):
return reftest_list
# Try to extract information from MANIFEST.json.
- match = re.match(r'virtual/[^/]+/', test_name)
- if match:
- test_name = test_name[match.end(0):]
- match = re.match(r'external/wpt/(.*)', test_name)
+ match = self.WPT_REGEX.match(test_name)
if not match:
return []
- path_in_wpt = match.group(1)
- for expectation, ref_path_in_wpt in self._wpt_manifest().extract_reference_list(path_in_wpt):
- ref_absolute_path = self._filesystem.join(self.web_tests_dir(), 'external/wpt' + ref_path_in_wpt)
+ wpt_path = match.group(1)
+ path_in_wpt = match.group(2)
+ for expectation, ref_path_in_wpt in self._wpt_manifest(wpt_path).extract_reference_list(path_in_wpt):
+ ref_absolute_path = self._filesystem.join(self.web_tests_dir(), wpt_path + ref_path_in_wpt)
reftest_list.append((expectation, ref_absolute_path))
return reftest_list
@@ -717,26 +737,29 @@ class Port(object):
suites = self.virtual_test_suites()
if paths:
tests.extend(self._virtual_tests_matching_paths(paths, suites))
- if any('external' in path for path in paths):
+ if (any(wpt_path in path for wpt_path in self.WPT_DIRS for path in paths)
+ # TODO(robertma): Remove this special case when external/wpt is moved to wpt.
+ or any('external' in path for path in paths)):
tests.extend(self._wpt_test_urls_matching_paths(paths))
else:
tests.extend(self._all_virtual_tests(suites))
- tests.extend(['external/wpt' + test for test in self._wpt_manifest().all_urls()])
+ tests.extend([wpt_path + self.TEST_PATH_SEPARATOR + test for wpt_path in self.WPT_DIRS
+ for test in self._wpt_manifest(wpt_path).all_urls()])
return tests
def real_tests(self, paths):
+ """Find all real tests in paths except WPT."""
# When collecting test cases, skip these directories.
- skipped_directories = set([
- 'platform', 'resources', 'support', 'script-tests',
- 'reference', 'reftest', 'external'
- ])
- is_non_wpt_real_test_file = lambda fs, dirname, filename: (
- self.is_test_file(fs, dirname, filename)
- and not re.search(r'[/\\]external[/\\]wpt([/\\].*)?$', dirname)
- )
+ skipped_directories = set(
+ ['platform', 'resources', 'support', 'script-tests',
+ 'reference', 'reftest'])
+ # Also ignore all WPT directories. Note that this is only an
+ # optimization; is_non_wpt_test_file should skip WPT regardless.
+ skipped_directories |= set(self.WPT_DIRS)
files = find_files.find(self._filesystem, self.web_tests_dir(), paths, skipped_directories,
- is_non_wpt_real_test_file, self.test_key)
+ lambda _, dirname, filename: self.is_non_wpt_test_file(dirname, filename),
+ self.test_key)
return [self.relative_test_filename(f) for f in files]
@staticmethod
@@ -758,56 +781,43 @@ class Port(object):
'.htm', '.php', '.svg', '.mht', '.pdf',
])
- @staticmethod
- def _has_supported_extension(filesystem, filename):
+ def _has_supported_extension(self, filename):
"""Returns True if filename is one of the file extensions we want to run a test on."""
- extension = filesystem.splitext(filename)[1]
- return extension in Port.supported_file_extensions
-
- def is_test_file(self, filesystem, dirname, filename):
- match = re.search(r'[/\\]external[/\\]wpt([/\\].*)?$', dirname)
- if match:
- if match.group(1):
- path_in_wpt = match.group(1)[1:].replace('\\', '/') + '/' + filename
- else:
- path_in_wpt = filename
- return self._wpt_manifest().is_test_file(path_in_wpt)
- extension = filesystem.splitext(filename)[1]
+ extension = self._filesystem.splitext(filename)[1]
+ return extension in self.supported_file_extensions
+
+ def is_non_wpt_test_file(self, dirname, filename):
+ # Convert dirname to a relative path to web_tests with slashes
+ # normalized and ensure it has a trailing slash.
+ normalized_test_dir = self.relative_test_filename(dirname) + self.TEST_PATH_SEPARATOR
+ if any(normalized_test_dir.startswith(d + self.TEST_PATH_SEPARATOR) for d in self.WPT_DIRS):
+ return False
+ extension = self._filesystem.splitext(filename)[1]
if 'inspector-protocol' in dirname and extension == '.js':
return True
if 'devtools' in dirname and extension == '.js':
return True
- return Port._has_supported_extension(
- filesystem, filename) and not Port.is_reference_html_file(filesystem, dirname, filename)
-
- def _convert_wpt_file_path_to_url_paths(self, file_path):
- tests = []
- # Path separators are normalized by relative_test_filename().
- match = re.search(r'external/wpt/(.*)$', file_path)
- if not match:
- return [file_path]
- urls = self._wpt_manifest().file_path_to_url_paths(match.group(1))
- for url in urls:
- tests.append(file_path[0:match.start(1)] + url)
- return tests
+ return (self._has_supported_extension(filename) and
+ not Port.is_reference_html_file(self._filesystem, dirname, filename))
@memoized
- def _wpt_manifest(self):
- manifest_path = self._filesystem.join(self.web_tests_dir(), 'external', 'wpt', 'MANIFEST.json')
+ def _wpt_manifest(self, path):
+ assert path in self.WPT_DIRS
+ # Convert '/' to the platform-specific separator.
+ path = self._filesystem.normpath(path)
+ manifest_path = self._filesystem.join(self.web_tests_dir(), path, MANIFEST_NAME)
if not self._filesystem.exists(manifest_path):
_log.error('Manifest not found at %s. Remove the --no-manifest-update argument to generate it.', manifest_path)
return WPTManifest('{}')
return WPTManifest(self._filesystem.read_text_file(manifest_path))
def is_slow_wpt_test(self, test_file):
- match = re.match(r'virtual/[^/]+/', test_file)
- if match:
- test_file = test_file[match.end(0):]
- # WPTManifest.is_slow_test() takes a WPT URL with the leading slash.
- match = re.match(r'external/wpt(.*)', test_file)
+ match = self.WPT_REGEX.match(test_file)
if not match:
return False
- return self._wpt_manifest().is_slow_test(match.group(1))
+ wpt_path = match.group(1)
+ path_in_wpt = match.group(2)
+ return self._wpt_manifest(wpt_path).is_slow_test(path_in_wpt)
def test_key(self, test_name):
"""Turns a test name into a pair of sublists: the natural sort key of the
@@ -1179,7 +1189,7 @@ class Port(object):
@staticmethod
def is_wpt_test(test):
"""Whether a test is considered a web-platform-tests test."""
- return re.match(r'(virtual/[^/]+/)?external/wpt/', test)
+ return Port.WPT_REGEX.match(test)
@staticmethod
def should_use_wptserve(test):
@@ -1209,6 +1219,7 @@ class Port(object):
cmd = [httpd_path,
'-t',
'-f', self.path_to_apache_config_file(),
+ '-C', 'ServerRoot "%s"' % self.apache_server_root(),
'-C', 'HttpProtocolOptions Unsafe',
'-C', intentional_syntax_error]
env = self.setup_environ_for_server()
@@ -1400,6 +1411,10 @@ class Port(object):
def path_to_generic_test_expectations_file(self):
return self._filesystem.join(self.web_tests_dir(), 'TestExpectations')
+ @memoized
+ def path_to_webdriver_expectations_file(self):
+ return self._filesystem.join(self.web_tests_dir(), 'WebDriverExpectations')
+
def repository_path(self):
"""Returns the repository path for the chromium code base."""
return self._path_from_chromium_base('build')
@@ -1419,6 +1434,14 @@ class Port(object):
"""
raise NotImplementedError('Port.path_to_apache')
+ def apache_server_root(self):
+ """Returns the root that the apache binary is installed to.
+
+ This is used for the ServerRoot directive.
+ """
+ executable = self.path_to_apache()
+ return self._filesystem.dirname(self._filesystem.dirname(executable))
+
def path_to_apache_config_file(self):
"""Returns the full path to the apache configuration file.
@@ -1603,39 +1626,47 @@ class Port(object):
return '*' in path
def _wpt_test_urls_matching_paths(self, paths):
- tests = []
+ # This is to make sure "external[\\/]?" can also match to external/wpt.
+ # TODO(robertma): Remove this special case when external/wpt is moved to wpt.
+ paths = [self._filesystem.join(path, 'wpt') if path.rstrip('\\/').endswith('external')
+ else path for path in paths]
# '/' is used throughout this function instead of filesystem.sep as the WPT manifest always
# uses '/' for paths (it is not OS dependent).
if self._filesystem.sep != '/':
paths = [path.replace(self._filesystem.sep, '/') for path in paths]
- for test_url_path in self._wpt_manifest().all_urls():
- if test_url_path[0] == '/':
- test_url_path = test_url_path[1:]
+ tests = []
+ for wpt_path in self.WPT_DIRS:
+ tests += self._wpt_test_urls(wpt_path, paths)
+ return tests
- full_test_url_path = 'external/wpt/' + test_url_path
+ def _wpt_test_urls(self, wpt_path, paths):
+ tests = []
+ for test_url_path in self._wpt_manifest(wpt_path).all_urls():
+ assert not test_url_path.startswith('/')
+ full_test_url_path = wpt_path + '/' + test_url_path
for path in paths:
- if 'external' not in path:
+ if not path.startswith(wpt_path):
continue
- wpt_path = path.replace('external/wpt/', '')
+ # Also remove the slash after wpt_path, if any.
+ path_in_wpt = path[len(wpt_path) + 1:]
- # When `test_url_path` is test.any.html or test.any.worker.html and path is test.any.js
+ # When `test_url_path` is test.any.html etc., and `path_in_wpt` is test.any.js:
matches_any_js_test = (
- self._wpt_manifest().is_test_file(wpt_path)
- and test_url_path.startswith(re.sub(r'\.js$', '', wpt_path))
+ self._wpt_manifest(wpt_path).is_test_file(path_in_wpt)
+ and test_url_path.startswith(re.sub(r'\.js$', '', path_in_wpt))
)
- # Get a list of directories for both paths, filter empty strings
+ # For all other path matches within WPT:
+ # Get a list of directories for both paths, filter empty strings.
full_test_url_directories = filter(None, full_test_url_path.split('/'))
path_directories = filter(None, path.split('/'))
+ test_is_in_path = path_directories == full_test_url_directories[0:len(path_directories)]
- # For all other path matches within WPT
- if matches_any_js_test or path_directories == full_test_url_directories[0:len(path_directories)]:
- wpt_file_paths = self._convert_wpt_file_path_to_url_paths(test_url_path)
- tests.extend('external/wpt/' + wpt_file_path for wpt_file_path in wpt_file_paths)
-
+ if matches_any_js_test or test_is_in_path:
+ tests.append(full_test_url_path)
return tests
def _populate_virtual_suite(self, suite):
@@ -1748,6 +1779,8 @@ class Port(object):
raise TestRunException(exit_codes.SYS_DEPS_EXIT_STATUS, message)
return result
+ def add_webdriver_subtest_suffix(self, test_name, subtest_name):
+ return test_name + self.WEBDRIVER_SUBTEST_SEPARATOR + subtest_name
class VirtualTestSuite(object):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
index 2bec6d06f26..ef04a8390cc 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
@@ -26,7 +26,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import functools
import json
import optparse
import unittest
@@ -55,6 +54,25 @@ class PortTest(LoggingTestCase):
return TestPort(host, **kwargs)
return Port(host, port_name or 'baseport', **kwargs)
+ def test_validate_wpt_dirs(self):
+ # Keys should not have trailing slashes.
+ for wpt_path in Port.WPT_DIRS.keys():
+ self.assertFalse(wpt_path.endswith('/'))
+ # Values should not be empty (except the last one).
+ for url_prefix in Port.WPT_DIRS.values()[:-1]:
+ self.assertNotEqual(url_prefix, '/')
+ self.assertEqual(Port.WPT_DIRS.values()[-1], '/')
+
+ def test_validate_wpt_regex(self):
+ self.assertEquals(Port.WPT_REGEX.match('external/wpt/foo/bar.html').groups(),
+ ('external/wpt', 'foo/bar.html'))
+ self.assertEquals(Port.WPT_REGEX.match('virtual/test/external/wpt/foo/bar.html').groups(),
+ ('external/wpt', 'foo/bar.html'))
+ self.assertEquals(Port.WPT_REGEX.match('wpt_internal/foo/bar.html').groups(),
+ ('wpt_internal', 'foo/bar.html'))
+ self.assertEquals(Port.WPT_REGEX.match('virtual/test/wpt_internal/foo/bar.html').groups(),
+ ('wpt_internal', 'foo/bar.html'))
+
def test_setup_test_run(self):
port = self.make_port()
# This routine is a no-op. We just test it for coverage.
@@ -467,25 +485,25 @@ class PortTest(LoggingTestCase):
'items': {
'testharness': {
'dom/ranges/Range-attributes.html': [
- ['/dom/ranges/Range-attributes.html', {}]
+ ['dom/ranges/Range-attributes.html', {}]
],
'dom/ranges/Range-attributes-slow.html': [
- ['/dom/ranges/Range-attributes-slow.html', {'timeout': 'long'}]
+ ['dom/ranges/Range-attributes-slow.html', {'timeout': 'long'}]
],
'console/console-is-a-namespace.any.js': [
- ['/console/console-is-a-namespace.any.html', {}],
- ['/console/console-is-a-namespace.any.worker.html', {'timeout': 'long'}],
+ ['console/console-is-a-namespace.any.html', {}],
+ ['console/console-is-a-namespace.any.worker.html', {'timeout': 'long'}],
],
'html/parse.html': [
- ['/html/parse.html?run_type=uri', {}],
- ['/html/parse.html?run_type=write', {'timeout': 'long'}],
+ ['html/parse.html?run_type=uri', {}],
+ ['html/parse.html?run_type=write', {'timeout': 'long'}],
],
},
'manual': {},
'reftest': {
'html/dom/elements/global-attributes/dir_auto-EN-L.html': [
[
- '/html/dom/elements/global-attributes/dir_auto-EN-L.html',
+ 'html/dom/elements/global-attributes/dir_auto-EN-L.html',
[
[
'/html/dom/elements/global-attributes/dir_auto-EN-L-ref.html',
@@ -498,9 +516,20 @@ class PortTest(LoggingTestCase):
},
}}))
filesystem.write_text_file(WEB_TEST_DIR + '/external/wpt/dom/ranges/Range-attributes.html', '')
+ filesystem.write_text_file(WEB_TEST_DIR + '/external/wpt/dom/ranges/Range-attributes-slow.html', '')
filesystem.write_text_file(WEB_TEST_DIR + '/external/wpt/console/console-is-a-namespace.any.js', '')
filesystem.write_text_file(WEB_TEST_DIR + '/external/wpt/common/blank.html', 'foo')
+ filesystem.write_text_file(WEB_TEST_DIR + '/wpt_internal/MANIFEST.json', json.dumps({
+ 'items': {
+ 'testharness': {
+ 'dom/bar.html': [
+ ['dom/bar.html', {}]
+ ]
+ }
+ }}))
+ filesystem.write_text_file(WEB_TEST_DIR + '/wpt_internal/dom/bar.html', 'baz')
+
def test_find_none_if_not_in_manifest(self):
port = self.make_port(with_tests=True)
PortTest._add_manifest_to_mock_file_system(port.host.filesystem)
@@ -533,26 +562,29 @@ class PortTest(LoggingTestCase):
self.assertEqual(port.tests(['external/csswg-test']), [])
self.assertEqual(sorted(port.tests(['external/wpt'])), all_wpt)
self.assertEqual(sorted(port.tests(['external/wpt/'])), all_wpt)
- self.assertEqual(port.tests(['external/wpt/console']),
- ['external/wpt/console/console-is-a-namespace.any.worker.html',
- 'external/wpt/console/console-is-a-namespace.any.html'])
- self.assertEqual(port.tests(['external/wpt/console/']),
- ['external/wpt/console/console-is-a-namespace.any.worker.html',
- 'external/wpt/console/console-is-a-namespace.any.html'])
- self.assertEqual(port.tests(['external/wpt/console/console-is-a-namespace.any.js']),
- ['external/wpt/console/console-is-a-namespace.any.worker.html',
- 'external/wpt/console/console-is-a-namespace.any.html'])
+ self.assertEqual(sorted(port.tests(['external/wpt/console'])),
+ ['external/wpt/console/console-is-a-namespace.any.html',
+ 'external/wpt/console/console-is-a-namespace.any.worker.html'])
+ self.assertEqual(sorted(port.tests(['external/wpt/console/'])),
+ ['external/wpt/console/console-is-a-namespace.any.html',
+ 'external/wpt/console/console-is-a-namespace.any.worker.html'])
+ self.assertEqual(sorted(port.tests(['external/wpt/console/console-is-a-namespace.any.js'])),
+ ['external/wpt/console/console-is-a-namespace.any.html',
+ 'external/wpt/console/console-is-a-namespace.any.worker.html'])
self.assertEqual(port.tests(['external/wpt/console/console-is-a-namespace.any.html']),
['external/wpt/console/console-is-a-namespace.any.html'])
- self.assertEqual(port.tests(['external/wpt/dom']),
+ self.assertEqual(sorted(port.tests(['external/wpt/dom'])),
['external/wpt/dom/ranges/Range-attributes-slow.html',
'external/wpt/dom/ranges/Range-attributes.html'])
- self.assertEqual(port.tests(['external/wpt/dom/']),
+ self.assertEqual(sorted(port.tests(['external/wpt/dom/'])),
['external/wpt/dom/ranges/Range-attributes-slow.html',
'external/wpt/dom/ranges/Range-attributes.html'])
self.assertEqual(port.tests(['external/wpt/dom/ranges/Range-attributes.html']),
['external/wpt/dom/ranges/Range-attributes.html'])
+ # wpt_internal should work the same.
+ self.assertEqual(port.tests(['wpt_internal']), ['wpt_internal/dom/bar.html'])
+
def test_virtual_wpt_tests_paths(self):
port = self.make_port(with_tests=True)
PortTest._add_manifest_to_mock_file_system(port.host.filesystem)
@@ -581,43 +613,37 @@ class PortTest(LoggingTestCase):
self.assertEqual(port.tests(['virtual/virtual_wpt_dom/external/wpt/dom/ranges/Range-attributes.html']),
['virtual/virtual_wpt_dom/external/wpt/dom/ranges/Range-attributes.html'])
- def test_is_test_file(self):
- port = self.make_port(with_tests=True)
- is_test_file = functools.partial(Port.is_test_file, port, port.host.filesystem)
- self.assertTrue(is_test_file('', 'foo.html'))
- self.assertTrue(is_test_file('', 'foo.svg'))
- self.assertTrue(is_test_file('', 'test-ref-test.html'))
- self.assertTrue(is_test_file('devtools', 'a.js'))
- self.assertFalse(is_test_file('', 'foo.png'))
- self.assertFalse(is_test_file('', 'foo-expected.html'))
- self.assertFalse(is_test_file('', 'foo-expected.svg'))
- self.assertFalse(is_test_file('', 'foo-expected.xht'))
- self.assertFalse(is_test_file('', 'foo-expected-mismatch.html'))
- self.assertFalse(is_test_file('', 'foo-expected-mismatch.svg'))
- self.assertFalse(is_test_file('', 'foo-expected-mismatch.xhtml'))
- self.assertFalse(is_test_file('', 'foo-ref.html'))
- self.assertFalse(is_test_file('', 'foo-notref.html'))
- self.assertFalse(is_test_file('', 'foo-notref.xht'))
- self.assertFalse(is_test_file('', 'foo-ref.xhtml'))
- self.assertFalse(is_test_file('', 'ref-foo.html'))
- self.assertFalse(is_test_file('', 'notref-foo.xhr'))
-
- def test_is_test_file_in_wpt(self):
- port = self.make_port(with_tests=True)
- filesystem = port.host.filesystem
- PortTest._add_manifest_to_mock_file_system(filesystem)
+ # wpt_internal should work the same.
+ self.assertEqual(port.tests(['virtual/virtual_wpt_dom/wpt_internal']),
+ ['virtual/virtual_wpt_dom/wpt_internal/dom/bar.html'])
+ self.assertEqual(port.tests(['virtual/virtual_wpt_dom/']),
+ dom_wpt + ['virtual/virtual_wpt_dom/wpt_internal/dom/bar.html'])
- # A file not in MANIFEST.json is not a test even if it has .html suffix.
- self.assertFalse(port.is_test_file(filesystem, WEB_TEST_DIR + '/external/wpt/common', 'blank.html'))
-
- # .js is not a test in general, but it is if MANIFEST.json contains an
- # entry for it.
- self.assertTrue(port.is_test_file(filesystem, WEB_TEST_DIR + '/external/wpt/console', 'console-is-a-namespace.any.js'))
-
- # A file in external/wpt, not a sub directory.
- self.assertFalse(port.is_test_file(filesystem, WEB_TEST_DIR + '/external/wpt', 'testharness_runner.html'))
- # A file in external/wpt_automation.
- self.assertTrue(port.is_test_file(filesystem, WEB_TEST_DIR + '/external/wpt_automation', 'foo.html'))
+ def test_is_non_wpt_test_file(self):
+ port = self.make_port(with_tests=True)
+ self.assertTrue(port.is_non_wpt_test_file('', 'foo.html'))
+ self.assertTrue(port.is_non_wpt_test_file('', 'foo.svg'))
+ self.assertTrue(port.is_non_wpt_test_file('', 'test-ref-test.html'))
+ self.assertTrue(port.is_non_wpt_test_file('devtools', 'a.js'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo.png'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-expected.html'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-expected.svg'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-expected.xht'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-expected-mismatch.html'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-expected-mismatch.svg'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-expected-mismatch.xhtml'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-ref.html'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-notref.html'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-notref.xht'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'foo-ref.xhtml'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'ref-foo.html'))
+ self.assertFalse(port.is_non_wpt_test_file('', 'notref-foo.xhr'))
+
+ self.assertFalse(port.is_non_wpt_test_file(WEB_TEST_DIR + '/external/wpt/common', 'blank.html'))
+ self.assertFalse(port.is_non_wpt_test_file(WEB_TEST_DIR + '/external/wpt/console', 'console-is-a-namespace.any.js'))
+ self.assertFalse(port.is_non_wpt_test_file(WEB_TEST_DIR + '/external/wpt', 'testharness_runner.html'))
+ self.assertTrue(port.is_non_wpt_test_file(WEB_TEST_DIR + '/external/wpt_automation', 'foo.html'))
+ self.assertFalse(port.is_non_wpt_test_file(WEB_TEST_DIR + '/wpt_internal/console', 'console-is-a-namespace.any.js'))
def test_is_wpt_test(self):
self.assertTrue(Port.is_wpt_test('external/wpt/dom/ranges/Range-attributes.html'))
@@ -912,6 +938,15 @@ class PortTest(LoggingTestCase):
self.assertTrue(port.skips_test('failures/expected/image.html'))
+ def test_add_webdriver_subtest_suffix(self):
+ port = self.make_port()
+ wb_test_name = "abd"
+ sub_test_name = "bar"
+
+ full_webdriver_name = port.add_webdriver_subtest_suffix(wb_test_name, sub_test_name)
+
+ self.assertEqual(full_webdriver_name, "abd>>bar")
+
class NaturalCompareTest(unittest.TestCase):
def setUp(self):
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py
index d966ec8cf9b..f7f0d68791d 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver.py
@@ -30,7 +30,6 @@ import base64
import logging
import re
import shlex
-import sys
import time
from blinkpy.common.system import path
@@ -156,6 +155,7 @@ class Driver(object):
port - reference back to the port object.
worker_number - identifier for a particular worker/driver instance
"""
+ self.WPT_DIRS = port.WPT_DIRS
self._port = port
self._worker_number = worker_number
self._no_timeout = no_timeout
@@ -176,6 +176,7 @@ class Driver(object):
# "#LEAK". This leak detection is enabled only when the flag
# --enable-leak-detection is passed to content_shell.
self._leaked = False
+ self._leak_log = None
# stderr reading is scoped on a per-test (not per-block) basis, so we store the accumulated
# stderr output, as well as if we've seen #EOF on this driver instance.
@@ -274,6 +275,7 @@ class Driver(object):
pid=pid)
def _get_crash_log(self, stdout, stderr, newer_than):
+ # pylint: disable=protected-access
return self._port._get_crash_log(self._crashed_process_name, self._crashed_pid, stdout, stderr, newer_than)
# FIXME: Seems this could just be inlined into callers.
@@ -289,7 +291,6 @@ class Driver(object):
HTTP_DIR = 'http/tests/'
HTTP_LOCAL_DIR = 'http/tests/local/'
HTTP_HOST_AND_PORTS = ('127.0.0.1', 8000, 8443)
- WPT_DIR = 'external/wpt/'
WPT_HOST_AND_PORTS = ('web-platform.test', 8001, 8444)
def is_http_test(self, test_name):
@@ -311,17 +312,29 @@ class Driver(object):
return path.abspath_to_uri(self._port.host.platform, self._port.abspath_for_test(test_name))
if using_wptserve:
- test_dir_prefix = self.WPT_DIR
+ for wpt_path, url_prefix in self.WPT_DIRS.items():
+ # The keys of WPT_DIRS do not have trailing slashes.
+ wpt_path += '/'
+ if test_name.startswith(wpt_path):
+ test_dir_prefix = wpt_path
+ test_url_prefix = url_prefix
+ break
+ else:
+ # We really shouldn't reach here, but in case we do, fail gracefully.
+ _log.error('Unrecognized WPT test name: %s', test_name)
+ test_dir_prefix = 'external/wpt/'
+ test_url_prefix = '/'
hostname, insecure_port, secure_port = self.WPT_HOST_AND_PORTS
else:
test_dir_prefix = self.HTTP_DIR
+ test_url_prefix = '/'
hostname, insecure_port, secure_port = self.HTTP_HOST_AND_PORTS
relative_path = test_name[len(test_dir_prefix):]
if '/https/' in test_name or '.https.' in test_name or '.serviceworker.' in test_name:
- return 'https://%s:%d/%s' % (hostname, secure_port, relative_path)
- return 'http://%s:%d/%s' % (hostname, insecure_port, relative_path)
+ return 'https://%s:%d%s%s' % (hostname, secure_port, test_url_prefix, relative_path)
+ return 'http://%s:%d%s%s' % (hostname, insecure_port, test_url_prefix, relative_path)
def _get_uri_prefixes(self, hostname, insecure_port, secure_port):
"""Returns the HTTP and HTTPS URI prefix for a hostname."""
@@ -347,7 +360,10 @@ class Driver(object):
return self.HTTP_DIR + uri[len(prefix):]
for prefix in self._get_uri_prefixes(*self.WPT_HOST_AND_PORTS):
if uri.startswith(prefix):
- return self.WPT_DIR + uri[len(prefix):]
+ url_path = '/' + uri[len(prefix):]
+ for wpt_path, url_prefix in self.WPT_DIRS.items():
+ if url_path.startswith(url_prefix):
+ return wpt_path + '/' + url_path[len(url_prefix):]
raise NotImplementedError('unknown url type: %s' % uri)
def has_crashed(self):
@@ -381,7 +397,6 @@ class Driver(object):
self._crashed_process_name = None
self._crashed_pid = None
self._leaked = False
- self._leak_log = None
cmd_line = self.cmd_line(per_test_args)
self._server_process = self._port.server_process_constructor(
self._port, server_name, cmd_line, environment, more_logging=self._port.get_option('driver_logging'))
@@ -579,6 +594,7 @@ class Driver(object):
if out_line[-1] != '\n':
_log.error(
'Last character read from DRT stdout line was not a newline! This indicates either a NRWT or DRT bug.')
+ # pylint: disable=protected-access
content_length_before_header_check = block._content_length
self._process_stdout_line(block, out_line)
# FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header.
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
index 45fe2ecda67..9e5d1bfcf83 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
@@ -38,6 +38,8 @@ from blinkpy.web_tests.port.server_process_mock import MockServerProcess
class DriverTest(unittest.TestCase):
+ # pylint: disable=protected-access
+
def make_port(self):
return Port(MockSystemHost(), 'test', optparse.Values({'configuration': 'Release'}))
@@ -62,9 +64,18 @@ class DriverTest(unittest.TestCase):
self.assertEqual(driver.test_to_uri('http/tests/https/bar.html'), 'https://127.0.0.1:8443/https/bar.html')
self.assertEqual(driver.test_to_uri('http/tests/bar.https.html'), 'https://127.0.0.1:8443/bar.https.html')
self.assertEqual(driver.test_to_uri('http/tests/barhttps.html'), 'http://127.0.0.1:8000/barhttps.html')
- self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.html'), 'http://web-platform.test:8001/foo/bar.html')
- self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.https.html'), 'https://web-platform.test:8444/foo/bar.https.html')
- self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.serviceworker.html'), 'https://web-platform.test:8444/foo/bar.serviceworker.html')
+ self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.html'),
+ 'http://web-platform.test:8001/foo/bar.html')
+ self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.https.html'),
+ 'https://web-platform.test:8444/foo/bar.https.html')
+ self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.serviceworker.html'),
+ 'https://web-platform.test:8444/foo/bar.serviceworker.html')
+ self.assertEqual(driver.test_to_uri('wpt_internal/foo/bar.html'),
+ 'http://web-platform.test:8001/wpt_internal/foo/bar.html')
+ self.assertEqual(driver.test_to_uri('wpt_internal/foo/bar.https.html'),
+ 'https://web-platform.test:8444/wpt_internal/foo/bar.https.html')
+ self.assertEqual(driver.test_to_uri('wpt_internal/foo/bar.serviceworker.html'),
+ 'https://web-platform.test:8444/wpt_internal/foo/bar.serviceworker.html')
def test_uri_to_test(self):
port = self.make_port()
@@ -73,9 +84,18 @@ class DriverTest(unittest.TestCase):
self.assertEqual(driver.uri_to_test('http://127.0.0.1:8000/foo.html'), 'http/tests/foo.html')
self.assertEqual(driver.uri_to_test('https://127.0.0.1:8443/https/bar.html'), 'http/tests/https/bar.html')
self.assertEqual(driver.uri_to_test('https://127.0.0.1:8443/bar.https.html'), 'http/tests/bar.https.html')
- self.assertEqual(driver.uri_to_test('http://web-platform.test:8001/foo/bar.html'), 'external/wpt/foo/bar.html')
- self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.https.html'), 'external/wpt/foo/bar.https.html')
- self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.serviceworker.html'), 'external/wpt/foo/bar.serviceworker.html')
+ self.assertEqual(driver.uri_to_test('http://web-platform.test:8001/foo/bar.html'),
+ 'external/wpt/foo/bar.html')
+ self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.https.html'),
+ 'external/wpt/foo/bar.https.html')
+ self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.serviceworker.html'),
+ 'external/wpt/foo/bar.serviceworker.html')
+ self.assertEqual(driver.uri_to_test('http://web-platform.test:8001/wpt_internal/foo/bar.html'),
+ 'wpt_internal/foo/bar.html')
+ self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/wpt_internal/foo/bar.https.html'),
+ 'wpt_internal/foo/bar.https.html')
+ self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/wpt_internal/foo/bar.serviceworker.html'),
+ 'wpt_internal/foo/bar.serviceworker.html')
def test_read_block(self):
port = self.make_port()
@@ -272,22 +292,22 @@ class CoalesceRepeatedSwitchesTest(unittest.TestCase):
def test_multiple_enable_features(self):
self._assert_coalesced_switches(
- [ '--A', '--enable-features=Z,X',
- '--enable-features=Y', '--X', '--enable-features=X,Y',
- '--enable-features=X', '--enable-features=X,X'],
+ ['--A', '--enable-features=Z,X',
+ '--enable-features=Y', '--X', '--enable-features=X,Y',
+ '--enable-features=X', '--enable-features=X,X'],
['--A', '--X', '--enable-features=X,Y,Z'])
def test_multiple_disable_features(self):
self._assert_coalesced_switches(
- [ '--A', '--disable-features=Z,X',
- '--disable-features=Y', '--X', '--disable-features=X,Y',
- '--disable-features=X', '--disable-features=X,X'],
+ ['--A', '--disable-features=Z,X',
+ '--disable-features=Y', '--X', '--disable-features=X,Y',
+ '--disable-features=X', '--disable-features=X,X'],
['--A', '--X', '--disable-features=X,Y,Z'])
def test_enable_and_disable_features(self):
# The coalescing of --enable-features and --disable-features is
# independent (may both enable and disable the same feature).
self._assert_coalesced_switches(
- [ '--A', '--disable-features=Z','--disable-features=E,X',
- '--enable-features=Y', '--X', '--enable-features=X,Y'],
+ ['--A', '--disable-features=Z', '--disable-features=E,X',
+ '--enable-features=Y', '--X', '--enable-features=X,Y'],
['--A', '--X', '--enable-features=X,Y', '--disable-features=E,X,Z'])
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory.py
index 0aeaa03e405..fb58b9e1de9 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/factory.py
@@ -126,6 +126,8 @@ def configuration_options():
help='Specify the target build subdirectory under src/out/'),
optparse.make_option('--release', action='store_const', const='Release', dest='configuration',
help='Set the configuration to Release'),
+ optparse.make_option('--no-xvfb', action='store_false', dest='use_xvfb', default=True,
+ help='Do not run tests with Xvfb'),
]
@@ -147,7 +149,7 @@ def _check_configuration_and_target(host, options):
expected_configuration = getattr(options, 'configuration')
if expected_configuration not in (None, gn_configuration):
raise ValueError('Configuration does not match the GN build args. '
- 'Expected "%s" but got "%s".' % (gn_configuration, expected_configuration))
+ 'Expected "%s" but got "%s".' % (expected_configuration, gn_configuration))
options.configuration = gn_configuration
return
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
index 5233f4dc508..dd5b05397b8 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
@@ -146,24 +146,9 @@ class _TargetHost(object):
ssh_args=forwarding_flags,
stderr=subprocess.PIPE)
- # Copy content_shell package to the device.
- device_package_path = \
- os.path.join('/data', os.path.basename(CONTENT_SHELL_PACKAGE_PATH))
- self._target.PutFile(
- os.path.join(build_path, CONTENT_SHELL_PACKAGE_PATH),
- device_package_path)
-
- pm_install = self._target.RunCommandPiped(
- ['pm', 'install', device_package_path],
- stderr=subprocess.PIPE)
- output = pm_install.stderr.readlines()
- pm_install.wait()
-
- if pm_install.returncode != 0:
- # Don't error out if the package already exists on the device.
- if len(output) != 1 or 'ErrAlreadyExists' not in output[0]:
- raise Exception('Failed to install content_shell: %s' % \
- '\n'.join(output))
+ package_path = os.path.join(build_path, CONTENT_SHELL_PACKAGE_PATH)
+ self._target.InstallPackage(package_path, "content_shell",
+ package_deps=[])
# Process will be forked for each worker, which may make QemuTarget
# unusable (e.g. waitpid() for qemu process returns ECHILD after
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/linux.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/linux.py
index 29a3d196a88..9e39ed7b632 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/linux.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/linux.py
@@ -110,13 +110,15 @@ class LinuxPort(base.Port):
def setup_test_run(self):
super(LinuxPort, self).setup_test_run()
- if not self._start_xvfb():
- return SYS_DEPS_EXIT_STATUS
+ if self.get_option('use_xvfb'):
+ if not self._start_xvfb():
+ return SYS_DEPS_EXIT_STATUS
self._setup_dummy_home_dir()
def clean_up_test_run(self):
super(LinuxPort, self).clean_up_test_run()
- self._stop_xvfb(save_logs=False)
+ if self.get_option('use_xvfb'):
+ self._stop_xvfb(save_logs=False)
self._clean_up_dummy_home_dir()
#
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac.py
index 149bbca69da..3817fba26e4 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac.py
@@ -91,13 +91,12 @@ class MacPort(base.Port):
#
def path_to_apache(self):
- return '/usr/sbin/httpd'
+ return self._path_from_chromium_base(
+ 'third_party', 'apache-mac', 'bin', 'httpd')
def path_to_apache_config_file(self):
- config_file_basename = 'apache2-httpd-' + self._apache_version()
- if self.host.platform.os_version in ['mac10.13', 'mac10.14']:
- config_file_basename += '-php7'
- return self._filesystem.join(self.apache_config_directory(), config_file_basename + '.conf')
+ config_file_basename = 'apache2-httpd-%s-php7.conf' % (self._apache_version(),)
+ return self._filesystem.join(self.apache_config_directory(), config_file_basename)
def _path_to_driver(self, target=None):
return self._build_path_with_target(target, self.driver_name() + '.app', 'Contents', 'MacOS', self.driver_name())
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac_unittest.py
index 7cf62d3ba76..670dbfe6e40 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/mac_unittest.py
@@ -56,13 +56,6 @@ class MacPortTest(port_testcase.PortTestCase):
def test_path_to_apache_config_file(self):
port = self.make_port()
- port._apache_version = lambda: '2.2' # pylint: disable=protected-access
- self.assertEqual(
- port.path_to_apache_config_file(),
- '/mock-checkout/third_party/blink/tools/apache_config/apache2-httpd-2.2.conf')
-
- def test_path_to_apache_config_file_on_10_13(self):
- port = self.make_port(os_version='mac10.13', port_name='mac')
port._apache_version = lambda: '2.4' # pylint: disable=protected-access
self.assertEqual(
port.path_to_apache_config_file(),
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py
index 11378b8d31a..e8ae31a6976 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/port_testcase.py
@@ -66,7 +66,7 @@ class PortTestCase(LoggingTestCase):
def make_port(self, host=None, port_name=None, options=None, os_name=None, os_version=None, **kwargs):
host = host or MockSystemHost(os_name=(os_name or self.os_name), os_version=(os_version or self.os_version))
- options = options or optparse.Values({'configuration': 'Release'})
+ options = options or optparse.Values({'configuration': 'Release', 'use_xvfb': True})
port_name = port_name or self.port_name
port_name = self.port_maker.determine_full_port_name(host, options, port_name)
return self.port_maker(host, port_name, options=options, **kwargs)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py
index f7b6b6de907..0d777d77c43 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py
@@ -31,7 +31,6 @@ import time
from blinkpy.common import exit_codes
from blinkpy.common.system.crash_logs import CrashLogs
-from blinkpy.web_tests.models import test_run_results
from blinkpy.web_tests.models.test_configuration import TestConfiguration
from blinkpy.web_tests.port.base import Port, VirtualTestSuite
from blinkpy.web_tests.port.driver import DeviceFailure, Driver, DriverOutput
@@ -513,6 +512,7 @@ class TestPort(Port):
args=['--virtual-arg'], references_use_default_args=True),
VirtualTestSuite(prefix='virtual_wpt', base='external/wpt', args=['--virtual-arg']),
VirtualTestSuite(prefix='virtual_wpt_dom', base='external/wpt/dom', args=['--virtual-arg']),
+ VirtualTestSuite(prefix='virtual_wpt_dom', base='wpt_internal/dom', args=['--virtual-arg']),
]
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py b/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
index 00a33b66d18..65dd5348fc7 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
@@ -279,6 +279,14 @@ def parse_args(args):
default=None,
help='Exit after the first N failures instead of running all tests'),
optparse.make_option(
+ '--fuzzy-diff',
+ action='store_true',
+ default=False,
+ help=('When running tests on an actual GPU, variance in pixel '
+ 'output can leads image differences causing failed expectations. '
+ 'Instead a fuzzy diff is used to account for this variance. '
+ 'See tools/imagediff/image_diff.cc')),
+ optparse.make_option(
'--ignore-builder-category',
action='store',
help=('The category of builders to use with the --ignore-flaky-tests option '
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py
index eb3e93c2eb3..0a532501870 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/servers/apache_http.py
@@ -53,7 +53,6 @@ class ApacheHTTP(server_base.ServerBase):
self._pid_file = self._filesystem.join(self._runtime_path, '%s.pid' % self._name)
executable = self._port_obj.path_to_apache()
- server_root = self._filesystem.dirname(self._filesystem.dirname(executable))
test_dir = self._port_obj.web_tests_dir()
document_root = self._filesystem.join(test_dir, 'http', 'tests')
@@ -75,7 +74,7 @@ class ApacheHTTP(server_base.ServerBase):
start_cmd = [
executable,
'-f', '%s' % self._port_obj.path_to_apache_config_file(),
- '-C', 'ServerRoot "%s"' % server_root,
+ '-C', 'ServerRoot "%s"' % self._port_obj.apache_server_root(),
'-C', 'DocumentRoot "%s"' % document_root,
'-c', 'Alias /js-test-resources "%s/resources"' % test_dir,
'-c', 'Alias /geolocation-api/js-test-resources "%s/geolocation-api/resources"' % test_dir,
@@ -180,6 +179,7 @@ class ApacheHTTP(server_base.ServerBase):
proc = self._executive.popen([self._port_obj.path_to_apache(),
'-f', self._port_obj.path_to_apache_config_file(),
+ '-C', 'ServerRoot "%s"' % self._port_obj.apache_server_root(),
'-c', 'PidFile "%s"' % self._pid_file,
'-k', 'stop'])
_, err = proc.communicate()
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py b/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py
index 81b4c88cfc1..9910eec2f31 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py
@@ -70,7 +70,8 @@ class TryFlag(object):
result = set()
path = self._flag_expectations_path()
for line in self._filesystem.read_text_file(path).split('\n'):
- expectation_line = TestExpectationLine.tokenize_line(path, line, 0)
+ expectation_line = TestExpectationLine.tokenize_line(
+ path, line, 0, self._host.port_factory.get())
test_name = expectation_line.name
if test_name:
result.add(test_name)