Auto merge of #27401 - servo-wpt-sync:wpt_update_25-07-2020, r=servo-wpt-sync

Sync WPT with upstream (25-07-2020)

Automated downstream sync of changes from upstream as of 25-07-2020.
[no-wpt-sync]
r? @servo-wpt-sync
This commit is contained in:
bors-servo 2020-07-25 06:33:29 -04:00 committed by GitHub
commit fa9b077e84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
85 changed files with 697 additions and 264 deletions

View file

@ -1,4 +0,0 @@
[hit-test-floats-003.html]
[Miss float below something else]
expected: FAIL

View file

@ -1,4 +0,0 @@
[hit-test-floats-004.html]
[Miss float below something else]
expected: FAIL

View file

@ -0,0 +1,4 @@
[hit-test-floats-005.html]
[Miss clipped float]
expected: FAIL

View file

@ -11,33 +11,6 @@
[[data-expected-height\] 2]
expected: FAIL
[[data-expected-height\] 1]
expected: FAIL
[[data-expected-height\] 10]
expected: FAIL
[[data-expected-height\] 2]
expected: FAIL
[[data-expected-height\] 5]
expected: FAIL
[[data-expected-height\] 6]
expected: FAIL
[[data-expected-height\] 9]
expected: FAIL
[[data-expected-height\] 8]
expected: FAIL
[[data-expected-height\] 13]
expected: FAIL
[[data-expected-height\] 12]
expected: FAIL
[[data-expected-height\] 11]
[[data-expected-height\] 4]
expected: FAIL

View file

@ -2,3 +2,6 @@
[Hit test intersecting scaled box]
expected: FAIL
[Hit test within unscaled box]
expected: FAIL

View file

@ -0,0 +1,4 @@
[CaretPosition-001.html]
[Element at (400, 100)]
expected: FAIL

View file

@ -2,3 +2,6 @@
[listeners are called when <iframe> is resized]
expected: FAIL
[listeners are called correct number of times]
expected: FAIL

View file

@ -1,4 +0,0 @@
[elementFromPoint-001.html]
[CSSOM View - 5 - extensions to the Document interface]
expected: FAIL

View file

@ -2,3 +2,6 @@
[elementsFromPoint on the root document for points in iframe elements]
expected: FAIL
[elementsFromPoint on inner documents]
expected: FAIL

View file

@ -315,15 +315,6 @@
[<iframe>: separate response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/plain */*]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html */*]
expected: FAIL
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
expected: FAIL
@ -336,6 +327,6 @@
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
expected: FAIL

View file

@ -53,6 +53,3 @@
[combined text/javascript ]
expected: FAIL
[separate text/javascript x/x]
expected: FAIL

View file

@ -11,3 +11,9 @@
[X-Content-Type-Options%3A%20nosniff%2C%2C%40%23%24%23%25%25%26%5E%26%5E*()()11!]
expected: FAIL
[X-Content-Type-Options%3A%20%22nosniFF%22]
expected: FAIL
[X-Content-Type-Options%3A%20%40%23%24%23%25%25%26%5E%26%5E*()()11!%2Cnosniff]
expected: FAIL

View file

@ -1,4 +0,0 @@
[traverse_the_history_1.html]
[Multiple history traversals from the same task]
expected: FAIL

View file

@ -0,0 +1,4 @@
[traverse_the_history_2.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -1,2 +0,0 @@
[cross-origin-objects-on-new-window.html]
expected: TIMEOUT

View file

@ -1,8 +1,7 @@
[embedded-opener-remove-frame.html]
expected: CRASH
[opener of discarded nested browsing context]
expected: FAIL
[opener of discarded auxiliary browsing context]
expected: TIMEOUT
expected: FAIL

View file

@ -1,16 +1,20 @@
[supported-elements.html]
expected: TIMEOUT
[Contenteditable element should support autofocus]
expected: FAIL
expected: TIMEOUT
[Host element with delegatesFocus including no focusable descendants should be skipped]
expected: FAIL
expected: NOTRUN
[Element with tabindex should support autofocus]
expected: FAIL
expected: NOTRUN
[Area element should support autofocus]
expected: FAIL
expected: NOTRUN
[Host element with delegatesFocus should support autofocus]
expected: FAIL
expected: NOTRUN
[Non-HTMLElement should not support autofocus]
expected: NOTRUN

View file

@ -1,5 +1,5 @@
[iframe_sandbox_popups_escaping-2.html]
expected: CRASH
expected: TIMEOUT
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT

View file

@ -1,5 +1,4 @@
[iframe_sandbox_popups_escaping-3.html]
expected: TIMEOUT
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT
expected: FAIL

View file

@ -1,5 +1,5 @@
[iframe_sandbox_popups_nonescaping-2.html]
expected: TIMEOUT
expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox]
expected: NOTRUN

View file

@ -1,5 +1,4 @@
[iframe_sandbox_popups_nonescaping-3.html]
expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox]
expected: FAIL

View file

@ -1,4 +0,0 @@
[module-static-import-delayed.html]
[document.write in an imported module]
expected: FAIL

View file

@ -1,5 +1,5 @@
[ignore-opens-during-unload.window.html]
expected: TIMEOUT
expected: CRASH
[document.open should bail out when ignore-opens-during-unload is greater than 0 during visibilitychange event (open(parent) while unloading parent and child)]
expected: TIMEOUT

View file

@ -1,10 +1,9 @@
[promise-job-entry.html]
expected: TIMEOUT
[Fulfillment handler on fulfilled promise]
expected: FAIL
[Rejection handler on pending-then-rejected promise]
expected: TIMEOUT
expected: FAIL
[Sanity check: this all works as expected with no promises involved]
expected: FAIL
@ -16,5 +15,5 @@
expected: FAIL
[Fulfillment handler on pending-then-fulfilled promise]
expected: TIMEOUT
expected: FAIL

View file

@ -0,0 +1,8 @@
[promise-rejection-events.html]
expected: TIMEOUT
[delayed handling: delaying handling rejected promise created from createImageBitmap will cause both events to fire]
expected: TIMEOUT
[unhandledrejection: from createImageBitmap which is UA triggered]
expected: FAIL

