aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/wpt/metadata/MANIFEST.json21
-rw-r--r--tests/wpt/metadata/css/css-fonts/variations/at-font-face-font-matching.html.ini24
-rw-r--r--tests/wpt/metadata/css/css-transitions/transitions-animatable-properties-01.html.ini3
-rw-r--r--tests/wpt/metadata/encoding/single-byte-decoder.html.ini65
-rw-r--r--tests/wpt/metadata/fetch/content-type/response.window.js.ini37
-rw-r--r--tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_3.html.ini (renamed from tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini)2
-rw-r--r--tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini (renamed from tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini)2
-rw-r--r--tests/wpt/metadata/html/semantics/embedded-content/the-img-element/non-active-document.html.ini10
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html.ini2
-rw-r--r--tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini1
-rw-r--r--tests/wpt/metadata/workers/modules/dedicated-worker-options-credentials.html.ini13
-rw-r--r--tests/wpt/mozilla/meta/css/transition_calc_implicit.html.ini2
-rw-r--r--tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js7
-rw-r--r--tests/wpt/web-platform-tests/interfaces/webaudio.idl4
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/lint.py264
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/rules.py316
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py215
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py58
-rw-r--r--tests/wpt/web-platform-tests/workers/modules/resources/credentials.py5
19 files changed, 778 insertions, 273 deletions
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index f4d36982ea4..85b062a1178 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -319097,6 +319097,11 @@
{}
]
],
+ "tools/lint/rules.py": [
+ [
+ {}
+ ]
+ ],
"tools/lint/tests/__init__.py": [
[
{}
@@ -649420,7 +649425,7 @@
"support"
],
"generic-sensor/generic-sensor-tests.js": [
- "8168d7a39f75fc22404c8c39937723e10c372d2d",
+ "a48b4c59aa89d0f1a0c7855f93bd80ce0f33fbf0",
"support"
],
"generic-sensor/idlharness.https.window.js": [
@@ -670296,7 +670301,7 @@
"support"
],
"interfaces/webaudio.idl": [
- "4f1914dbae23a5619b72b92b761bd146d1aaacf9",
+ "4679558023ae87655f46b10d5a57d39269c6e8c9",
"support"
],
"interfaces/webauthn.idl": [
@@ -704876,7 +704881,11 @@
"support"
],
"tools/lint/lint.py": [
- "ccadcdc16c72a9790c7de697c6f7762f0cbe06f1",
+ "19d0c112186a09ab2ca5fb449faf4ea90bb66e04",
+ "support"
+ ],
+ "tools/lint/rules.py": [
+ "78f9d072a8a71c7af0494dc3625bd7aa937a5554",
"support"
],
"tools/lint/tests/__init__.py": [
@@ -705016,7 +705025,7 @@
"support"
],
"tools/lint/tests/test_file_lints.py": [
- "28ccacc8787c61c2a6cf34552f179ef893360fed",
+ "ddf03986e10f5c336ea7ce7731bbcdd2135235d0",
"support"
],
"tools/lint/tests/test_lint.py": [
@@ -705024,7 +705033,7 @@
"support"
],
"tools/lint/tests/test_path_lints.py": [
- "bf8418d52a02e1a22b83fbb15c0b468969546dc6",
+ "ab44c559187e8e435a34d5e13076feb420a15270",
"support"
],
"tools/localpaths.py": [
@@ -722416,7 +722425,7 @@
"testharness"
],
"workers/modules/resources/credentials.py": [
- "7623d849625db4df7a9a10b8edd6f5e5e3187faf",
+ "fb1c7fe96cba4f41ac4b32c09642aea44fe05b23",
"support"
],
"workers/modules/resources/dynamic-import-and-then-static-import-worker.js": [
diff --git a/tests/wpt/metadata/css/css-fonts/variations/at-font-face-font-matching.html.ini b/tests/wpt/metadata/css/css-fonts/variations/at-font-face-font-matching.html.ini
index 37f7f11182a..468859377f2 100644
--- a/tests/wpt/metadata/css/css-fonts/variations/at-font-face-font-matching.html.ini
+++ b/tests/wpt/metadata/css/css-fonts/variations/at-font-face-font-matching.html.ini
@@ -311,3 +311,27 @@
[Matching font-style: 'oblique -10deg' should prefer 'oblique -1deg 0deg' over 'oblique -20deg -15deg']
expected: FAIL
+ [Matching font-weight: '430' should prefer '350 399' over '340 398']
+ expected: FAIL
+
+ [Matching font-stretch: '100%' should prefer '110% 120%' over '115% 116%']
+ expected: FAIL
+
+ [Matching font-weight: '430' should prefer '500' over '400 425']
+ expected: FAIL
+
+ [Matching font-stretch: '110%' should prefer '105%' over '100%']
+ expected: FAIL
+
+ [Matching font-style: 'oblique 0deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg']
+ expected: FAIL
+
+ [Matching font-weight: '400' should prefer '351 398' over '501 550']
+ expected: FAIL
+
+ [Matching font-style: 'oblique -20deg' should prefer 'oblique -20deg' over 'oblique -60deg -40deg']
+ expected: FAIL
+
+ [Matching font-style: 'oblique -10deg' should prefer 'italic' over 'oblique 0deg 10deg']
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/css-transitions/transitions-animatable-properties-01.html.ini b/tests/wpt/metadata/css/css-transitions/transitions-animatable-properties-01.html.ini
index 8850ec200da..323528d3385 100644
--- a/tests/wpt/metadata/css/css-transitions/transitions-animatable-properties-01.html.ini
+++ b/tests/wpt/metadata/css/css-transitions/transitions-animatable-properties-01.html.ini
@@ -74,3 +74,6 @@
[opacity end]
expected: FAIL
+ [letter-spacing end]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/encoding/single-byte-decoder.html.ini b/tests/wpt/metadata/encoding/single-byte-decoder.html.ini
index d146040e0c1..3d135f3bd66 100644
--- a/tests/wpt/metadata/encoding/single-byte-decoder.html.ini
+++ b/tests/wpt/metadata/encoding/single-byte-decoder.html.ini
@@ -2,7 +2,7 @@
type: testharness
[single-byte-decoder.html?document]
- expected: CRASH
+ expected: TIMEOUT
[ISO-8859-4: iso_8859-4:1988 (document.characterSet and document.inputEncoding)]
expected: FAIL
@@ -32,7 +32,6 @@
[single-byte-decoder.html?XMLHttpRequest]
- expected: CRASH
[ISO-8859-2: iso_8859-2:1987 (XMLHttpRequest)]
expected: FAIL
@@ -58,67 +57,7 @@
expected: FAIL
[windows-1254: iso_8859-9:1989 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1254: windows-1254 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1257: cp1257 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1254: x-cp1254 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1255: windows-1255 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1258: x-cp1258 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [x-mac-cyrillic: x-mac-cyrillic (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1258: cp1258 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1257: x-cp1257 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1254: iso88599 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1254: iso_8859-9 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1257: windows-1257 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1258: windows-1258 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1256: cp1256 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [x-mac-cyrillic: x-mac-ukrainian (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1255: x-cp1255 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1256: x-cp1256 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1256: windows-1256 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1254: l5 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1254: latin5 (XMLHttpRequest)]
- expected: TIMEOUT
-
- [windows-1254: iso8859-9 (XMLHttpRequest)]
- expected: TIMEOUT
+ expected: FAIL
[single-byte-decoder.html?TextDecoder]
diff --git a/tests/wpt/metadata/fetch/content-type/response.window.js.ini b/tests/wpt/metadata/fetch/content-type/response.window.js.ini
index 18f786d4963..72022cb4ff0 100644
--- a/tests/wpt/metadata/fetch/content-type/response.window.js.ini
+++ b/tests/wpt/metadata/fetch/content-type/response.window.js.ini
@@ -22,7 +22,7 @@
expected: NOTRUN
[<iframe>: combined response Content-Type: text/plain */*;charset=gbk]
- expected: FAIL
+ expected: TIMEOUT
[fetch(): separate response Content-Type: text/html;x=" text/plain]
expected: NOTRUN
@@ -163,7 +163,7 @@
expected: NOTRUN
[<iframe>: combined response Content-Type: text/html;" " text/plain]
- expected: FAIL
+ expected: TIMEOUT
[Request: combined response Content-Type: text/plain;charset=gbk;x=foo text/plain]
expected: NOTRUN
@@ -172,7 +172,7 @@
expected: NOTRUN
[<iframe>: combined response Content-Type: text/html;" \\" text/plain ";charset=GBK]
- expected: FAIL
+ expected: TIMEOUT
[Response: combined response Content-Type: text/html;x=" text/plain]
expected: NOTRUN
@@ -202,7 +202,7 @@
expected: NOTRUN
[<iframe>: separate response Content-Type: text/html;" " text/plain]
- expected: FAIL
+ expected: TIMEOUT
[fetch(): separate response Content-Type: text/plain */*;charset=gbk]
expected: NOTRUN
@@ -286,7 +286,7 @@
expected: NOTRUN
[<iframe>: separate response Content-Type: text/html;" \\" text/plain ";charset=GBK]
- expected: FAIL
+ expected: TIMEOUT
[fetch(): combined response Content-Type: text/html;" " text/plain]
expected: NOTRUN
@@ -310,5 +310,32 @@
expected: NOTRUN
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
+ expected: TIMEOUT
+
+ [<iframe>: combined response Content-Type: text/html;" text/plain]
+ expected: TIMEOUT
+
+ [<iframe>: separate response Content-Type: text/html;" text/plain]
+ expected: TIMEOUT
+
+ [<iframe>: separate response Content-Type: text/html */*;charset=gbk]
+ expected: TIMEOUT
+
+ [<iframe>: separate response Content-Type: text/html */*]
expected: FAIL
+ [<iframe>: combined response Content-Type: text/html */*;charset=gbk]
+ expected: TIMEOUT
+
+ [<iframe>: separate response Content-Type: text/html;x=" text/plain]
+ expected: TIMEOUT
+
+ [<iframe>: combined response Content-Type: text/html;" \\" text/plain]
+ expected: TIMEOUT
+
+ [<iframe>: separate response Content-Type: text/html;" \\" text/plain]
+ expected: TIMEOUT
+
+ [<iframe>: combined response Content-Type: text/html;x=" text/plain]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_3.html.ini
index 75d75b4cda2..51f8272a6de 100644
--- a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini
+++ b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_3.html.ini
@@ -1,4 +1,4 @@
-[traverse_the_history_2.html]
+[traverse_the_history_3.html]
[Multiple history traversals, last would be aborted]
expected: FAIL
diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini
index 385376c7321..dc2e45516de 100644
--- a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini
+++ b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini
@@ -1,4 +1,4 @@
-[traverse_the_history_4.html]
+[traverse_the_history_5.html]
[Multiple history traversals, last would be aborted]
expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-img-element/non-active-document.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-img-element/non-active-document.html.ini
new file mode 100644
index 00000000000..8cc42056d34
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/embedded-content/the-img-element/non-active-document.html.ini
@@ -0,0 +1,10 @@
+[non-active-document.html]
+ [DOMParser]
+ expected: FAIL
+
+ [createHTMLDocument]
+ expected: FAIL
+
+ [<template>]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html.ini
deleted file mode 100644
index 178680e5d14..00000000000
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[script-onerror-insertion-point-2.html]
- expected: TIMEOUT
diff --git a/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini b/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini
index 66bd350083b..a56bad443a2 100644
--- a/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini
+++ b/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini
@@ -1,4 +1,5 @@
[realtimeanalyser-fft-scaling.html]
+ expected: TIMEOUT
[X 2048-point FFT peak position is not equal to 64. Got 0.]
expected: FAIL
diff --git a/tests/wpt/metadata/workers/modules/dedicated-worker-options-credentials.html.ini b/tests/wpt/metadata/workers/modules/dedicated-worker-options-credentials.html.ini
index b9bc1e26d74..c2ee9826593 100644
--- a/tests/wpt/metadata/workers/modules/dedicated-worker-options-credentials.html.ini
+++ b/tests/wpt/metadata/workers/modules/dedicated-worker-options-credentials.html.ini
@@ -58,10 +58,10 @@
expected: NOTRUN
[new Worker() with type=module and credentials=omit should not send the credentials]
- expected: NOTRUN
+ expected: FAIL
[new Worker() with type=module and default credentials option should behave as credentials=same-origin and send the credentials for same-origin static imports]
- expected: NOTRUN
+ expected: TIMEOUT
[new Worker() with type=classic should always send the credentials regardless of the credentials option (same-origin).]
expected: NOTRUN
@@ -93,12 +93,3 @@
[new Worker() with type=module and credentials=include should send the credentials for same-origin dynamic imports]
expected: NOTRUN
- [new Worker() with type=module and credentials=same-origin should send the credentials]
- expected: NOTRUN
-
- [new Worker() with type=module and credentials=include should send the credentials]
- expected: NOTRUN
-
- [new Worker() with type=module and default credentials option should behave as credentials=same-origin and send the credentials]
- expected: TIMEOUT
-
diff --git a/tests/wpt/mozilla/meta/css/transition_calc_implicit.html.ini b/tests/wpt/mozilla/meta/css/transition_calc_implicit.html.ini
deleted file mode 100644
index dbea4f293ad..00000000000
--- a/tests/wpt/mozilla/meta/css/transition_calc_implicit.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[transition_calc_implicit.html]
- expected: TIMEOUT
diff --git a/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js b/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js
index 8168d7a39f7..a48b4c59aa8 100644
--- a/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js
+++ b/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js
@@ -7,7 +7,7 @@
//
// --enable-blink-features=MojoJS,MojoJSTest
let loadChromiumResources = Promise.resolve().then(() => {
- if (!MojoInterfaceInterceptor) {
+ if (!window.MojoInterfaceInterceptor) {
// Do nothing on non-Chromium-based browsers or when the Mojo bindings are
// not present in the global namespace.
return;
@@ -37,7 +37,10 @@ async function initialize_generic_sensor_tests() {
if (typeof GenericSensorTest === 'undefined') {
await loadChromiumResources;
}
- assert_true(typeof GenericSensorTest !== 'undefined');
+ assert_true(
+ typeof GenericSensorTest !== 'undefined',
+ 'Mojo testing interface is not available.'
+ );
let sensorTest = new GenericSensorTest();
await sensorTest.initialize();
return sensorTest;
diff --git a/tests/wpt/web-platform-tests/interfaces/webaudio.idl b/tests/wpt/web-platform-tests/interfaces/webaudio.idl
index 4f1914dbae2..4679558023a 100644
--- a/tests/wpt/web-platform-tests/interfaces/webaudio.idl
+++ b/tests/wpt/web-platform-tests/interfaces/webaudio.idl
@@ -551,9 +551,11 @@ dictionary WaveShaperOptions : AudioNodeOptions {
interface AudioWorklet : Worklet {
};
+callback AudioWorkletProcessorConstructor = AudioWorkletProcessor (object options);
+
[Global=(Worklet, AudioWorklet), Exposed=AudioWorklet]
interface AudioWorkletGlobalScope : WorkletGlobalScope {
- void registerProcessor (DOMString name, VoidFunction processorCtor);
+ void registerProcessor (DOMString name, AudioWorkletProcessorConstructor processorCtor);
readonly attribute unsigned long long currentFrame;
readonly attribute double currentTime;
readonly attribute float sampleRate;
diff --git a/tests/wpt/web-platform-tests/tools/lint/lint.py b/tests/wpt/web-platform-tests/tools/lint/lint.py
index ccadcdc16c7..19d0c112186 100644
--- a/tests/wpt/web-platform-tests/tools/lint/lint.py
+++ b/tests/wpt/web-platform-tests/tools/lint/lint.py
@@ -13,6 +13,7 @@ import tempfile
from collections import defaultdict
from . import fnmatch
+from . import rules
from .. import localpaths
from ..gitignore.gitignore import PathFilter
from ..wpt import testfiles
@@ -117,7 +118,7 @@ def _all_files_equal(paths):
def check_path_length(repo_root, path):
if len(path) + 1 > 150:
- return [("PATH LENGTH", "/%s longer than maximum path length (%d > 150)" % (path, len(path) + 1), path, None)]
+ return [rules.PathLength.error(path, (path, len(path) + 1))]
return []
@@ -127,10 +128,7 @@ def check_worker_collision(repo_root, path):
(".worker.html", ".worker.js")]
for path_ending, generated in endings:
if path.endswith(path_ending):
- return [("WORKER COLLISION",
- "path ends with %s which collides with generated tests from %s files" % (path_ending, generated),
- path,
- None)]
+ return [rules.WorkerCollision.error(path, (path_ending, generated))]
return []
@@ -150,16 +148,13 @@ def check_gitignore_file(repo_root, path):
path_parts[:3] == ["css", "tools", "apiclient"]):
return []
- return [("GITIGNORE",
- ".gitignore found outside the root",
- path,
- None)]
+ return [rules.GitIgnoreFile.error(path)]
def check_ahem_copy(repo_root, path):
lpath = path.lower()
if "ahem" in lpath and lpath.endswith(".ttf"):
- return [("AHEM COPY", "Don't add extra copies of Ahem, use /fonts/Ahem.ttf", path, None)]
+ return [rules.AhemCopy.error(path)]
return []
@@ -177,8 +172,7 @@ def check_git_ignore(repo_root, paths):
# If the matching filter reported by check-ignore is a special-case exception,
# that's fine. Otherwise, it requires a new special-case exception.
if filter_string[0] != '!':
- errors += [("IGNORED PATH", "%s matches an ignore filter in .gitignore - "
- "please add a .gitignore exception" % path, path, None)]
+ errors.append(rules.IgnoredPath.error(path, (path,)))
except subprocess.CalledProcessError:
# Nonzero return code means that no match exists.
pass
@@ -264,25 +258,19 @@ def check_css_globally_unique(repo_root, paths):
for spec, paths in iteritems(by_spec):
if not _all_files_equal([os.path.join(repo_root, x) for x in paths]):
for x in paths:
- errors.append(("CSS-COLLIDING-TEST-NAME",
- "The filename %s in the %s testsuite is shared by: %s"
- % (name,
- spec,
- ", ".join(sorted(paths))),
- x,
- None))
-
- for error_name, d in [("CSS-COLLIDING-REF-NAME", ref_files),
- ("CSS-COLLIDING-SUPPORT-NAME", support_files)]:
+ context = (name, spec, ", ".join(sorted(paths)))
+ errors.append(rules.CSSCollidingTestName.error(x,
+ context))
+
+ for rule_class, d in [(rules.CSSCollidingRefName, ref_files),
+ (rules.CSSCollidingSupportName, support_files)]:
for name, colliding in iteritems(d):
if len(colliding) > 1:
if not _all_files_equal([os.path.join(repo_root, x) for x in colliding]):
+ context = (name, ", ".join(sorted(colliding)))
+
for x in colliding:
- errors.append((error_name,
- "The filename %s is shared by: %s" % (name,
- ", ".join(sorted(colliding))),
- x,
- None))
+ errors.append(rule_class.error(x, context))
return errors
@@ -341,102 +329,20 @@ def filter_whitelist_errors(data, errors):
return [item for i, item in enumerate(errors) if not whitelisted[i]]
-class Regexp(object):
- pattern = None
- file_extensions = None
- error = None
- _re = None
-
- def __init__(self):
- self._re = re.compile(self.pattern)
-
- def applies(self, path):
- return (self.file_extensions is None or
- os.path.splitext(path)[1] in self.file_extensions)
-
- def search(self, line):
- return self._re.search(line)
-
-class TrailingWhitespaceRegexp(Regexp):
- pattern = b"[ \t\f\v]$"
- error = "TRAILING WHITESPACE"
- description = "Whitespace at EOL"
-
-class TabsRegexp(Regexp):
- pattern = b"^\t"
- error = "INDENT TABS"
- description = "Tabs used for indentation"
-
-class CRRegexp(Regexp):
- pattern = b"\r$"
- error = "CR AT EOL"
- description = "CR character in line separator"
-
-class SetTimeoutRegexp(Regexp):
- pattern = br"setTimeout\s*\("
- error = "SET TIMEOUT"
- file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
- description = "setTimeout used; step_timeout should typically be used instead"
-
-class W3CTestOrgRegexp(Regexp):
- pattern = br"w3c\-test\.org"
- error = "W3C-TEST.ORG"
- description = "External w3c-test.org domain used"
-
-class WebPlatformTestRegexp(Regexp):
- pattern = br"web\-platform\.test"
- error = "WEB-PLATFORM.TEST"
- description = "Internal web-platform.test domain used"
-
-class Webidl2Regexp(Regexp):
- pattern = br"webidl2\.js"
- error = "WEBIDL2.JS"
- description = "Legacy webidl2.js script used"
-
-class ConsoleRegexp(Regexp):
- pattern = br"console\.[a-zA-Z]+\s*\("
- error = "CONSOLE"
- file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
- description = "Console logging API used"
-
-class GenerateTestsRegexp(Regexp):
- pattern = br"generate_tests\s*\("
- error = "GENERATE_TESTS"
- file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
- description = "generate_tests used"
-
-class PrintRegexp(Regexp):
- pattern = br"print(?:\s|\s*\()"
- error = "PRINT STATEMENT"
- file_extensions = [".py"]
- description = "Print function used"
-
-class LayoutTestsRegexp(Regexp):
- pattern = br"eventSender|testRunner|window\.internals"
- error = "LAYOUTTESTS APIS"
- file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
- description = "eventSender/testRunner/window.internals used; these are LayoutTests-specific APIs (WebKit/Blink)"
-
-class SpecialPowersRegexp(Regexp):
- pattern = b"SpecialPowers"
- error = "SPECIALPOWERS API"
- file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
- description = "SpecialPowers used; this is gecko-specific and not supported in wpt"
-
regexps = [item() for item in
- [TrailingWhitespaceRegexp,
- TabsRegexp,
- CRRegexp,
- SetTimeoutRegexp,
- W3CTestOrgRegexp,
- WebPlatformTestRegexp,
- Webidl2Regexp,
- ConsoleRegexp,
- GenerateTestsRegexp,
- PrintRegexp,
- LayoutTestsRegexp,
- SpecialPowersRegexp]]
+ [rules.TrailingWhitespaceRegexp,
+ rules.TabsRegexp,
+ rules.CRRegexp,
+ rules.SetTimeoutRegexp,
+ rules.W3CTestOrgRegexp,
+ rules.WebPlatformTestRegexp,
+ rules.Webidl2Regexp,
+ rules.ConsoleRegexp,
+ rules.GenerateTestsRegexp,
+ rules.PrintRegexp,
+ rules.LayoutTestsRegexp,
+ rules.SpecialPowersRegexp]]
def check_regexp_line(repo_root, path, f):
errors = []
@@ -446,7 +352,7 @@ def check_regexp_line(repo_root, path, f):
for i, line in enumerate(f):
for regexp in applicable_regexps:
if regexp.search(line):
- errors.append((regexp.error, regexp.description, path, i+1))
+ errors.append((regexp.name, regexp.description, path, i+1))
return errors
@@ -459,12 +365,12 @@ def check_parsed(repo_root, path, f):
if (source_file.type == "support" and
not source_file.name_is_non_test and
not source_file.name_is_reference):
- return [("SUPPORT-WRONG-DIR", "Support file not in support directory", path, None)]
+ return [rules.SupportWrongDir.error(path)]
if (source_file.type != "support" and
not source_file.name_is_reference and
not source_file.spec_links):
- return [("MISSING-LINK", "Testcase file must have a link to a spec", path, None)]
+ return [rules.MissingLink.error(path)]
if source_file.name_is_non_test:
return []
@@ -473,13 +379,13 @@ def check_parsed(repo_root, path, f):
return []
if source_file.root is None:
- return [("PARSE-FAILED", "Unable to parse file", path, None)]
+ return [rules.ParseFailed.error(path)]
if source_file.type == "manual" and not source_file.name_is_manual:
- errors.append(("CONTENT-MANUAL", "Manual test whose filename doesn't end in '-manual'", path, None))
+ errors.append(rules.ContentManual.error(path))
if source_file.type == "visual" and not source_file.name_is_visual:
- errors.append(("CONTENT-VISUAL", "Visual test whose filename doesn't end in '-visual'", path, None))
+ errors.append(rules.ContentVisual.error(path))
about_blank_parts = urlsplit("about:blank")
for reftest_node in source_file.reftest_nodes:
@@ -490,18 +396,14 @@ def check_parsed(repo_root, path, f):
continue
if (parts.scheme or parts.netloc):
- errors.append(("ABSOLUTE-URL-REF",
- "Reference test with a reference file specified via an absolute URL: '%s'" % href, path, None))
+ errors.append(rules.AbsoluteUrlRef.error(path, (href,)))
continue
ref_url = urljoin(source_file.url, href)
ref_parts = urlsplit(ref_url)
if source_file.url == ref_url:
- errors.append(("SAME-FILE-REF",
- "Reference test which points at itself as a reference",
- path,
- None))
+ errors.append(rules.SameFileRef.error(path))
continue
assert ref_parts.path != ""
@@ -510,45 +412,39 @@ def check_parsed(repo_root, path, f):
reference_rel = reftest_node.attrib.get("rel", "")
if not os.path.isfile(reference_file):
- errors.append(("NON-EXISTENT-REF",
- "Reference test with a non-existent '%s' relationship reference: '%s'" % (reference_rel, href), path, None))
+ errors.append(rules.NonexistentRef.error(path,
+ (reference_rel, href)))
if len(source_file.timeout_nodes) > 1:
- errors.append(("MULTIPLE-TIMEOUT", "More than one meta name='timeout'", path, None))
+ errors.append(rules.MultipleTimeout.error(path))
for timeout_node in source_file.timeout_nodes:
timeout_value = timeout_node.attrib.get("content", "").lower()
if timeout_value != "long":
- errors.append(("INVALID-TIMEOUT", "Invalid timeout value %s" % timeout_value, path, None))
+ errors.append(rules.InvalidTimeout.error(path, (timeout_value,)))
if source_file.testharness_nodes:
if len(source_file.testharness_nodes) > 1:
- errors.append(("MULTIPLE-TESTHARNESS",
- "More than one <script src='/resources/testharness.js'>", path, None))
+ errors.append(rules.MultipleTestharness.error(path))
testharnessreport_nodes = source_file.root.findall(".//{http://www.w3.org/1999/xhtml}script[@src='/resources/testharnessreport.js']")
if not testharnessreport_nodes:
- errors.append(("MISSING-TESTHARNESSREPORT",
- "Missing <script src='/resources/testharnessreport.js'>", path, None))
+ errors.append(rules.MissingTestharnessReport.error(path))
else:
if len(testharnessreport_nodes) > 1:
- errors.append(("MULTIPLE-TESTHARNESSREPORT",
- "More than one <script src='/resources/testharnessreport.js'>", path, None))
+ errors.append(rules.MultipleTestharnessReport.error(path))
testharnesscss_nodes = source_file.root.findall(".//{http://www.w3.org/1999/xhtml}link[@href='/resources/testharness.css']")
if testharnesscss_nodes:
- errors.append(("PRESENT-TESTHARNESSCSS",
- "Explicit link to testharness.css present", path, None))
+ errors.append(rules.PresentTestharnessCSS.error(path))
for element in source_file.variant_nodes:
if "content" not in element.attrib:
- errors.append(("VARIANT-MISSING",
- "<meta name=variant> missing 'content' attribute", path, None))
+ errors.append(rules.VariantMissing.error(path))
else:
variant = element.attrib["content"]
if variant != "" and variant[0] not in ("?", "#"):
- errors.append(("MALFORMED-VARIANT",
- "%s <meta name=variant> 'content' attribute must be the empty string or start with '?' or '#'" % path, None))
+ errors.append(rules.MalformedVariant.error(path, (path,)))
seen_elements = {"timeout": False,
"testharness": False,
@@ -562,8 +458,7 @@ def check_parsed(repo_root, path, f):
if source_file.timeout_nodes and elem == source_file.timeout_nodes[0]:
seen_elements["timeout"] = True
if seen_elements["testharness"]:
- errors.append(("LATE-TIMEOUT",
- "<meta name=timeout> seen after testharness.js script", path, None))
+ errors.append(rules.LateTimeout.error(path))
elif elem == source_file.testharness_nodes[0]:
seen_elements["testharness"] = True
@@ -571,46 +466,53 @@ def check_parsed(repo_root, path, f):
elif testharnessreport_nodes and elem == testharnessreport_nodes[0]:
seen_elements["testharnessreport"] = True
if not seen_elements["testharness"]:
- errors.append(("EARLY-TESTHARNESSREPORT",
- "testharnessreport.js script seen before testharness.js script", path, None))
+ errors.append(rules.EarlyTestharnessReport.error(path))
if all(seen_elements[name] for name in required_elements):
break
if source_file.testdriver_nodes:
if len(source_file.testdriver_nodes) > 1:
- errors.append(("MULTIPLE-TESTDRIVER",
- "More than one <script src='/resources/testdriver.js'>", path, None))
+ errors.append(rules.MultipleTestdriver.error(path))
testdriver_vendor_nodes = source_file.root.findall(".//{http://www.w3.org/1999/xhtml}script[@src='/resources/testdriver-vendor.js']")
if not testdriver_vendor_nodes:
- errors.append(("MISSING-TESTDRIVER-VENDOR",
- "Missing <script src='/resources/testdriver-vendor.js'>", path, None))
+ errors.append(rules.MissingTestdriverVendor.error(path))
else:
if len(testdriver_vendor_nodes) > 1:
- errors.append(("MULTIPLE-TESTDRIVER-VENDOR",
- "More than one <script src='/resources/testdriver-vendor.js'>", path, None))
+ errors.append(rules.MultipleTestdriverVendor.error(path))
for element in source_file.root.findall(".//{http://www.w3.org/1999/xhtml}script[@src]"):
src = element.attrib["src"]
- for name in ["testharness", "testharnessreport", "testdriver", "testdriver-vendor"]:
- if "%s.js" % name == src or ("/%s.js" % name in src and src != "/resources/%s.js" % name):
- errors.append(("%s-PATH" % name.upper(), "%s.js script seen with incorrect path" % name, path, None))
+
+ def incorrect_path(script, src):
+ return (script == src or
+ ("/%s" % script in src and src != "/resources/%s" % script))
+
+ if incorrect_path("testharness.js", src):
+ errors.append(rules.TestharnessPath.error(path))
+
+ if incorrect_path("testharnessreport.js", src):
+ errors.append(rules.TestharnessReportPath.error(path))
+
+ if incorrect_path("testdriver.js", src):
+ errors.append(rules.TestdriverPath.error(path))
+
+ if incorrect_path("testdriver-vendor.js", src):
+ errors.append(rules.TestdriverVendorPath.error(path))
return errors
class ASTCheck(object):
__metaclass__ = abc.ABCMeta
- error = None
- description = None
+ rule = None
@abc.abstractmethod
def check(self, root):
pass
class OpenModeCheck(ASTCheck):
- error = "OPEN-NO-MODE"
- description = "File opened without providing an explicit mode (note: binary files must be read with 'b' in the mode flags)"
+ rule = rules.OpenNoMode
def check(self, root):
errors = []
@@ -631,12 +533,12 @@ def check_python_ast(repo_root, path, f):
try:
root = ast.parse(f.read())
except SyntaxError as e:
- return [("PARSE-FAILED", "Unable to parse file", path, e.lineno)]
+ return [rules.ParseFailed.error(path, line_no=e.lineno)]
errors = []
for checker in ast_checkers:
for lineno in checker.check(root):
- errors.append((checker.error, checker.description, path, lineno))
+ errors.append(checker.rule.error(path, line_no=lineno))
return errors
@@ -654,19 +556,21 @@ def check_global_metadata(value):
if global_value.startswith(b"!"):
excluded_value = global_value[1:]
if not get_any_variants(excluded_value):
- yield ("UNKNOWN-GLOBAL-METADATA", "Unexpected value for global metadata")
+ yield (rules.UnknownGlobalMetadata, ())
elif excluded_value in global_values:
- yield ("BROKEN-GLOBAL-METADATA", "Cannot specify both %s and %s" % (global_value, excluded_value))
+ yield (rules.BrokenGlobalMetadata,
+ ("Cannot specify both %s and %s" % (global_value, excluded_value)))
else:
excluded_variants = get_any_variants(excluded_value)
if not (excluded_variants & included_variants):
- yield ("BROKEN-GLOBAL-METADATA", "Cannot exclude %s if it is not included" % (excluded_value,))
+ yield (rules.BrokenGlobalMetadata,
+ ("Cannot exclude %s if it is not included" % (excluded_value,)))
else:
if not get_any_variants(global_value):
- yield ("UNKNOWN-GLOBAL-METADATA", "Unexpected value for global metadata")
+ yield (rules.UnknownGlobalMetadata, ())
def check_script_metadata(repo_root, path, f):
@@ -688,10 +592,12 @@ def check_script_metadata(repo_root, path, f):
if m:
key, value = m.groups()
if key == b"global":
- errors.extend((kind, message, path, idx + 1) for (kind, message) in check_global_metadata(value))
+ for rule_class, context in check_global_metadata(value):
+ errors.append(rule_class.error(path, context, idx + 1))
elif key == b"timeout":
if value != b"long":
- errors.append(("UNKNOWN-TIMEOUT-METADATA", "Unexpected value for timeout metadata", path, idx + 1))
+ errors.append(rules.UnknownTimeoutMetadata.error(path,
+ line_no=idx + 1))
elif key == b"title":
pass
elif key == b"script":
@@ -699,17 +605,19 @@ def check_script_metadata(repo_root, path, f):
elif key == b"variant":
pass
else:
- errors.append(("UNKNOWN-METADATA", "Unexpected kind of metadata", path, idx + 1))
+ errors.append(rules.UnknownMetadata.error(path,
+ line_no=idx + 1))
else:
done = True
if done:
if meta_re.match(line):
- errors.append(("STRAY-METADATA", "Metadata comments should start the file", path, idx + 1))
+ errors.append(rules.StrayMetadata.error(path, line_no=idx + 1))
elif meta_re.search(line):
- errors.append(("INDENTED-METADATA", "Metadata comments should start the line", path, idx + 1))
+ errors.append(rules.IndentedMetadata.error(path,
+ line_no=idx + 1))
elif broken_metadata.search(line):
- errors.append(("BROKEN-METADATA", "Metadata comment is not formatted correctly", path, idx + 1))
+ errors.append(rules.BrokenMetadata.error(path, line_no=idx + 1))
return errors
diff --git a/tests/wpt/web-platform-tests/tools/lint/rules.py b/tests/wpt/web-platform-tests/tools/lint/rules.py
new file mode 100644
index 00000000000..78f9d072a8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/lint/rules.py
@@ -0,0 +1,316 @@
+from __future__ import unicode_literals
+import os
+import re
+
+class Rule(object):
+ name = None
+ description = None
+ to_fix = None
+
+ @classmethod
+ def error(cls, path, context=(), line_no=None):
+ description = cls.description % context
+ return (cls.name, description, path, line_no)
+
+
+class MissingLink(Rule):
+ name = "MISSING-LINK"
+ description = "Testcase file must have a link to a spec"
+ to_fix = """
+ Ensure that there is a `<link rel="help" href="[url]">` for the spec.
+ `MISSING-LINK` is designed to ensure that the CSS build tool can find
+ the tests. Note that the CSS build system is primarily used by
+ [test.csswg.org/](http://test.csswg.org/), which doesn't use
+ `wptserve`, so `*.any.js` and similar tests won't work there; stick
+ with the `.html` equivalent.
+ """
+
+
+class PathLength(Rule):
+ name = "PATH LENGTH"
+ description = "/%s longer than maximum path length (%d > 150)"
+
+
+class WorkerCollision(Rule):
+ name = "WORKER COLLISION"
+ description = ("path ends with %s which collides with generated tests "
+ "from %s files")
+
+
+class GitIgnoreFile(Rule):
+ name = "GITIGNORE"
+ description = ".gitignore found outside the root"
+
+
+class AhemCopy(Rule):
+ name = "AHEM COPY"
+ description = "Don't add extra copies of Ahem, use /fonts/Ahem.ttf"
+
+
+# TODO: Add tests for this rule
+class IgnoredPath(Rule):
+ name = "IGNORED PATH"
+ description = ("%s matches an ignore filter in .gitignore - "
+ "please add a .gitignore exception")
+
+
+class CSSCollidingTestName(Rule):
+ name = "CSS-COLLIDING-TEST-NAME"
+ description = "The filename %s in the %s testsuite is shared by: %s"
+
+
+class CSSCollidingRefName(Rule):
+ name = "CSS-COLLIDING-REF-NAME"
+ description = "The filename %s is shared by: %s"
+
+
+class CSSCollidingSupportName(Rule):
+ name = "CSS-COLLIDING-SUPPORT-NAME"
+ description = "The filename %s is shared by: %s"
+
+
+class SupportWrongDir(Rule):
+ name = "SUPPORT-WRONG-DIR"
+ description = "Support file not in support directory"
+
+
+class ParseFailed(Rule):
+ name = "PARSE-FAILED"
+ description = "Unable to parse file"
+
+
+class ContentManual(Rule):
+ name = "CONTENT-MANUAL"
+ description = "Manual test whose filename doesn't end in '-manual'"
+
+
+class ContentVisual(Rule):
+ name = "CONTENT-VISUAL"
+ description = "Visual test whose filename doesn't end in '-visual'"
+
+
+class AbsoluteUrlRef(Rule):
+ name = "ABSOLUTE-URL-REF"
+ description = ("Reference test with a reference file specified via an "
+ "absolute URL: '%s'")
+
+
+class SameFileRef(Rule):
+ name = "SAME-FILE-REF"
+ description = "Reference test which points at itself as a reference"
+
+
+class NonexistentRef(Rule):
+ name = "NON-EXISTENT-REF"
+ description = ("Reference test with a non-existent '%s' relationship "
+ "reference: '%s'")
+
+
+class MultipleTimeout(Rule):
+ name = "MULTIPLE-TIMEOUT"
+ description = "More than one meta name='timeout'"
+
+
+class InvalidTimeout(Rule):
+ name = "INVALID-TIMEOUT"
+ description = "Invalid timeout value %s"
+
+
+class MultipleTestharness(Rule):
+ name = "MULTIPLE-TESTHARNESS"
+ description = "More than one <script src='/resources/testharness.js'>"
+
+
+class MissingTestharnessReport(Rule):
+ name = "MISSING-TESTHARNESSREPORT"
+ description = "Missing <script src='/resources/testharnessreport.js'>"
+
+
+class MultipleTestharnessReport(Rule):
+ name = "MULTIPLE-TESTHARNESSREPORT"
+ description = "More than one <script src='/resources/testharnessreport.js'>"
+
+
+class PresentTestharnessCSS(Rule):
+ name = "PRESENT-TESTHARNESSCSS"
+ description = "Explicit link to testharness.css present"
+
+
+class VariantMissing(Rule):
+ name = "VARIANT-MISSING"
+ description = "<meta name=variant> missing 'content' attribute"
+
+
+class MalformedVariant(Rule):
+ name = "MALFORMED-VARIANT"
+ description = ("%s <meta name=variant> 'content' attribute must be the "
+ "empty string or start with '?' or '#'")
+
+
+class LateTimeout(Rule):
+ name = "LATE-TIMEOUT"
+ description = "<meta name=timeout> seen after testharness.js script"
+
+
+class EarlyTestharnessReport(Rule):
+ name = "EARLY-TESTHARNESSREPORT"
+ description = "testharnessreport.js script seen before testharness.js script"
+
+
+class MultipleTestdriver(Rule):
+ name = "MULTIPLE-TESTDRIVER"
+ description = "More than one <script src='/resources/testdriver.js'>"
+
+
+class MissingTestdriverVendor(Rule):
+ name = "MISSING-TESTDRIVER-VENDOR"
+ description = "Missing <script src='/resources/testdriver-vendor.js'>"
+
+
+class MultipleTestdriverVendor(Rule):
+ name = "MULTIPLE-TESTDRIVER-VENDOR"
+ description = "More than one <script src='/resources/testdriver-vendor.js'>"
+
+
+class TestharnessPath(Rule):
+ name = "TESTHARNESS-PATH"
+ description = "testharness.js script seen with incorrect path"
+
+
+class TestharnessReportPath(Rule):
+ name = "TESTHARNESSREPORT-PATH"
+ description = "testharnessreport.js script seen with incorrect path"
+
+
+class TestdriverPath(Rule):
+ name = "TESTDRIVER-PATH"
+ description = "testdriver.js script seen with incorrect path"
+
+
+class TestdriverVendorPath(Rule):
+ name = "TESTDRIVER-VENDOR-PATH"
+ description = "testdriver-vendor.js script seen with incorrect path"
+
+
+class OpenNoMode(Rule):
+ name = "OPEN-NO-MODE"
+ description = "File opened without providing an explicit mode (note: binary files must be read with 'b' in the mode flags)"
+
+
+class UnknownGlobalMetadata(Rule):
+ name = "UNKNOWN-GLOBAL-METADATA"
+ description = "Unexpected value for global metadata"
+
+
+class BrokenGlobalMetadata(Rule):
+ name = "BROKEN-GLOBAL-METADATA"
+ description = "Invalid global metadata: %s"
+
+
+class UnknownTimeoutMetadata(Rule):
+ name = "UNKNOWN-TIMEOUT-METADATA"
+ description = "Unexpected value for timeout metadata"
+
+
+class UnknownMetadata(Rule):
+ name = "UNKNOWN-METADATA"
+ description = "Unexpected kind of metadata"
+
+
+class StrayMetadata(Rule):
+ name = "STRAY-METADATA"
+ description = "Metadata comments should start the file"
+
+
+class IndentedMetadata(Rule):
+ name = "INDENTED-METADATA"
+ description = "Metadata comments should start the line"
+
+
+class BrokenMetadata(Rule):
+ name = "BROKEN-METADATA"
+ description = "Metadata comment is not formatted correctly"
+
+
+class Regexp(Rule):
+ pattern = None
+ file_extensions = None
+ _re = None
+
+ def __init__(self):
+ self._re = re.compile(self.pattern)
+
+ def applies(self, path):
+ return (self.file_extensions is None or
+ os.path.splitext(path)[1] in self.file_extensions)
+
+ def search(self, line):
+ return self._re.search(line)
+
+
+class TabsRegexp(Regexp):
+ pattern = b"^\t"
+ name = "INDENT TABS"
+ description = "Tabs used for indentation"
+
+class CRRegexp(Regexp):
+ pattern = b"\r$"
+ name = "CR AT EOL"
+ description = "CR character in line separator"
+
+class SetTimeoutRegexp(Regexp):
+ pattern = br"setTimeout\s*\("
+ name = "SET TIMEOUT"
+ file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
+ description = "setTimeout used; step_timeout should typically be used instead"
+
+class W3CTestOrgRegexp(Regexp):
+ pattern = br"w3c\-test\.org"
+ name = "W3C-TEST.ORG"
+ description = "External w3c-test.org domain used"
+
+class WebPlatformTestRegexp(Regexp):
+ pattern = br"web\-platform\.test"
+ name = "WEB-PLATFORM.TEST"
+ description = "Internal web-platform.test domain used"
+
+class Webidl2Regexp(Regexp):
+ pattern = br"webidl2\.js"
+ name = "WEBIDL2.JS"
+ description = "Legacy webidl2.js script used"
+
+class ConsoleRegexp(Regexp):
+ pattern = br"console\.[a-zA-Z]+\s*\("
+ name = "CONSOLE"
+ file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
+ description = "Console logging API used"
+
+class GenerateTestsRegexp(Regexp):
+ pattern = br"generate_tests\s*\("
+ name = "GENERATE_TESTS"
+ file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
+ description = "generate_tests used"
+
+class PrintRegexp(Regexp):
+ pattern = br"print(?:\s|\s*\()"
+ name = "PRINT STATEMENT"
+ file_extensions = [".py"]
+ description = "Print function used"
+
+class LayoutTestsRegexp(Regexp):
+ pattern = br"eventSender|testRunner|window\.internals"
+ name = "LAYOUTTESTS APIS"
+ file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
+ description = "eventSender/testRunner/window.internals used; these are LayoutTests-specific APIs (WebKit/Blink)"
+
+class SpecialPowersRegexp(Regexp):
+ pattern = b"SpecialPowers"
+ name = "SPECIALPOWERS API"
+ file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
+ description = "SpecialPowers used; this is gecko-specific and not supported in wpt"
+
+class TrailingWhitespaceRegexp(Regexp):
+ name = "TRAILING WHITESPACE"
+ description = "Whitespace at EOL"
+ pattern = b"[ \t\f\v]$"
+ to_fix = """Remove trailing whitespace from all lines in the file."""
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py b/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py
index 28ccacc8787..ddf03986e10 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py
@@ -296,6 +296,79 @@ def test_multiple_testharnessreport():
]
+def test_multiple_testdriver():
+ code = b"""
+<html xmlns="http://www.w3.org/1999/xhtml">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+</html>
+"""
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ if kind in ["web-lax", "web-strict"]:
+ assert errors == [
+ ("MULTIPLE-TESTDRIVER", "More than one <script src='/resources/testdriver.js'>", filename, None),
+ ]
+ elif kind == "python":
+ assert errors == [
+ ("PARSE-FAILED", "Unable to parse file", filename, 2),
+ ]
+
+
+def test_multiple_testdriver_vendor():
+ code = b"""
+<html xmlns="http://www.w3.org/1999/xhtml">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+</html>
+"""
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ if kind in ["web-lax", "web-strict"]:
+ assert errors == [
+ ("MULTIPLE-TESTDRIVER-VENDOR", "More than one <script src='/resources/testdriver-vendor.js'>", filename, None),
+ ]
+ elif kind == "python":
+ assert errors == [
+ ("PARSE-FAILED", "Unable to parse file", filename, 2),
+ ]
+
+
+def test_missing_testdriver_vendor():
+ code = b"""
+<html xmlns="http://www.w3.org/1999/xhtml">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+</html>
+"""
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ if kind in ["web-lax", "web-strict"]:
+ assert errors == [
+ ("MISSING-TESTDRIVER-VENDOR", "Missing <script src='/resources/testdriver-vendor.js'>", filename, None),
+ ]
+ elif kind == "python":
+ assert errors == [
+ ("PARSE-FAILED", "Unable to parse file", filename, 2),
+ ]
+
+
def test_present_testharnesscss():
code = b"""
<html xmlns="http://www.w3.org/1999/xhtml">
@@ -373,12 +446,81 @@ def test_testharnessreport_path():
assert errors == expected
+def test_testdriver_path():
+ code = b"""\
+<html xmlns="http://www.w3.org/1999/xhtml">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="testdriver.js"></script>
+<script src="/elsewhere/testdriver.js"></script>
+<script src="/elsewhere/resources/testdriver.js"></script>
+<script src="/resources/elsewhere/testdriver.js"></script>
+<script src="../resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+</html>
+"""
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ expected = []
+ if kind == "python":
+ expected.append(("PARSE-FAILED", "Unable to parse file", filename, 1))
+ elif kind in ["web-lax", "web-strict"]:
+ expected.extend([
+ ("TESTDRIVER-PATH", "testdriver.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-PATH", "testdriver.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-PATH", "testdriver.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-PATH", "testdriver.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-PATH", "testdriver.js script seen with incorrect path", filename, None)
+ ])
+ assert errors == expected
+
+
+def test_testdriver_vendor_path():
+ code = b"""\
+<html xmlns="http://www.w3.org/1999/xhtml">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="testdriver-vendor.js"></script>
+<script src="/elsewhere/testdriver-vendor.js"></script>
+<script src="/elsewhere/resources/testdriver-vendor.js"></script>
+<script src="/resources/elsewhere/testdriver-vendor.js"></script>
+<script src="../resources/testdriver-vendor.js"></script>
+</html>
+"""
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ if kind == "python":
+ expected = set([("PARSE-FAILED", "Unable to parse file", filename, 1)])
+ elif kind in ["web-lax", "web-strict"]:
+ expected = set([
+ ("MISSING-TESTDRIVER-VENDOR", "Missing <script src='/resources/testdriver-vendor.js'>", filename, None),
+ ("TESTDRIVER-VENDOR-PATH", "testdriver-vendor.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-VENDOR-PATH", "testdriver-vendor.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-VENDOR-PATH", "testdriver-vendor.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-VENDOR-PATH", "testdriver-vendor.js script seen with incorrect path", filename, None),
+ ("TESTDRIVER-VENDOR-PATH", "testdriver-vendor.js script seen with incorrect path", filename, None)
+ ])
+ else:
+ expected = set()
+
+ assert set(errors) == expected
+
+
def test_not_testharness_path():
code = b"""\
<html xmlns="http://www.w3.org/1999/xhtml">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/webperftestharness.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
</html>
"""
error_map = check_with_files(code)
@@ -394,6 +536,79 @@ def test_not_testharness_path():
assert errors == []
+def test_variant_missing():
+ code = b"""\
+<html xmlns="http://www.w3.org/1999/xhtml">
+<meta name="variant">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</html>
+"""
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ if kind == "python":
+ assert errors == [
+ ("PARSE-FAILED", "Unable to parse file", filename, 1),
+ ]
+ elif kind == "web-lax":
+ assert errors == [
+ ("VARIANT-MISSING", "<meta name=variant> missing 'content' attribute", filename, None)
+ ]
+
+
+# A corresponding "positive" test cannot be written because the manifest
+# SourceFile implementation raises a runtime exception for the condition this
+# linting rule describes
+@pytest.mark.parametrize("content", ["",
+ "?"
+ "#"])
+def test_variant_malformed_negative(content):
+ code = """\
+<html xmlns="http://www.w3.org/1999/xhtml">
+<meta name="variant" content="{}">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</html>
+""".format(content).encode("utf-8")
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ if kind == "python":
+ assert errors == [
+ ("PARSE-FAILED", "Unable to parse file", filename, 1),
+ ]
+ elif kind == "web-lax":
+ assert errors == []
+
+
+def test_late_timeout():
+ code = b"""\
+<html xmlns="http://www.w3.org/1999/xhtml">
+<script src="/resources/testharness.js"></script>
+<meta name="timeout" content="long">
+<script src="/resources/testharnessreport.js"></script>
+</html>
+"""
+ error_map = check_with_files(code)
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ if kind == "python":
+ assert errors == [
+ ("PARSE-FAILED", "Unable to parse file", filename, 1),
+ ]
+ elif kind == "web-lax":
+ assert errors == [
+ ("LATE-TIMEOUT", "<meta name=timeout> seen after testharness.js script", filename, None)
+ ]
+
+
@pytest.mark.skipif(six.PY3, reason="Cannot parse print statements from python 3")
def test_print_statement():
error_map = check_with_files(b"def foo():\n print 'statement'\n print\n")
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py b/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py
index bf8418d52a0..ab44c559187 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py
@@ -38,3 +38,61 @@ def test_forbidden_path_endings(path_ending, generated):
errors = check_path("/foo/", path)
check_errors(errors)
assert errors == [("WORKER COLLISION", message, path, None)]
+
+
+@pytest.mark.parametrize("path", ["ahem.ttf",
+ "Ahem.ttf",
+ "ahem.tTf",
+ "not-ahem.ttf",
+ "support/ahem.ttf",
+ "ahem/other.ttf"])
+def test_ahem_copy(path):
+ expected_error = ("AHEM COPY",
+ "Don't add extra copies of Ahem, use /fonts/Ahem.ttf",
+ path,
+ None)
+
+ errors = check_path("/foo/", path)
+
+ assert errors == [expected_error]
+
+@pytest.mark.parametrize("path", ["ahem.woff",
+ "ahem.ttff",
+ "support/ahem.woff",
+ "ahem/other.woff"])
+def test_ahem_copy_negative(path):
+ errors = check_path("/foo/", path)
+
+ assert errors == []
+
+@pytest.mark.parametrize("path", ["elsewhere/.gitignore",
+ "else/where/.gitignore"
+ "elsewhere/tools/.gitignore",
+ "elsewhere/docs/.gitignore",
+ "elsewhere/resources/webidl2/.gitignore",
+ "elsewhere/css/tools/apiclient/.gitignore"])
+def test_gitignore_file(path):
+ expected_error = ("GITIGNORE",
+ ".gitignore found outside the root",
+ path,
+ None)
+
+ errors = check_path("/foo/", path)
+
+ assert errors == [expected_error]
+
+@pytest.mark.parametrize("path", [".gitignore",
+ "elsewhere/.gitignores",
+ "elsewhere/name.gitignore",
+ "tools/.gitignore",
+ "tools/elsewhere/.gitignore",
+ "docs/.gitignore"
+ "docs/elsewhere/.gitignore",
+ "resources/webidl2/.gitignore",
+ "resources/webidl2/elsewhere/.gitignore",
+ "css/tools/apiclient/.gitignore",
+ "css/tools/apiclient/elsewhere/.gitignore"])
+def test_gitignore_negative(path):
+ errors = check_path("/foo/", path)
+
+ assert errors == []
diff --git a/tests/wpt/web-platform-tests/workers/modules/resources/credentials.py b/tests/wpt/web-platform-tests/workers/modules/resources/credentials.py
index 7623d849625..fb1c7fe96cb 100644
--- a/tests/wpt/web-platform-tests/workers/modules/resources/credentials.py
+++ b/tests/wpt/web-platform-tests/workers/modules/resources/credentials.py
@@ -2,9 +2,12 @@ def main(request, response):
cookie = request.cookies.first("COOKIE_NAME", None)
response_headers = [("Content-Type", "text/javascript"),
- ("Access-Control-Allow-Origin", request.headers.get("Origin")),
("Access-Control-Allow-Credentials", "true")]
+ origin = request.headers.get("Origin", None)
+ if origin:
+ response_headers.append(("Access-Control-Allow-Origin", origin))
+
cookie_value = '';
if cookie:
cookie_value = cookie.value;