#!/usr/bin/env python3
# Usage: python3 generate.py
#
# This will remove all existing .html files in the generated directories and generate new tests.
# Notes on potential confusion with the 3 string substitution features in different layers:
#
# - In Python strings when calling .format(): {something} or {}
# To get a literal {} use {{}}.
# The template_* variables are ones below are those that will use .format().
# https://docs.python.org/3/library/string.html#formatstrings
# - JS template literals: ${something}
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
# - wptserve server-side substitution when generating a response: {{GET[something]}}
# https://web-platform-tests.org/writing-tests/server-pipes.html#sub
import os, shutil
target_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/generated"
delay = u'1500' # Lower value makes the test complete faster, but also higher risk of flaky results
# Test data
tentative_tests = [
# title,
# encoding,
# template_testcase_markup,
# template_nonspeculative_testcase_markup (if different from template_testcase_markup),
# expect_load,
# test_nonspeculative
(
u'script-src',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'meta-charset-script-src',
None,
u'',
u'',
u'true',
u'true'
),
(
# This test is only valid on "mobile" where meta viewport has an effect
u'meta-viewport-link-stylesheet-media',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'meta-csp-img-src-none',
u'utf-8',
u'
',
None,
u'false',
u'true'
),
(
u'meta-csp-img-src-asterisk',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'meta-referrer-no-referrer-img-src',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'base-href-script-src',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'script-src-unsupported-type',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'script-src-type-application-ecmascript',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'script-src-nomodule',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'script-src-module',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'script-src-async',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'script-src-defer',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'script-src-crossorigin',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'script-src-integrity',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'script-src-referrerpolicy-no-referrer',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'template-script-src',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'template-link-stylesheet',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'template-img-src',
u'utf-8',
u'
',
None,
u'false',
u'true'
),
(
u'template-shadowrootmode-script-src',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'template-shadowrootmode-link-stylesheet',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'template-shadowrootmode-img-src',
u'utf-8',
u'![]({})
',
None,
u'true',
u'true'
),
(
u'nested-template-shadowrootmode-1',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'nested-template-shadowrootmode-2',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'link-no-rel',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'link-rel-stylesheet',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-alternate-stylesheet',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'link-rel-stylesheet-disabled',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'link-rel-stylesheet-nomatch-media',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'link-rel-stylesheet-unsupported-type',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'link-rel-stylesheet-type-text-css',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-stylesheet-crossorigin',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-stylesheet-integrity',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-stylesheet-referrerpolicy-no-referrer',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-preload-as-style',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-preload-as-font-crossorigin',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-preload-as-script',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'link-rel-preload-as-image',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'img-src',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'img-data-src',
u'utf-8',
u'
',
None,
u'false',
u'true'
),
(
# is turned into
in the tree builder
u'image-src',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'img-srcset',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'img-src-crossorigin',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'img-src-referrerpolicy-no-referrer',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'img-src-loading-lazy',
u'utf-8',
u'
',
None,
u'false',
u'false'
),
(
u'picture-source-unsupported-type',
u'utf-8',
u'
',
None,
u'false',
u'true'
),
(
u'picture-source-nomatch-media',
u'utf-8',
u'
',
None,
u'false',
u'true'
),
(
u'picture-source-no-img',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'picture-source-br-img',
u'utf-8',
u'
',
None,
u'true',
u'true'
),
(
u'video-poster',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'xmp-script-src',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
# MathML doesn't have script
u'math-script-src',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'math-font-script-src',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
# This breaks out of foreign content, so the script is an HTML script
# https://html.spec.whatwg.org/multipage/#parsing-main-inforeign
u'math-font-face-script-src',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'svg-script-href',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'svg-script-xlinkhref',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
# SVG script element doesn't have a src attribute
u'svg-script-src',
u'utf-8',
u'',
None,
u'false',
u'true'
),
(
u'svg-image-href',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
u'svg-image-xlinkhref',
u'utf-8',
u'',
None,
u'true',
u'true'
),
(
# SVG image element doesn't have a src attribute
u'svg-image-src',
u'utf-8',
u'',
None,
u'false',
u'true'
),
]
tests = [
# title,
# encoding,
# template_testcase_markup,
# expect_load,
# test_nonspeculative
]
# Templates
preamble = u"""
"""
no_meta_charset = u"""
"""
# Notes on `encodingcheck` in the URL below
#
# - Ğ is the HTML character reference for U+011E LATIN CAPITAL LETTER G WITH BREVE
# - In windows-1254, this character is encoded as 0xD0.
# When used in the query part of a URL, it gets percent-encoded as %D0.
# - In windows-1252 (usually the fallback encoding), that character can't be encoded, so is instead
# represented as Ğ percent-encoded, so %26%23286%3B.
# https://url.spec.whatwg.org/#query-state
# https://url.spec.whatwg.org/#code-point-percent-encode-after-encoding
# - In utf-8, it's percent-encoded as utf-8: %C4%9E
# - stash.py will store this value as "param-encodingcheck"
url_wptserve_sub = u"/html/syntax/speculative-parsing/resources/stash.py?action=put&uuid={{GET[uuid]}}&encodingcheck=Ğ"
url_js_sub = u"/html/syntax/speculative-parsing/resources/stash.py?action=put&uuid=${uuid}&encodingcheck=Ğ"
# Non-speculative (normal) case to compare results with
template_nonspeculative = u"""{preamble}
{encoding_decl}
Speculative parsing, non-speculative (helper file): {title}
{nonspeculative_testcase_markup}
"""
# Scenario: page load
template_pageload_toplevel = u"""{preamble}
{encoding_decl}
Speculative parsing, page load: {title}
"""
template_pageload_framed = u"""{preamble}
{encoding_decl}
Speculative parsing, page load (helper file): {title}
{testcase_markup}
"""
# Scenario: document.write()
template_docwrite = u"""{preamble}
{encoding_decl}
Speculative parsing, document.write(): {title}
"""
# Scenario: - TODO(zcorpan)
template_prerender_toplevel = u"""{preamble}
{encoding_decl}
Speculative parsing, prerender: {title}
...
"""
template_prerender_linked = u"""{preamble}
{encoding_decl}
Speculative parsing, prerender (helper file): {title}
...
"""
# Generate tests
# wipe target_dir of HTML files
if os.path.isdir(target_dir):
for root, dirs, files in os.walk(target_dir):
for name in files:
if name.endswith('.html'):
path = os.path.join(root, name)
if os.path.isfile(path):
os.remove(path)
def write_file(path, content):
path = os.path.join(target_dir, path)
os.makedirs(os.path.dirname(path), exist_ok=True)
file = open(os.path.join(target_dir, path), 'w')
file.write(content)
file.close()
def generate_tests(testcase, tentative):
title, encoding, template_testcase_markup, template_nonspeculative_testcase_markup, expect_load, test_nonspeculative = testcase
if template_nonspeculative_testcase_markup == None:
template_nonspeculative_testcase_markup = template_testcase_markup
ext = u""
if tentative:
ext = u".tentative"
if encoding == None:
encoding_decl = no_meta_charset
else:
encoding_decl = f""
html_testcase_markup = template_testcase_markup.format(url_wptserve_sub)
html_nonspeculative_testcase_markup = template_nonspeculative_testcase_markup.format(url_wptserve_sub)
js_testcase_markup = template_testcase_markup.format(url_js_sub).replace(u"", u"<\\/script>").replace(u"