View file

@ -1,2 +1,4 @@
[resource_initiator_types.html]
expected: TIMEOUT
[Testing resource entries]
expected: FAIL

View file

@ -1,5 +0,0 @@
[017.html]
expected: TIMEOUT
[origin of the script that invoked the method, about:blank]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[Worker-constructor.html]
expected: ERROR

View file

@ -1,5 +1,4 @@
[003.html]
expected: ERROR
[shared]
expected: FAIL

View file

@ -162101,6 +162101,32 @@
{}
]
],
"active-selection-031.html": [
"387bb82082f3a13cd5867aefa33b44d836d18eb8",
[
null,
[
[
"/css/css-pseudo/reference/active-selection-031-ref.html",
"=="
]
],
{}
]
],
"active-selection-045.html": [
"415aa60610a85327362f3a4e592168ab9fccbbe3",
[
null,
[
[
"/css/reference/ref-nothing-below.xht",
"=="
]
],
{}
]
],
"active-selection-051.html": [
"caab01e392428560331729292f99b91bd20ac20e",
[
@ -247708,7 +247734,7 @@
[]
],
".taskcluster.yml": [
"47a243a855db0ff3ed9f191170f02762e44392e1",
"526fc13212e9b2ac9abfb54fcdcddea63a63c80a",
[]
],
".well-known": {
@ -305969,6 +305995,10 @@
"active-selection-024-ref.html": [
"e6dda1c1371b53e12f9a6601eea67ac4f5604a3b",
[]
],
"active-selection-031-ref.html": [
"0e3680844f887050520d8fb9b9bd2f68a2234e85",
[]
]
},
"selection-text-shadow-016-ref.html": [
@ -305979,6 +306009,12 @@
"1e068262780074b3f2acb50ae8cee69b84c72af3",
[]
],
"support": {
"100x100-red.png": [
"57bf3ddc5213d06e0975de38f330ffb7c441b268",
[]
]
},
"textpath-selection-011-ref.html": [
"d9ba940518e121eeb0e9701ccd4e36772fdfa786",
[]
@ -345563,7 +345599,7 @@
[]
],
"testdriver.js": [
"a8588b44f94c78f0a3c2542385bce20cfd1a64c9",
"4d373c9281d85e6ff37a6d0dfe4cdc2fc9c10787",
[]
],
"testdriver.js.headers": [
@ -348613,7 +348649,13 @@
"helpers.js": [
"c8c40646481a055cd1b7abf693e8f45cab769fba",
[]
]
],
"resources": {
"set-cookie.py": [
"019697a4a8608943e0258664138ce9a7b6ae6876",
[]
]
}
},
"streams": {
"META.yml": [
@ -349905,7 +349947,7 @@
[]
],
"decision.py": [
"070ae5f1903b6dbf56f535990611c04b89690bdf",
"0820a6798b5b233581eb561a973cb97ff2af44e1",
[]
],
"download.py": [
@ -349922,7 +349964,7 @@
],
"tasks": {
"test.yml": [
"9e8e689d8163368abfb0bc7bef776581643d29d7",
"dd14fc71b915e90f0625dc1120aed3c86a787e53",
[]
]
},
@ -349984,7 +350026,7 @@
[]
],
"Dockerfile": [
"6b49393bc872adc021333d6578bca41f3481ebc1",
"d8b64c2585f9998ecec4db2ca9adb97f650167b1",
[]
],
"README.md": [
@ -355687,7 +355729,7 @@
}
},
"tox.ini": [
"45358c081efbb00d528d6d176b93d28dd081b8cb",
"1a94ec340216417584bc54bf3527d90920993789",
[]
],
"wave": {
@ -356306,7 +356348,7 @@
[]
],
"browser.py": [
"cb5974078a8022d30402a5dac8137470e8fd1ecc",
"85b7b63c21972614208bda68979fd8b974535e97",
[]
],
"commands.json": [
@ -356318,7 +356360,7 @@
[]
],
"install.py": [
"1fe091879b5ca04c16e9c965380b97025ec74521",
"81770225428d4605b142e18914ce142f7724b1cd",
[]
],
"mach-emulator.manifest": [
@ -356342,7 +356384,7 @@
[]
],
"run.py": [
"32f903ce9bd64474aa387ac03a7bcb36d47bb8ae",
"79329a5dab4472d73fefeaf9b0d48057dc40eba1",
[]
],
"testfiles.py": [
@ -356375,12 +356417,12 @@
[]
],
"test_wpt.py": [
"f897b688ad6f682be9d769da98579c788505c09a",
"d2d0b541a3796528929522ef62c2e80cb7e8735c",
[]
]
},
"tox.ini": [
"8e3e26e135b4d376a492aea5adbd242797b03fe0",
"7e6eb8e42a4c7b248988ef1984a0583961e08105",
[]
],
"update.py": [
@ -356388,7 +356430,7 @@
[]
],
"utils.py": [
"18551481ab8cae42a6707156922619df3fa59b48",
"6608af754b2adaf77610552f0db4ee67e4b4e621",
[]
],
"virtualenv.py": [
@ -356634,7 +356676,7 @@
}
},
"tox.ini": [
"c544da7a95d2a982cab8b68af537440b71fa096b",
"798f64a3e422e4da0b4e4b6fe15d686b20af572e",
[]
],
"wptrunner": {
@ -485259,7 +485301,7 @@
]
],
"payment-request-hasenrolledinstrument-method.tentative.https.html": [
"c55312ce33b0da2fcd1d1619b6d7ff8c614a4f6b",
"4f6b7e9239b67e4317c325af651ab685f0c63c44",
[
null,
{
@ -485324,7 +485366,7 @@
]
],
"payment-request-show-method.https.html": [
"dcf78ef4281c4256ecb4141b3f93d15a947805a3",
"20d5bab0d14b79fb3dcf3e82e08dc495d038a33d",
[
null,
{
@ -504577,6 +504619,15 @@
"storage-access-api/sandboxAttribute.window.html",
{}
]
],
"storageAccess.testdriver.sub.html": [
"59f925f4bf503ce1cdacbe9cf17b9c10406790e4",
[
null,
{
"testdriver": true
}
]
]
},
"streams": {
@ -505592,7 +505643,7 @@
]
],
"then-interception.any.js": [
"848bb5affd87080077c2729d91943e283f3e0c8e",
"9f772ea5841d8f35487e7fa978bdd187b89896cd",
[
null,
{
@ -507699,7 +507750,7 @@
]
],
"patched-global.any.js": [
"bf353bc241ffab12c558912851940785bcdf62f2",
"416edf815c3867511ee16057624307c3e9a3fa5c",
[
null,
{

View file

@ -1,4 +0,0 @@
[hit-test-floats-003.html]
[Miss float below something else]
expected: FAIL

View file

@ -1,4 +0,0 @@
[hit-test-floats-004.html]
[Miss float below something else]
expected: FAIL

View file

@ -0,0 +1,4 @@
[hit-test-floats-005.html]
[Miss clipped float]
expected: FAIL

View file

@ -8,9 +8,6 @@
[[data-expected-height\] 3]
expected: FAIL
[[data-expected-height\] 1]
expected: FAIL
[[data-expected-height\] 2]
[[data-expected-height\] 4]
expected: FAIL

View file

@ -2,3 +2,6 @@
[Hit test intersecting scaled box]
expected: FAIL
[Hit test within unscaled box]
expected: FAIL

View file

@ -0,0 +1,4 @@
[CaretPosition-001.html]
[Element at (400, 100)]
expected: FAIL

View file

@ -2,3 +2,6 @@
[listeners are called when <iframe> is resized]
expected: FAIL
[listeners are called correct number of times]
expected: FAIL

View file

@ -1,4 +0,0 @@
[elementFromPoint-001.html]
[CSSOM View - 5 - extensions to the Document interface]
expected: FAIL

View file

@ -2,3 +2,6 @@
[elementsFromPoint on the root document for points in iframe elements]
expected: FAIL
[elementsFromPoint on inner documents]
expected: FAIL

View file

@ -315,15 +315,6 @@
[<iframe>: separate response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/plain */*]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html */*]
expected: FAIL
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
expected: FAIL
@ -336,6 +327,6 @@
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
expected: FAIL

View file

@ -53,6 +53,3 @@
[combined text/javascript ]
expected: FAIL
[separate text/javascript x/x]
expected: FAIL

View file

@ -11,3 +11,9 @@
[X-Content-Type-Options%3A%20nosniff%2C%2C%40%23%24%23%25%25%26%5E%26%5E*()()11!]
expected: FAIL
[X-Content-Type-Options%3A%20%22nosniFF%22]
expected: FAIL
[X-Content-Type-Options%3A%20%40%23%24%23%25%25%26%5E%26%5E*()()11!%2Cnosniff]
expected: FAIL

View file

@ -1,4 +0,0 @@
[traverse_the_history_1.html]
[Multiple history traversals from the same task]
expected: FAIL

View file

@ -0,0 +1,4 @@
[traverse_the_history_2.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -1,2 +0,0 @@
[cross-origin-objects-on-new-window.html]
expected: TIMEOUT

View file

@ -1,5 +1,4 @@
[embedded-opener-remove-frame.html]
expected: CRASH
[opener and "removed" embedded documents]
expected: FAIL
@ -7,5 +6,5 @@
expected: FAIL
[opener of discarded auxiliary browsing context]
expected: TIMEOUT
expected: FAIL

View file

@ -1,16 +1,20 @@
[supported-elements.html]
expected: TIMEOUT
[Contenteditable element should support autofocus]
expected: FAIL
expected: TIMEOUT
[Element with tabindex should support autofocus]
expected: FAIL
expected: NOTRUN
[Host element with delegatesFocus including no focusable descendants should be skipped]
expected: FAIL
expected: NOTRUN
[Area element should support autofocus]
expected: FAIL
expected: NOTRUN
[Host element with delegatesFocus should support autofocus]
expected: FAIL
expected: NOTRUN
[Non-HTMLElement should not support autofocus]
expected: NOTRUN

View file

@ -1,5 +1,5 @@
[iframe_sandbox_popups_escaping-2.html]
expected: CRASH
expected: TIMEOUT
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT

View file

@ -1,6 +1,5 @@
[iframe_sandbox_popups_escaping-3.html]
type: testharness
expected: TIMEOUT
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT
expected: FAIL

View file

@ -1,6 +1,6 @@
[iframe_sandbox_popups_nonescaping-2.html]
type: testharness
expected: TIMEOUT
expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox]
expected: NOTRUN

View file

@ -1,6 +1,5 @@
[iframe_sandbox_popups_nonescaping-3.html]
type: testharness
expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox]
expected: FAIL

View file

@ -9,3 +9,9 @@
[Check that rel=noopener with target=_top does a normal load]
expected: FAIL
[Check that rel=noopener with target=_self does a normal load]
expected: FAIL
[Check that rel=noopener with target=_parent does a normal load]
expected: FAIL

View file

@ -1,4 +0,0 @@
[module-static-import-delayed.html]
[document.write in an imported module]
expected: FAIL

View file

@ -1,5 +1,5 @@
[ignore-opens-during-unload.window.html]
expected: TIMEOUT
expected: CRASH
[ignore-opens-during-unload]
expected: FAIL

View file

@ -1,10 +1,9 @@
[promise-job-entry.html]
expected: TIMEOUT
[Fulfillment handler on fulfilled promise]
expected: FAIL
[Rejection handler on pending-then-rejected promise]
expected: TIMEOUT
expected: FAIL
[Sanity check: this all works as expected with no promises involved]
expected: FAIL
@ -16,5 +15,5 @@
expected: FAIL
[Fulfillment handler on pending-then-fulfilled promise]
expected: TIMEOUT
expected: FAIL

View file

@ -1,6 +1,7 @@
[promise-rejection-events.html]
expected: TIMEOUT
[delayed handling: delaying handling rejected promise created from createImageBitmap will cause both events to fire]
expected: FAIL
expected: TIMEOUT
[unhandledrejection: from createImageBitmap which is UA triggered]
expected: FAIL

View file

@ -1,5 +1,4 @@
[resource_initiator_types.html]
expected: TIMEOUT
[http://web-platform.test:8000/resource-timing/resources/all_resource_types.htm is not expected to be in the Resource Timing buffer]
expected: FAIL

View file

@ -1,5 +0,0 @@
[017.html]
expected: TIMEOUT
[origin of the script that invoked the method, about:blank]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[Worker-constructor.html]
expected: ERROR

View file

@ -1,6 +1,5 @@
[003.html]
type: testharness
expected: ERROR
[shared]
expected: FAIL

View file

@ -57,7 +57,7 @@ tasks:
owner: ${owner}
source: ${event.repository.clone_url}
payload:
image: webplatformtests/wpt:0.42
image: webplatformtests/wpt:0.46
maxRunTime: 7200
artifacts:
public/results:

View file

@ -0,0 +1,86 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<title>CSS Pseudo-Elements Test: active selection and vertical writing-modes</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
<link rel="help" href="https://www.w3.org/TR/css-pseudo-4/#highlight-styling">
<link rel="match" href="reference/active-selection-031-ref.html">
<meta content="" name="flags">
<style>
div > div
{
color: red;
float: left;
font-size: 48px;
margin-left: 16px;
}
div.vrl
{
writing-mode: vertical-rl;
}
div.vlr
{
writing-mode: vertical-lr;
}
div.mixed
{
text-orientation: mixed;
}
div.sideways
{
text-orientation: sideways;
}
div.upright
{
text-orientation: upright;
}
div::selection
{
background-color: yellow;
color: green;
}
</style>
<script>
function startTest()
{
var targetRange = document.createRange();
/* We first create an empty range */
targetRange.selectNodeContents(document.getElementById("test"));
/* Then we set the range boundaries to the contents of div#test */
window.getSelection().addRange(targetRange);
/* Finally, we now add such range of content into a selection */
}
</script>
<body onload="startTest();">
<p>Test passes if each glyph of the 6 "Selected Text" is green and if there is <strong>no red</strong>.
<div id="test">
<div class="vrl mixed">Selected Text</div>
<div class="vrl sideways">Selected Text</div>
<div class="vrl upright">Selected Text</div>
<div class="vlr mixed">Selected Text</div>
<div class="vlr sideways">Selected Text</div>
<div class="vlr upright">Selected Text</div>
</div>

View file

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html class="reftest-wait">
<meta charset="UTF-8">
<title>CSS Pseudo-Elements Test: active selection and image</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
<link rel="help" href="https://www.w3.org/TR/css-pseudo-4/#highlight-painting">
<link rel="match" href="../reference/ref-nothing-below.xht">
<meta content="" name="flags">
<meta name="assert" content="This test checks that the associated overlay for image must not cover (or leak) outside the image's content box.">
<style>
/*
Chromium 80+ highlights the
top of line box minus
content box and the bottom
of line box minus content
box.
Firefox 72+ consistently highlights
only the image content box itself.
*/
div
{
font-size: 300px;
}
img::selection
{
background-color: red;
}
span#masking
{
background-color: white;
display: inline-block;
height: 100px;
position: relative;
right: 100px;
width: 100px;
}
</style>
<script>
function startTest()
{
var targetRange = document.createRange();
/* We first create an empty range */
targetRange.selectNodeContents(document.getElementById("test"));
/* Then we set the range boundaries to the children of div#test */
window.getSelection().addRange(targetRange);
/* Finally, we now select such range of content */
document.documentElement.className = "";
}
</script>
<body onload="startTest();">
<p>Test passes if there is nothing below.
<div id="test"><img src="support/100x100-red.png" alt="Image download support must be enabled"><span id="masking"></span></div>

View file

@ -0,0 +1,57 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<title>CSS Reftest Reference</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
<style>
div
{
background-color: yellow;
color: green;
float: left;
font-size: 48px;
margin-left: 16px;
}
div.vrl
{
writing-mode: vertical-rl;
}
div.vlr
{
writing-mode: vertical-lr;
}
div.mixed
{
text-orientation: mixed;
}
div.sideways
{
text-orientation: sideways;
}
div.upright
{
text-orientation: upright;
}
</style>
<p>Test passes if each glyph of the 6 "Selected Text" is green and if there is <strong>no red</strong>.
<div class="vrl mixed">Selected Text</div>
<div class="vrl sideways">Selected Text</div>
<div class="vrl upright">Selected Text</div>
<div class="vlr mixed">Selected Text</div>
<div class="vlr sideways">Selected Text</div>
<div class="vlr upright">Selected Text</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

View file

@ -8,6 +8,9 @@
<script src='/resources/testdriver-vendor.js'></script>
<script>
"use strict";
setup({ allow_uncaught_exception: true });
const unsupportedMethods = [
{ supportedMethods: "this-is-not-supported" },
{ supportedMethods: "https://not.supported" },

View file

@ -8,6 +8,9 @@
<script src="/resources/testdriver-vendor.js"></script>
<script>
"use strict";
setup({ allow_uncaught_exception: true });
const defaultMethods = Object.freeze([
{ supportedMethods: "basic-card" },
{

View file

@ -355,6 +355,32 @@
set_user_verified: function(authenticator_id, uv) {
return window.test_driver_internal.set_user_verified(authenticator_id, uv);
},
/**
* Sets the storage access rule for an origin when embedded
* in a third-party context.
*
* {@link https://privacycg.github.io/storage-access/#set-storage-access-command}
*
* @param {String} origin - A third-party origin to block or allow.
* May be "*" to indicate all origins.
* @param {String} embedding_origin - an embedding (first-party) origin
* on which {origin}'s access should
* be blocked or allowed.
* May be "*" to indicate all origins.
* @param {String} state - The storage access setting.
* Must be either "allowed" or "blocked".
*
* @returns {Promise} Fulfilled after the storage access rule has been
* set, or rejected if setting the rule fails.
*/
set_storage_access: function(origin, embedding_origin, state) {
if (state !== "allowed" && state !== "blocked") {
throw new Error("storage access status must be 'allowed' or 'blocked'");
}
const blocked = state === "blocked";
return window.test_driver_internal.set_storage_access(origin, embedding_origin, blocked);
},
};
window.test_driver_internal = {
@ -569,5 +595,13 @@
set_user_verified: function(authenticator_id, uv) {
return Promise.reject(new Error("unimplemented"));
},
/**
* Sets the storage access policy for a third-party origin when loaded
* in the current first party context
*/
set_storage_access: function(origin, embedding_origin, blocked) {
return Promise.reject(new Error("unimplemented"));
},
};
})();

View file

@ -0,0 +1,27 @@
def main(request, response):
name = request.GET.first(b"name")
value = request.GET.first(b"value")
testcase = request.GET.first(b"testcase")
response_headers = [(b"Set-Cookie", name + b"=" + value)]
body = b"""
<!DOCTYPE html>
<meta charset="utf-8">
<title>Set Storage Access Subframe</title>
<script src="/resources/testharness.js"></script>
<script>
let querystring = window.location.search.substring(1).split("&");
const allowed = querystring.some(param => param.toLowerCase() === "allowed=true");
test(() => {
if (allowed) {
assert_equals(document.cookie, "%s=%s");
} else {
assert_equals(document.cookie, "");
}
}, "[%s] Cookie access is allowed: " + allowed);
</script>
""" % (name, value, testcase)
return (200, response_headers, body)

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<head>
<title>TestDriver - Set Storage Access Command Tests</title>
<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="helpers.js"></script>
</head>
<body>
<script>
"use strict";
promise_test(async t => {
// Allow a third-party site embedded in this first-party site.
await window.test_driver.set_storage_access("http://{{domains[www]}}:{{ports[http][0]}}/", "http://{{domains[]}}:{{ports[http][0]}}/", "allowed");
// Block a third-party site embedded in this first-party site.
await window.test_driver.set_storage_access("http://{{domains[www1]}}:{{ports[http][0]}}/", "http://{{domains[]}}:{{ports[http][0]}}/", "blocked");
// Block a third-party site on all first-party sites.
await window.test_driver.set_storage_access("http://{{domains[www2]}}:{{ports[http][0]}}/", "*", "blocked");
}, "Set up storage access rules");
RunTestsInIFrame("http://{{domains[]}}:{{ports[http][0]}}/storage-access-api/resources/set-cookie.py?name=hello0&value=world0&allowed=true&testcase=same-site");
RunTestsInIFrame("http://{{domains[www]}}:{{ports[http][0]}}/storage-access-api/resources/set-cookie.py?name=hello&value=world&allowed=true&testcase=third-party-allowed-on-first-party-site");
RunTestsInIFrame("http://{{domains[www1]}}:{{ports[http][0]}}/storage-access-api/resources/set-cookie.py?name=hello1&value=world1&allowed=false&testcase=third-party-blocked-on-first-party-site");
RunTestsInIFrame("http://{{domains[www2]}}:{{ports[http][0]}}/storage-access-api/resources/set-cookie.py?name=hello2&value=world2&allowed=false&testcase=third-party-blocked-all");
</script>
</body>

View file

@ -5,7 +5,7 @@
function interceptThen() {
const intercepted = [];
const callCount = 0;
let callCount = 0;
Object.prototype.then = function(resolver) {
if (!this.done) {
intercepted.push(this.value);
@ -21,7 +21,7 @@ function interceptThen() {
return intercepted;
}
promise_test(async () => {
promise_test(async t => {
const rs = new ReadableStream({
start(controller) {
controller.enqueue('a');
@ -31,6 +31,9 @@ promise_test(async () => {
const ws = recordingWritableStream();
const intercepted = interceptThen();
t.add_cleanup(() => {
delete Object.prototype.then;
});
await rs.pipeTo(ws);
delete Object.prototype.then;
@ -40,7 +43,7 @@ promise_test(async () => {
assert_array_equals(ws.events, ['write', 'a', 'close'], 'written chunk should be "a"');
}, 'piping should not be observable');
promise_test(async () => {
promise_test(async t => {
const rs = new ReadableStream({
start(controller) {
controller.enqueue('a');
@ -52,6 +55,9 @@ promise_test(async () => {
const [ branch1, branch2 ] = rs.tee();
const intercepted = interceptThen();
t.add_cleanup(() => {
delete Object.prototype.then;
});
await branch1.pipeTo(ws);
delete Object.prototype.then;

View file

@ -1,19 +1,25 @@
// META: global=window,worker,jsshell
'use strict';
// Tests which patch the global environment are kept separate to avoid interfering with other tests.
// Tests which patch the global environment are kept separate to avoid
// interfering with other tests.
// eslint-disable-next-line no-extend-native, accessor-pairs
Object.defineProperty(Object.prototype, 'highWaterMark', {
set() { throw new Error('highWaterMark setter called'); }
});
test(t => {
// eslint-disable-next-line no-extend-native, accessor-pairs
Object.defineProperty(Object.prototype, 'highWaterMark', {
set() { throw new Error('highWaterMark setter called'); }
});
// eslint-disable-next-line no-extend-native, accessor-pairs
Object.defineProperty(Object.prototype, 'size', {
set() { throw new Error('size setter called'); }
});
// eslint-disable-next-line no-extend-native, accessor-pairs
Object.defineProperty(Object.prototype, 'size', {
set() { throw new Error('size setter called'); }
});
t.add_cleanup(() => {
delete Object.prototype.highWaterMark;
delete Object.prototype.size;
});
test(() => {
assert_not_equals(new TransformStream(), null, 'constructor should work');
}, 'TransformStream constructor should not call setters for highWaterMark or size');

View file

@ -199,7 +199,6 @@ def build_full_command(event, task):
~/start.sh \
%(repo_url)s \
%(fetch_ref)s;
sudo add-apt-repository ppa:deadsnakes/ppa
%(install_str)s
cd web-platform-tests;
./tools/ci/run_tc.py %(options_str)s -- %(task_cmd)s;

View file

@ -4,7 +4,7 @@ components:
workerType: ci
schedulerId: taskcluster-github
deadline: "24 hours"
image: webplatformtests/wpt:0.42
image: webplatformtests/wpt:0.46
maxRunTime: 7200
artifacts:
public/results:
@ -392,6 +392,9 @@ tasks:
- trigger-pr
- tox-python3
command: ./tools/ci/ci_tools_unittest.sh
install:
- python3.6
- python3.6-dev
env:
HYPOTHESIS_PROFILE: ci
schedule-if:
@ -444,6 +447,8 @@ tasks:
command: ./tools/ci/ci_tools_integration_test.sh
install:
- libnss3-tools
- python3.6
- python3.6-dev
options:
oom-killer: true
browser:

View file

@ -1,4 +1,4 @@
FROM ubuntu:18.04
FROM ubuntu:20.04
# No interactive frontend during docker build
ENV DEBIAN_FRONTEND=noninteractive \
@ -10,12 +10,14 @@ RUN apt-get -qqy update \
bridge-utils \
bzip2 \
ca-certificates \
curl \
dbus-x11 \
earlyoom \
fluxbox \
gdebi \
git \
gstreamer1.0-plugins-bad \
gstreamer1.0-gl \
libosmesa6-dev \
libvirt-daemon-system \
libvirt-clients \
@ -24,10 +26,12 @@ RUN apt-get -qqy update \
locales \
openjdk-8-jre-headless \
pulseaudio \
python \
python-pip \
python2 \
python2-dev \
python3 \
python3-dev \
python3-pip \
software-properties-common \
qemu-kvm \
tzdata \
sudo \
@ -35,6 +39,16 @@ RUN apt-get -qqy update \
wget \
xvfb
# python3.6 is not available by default in new versions of Ubuntu.
RUN apt-add-repository -y ppa:deadsnakes/ppa
# Ensure that scripts referencing `/usr/bin/env python` work.
RUN apt install python-is-python2
# The python-pip package no longer exists in new versions of Ubuntu.
RUN curl https://bootstrap.pypa.io/get-pip.py --output get-pip.py
RUN python2 get-pip.py
# Installing just the deps of firefox and chrome is moderately tricky, so
# just install the default versions of them, and some extra deps we happen
# to know that chrome requires

View file

@ -7,7 +7,8 @@ skip_missing_interpreters = False
deps =
pytest
pytest-cov
mock
# mock no longer supports Python 2 since v4
mock==3.*
hypothesis
requests
taskcluster

View file

@ -3,7 +3,6 @@ import platform
import re
import shutil
import stat
import errno
import subprocess
import tempfile
from abc import ABCMeta, abstractmethod
@ -13,7 +12,7 @@ from distutils.spawn import find_executable
from six.moves.urllib.parse import urlsplit
import requests
from .utils import call, get, untar, unzip
from .utils import call, get, rmtree, untar, unzip
uname = platform.uname()
@ -31,15 +30,6 @@ def _get_fileversion(binary, logger=None):
return None
def handle_remove_readonly(func, path, exc):
excvalue = exc[1]
if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777
func(path)
else:
raise
def get_ext(filename):
"""Get the extension from a filename with special handling for .tar.foo"""
name, ext = os.path.splitext(filename)
@ -63,6 +53,18 @@ class Browser(object):
def __init__(self, logger):
self.logger = logger
def _get_dest(self, dest, channel):
if dest is None:
# os.getcwd() doesn't include the venv path
dest = os.path.join(os.getcwd(), "_venv")
dest = os.path.join(dest, "browsers", channel)
if not os.path.exists(dest):
os.makedirs(dest)
return dest
@abstractmethod
def download(self, dest=None, channel=None, rename=None):
"""Download a package or installer for the browser
@ -156,18 +158,6 @@ class Firefox(Browser):
return "%s%s" % (self.platform, bits)
def _get_dest(self, dest, channel):
if dest is None:
# os.getcwd() doesn't include the venv path
dest = os.path.join(os.getcwd(), "_venv")
dest = os.path.join(dest, "browsers", channel)
if not os.path.exists(dest):
os.makedirs(dest)
return dest
def download(self, dest=None, channel="nightly", rename=None):
product = {
"nightly": "firefox-nightly-latest-ssl",
@ -374,7 +364,7 @@ class Firefox(Browser):
# If we don't have a recent download, grab and extract the latest one
if not have_cache:
if os.path.exists(dest):
shutil.rmtree(dest)
rmtree(dest)
os.makedirs(dest)
url = self.get_profile_bundle_url(version, channel)
@ -389,7 +379,7 @@ class Firefox(Browser):
path = os.path.join(profiles, name)
shutil.move(path, dest)
finally:
shutil.rmtree(extract_dir)
rmtree(extract_dir)
else:
self.logger.info("Using cached test prefs from %s" % dest)
@ -534,22 +524,48 @@ class Chrome(Browser):
product = "chrome"
requirements = "requirements_chrome.txt"
platforms = {
"Linux": "Linux",
"Windows": "Win",
"Darwin": "Mac",
}
def __init__(self, logger):
super(Chrome, self).__init__(logger)
self._last_change = None
def download(self, dest=None, channel=None, rename=None):
raise NotImplementedError
if channel != "nightly":
raise NotImplementedError("We can only download Chrome Nightly (Chromium ToT) for you.")
if dest is None:
dest = self._get_dest(None, channel)
filename = self._chromium_package_name() + ".zip"
url = self._latest_chromium_snapshot_url() + filename
self.logger.info("Downloading Chrome from %s" % url)
resp = get(url)
installer_path = os.path.join(dest, filename)
with open(installer_path, "wb") as f:
f.write(resp.content)
return installer_path
def install(self, dest=None, channel=None):
raise NotImplementedError
if channel != "nightly":
raise NotImplementedError("We can only install Chrome Nightly (Chromium ToT) for you.")
dest = self._get_dest(dest, channel)
def platform_string(self):
platform = {
"Linux": "linux",
"Windows": "win",
"Darwin": "mac"
}.get(uname[0])
installer_path = self.download(dest, channel)
with open(installer_path, "rb") as f:
unzip(f, dest)
os.remove(installer_path)
return self.find_nightly_binary(dest, channel)
def _chromedriver_platform_string(self):
platform = self.platforms.get(uname[0])
if platform is None:
raise ValueError("Unable to construct a valid Chrome package name for current platform")
platform = platform.lower()
if platform == "linux":
bits = "64" if uname[4] == "x86_64" else "32"
@ -560,12 +576,8 @@ class Chrome(Browser):
return "%s%s" % (platform, bits)
def chromium_platform_string(self):
platform = {
"Linux": "Linux",
"Windows": "Win",
"Darwin": "Mac"
}.get(uname[0])
def _chromium_platform_string(self):
platform = self.platforms.get(uname[0])
if platform is None:
raise ValueError("Unable to construct a valid Chromium package name for current platform")
@ -575,7 +587,26 @@ class Chrome(Browser):
return platform
def _chromium_package_name(self):
return "chrome-%s" % self.platforms.get(uname[0]).lower()
def _latest_chromium_snapshot_url(self):
# Make sure we use the same revision in an invocation.
architecture = self._chromium_platform_string()
if self._last_change is None:
revision_url = "https://storage.googleapis.com/chromium-browser-snapshots/%s/LAST_CHANGE" % architecture
self._last_change = get(revision_url).text.strip()
return "https://storage.googleapis.com/chromium-browser-snapshots/%s/%s/" % (architecture, self._last_change)
def find_nightly_binary(self, dest, channel):
binary = "Chromium" if uname[0] == "Darwin" else "chrome"
# find_executable will add .exe on Windows automatically.
return find_executable(binary, os.path.join(dest, self._chromium_package_name()))
def find_binary(self, venv_path=None, channel=None):
if channel == "nightly":
return self.find_nightly_binary(self._get_dest(venv_path, channel))
if uname[0] == "Linux":
name = "google-chrome"
if channel == "stable":
@ -613,25 +644,23 @@ class Chrome(Browser):
except requests.RequestException:
return None
return "https://chromedriver.storage.googleapis.com/%s/chromedriver_%s.zip" % (
latest, self.platform_string())
latest, self._chromedriver_platform_string())
def _chromium_chromedriver_url(self, chrome_version):
try:
# Try to find the Chromium build with the same revision.
omaha = get("https://omahaproxy.appspot.com/deps.json?version=" + chrome_version).json()
revision = omaha['chromium_base_position']
url = "https://storage.googleapis.com/chromium-browser-snapshots/%s/%s/chromedriver_%s.zip" % (
self.chromium_platform_string(), revision, self.platform_string())
# Check the status without downloading the content (this is a streaming request).
get(url)
except requests.RequestException:
# Fall back to the tip-of-tree Chromium build.
revision_url = "https://storage.googleapis.com/chromium-browser-snapshots/%s/LAST_CHANGE" % (
self.chromium_platform_string())
revision = get(revision_url).text.strip()
url = "https://storage.googleapis.com/chromium-browser-snapshots/%s/%s/chromedriver_%s.zip" % (
self.chromium_platform_string(), revision, self.platform_string())
return url
if chrome_version:
try:
# Try to find the Chromium build with the same revision.
omaha = get("https://omahaproxy.appspot.com/deps.json?version=" + chrome_version).json()
revision = omaha['chromium_base_position']
url = "https://storage.googleapis.com/chromium-browser-snapshots/%s/%s/chromedriver_%s.zip" % (
self._chromium_platform_string(), revision, self._chromedriver_platform_string())
# Check the status without downloading the content (this is a streaming request).
get(url)
return url
except requests.RequestException:
pass
# Fall back to the tip-of-tree Chromium build.
return "%schromedriver_%s.zip" % (self._latest_chromium_snapshot_url(), self._chromedriver_platform_string())
def _latest_chromedriver_url(self, chrome_version):
# Remove channel suffixes (e.g. " dev").
@ -640,20 +669,25 @@ class Chrome(Browser):
self._chromium_chromedriver_url(chrome_version))
def install_webdriver_by_version(self, version, dest=None):
assert version, "Cannot install ChromeDriver without Chrome version"
if dest is None:
dest = os.pwd
url = self._latest_chromedriver_url(version)
url = self._latest_chromedriver_url(version) if version \
else self._chromium_chromedriver_url(None)
self.logger.info("Downloading ChromeDriver from %s" % url)
unzip(get(url).raw, dest)
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)
dest, 'chromedriver_%s' % self._chromedriver_platform_string())
unzipped_path = find_executable("chromedriver", chromedriver_dir)
assert unzipped_path is not None
shutil.move(unzipped_path, dest)
rmtree(chromedriver_dir)
return find_executable("chromedriver", dest)
def install_webdriver(self, dest=None, channel=None, browser_binary=None):
if channel == "nightly":
# The "nightly" channel is not an official channel, so we simply download ToT.
return self.install_webdriver_by_version(None, dest)
if browser_binary is None:
browser_binary = self.find_binary(channel)
return self.install_webdriver_by_version(
@ -878,7 +912,7 @@ class Opera(Browser):
operadriver_dir = os.path.join(dest, "operadriver_%s" % self.platform_string())
shutil.move(os.path.join(operadriver_dir, "operadriver"), dest)
shutil.rmtree(operadriver_dir)
rmtree(operadriver_dir)
path = find_executable("operadriver")
st = os.stat(path)
@ -975,7 +1009,7 @@ class EdgeChromium(Browser):
driver_notes_path = os.path.join(dest, "Driver_notes")
if os.path.isdir(driver_notes_path):
print("Delete %s folder" % driver_notes_path)
shutil.rmtree(driver_notes_path, ignore_errors=False, onerror=handle_remove_readonly)
rmtree(driver_notes_path)
self.logger.info("Downloading MSEdgeDriver from %s" % url)
unzip(get(url).raw, dest)

View file

@ -3,7 +3,7 @@ from . import browser
latest_channels = {
'firefox': 'nightly',
'chrome': 'dev',
'chrome': 'nightly',
'chrome_android': 'dev',
'edgechromium': 'dev',
'safari': 'preview',
@ -14,11 +14,11 @@ channel_by_name = {
'stable': 'stable',
'release': 'stable',
'beta': 'beta',
'dev': 'dev',
'canary': 'canary',
'nightly': latest_channels,
'dev': latest_channels,
'preview': latest_channels,
'experimental': latest_channels,
'canary': 'canary',
}
channel_args = argparse.ArgumentParser(add_help=False)

View file

@ -343,8 +343,8 @@ class Chrome(BrowserSetup):
kwargs["webdriver_binary"] = webdriver_binary
else:
raise WptrunError("Unable to locate or install chromedriver binary")
if browser_channel in ("dev", "canary"):
logger.info("Automatically turning on experimental features for Chrome Dev/Canary")
if browser_channel in ("dev", "canary", "nightly"):
logger.info("Automatically turning on experimental features for Chrome Dev/Canary or Chromium trunk")
kwargs["binary_args"].append("--enable-experimental-web-platform-features")
# HACK(Hexcles): work around https://github.com/web-platform-tests/wpt/issues/16448
kwargs["webdriver_args"].append("--disable-build-check")

View file

@ -16,7 +16,7 @@ except ImportError:
import pytest
from tools.wpt import wpt
from tools.wpt import utils, wpt
here = os.path.abspath(os.path.dirname(__file__))
@ -61,7 +61,7 @@ def manifest_dir():
os.path.join(path, "MANIFEST.json"))
yield path
finally:
shutil.rmtree(path)
utils.rmtree(path)
@pytest.fixture
@ -86,7 +86,7 @@ def temp_test():
yield make_test
shutil.rmtree("../../.tools-tests")
utils.rmtree("../../.tools-tests")
def test_missing():
@ -185,6 +185,7 @@ def test_run_zero_tests():
"chrome", "/non-existent-dir/non-existent-file.html"])
assert excinfo.value.code != 0
@pytest.mark.slow
@pytest.mark.remote_network
def test_run_failing_test():
@ -238,6 +239,25 @@ def test_run_verify_unstable(temp_test):
assert excinfo.value.code == 0
@pytest.mark.slow
@pytest.mark.remote_network
def test_install_chromium():
if sys.platform == "win32":
chromium_path = os.path.join(wpt.localpaths.repo_root, wpt.venv_dir(), "browsers", "nightly", "chrome-win")
elif sys.platform == "darwin":
chromium_path = os.path.join(wpt.localpaths.repo_root, wpt.venv_dir(), "browsers", "nightly", "chrome-mac")
else:
chromium_path = os.path.join(wpt.localpaths.repo_root, wpt.venv_dir(), "browsers", "nightly", "chrome-linux")
if os.path.exists(chromium_path):
utils.rmtree(chromium_path)
with pytest.raises(SystemExit) as excinfo:
wpt.main(argv=["install", "chrome", "browser", "--channel=nightly"])
assert excinfo.value.code == 0
assert os.path.exists(chromium_path)
utils.rmtree(chromium_path)
@pytest.mark.slow
@pytest.mark.remote_network
def test_install_chromedriver():
@ -251,7 +271,13 @@ def test_install_chromedriver():
wpt.main(argv=["install", "chrome", "webdriver"])
assert excinfo.value.code == 0
assert os.path.exists(chromedriver_path)
os.unlink(chromedriver_path)
# FIXME: On Windows, this may sometimes fail (access denied), possibly
# because the file handler is not released immediately.
try:
os.unlink(chromedriver_path)
except OSError:
if sys.platform != "win32":
raise
@pytest.mark.slow
@ -264,12 +290,12 @@ def test_install_firefox():
else:
fx_path = os.path.join(wpt.localpaths.repo_root, wpt.venv_dir(), "browsers", "nightly", "firefox")
if os.path.exists(fx_path):
shutil.rmtree(fx_path)
utils.rmtree(fx_path)
with pytest.raises(SystemExit) as excinfo:
wpt.main(argv=["install", "firefox", "browser", "--channel=nightly"])
assert excinfo.value.code == 0
assert os.path.exists(fx_path)
shutil.rmtree(fx_path)
utils.rmtree(fx_path)
def test_files_changed(capsys):

View file

@ -8,7 +8,8 @@ deps =
pytest
pytest-cov
hypothesis
mock
# mock no longer supports Python 2 since v4
mock==3.*
-r{toxinidir}/../wptrunner/requirements.txt
-r{toxinidir}/../wptrunner/requirements_chrome.txt
-r{toxinidir}/../wptrunner/requirements_firefox.txt

View file

@ -1,5 +1,8 @@
import errno
import logging
import os
import shutil
import stat
import subprocess
import tarfile
import zipfile
@ -95,3 +98,19 @@ def get(url):
resp = requests.get(url, stream=True)
resp.raise_for_status()
return resp
def rmtree(path):
# This works around two issues:
# 1. Cannot delete read-only files owned by us (e.g. files extracted from tarballs)
# 2. On Windows, we sometimes just need to retry in case the file handler
# hasn't been fully released (a common issue).
def handle_remove_readonly(func, path, exc):
excvalue = exc[1]
if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777
func(path)
else:
raise
return shutil.rmtree(path, onerror=handle_remove_readonly)

View file

@ -10,7 +10,8 @@ deps =
pytest>=2.9
pytest-cov
pytest-xdist
mock
# mock no longer supports Python 2 since v4
mock==3.*
-r{toxinidir}/requirements.txt
chrome: -r{toxinidir}/requirements_chrome.txt
edge: -r{toxinidir}/requirements_edge.txt