Auto merge of #23155 - servo-wpt-sync:wpt_update_02-04-2019, r=jdm

Sync WPT with upstream (02-04-2019)

Automated downstream sync of changes from upstream as of 02-04-2019.
[no-wpt-sync]

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23155)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-04-02 12:03:01 -04:00 committed by GitHub
commit 1ff56aa84f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 2034 additions and 3665 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
[flex-minimum-height-flex-items-014.html]
expected: FAIL

View file

@ -44,9 +44,6 @@
[Matching font-weight: '501' should prefer '503 520' over '500'] [Matching font-weight: '501' should prefer '503 520' over '500']
expected: FAIL expected: FAIL
[Matching font-weight: '501' should prefer '450 460' over '390 410']
expected: FAIL
[Matching font-weight: '399' should prefer '200 300' over '400'] [Matching font-weight: '399' should prefer '200 300' over '400']
expected: FAIL expected: FAIL
@ -80,9 +77,6 @@
[Matching font-style: 'oblique 21deg' should prefer 'italic' over 'oblique 0deg'] [Matching font-style: 'oblique 21deg' should prefer 'italic' over 'oblique 0deg']
expected: FAIL expected: FAIL
[Matching font-style: 'oblique 21deg' should prefer 'oblique 0deg' over 'oblique -50deg -20deg']
expected: FAIL
[Matching font-style: 'oblique 21deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] [Matching font-style: 'oblique 21deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg']
expected: FAIL expected: FAIL
@ -104,24 +98,15 @@
[Matching font-style: 'oblique 0deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] [Matching font-style: 'oblique 0deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg']
expected: FAIL expected: FAIL
[Matching font-style: 'oblique 0deg' should prefer 'italic' over 'oblique -50deg -20deg']
expected: FAIL
[Matching font-style: 'oblique 0deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] [Matching font-style: 'oblique 0deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg']
expected: FAIL expected: FAIL
[Matching font-style: 'oblique -10deg' should prefer 'oblique -10deg' over 'oblique -5deg'] [Matching font-style: 'oblique -10deg' should prefer 'oblique -10deg' over 'oblique -5deg']
expected: FAIL expected: FAIL
[Matching font-style: 'oblique -10deg' should prefer 'oblique -1deg 0deg' over 'oblique -20deg -15deg']
expected: FAIL
[Matching font-style: 'oblique -10deg' should prefer 'oblique -20deg -15deg' over 'oblique -60deg -30deg'] [Matching font-style: 'oblique -10deg' should prefer 'oblique -20deg -15deg' over 'oblique -60deg -30deg']
expected: FAIL expected: FAIL
[Matching font-style: 'oblique -10deg' should prefer 'oblique -60deg -30deg' over 'oblique -50deg -40deg']
expected: FAIL
[Matching font-style: 'oblique -10deg' should prefer 'italic' over 'oblique 0deg 10deg'] [Matching font-style: 'oblique -10deg' should prefer 'italic' over 'oblique 0deg 10deg']
expected: FAIL expected: FAIL
@ -155,9 +140,6 @@
[Descriptor mathcing priority: Style has higher priority than weight] [Descriptor mathcing priority: Style has higher priority than weight]
expected: FAIL expected: FAIL
[Matching font-stretch: '100%' should prefer '110% 120%' over '115% 116%']
expected: FAIL
[Matching font-stretch: '110%' should prefer '115% 116%' over '105%'] [Matching font-stretch: '110%' should prefer '115% 116%' over '105%']
expected: FAIL expected: FAIL
@ -182,9 +164,6 @@
[Matching font-style: 'normal' should prefer 'oblique 0deg' over 'oblique 10deg 40deg'] [Matching font-style: 'normal' should prefer 'oblique 0deg' over 'oblique 10deg 40deg']
expected: FAIL expected: FAIL
[Matching font-style: 'normal' should prefer 'oblique 10deg 40deg' over 'oblique 20deg 30deg']
expected: FAIL
[Matching font-style: 'normal' should prefer 'oblique 20deg 30deg' over 'oblique -50deg -20deg'] [Matching font-style: 'normal' should prefer 'oblique 20deg 30deg' over 'oblique -50deg -20deg']
expected: FAIL expected: FAIL
@ -242,18 +221,9 @@
[Matching font-weight: '430' should prefer '420 440' over '450 460'] [Matching font-weight: '430' should prefer '420 440' over '450 460']
expected: FAIL expected: FAIL
[Matching font-style: 'oblique -20deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg']
expected: FAIL
[Matching font-style: 'oblique 0deg' should prefer 'oblique 15deg 20deg' over 'oblique 30deg 60deg'] [Matching font-style: 'oblique 0deg' should prefer 'oblique 15deg 20deg' over 'oblique 30deg 60deg']
expected: FAIL expected: FAIL
[Matching font-style: 'italic' should prefer 'oblique 5deg' over 'normal']
expected: FAIL
[Matching font-style: 'oblique 20deg' should prefer 'oblique 20deg' over 'oblique 30deg 60deg']
expected: FAIL
[Matching font-style: 'oblique -21deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg'] [Matching font-style: 'oblique -21deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg']
expected: FAIL expected: FAIL
@ -314,9 +284,6 @@
[Matching font-style: 'oblique -10deg' should prefer 'oblique -50deg -40deg' over 'italic'] [Matching font-style: 'oblique -10deg' should prefer 'oblique -50deg -40deg' over 'italic']
expected: FAIL expected: FAIL
[Matching font-style: 'oblique -21deg' should prefer 'oblique -10deg' over 'italic']
expected: FAIL
[Matching font-weight: '399' should prefer '340 360' over '200 300'] [Matching font-weight: '399' should prefer '340 360' over '200 300']
expected: FAIL expected: FAIL

View file

@ -1,5 +1,5 @@
[elementsFromPoint-iframes.html] [elementsFromPoint-iframes.html]
expected: CRASH expected: TIMEOUT
[elementsFromPoint on the root document for points in iframe elements] [elementsFromPoint on the root document for points in iframe elements]
expected: FAIL expected: FAIL

View file

@ -252,3 +252,51 @@
[In-document Element.querySelector: Descendant combinator '>>', not matching element with id that is not a descendant of an element with id: #descendant-div1>>#descendant-div4] [In-document Element.querySelector: Descendant combinator '>>', not matching element with id that is not a descendant of an element with id: #descendant-div1>>#descendant-div4]
expected: FAIL expected: FAIL
[Detached Element.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[Detached Element.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Detached Element.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[In-document Element.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[Fragment.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Fragment.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[Fragment.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[Detached Element.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[In-document Element.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[Fragment.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[In-document Element.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[In-document Element.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL

View file

@ -252,3 +252,51 @@
[In-document Element.querySelector: Descendant combinator '>>', not matching element with id that is not a descendant of an element with id: #descendant-div1>>#descendant-div4] [In-document Element.querySelector: Descendant combinator '>>', not matching element with id that is not a descendant of an element with id: #descendant-div1>>#descendant-div4]
expected: FAIL expected: FAIL
[Detached Element.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[Detached Element.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Detached Element.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[In-document Element.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[Fragment.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Fragment.querySelector: Slotted selector: ::slotted(foo)]
expected: FAIL
[Fragment.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[Detached Element.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[In-document Element.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[Fragment.querySelectorAll: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[Document.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL
[In-document Element.querySelectorAll: Slotted selector: ::slotted(foo)]
expected: FAIL
[In-document Element.querySelector: Slotted selector (no matching closing paren): ::slotted(foo]
expected: FAIL

View file

@ -11,6 +11,3 @@
[X-Content-Type-Options%3A%20nosniff%0C] [X-Content-Type-Options%3A%20nosniff%0C]
expected: FAIL expected: FAIL
[X-Content-Type-Options%3A%20%2Cnosniff]
expected: FAIL

View file

@ -1,4 +0,0 @@
[javascript-url-abort-return-value-string.tentative.html]
[Aborting fetch for javascript:string navigation]
expected: FAIL

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
[closed-attribute.window.html] [closed-attribute.window.html]
expected: CRASH
[closed and cross-site nested browsing context] [closed and cross-site nested browsing context]
expected: FAIL expected: FAIL

View file

@ -9372,6 +9372,18 @@
[HTMLImageElement interface: named constructor without 'new'] [HTMLImageElement interface: named constructor without 'new']
expected: FAIL expected: FAIL
[HTMLLinkElement interface: attribute imageSizes]
expected: FAIL
[HTMLLinkElement interface: document.createElement("link") must inherit property "imageSizes" with the proper type]
expected: FAIL
[HTMLLinkElement interface: document.createElement("link") must inherit property "imageSrcset" with the proper type]
expected: FAIL
[HTMLLinkElement interface: attribute imageSrcset]
expected: FAIL
[interfaces.https.html?exclude=(Document|Window|HTML.*)] [interfaces.https.html?exclude=(Document|Window|HTML.*)]
[HTML IDL tests] [HTML IDL tests]

View file

@ -0,0 +1,2 @@
[script-onerror-insertion-point-2.html]
expected: TIMEOUT

View file

@ -1,4 +0,0 @@
[DOMContentLoaded-defer.html]
[The end: DOMContentLoaded and defer scripts]
expected: FAIL

View file

@ -1,4 +1,5 @@
[realtimeanalyser-fft-scaling.html] [realtimeanalyser-fft-scaling.html]
expected: TIMEOUT
[X 2048-point FFT peak position is not equal to 64. Got 0.] [X 2048-point FFT peak position is not equal to 64. Got 0.]
expected: FAIL expected: FAIL

View file

@ -1,11 +1,5 @@
{ {
"items": { "items": {
"conformancechecker": {
"mozilla/remove_video_iframe.html": []
},
"manual": {
"mozilla/remove_video_iframe.html": []
},
"reftest": { "reftest": {
"css/abs-overflow-stackingcontext.html": [ "css/abs-overflow-stackingcontext.html": [
[ [
@ -7331,7 +7325,6 @@
{} {}
] ]
], ],
"mozilla/remove_video_iframe.html": [],
"mozilla/reparse_style_elements.html": [ "mozilla/reparse_style_elements.html": [
[ [
"mozilla/reparse_style_elements.html", "mozilla/reparse_style_elements.html",
@ -7633,11 +7626,7 @@
], ],
{} {}
] ]
], ]
"mozilla/remove_video_iframe.html": []
},
"stub": {
"mozilla/remove_video_iframe.html": []
}, },
"support": { "support": {
".gitignore": [ ".gitignore": [
@ -10875,7 +10864,6 @@
{} {}
] ]
], ],
"mozilla/remove_video_iframe.html": [],
"mozilla/reparse_style_elements_ref.html": [ "mozilla/reparse_style_elements_ref.html": [
[ [
{} {}
@ -13133,9 +13121,7 @@
"mozilla/globals/entry.worker.js": [ "mozilla/globals/entry.worker.js": [
[ [
"mozilla/globals/entry.worker.html", "mozilla/globals/entry.worker.html",
{ {}
"script_metadata": []
}
] ]
], ],
"mozilla/history.html": [ "mozilla/history.html": [
@ -13315,9 +13301,7 @@
"mozilla/interfaces.worker.js": [ "mozilla/interfaces.worker.js": [
[ [
"mozilla/interfaces.worker.html", "mozilla/interfaces.worker.html",
{ {}
"script_metadata": []
}
] ]
], ],
"mozilla/invalid-this.html": [ "mozilla/invalid-this.html": [
@ -13574,7 +13558,7 @@
], ],
"mozilla/remove_video_iframe.html": [ "mozilla/remove_video_iframe.html": [
[ [
"/_mozilla/mozilla/remove_video_iframe.html", "mozilla/remove_video_iframe.html",
{} {}
] ]
], ],
@ -13890,12 +13874,6 @@
{} {}
] ]
] ]
},
"visual": {
"mozilla/remove_video_iframe.html": []
},
"wdspec": {
"mozilla/remove_video_iframe.html": []
} }
}, },
"paths": { "paths": {
@ -21057,5 +21035,5 @@
] ]
}, },
"url_base": "/_mozilla/", "url_base": "/_mozilla/",
"version": 5 "version": 6
} }

View file

@ -18,6 +18,7 @@ div {
#test { #test {
background: green; background: green;
contain: size;
columns: 2 40px; columns: 2 40px;
column-gap: 20px; column-gap: 20px;
min-height: 100px; min-height: 100px;

View file

@ -14,4 +14,4 @@ div {
} }
</style> </style>
<p>This test passes if it has the same output as the reference.</p> <p>This test passes if it has the same output as the reference.</p>
<div></div> <div>FAIL</div>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Containment Test: Size containment scrollbars</title>
<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size">
<link rel="match" href="reference/contain-size-scrollbars-001-ref.html">
<meta name=assert content="This test checks that the size of a flexbox container with 'contain: size' includes the scrollbars too.">
<style>
div {
contain: size;
display: inline-flex;
border: solid thick;
overflow: scroll;
}
</style>
<p>This test passes if it has the same output as the reference.</p>
<div>FAIL</div>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Containment Test: Size containment scrollbars</title>
<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size">
<link rel="match" href="reference/contain-size-scrollbars-001-ref.html">
<meta name=assert content="This test checks that the size of a grid container with 'contain: size' includes the scrollbars too.">
<style>
div {
contain: size;
display: inline-grid;
border: solid thick;
overflow: scroll;
}
</style>
<p>This test passes if it has the same output as the reference.</p>
<div>FAIL</div>

View file

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<title>CSS Flexbox: min-height: auto with nested flexboxes and justify-content</title>
<link rel="author" title="Google LLC" href="https://www.google.com/" />
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#min-size-auto" />
<link rel="issue" href="https://bugs.chromium.org/p/chromium/issues/detail?id=945214" />
<link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
<style>
.overlapped-green {
position: absolute;
background-color: green;
width: 100px;
height: 100px;
z-index: 1;
}
.outer {
display: flex;
flex-direction: column;
height: 100px;
width: 100px;
background: green;
}
.inner {
display: flex;
flex-direction: column;
justify-content: flex-end;
height: 100%;
background-color: red;
}
.spacer {
height: 30px;
width: 100px;
background: red;
flex: none;
}
</style>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div class="overlapped-green"></div>
<div class="outer">
<div class="spacer"></div>
<div class="inner">
<div class="spacer"></div>
</div>
</div>
</body>
</html>

View file

@ -30,6 +30,10 @@ test_initial_value({ syntax: '<color>', initialValue: 'purple' }, 'rgb(128, 0, 1
test_initial_value({ syntax: '<transform-function>', initialValue: 'rotate(42deg)' }, 'rotate(42deg)'); test_initial_value({ syntax: '<transform-function>', initialValue: 'rotate(42deg)' }, 'rotate(42deg)');
test_initial_value({ syntax: '<transform-list>', initialValue: 'scale(calc(2 + 2))' }, 'scale(4)'); test_initial_value({ syntax: '<transform-list>', initialValue: 'scale(calc(2 + 2))' }, 'scale(4)');
test_initial_value({ syntax: '<transform-list>', initialValue: 'scale(calc(2 + 1)) translateX(calc(3px + 1px))' }, 'scale(3) translateX(4px)'); test_initial_value({ syntax: '<transform-list>', initialValue: 'scale(calc(2 + 1)) translateX(calc(3px + 1px))' }, 'scale(3) translateX(4px)');
test_initial_value({ syntax: '<url>', initialValue: 'url(a)' },
`url("${new URL('a', document.baseURI)}")`);
test_initial_value({ syntax: '<url>+', initialValue: 'url(a) url(a)' },
`url("${new URL('a', document.baseURI)}") url("${new URL('a', document.baseURI)}")`);
// Test that the initial value of the custom property 'reg' is successfully // Test that the initial value of the custom property 'reg' is successfully
// substituted into 'property'. // substituted into 'property'.

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Text Test: white-space: break-spaces</title>
<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
<link rel="help" title="3. White Space and Wrapping: the white-space property" href="https://drafts.csswg.org/css-text-3/#white-space-property">
<link rel="help" title="5.2. Breaking Rules for Letters: the word-break property" href="https://drafts.csswg.org/css-text-3/#word-break-property">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-white-space-break-spaces">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-word">
<meta name="flags" content="ahem">
<link rel="match" href="reference/white-space-break-spaces-005-ref.html">
<meta name="assert" content="break-word + break-spaces do not allow a break
between the last character of a word and the first space of a sequence of preserved spaces
if there are other wrapping opportunities earlier in the line.">
<style>
div {
position: relative;
font: 25px/1 Ahem;
}
.fail {
position: absolute;
color: red;
z-index: -1;
}
span { color: green; }
.test {
color: green;
width: 4ch;
white-space: break-spaces;
word-break: break-word;
}
</style>
<body>
<p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
<div class="fail">XX<span>XX</span><br>X<span>X</span>X<span>X<br>XXXX<br>XXXX</span></div>
<div class="test">XX X X</div>
</body>

View file

@ -71,7 +71,7 @@ https://chromium.googlesource.com/chromium/src/+/c825d655f6aaf73484f9d56e9012793
verifyComputedStyle("opacity", "initial", "calc(2 / 4)", "0.5", "testing opacity: calc(2 / 4)"); verifyComputedStyle("opacity", "initial", "calc(2 / 4)", "0.5", "testing opacity: calc(2 / 4)");
verifyComputedStyle("tab-size", "12345", "calc(2 / 4)", "1", "testing tab-size: calc(2 / 4)"); verifyComputedStyle("tab-size", "12345", "calc(2 / 4)", "0.5", "testing tab-size: calc(2 / 4)");
/* /*
'tab-size' accepts <number> values. 'tab-size' accepts <number> values.
*/ */

View file

@ -7,8 +7,9 @@
<div> <div>
<p>Expected: A green box, color-inverted inside the short, wide box with a<br> <p>Expected: A green box, color-inverted inside the short, wide box with a<br>
blue border, and not color-inverted anywhere else. In particular, there should be<br> blue border and rounded corners, and not color-inverted anywhere else. In<br>
no color inversion inside the tall, narrow box, or anywhere outside that.</p> particular, there should be no color inversion inside the tall, narrow box,<br>
or anywhere outside that.</p>
</div> </div>
<div class="box"></div> <div class="box"></div>
<div class="navbar"></div> <div class="navbar"></div>
@ -31,21 +32,22 @@ div {
height: 50px; height: 50px;
top: 150px; top: 150px;
left: 50px; left: 50px;
border: 1px solid blue; border: 2px solid blue;
backdrop-filter: invert(1); backdrop-filter: invert(1);
border-radius: 10px 20px 30px 40px;
} }
.menu { .menu {
width: 100px; width: 100px;
height: 150px; height: 150px;
top: 201px; top: 202px;
left: 146px; left: 147px;
border: 1px solid blue; border: 2px solid red;
} }
.menu2 { .menu2 {
width: 100px; width: 100px;
height: 30px; height: 30px;
top: 119px; top: 118px;
left: 146px; left: 147px;
border: 1px solid blue; border: 2px solid red;
} }
</style> </style>

View file

@ -7,8 +7,9 @@
<div> <div>
<p>Expected: A green box, color-inverted inside the short, wide box with a<br> <p>Expected: A green box, color-inverted inside the short, wide box with a<br>
blue border, and not color-inverted anywhere else. In particular, there should be<br> blue border and rounded corners, and not color-inverted anywhere else. In<br>
no color inversion inside the tall, narrow box, or anywhere outside that.</p> particular, there should be no color inversion inside the tall, narrow box,<br>
or anywhere outside that.</p>
</div> </div>
<div class="box"></div> <div class="box"></div>
<div class="navbar"> <div class="navbar">
@ -31,21 +32,22 @@ div {
height: 50px; height: 50px;
top: 150px; top: 150px;
left: 50px; left: 50px;
border: 1px solid blue; border: 2px solid blue;
backdrop-filter: invert(1); backdrop-filter: invert(1);
border-radius: 10px 20px 30px 40px;
} }
.menu { .menu {
width: 100px; width: 100px;
height: 150px; height: 150px;
top: 50px; top: 50px;
left: 95px; left: 95px;
border: 1px solid blue; border: 2px solid red;
} }
.menu2 { .menu2 {
width: 100px; width: 100px;
height: 30px; height: 30px;
top: -32px; top: -34px;
left: 95px; left: 95px;
border: 1px solid blue; border: 2px solid red;
} }
</style> </style>

View file

@ -7,8 +7,9 @@
<div> <div>
<p>Expected: A green box, color-inverted inside the short, wide box with a<br> <p>Expected: A green box, color-inverted inside the short, wide box with a<br>
blue border, and not color-inverted anywhere else. In particular, there should be<br> blue border and rounded corners, and not color-inverted anywhere else. In<br>
no color inversion inside the tall, narrow box, or anywhere outside that.</p> particular, there should be no color inversion inside the tall, narrow box,<br>
or anywhere outside that.</p>
</div> </div>
<div class="box"></div> <div class="box"></div>
<div class="navbar"> <div class="navbar">
@ -43,21 +44,22 @@ div {
height: 50px; height: 50px;
top: 150px; top: 150px;
left: 50px; left: 50px;
border: 1px solid blue; border: 2px solid blue;
backdrop-filter: url(#svgInvert); backdrop-filter: url(#svgInvert);
border-radius: 10px 20px 30px 40px;
} }
.menu { .menu {
width: 100px; width: 100px;
height: 150px; height: 150px;
top: 50px; top: 50px;
left: 95px; left: 95px;
border: 1px solid blue; border: 2px solid red;
} }
.menu2 { .menu2 {
width: 100px; width: 100px;
height: 30px; height: 30px;
top: -32px; top: -34px;
left: 95px; left: 95px;
border: 1px solid blue; border: 2px solid red;
} }
</style> </style>

View file

@ -373,6 +373,10 @@ var validSelectors = [
{name: "Syntax, group of selectors separator, whitespace after", selector: "#group em,\t\r\n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, {name: "Syntax, group of selectors separator, whitespace after", selector: "#group em,\t\r\n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
{name: "Syntax, group of selectors separator, whitespace before", selector: "#group em\t\r\n,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, {name: "Syntax, group of selectors separator, whitespace before", selector: "#group em\t\r\n,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
{name: "Syntax, group of selectors separator, no whitespace", selector: "#group em,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, {name: "Syntax, group of selectors separator, no whitespace", selector: "#group em,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
// ::slotted (shouldn't match anything, but is a valid selector)
{name: "Slotted selector", selector: "::slotted(foo)", expect: [], level: 3, testType: TEST_QSA},
{name: "Slotted selector (no matching closing paren)", selector: "::slotted(foo", expect: [], level: 3, testType: TEST_QSA},
]; ];

View file

@ -18,6 +18,7 @@
const img = document.createElement('img'); const img = document.createElement('img');
img.src = 'resources/square20.jpg'; img.src = 'resources/square20.jpg';
img.setAttribute('elementtiming', 'my_image'); img.setAttribute('elementtiming', 'my_image');
img.setAttribute('id', 'my_id');
document.body.appendChild(img); document.body.appendChild(img);
window.onload = t.step_func_done( () => { window.onload = t.step_func_done( () => {
const entries = performance.getEntriesByType('element'); const entries = performance.getEntriesByType('element');
@ -27,7 +28,8 @@
const index = window.location.href.lastIndexOf('/'); const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index) + const pathname = window.location.href.substring(0, index) +
'/resources/square20.jpg'; '/resources/square20.jpg';
checkElement(entry, pathname, 'my_image', beforeRender); checkElement(entry, pathname, 'my_image', 'my_id', beforeRender);
checkNaturalSize(entry, 20, 20);
}); });
}, "Element Timing: image loads before onload."); }, "Element Timing: image loads before onload.");

View file

@ -18,10 +18,11 @@ body {
t.step_func_done((entryList) => { t.step_func_done((entryList) => {
assert_equals(entryList.getEntries().length, 1); assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0]; const entry = entryList.getEntries()[0];
checkElement(entry, pathname, 'my_image', 0); checkElement(entry, pathname, 'my_image', 'the_id', 0);
assert_equals(entry.startTime, 0, assert_equals(entry.startTime, 0,
'The startTime of a cross-origin image should be 0.'); 'The startTime of a cross-origin image should be 0.');
checkRect(entry, [0, 100, 0, 100]); checkRect(entry, [0, 100, 0, 100]);
checkNaturalSize(entry, 100, 100);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
@ -33,6 +34,7 @@ body {
const img = document.createElement('img'); const img = document.createElement('img');
img.src = pathname; img.src = pathname;
img.setAttribute('elementtiming', 'my_image'); img.setAttribute('elementtiming', 'my_image');
img.setAttribute('id', 'the_id');
document.body.appendChild(img); document.body.appendChild(img);
}); });
}, 'Cross-origin image element is NOT observable.'); }, 'Cross-origin image element is NOT observable.');

View file

@ -19,9 +19,10 @@ body {
t.step_func_done((entryList) => { t.step_func_done((entryList) => {
assert_equals(entryList.getEntries().length, 1); assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0]; const entry = entryList.getEntries()[0];
checkElement(entry, img_src, 'my_image', beforeRender); checkElement(entry, img_src, 'my_image', 'my_id', beforeRender);
// Assume viewport has size at least 20, so the element is fully visible. // Assume viewport has size at least 20, so the element is fully visible.
checkRect(entry, [0, 20, 0, 20]); checkRect(entry, [0, 20, 0, 20]);
checkNaturalSize(entry, 20, 20);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
@ -32,6 +33,7 @@ body {
const img = document.createElement('img'); const img = document.createElement('img');
img.src = img_src; img.src = img_src;
img.setAttribute('elementtiming', 'my_image'); img.setAttribute('elementtiming', 'my_image');
img.setAttribute('id', 'my_id');
img.onload = t.step_func(() => { img.onload = t.step_func(() => {
// After a short delay, assume that the entry was not dispatched. // After a short delay, assume that the entry was not dispatched.
t.step_timeout(() => { t.step_timeout(() => {

View file

@ -17,10 +17,10 @@ body {
<div class="slideshow-container"> <div class="slideshow-container">
<div class='carousel-image'> <div class='carousel-image'>
<img src="resources/circle.svg" elementtiming='image0'> <img src="resources/circle.svg" elementtiming='image0' id='image0'>
</div> </div>
<div class='carousel-image'> <div class='carousel-image'>
<img src="resources/square100.png" elementtiming='image1'> <img src="resources/square100.png" elementtiming='image1' id='image1'>
</div> </div>
</div> </div>
@ -37,13 +37,15 @@ body {
const observer = new PerformanceObserver(list => { const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => { list.getEntries().forEach(entry => {
if (entry_count % 2 == 0) { if (entry_count % 2 == 0) {
checkElement(entry, pathname0, 'image0', beforeRenderTimes[entry_count]); checkElement(entry, pathname0, 'image0', 'image0', beforeRenderTimes[entry_count]);
checkRect(entry, [0, 200, 0, 200]); checkRect(entry, [0, 200, 0, 200]);
checkNaturalSize(entry, 200, 200);
entry_count_per_element[0]++; entry_count_per_element[0]++;
} }
else { else {
checkElement(entry, pathname1, 'image1', beforeRenderTimes[entry_count]); checkElement(entry, pathname1, 'image1', 'image1', beforeRenderTimes[entry_count]);
checkRect(entry, [0, 100, 0, 100]); checkRect(entry, [0, 100, 0, 100]);
checkNaturalSize(entry, 100, 100);
entry_count_per_element[1]++; entry_count_per_element[1]++;
} }
entry_count++; entry_count++;

View file

@ -14,9 +14,10 @@ async_test(function (t) {
const index = window.location.href.lastIndexOf('/'); const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index) + const pathname = window.location.href.substring(0, index) +
'/resources/circle.svg'; '/resources/circle.svg';
checkElement(entry, pathname, 'my_svg', beforeRender); checkElement(entry, pathname, 'my_svg', 'SVG', beforeRender);
// Image size is 200x200 but SVG size is 100x100 so it is clipped. // Image size is 200x200 but SVG size is 100x100 so it is clipped.
checkRect(entry, [0, 100, 0, 100]); checkRect(entry, [0, 100, 0, 100]);
checkNaturalSize(entry, 200, 200);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
@ -29,5 +30,5 @@ body {
} }
</style> </style>
<svg width="100" height="100"> <svg width="100" height="100">
<image href='resources/circle.svg' elementtiming='my_svg'/> <image href='resources/circle.svg' elementtiming='my_svg' id='SVG'/>
</svg> </svg>

View file

@ -20,11 +20,12 @@ body {
const index = window.location.href.lastIndexOf('/'); const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index) + const pathname = window.location.href.substring(0, index) +
'/resources/square20.png'; '/resources/square20.png';
checkElement(entry, pathname, 'not_fully_visible', beforeRender); checkElement(entry, pathname, 'not_fully_visible', '', beforeRender);
// Image will not be fully visible. It should start from the top left part // Image will not be fully visible. It should start from the top left part
// of the document, excluding the margin, and then overflow. // of the document, excluding the margin, and then overflow.
checkRect(entry, checkRect(entry,
[100, document.documentElement.clientWidth, 200, document.documentElement.clientHeight]); [100, document.documentElement.clientWidth, 200, document.documentElement.clientHeight]);
checkNaturalSize(entry, 20, 20);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});

View file

@ -20,6 +20,9 @@ body {
assert_equals(rect.right, 100); assert_equals(rect.right, 100);
assert_equals(rect.top, 0); assert_equals(rect.top, 0);
assert_equals(rect.bottom, 100); assert_equals(rect.bottom, 100);
assert_equals(e.data.naturalWidth, 100);
assert_equals(e.data.naturalHeight, 100);
assert_equals(e.data.id, 'iframe_img_id');
t.done(); t.done();
}); });
}, 'Element Timing entry in iframe has coordinates relative to the iframe.'); }, 'Element Timing entry in iframe has coordinates relative to the iframe.');

View file

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Element Timing: image with scaling.</title>
<head>
<style>
/* The margin of 50px allows the rect to be fully shown when the div is scaled. */
body {
margin: 50px;
}
.my_div {
width: 100px;
height: 50px;
transform: scale(2);
}
</style>
</head>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<script>
const beforeRender = performance.now();
async_test(function (t) {
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index - 14) +
'images/black-rectangle.png';
checkElement(entry, pathname, 'rectangle', 'rect_id', beforeRender);
checkRect(entry, [0, 200, 25, 125]);
checkNaturalSize(entry, 100, 50);
})
);
observer.observe({entryTypes: ['element']});
}, 'Image intersectionRect is affected by scaling, but not its intrinsic size.');
</script>
<div class="my_div" id='div_id'>
<img src="/images/black-rectangle.png" elementtiming="rectangle" id='rect_id'/>
</div>
</body>

View file

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Element Timing: image with rotation.</title>
<head>
<style>
body {
margin: 0px;
}
.my_div {
width: 100px;
height: 50px;
transform: rotate(45deg);
transform-origin: top left;
}
</style>
</head>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<script>
const beforeRender = performance.now();
async_test(function (t) {
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index - 14) +
'images/black-rectangle.png';
checkElement(entry, pathname, 'rectangle', 'rect_id', beforeRender);
checkNaturalSize(entry, 100, 50);
const rect = entry.intersectionRect;
// The div rotates with respect to the origin, so part of it will be invisible.
// The width of the visible part will be 100 / sqrt(2) and the height will be
// 100 / sqrt(2) + 50 / sqrt(2).
assert_equals(rect.left, 0);
// Checking precision only to the nearest integer.
assert_equals(Math.round(rect.right), 71);
assert_equals(rect.top, 0);
assert_equals(Math.round(rect.bottom), 106);
})
);
observer.observe({entryTypes: ['element']});
}, 'Image intersectionRect is affected by rotation, but not its intrinsic size.');
</script>
<div class="my_div" id="div_id">
<img src="/images/black-rectangle.png" elementtiming="rectangle" id="rect_id"/>
</div>
</body>

View file

@ -22,7 +22,8 @@ body {
const observer = new PerformanceObserver( const observer = new PerformanceObserver(
t.step_func(function(entryList) { t.step_func(function(entryList) {
entryList.getEntries().forEach(entry => { entryList.getEntries().forEach(entry => {
checkElement(entry, pathname, entry.identifier, beforeRender); checkElement(entry, pathname, entry.identifier, 'image_id', beforeRender);
checkNaturalSize(entry, 100, 100);
if (entry.identifier === 'my_image') { if (entry.identifier === 'my_image') {
++numEntries; ++numEntries;
responseEnd1 = entry.responseEnd; responseEnd1 = entry.responseEnd;
@ -46,11 +47,13 @@ body {
const img = document.createElement('img'); const img = document.createElement('img');
img.src = 'resources/square100.png'; img.src = 'resources/square100.png';
img.setAttribute('elementtiming', 'my_image'); img.setAttribute('elementtiming', 'my_image');
img.setAttribute('id', 'image_id');
document.body.appendChild(img); document.body.appendChild(img);
const img2 = document.createElement('img'); const img2 = document.createElement('img');
img2.src = 'resources/square100.png'; img2.src = 'resources/square100.png';
img2.setAttribute('elementtiming', 'my_image2'); img2.setAttribute('elementtiming', 'my_image2');
img2.setAttribute('id', 'image_id');
document.body.appendChild(img2); document.body.appendChild(img2);
beforeRender = performance.now(); beforeRender = performance.now();

View file

@ -20,19 +20,21 @@ body {
const index = window.location.href.lastIndexOf('/'); const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index) + const pathname = window.location.href.substring(0, index) +
'/resources/square100.png'; '/resources/square100.png';
checkElement(entry, pathname, 'my_image', beforeRender); checkElement(entry, pathname, 'my_image', 'my_id', beforeRender);
// Assume viewport has size at least 100, so the element is fully visible. // Assume viewport has size at least 100, so the element is fully visible.
checkRect(entry, [0, 100, 0, 100]); checkRect(entry, [0, 100, 0, 100]);
checkNaturalSize(entry, 100, 100);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
// We add the image during onload to be sure that the observer is registered // We add the image during onload to be sure that the observer is registered
// in time for it to observe the element timing. // in time for it to observe the element timing.
window.onload = () => { window.onload = () => {
// Add image of width and height equal to 100. // Add image of width equal to 100 and height equal to 100.
const img = document.createElement('img'); const img = document.createElement('img');
img.src = 'resources/square100.png'; img.src = 'resources/square100.png';
img.setAttribute('elementtiming', 'my_image'); img.setAttribute('elementtiming', 'my_image');
img.setAttribute('id', 'my_id');
document.body.appendChild(img); document.body.appendChild(img);
beforeRender = performance.now(); beforeRender = performance.now();
}; };

View file

@ -20,10 +20,11 @@ body {
const index = window.location.href.lastIndexOf('/'); const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index) + const pathname = window.location.href.substring(0, index) +
'/resources/square20.jpg'; '/resources/square20.jpg';
checkElement(entry, pathname, '', beforeRender); checkElement(entry, pathname, '', 'large_one', beforeRender);
// Assume viewport hasn't changed, so the element occupies all of it. // Assume viewport hasn't changed, so the element occupies all of it.
checkRect(entry, checkRect(entry,
[0, document.documentElement.clientWidth, 0, document.documentElement.clientHeight]); [0, document.documentElement.clientWidth, 0, document.documentElement.clientHeight]);
checkNaturalSize(entry, 20, 20);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
@ -35,6 +36,7 @@ body {
img.src = 'resources/square20.jpg'; img.src = 'resources/square20.jpg';
img.width = document.documentElement.clientWidth; img.width = document.documentElement.clientWidth;
img.height = document.documentElement.clientHeight; img.height = document.documentElement.clientHeight;
img.setAttribute('id', 'large_one');
document.body.appendChild(img); document.body.appendChild(img);
beforeRender = performance.now(); beforeRender = performance.now();
}; };

View file

@ -34,7 +34,8 @@ body {
image1Observed = 1; image1Observed = 1;
const pathname1 = window.location.href.substring(0, index) + const pathname1 = window.location.href.substring(0, index) +
'/resources/square100.png'; '/resources/square100.png';
checkElement(entry, pathname1, 'image1', beforeRender); // The images do not contain ID, so expect an empty ID.
checkElement(entry, pathname1, 'image1', 'img1', beforeRender);
// This image is horizontally centered. // This image is horizontally centered.
// Using abs and comparing to 1 because the viewport sizes could be odd. // Using abs and comparing to 1 because the viewport sizes could be odd.
// If a size is odd, then image cannot be in the pure center, but left // If a size is odd, then image cannot be in the pure center, but left
@ -48,6 +49,7 @@ body {
assert_equals(entry.intersectionRect.top, 0, 'top of rect for image1'); assert_equals(entry.intersectionRect.top, 0, 'top of rect for image1');
assert_equals(entry.intersectionRect.bottom, assert_equals(entry.intersectionRect.bottom,
100, 'bottom of rect for image1'); 100, 'bottom of rect for image1');
checkNaturalSize(entry, 100, 100);
} }
else if (entry.identifier === 'image2') { else if (entry.identifier === 'image2') {
if (image2Observed) { if (image2Observed) {
@ -57,9 +59,10 @@ body {
image2Observed = 1; image2Observed = 1;
const pathname2 = window.location.href.substring(0, index) + const pathname2 = window.location.href.substring(0, index) +
'/resources/square20.png'; '/resources/square20.png';
checkElement(entry, pathname2, 'image2', beforeRender); checkElement(entry, pathname2, 'image2', 'img2', beforeRender);
// This image should be below image 1, and should respect the margin. // This image should be below image 1, and should respect the margin.
checkRect(entry, [50, 250, 250, 450], "of image2"); checkRect(entry, [50, 250, 250, 450], "of image2");
checkNaturalSize(entry, 20, 20);
} }
else if (entry.identifier === 'image3') { else if (entry.identifier === 'image3') {
if (image3Observed) { if (image3Observed) {
@ -69,9 +72,10 @@ body {
image3Observed = 1; image3Observed = 1;
const pathname3 = window.location.href.substring(0, index) + const pathname3 = window.location.href.substring(0, index) +
'/resources/circle.svg'; '/resources/circle.svg';
checkElement(entry, pathname3, 'image3', beforeRender); checkElement(entry, pathname3, 'image3', 'img3', beforeRender);
// This image is just to the right of image2. // This image is just to the right of image2.
checkRect(entry, [250, 450, 250, 450], "of image3"); checkRect(entry, [250, 450, 250, 450], "of image3");
checkNaturalSize(entry, 200, 200);
} }
else { else {
assert_unreached("Received an unexpected identifier."); assert_unreached("Received an unexpected identifier.");
@ -87,6 +91,7 @@ body {
function addImage(number, source, width=0) { function addImage(number, source, width=0) {
const img = document.createElement('img'); const img = document.createElement('img');
img.src = source; img.src = source;
// Set a different id and elementtiming value for each image.
img.id = 'img' + number; img.id = 'img' + number;
img.setAttribute('elementtiming', 'image' + number); img.setAttribute('elementtiming', 'image' + number);
if (width !== 0) if (width !== 0)

View file

@ -14,9 +14,10 @@ async_test(function (t) {
const index = window.location.href.lastIndexOf('/'); const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index) + const pathname = window.location.href.substring(0, index) +
'/resources/circle.svg'; '/resources/circle.svg';
checkElement(entry, pathname, 'my_svg', beforeRender); checkElement(entry, pathname, 'my_svg', 'svg_id', beforeRender);
// Assume viewport has size at least 200, so the element is fully visible. // Assume viewport has size at least 200, so the element is fully visible.
checkRect(entry, [0, 200, 0, 200]); checkRect(entry, [0, 200, 0, 200]);
checkNaturalSize(entry, 200, 200);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
@ -29,5 +30,5 @@ body {
} }
</style> </style>
<svg width="300" height="300"> <svg width="300" height="300">
<image href='resources/circle.svg' elementtiming='my_svg'/> <image href='resources/circle.svg' elementtiming='my_svg' id='svg_id'/>
</svg> </svg>

View file

@ -14,9 +14,10 @@ async_test(function (t) {
const index = window.location.href.lastIndexOf('/'); const index = window.location.href.lastIndexOf('/');
const pathname = window.location.href.substring(0, index) + const pathname = window.location.href.substring(0, index) +
'/resources/circle.svg'; '/resources/circle.svg';
checkElement(entry, pathname, 'my_poster', beforeRender); checkElement(entry, pathname, 'my_poster', 'the_poster', beforeRender);
// Assume viewport has size at least 200, so the element is fully visible. // Assume viewport has size at least 200, so the element is fully visible.
checkRect(entry, [0, 200, 0, 200]); checkRect(entry, [0, 200, 0, 200]);
checkNaturalSize(entry, 200, 200);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
@ -28,4 +29,4 @@ body {
margin: 0; margin: 0;
} }
</style> </style>
<video elementtiming='my_poster' src='/media/test.mp4' poster='resources/circle.svg'/> <video elementtiming='my_poster' id='the_poster' src='/media/test.mp4' poster='resources/circle.svg'/>

View file

@ -24,7 +24,8 @@
img_src; img_src;
// Since the image is only fully loaded after the sleep, the render timestamp // Since the image is only fully loaded after the sleep, the render timestamp
// must be greater than |beforeRender| + |sleep|. // must be greater than |beforeRender| + |sleep|.
checkElement(entry, pathname, 'my_image', beforeRender + sleep); checkElement(entry, pathname, 'my_image', '', beforeRender + sleep);
checkNaturalSize(entry, 20, 20);
}) })
); );
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});

View file

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Element Timing: observe a rectangular image</title>
<body>
<style>
body {
margin: 20px;
}
</style>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<script>
let beforeRender;
async_test(function (t) {
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
const index = window.location.href.lastIndexOf('/');
// Subtracting 14 to remove 'element-timing'.
const pathname = window.location.href.substring(0, index - 14) +
'images/black-rectangle.png';
checkElement(entry, pathname, 'my_image', 'rectangle', beforeRender);
// Assume viewport has size at least 100, so the element is fully visible.
checkRect(entry, [20, 120, 20, 70]);
checkNaturalSize(entry, 100, 50);
})
);
observer.observe({entryTypes: ['element']});
// We add the image during onload to be sure that the observer is registered
// in time for it to observe the element timing.
window.onload = () => {
// Add image of width equal to 100 and height equal to 50.
const img = document.createElement('img');
img.src = '/images/black-rectangle.png';
img.id = 'rectangle';
img.setAttribute('elementtiming', 'my_image');
document.body.appendChild(img);
beforeRender = performance.now();
};
}, 'Element with rectangular image has correct rect and instrinsic size.');
</script>
</body>

View file

@ -1,10 +1,11 @@
// Checks that this is an ElementTiming entry with name |expectedName|. It also // Checks that this is an ElementTiming entry with name |expectedName|. It also
// does a very basic check on |startTime|: after |beforeRender| and before now(). // does a very basic check on |startTime|: after |beforeRender| and before now().
function checkElement(entry, expectedName, expectedIdentifier, beforeRender) { function checkElement(entry, expectedName, expectedIdentifier, expectedID, beforeRender) {
assert_equals(entry.entryType, 'element'); assert_equals(entry.entryType, 'element');
assert_equals(entry.name, expectedName); assert_equals(entry.name, expectedName);
assert_equals(entry.identifier, expectedIdentifier); assert_equals(entry.identifier, expectedIdentifier);
assert_equals(entry.duration, 0); assert_equals(entry.duration, 0);
assert_equals(entry.id, expectedID);
assert_greater_than_equal(entry.startTime, beforeRender); assert_greater_than_equal(entry.startTime, beforeRender);
assert_greater_than_equal(performance.now(), entry.startTime); assert_greater_than_equal(performance.now(), entry.startTime);
const rt_entries = performance.getEntriesByName(expectedName, 'resource'); const rt_entries = performance.getEntriesByName(expectedName, 'resource');
@ -12,7 +13,7 @@ function checkElement(entry, expectedName, expectedIdentifier, beforeRender) {
assert_equals(rt_entries[0].responseEnd, entry.responseEnd); assert_equals(rt_entries[0].responseEnd, entry.responseEnd);
} }
// Checks that the rect matches the desired values [left right top bottom] // Checks that the rect matches the desired values [left right top bottom].
function checkRect(entry, expected, description="") { function checkRect(entry, expected, description="") {
assert_equals(entry.intersectionRect.left, expected[0], assert_equals(entry.intersectionRect.left, expected[0],
'left of rect ' + description); 'left of rect ' + description);
@ -23,3 +24,9 @@ function checkRect(entry, expected, description="") {
assert_equals(entry.intersectionRect.bottom, expected[3], assert_equals(entry.intersectionRect.bottom, expected[3],
'bottom of rect ' + description); 'bottom of rect ' + description);
} }
// Checks that the intrinsic size matches the desired values.
function checkNaturalSize(entry, width, height) {
assert_equals(entry.naturalWidth, width);
assert_equals(entry.naturalHeight, height);
}

View file

@ -12,10 +12,13 @@ body {
'length' : entryList.getEntries().length, 'length' : entryList.getEntries().length,
'entryType' : entryList.getEntries()[0].entryType, 'entryType' : entryList.getEntries()[0].entryType,
'rect' : entryList.getEntries()[0].intersectionRect, 'rect' : entryList.getEntries()[0].intersectionRect,
'naturalWidth' : entryList.getEntries()[0].naturalWidth,
'naturalHeight' : entryList.getEntries()[0].naturalHeight,
'id': entryList.getEntries()[0].id,
}, '*'); }, '*');
}); });
observer.observe({entryTypes: ['element']}); observer.observe({entryTypes: ['element']});
</script> </script>
<img src=square100.png elementtiming=my_image/> <img src=square100.png id=iframe_img_id elementtiming=my_image/>
</body> </body>
</html> </html>

View file

@ -8,11 +8,14 @@
// no normative requirements on what navigationUI should do, just test for // no normative requirements on what navigationUI should do, just test for
// basic support. (One could also check that the three allowed enum valid are // basic support. (One could also check that the three allowed enum valid are
// supported and no others, but that would overlap with UA-specific tests.) // supported and no others, but that would overlap with UA-specific tests.)
test(() => { promise_test(() => {
let invoked = false; let invoked = false;
document.body.requestFullscreen({ return document.body.requestFullscreen({
get navigationUI() { invoked = true; return "irrelevant-value"; } get navigationUI() { invoked = true; return "irrelevant-value"; }
}).then(() => {
assert_unreached("promise should be rejected due to invalid navigationUI value");
}, () => {
assert_true(invoked, "navigationUI getter invoked");
}); });
assert_true(invoked, "navigationUI getter invoked");
}); });
</script> </script>

View file

@ -114,8 +114,6 @@ interface HTMLElement : Element {
[CEReactions] attribute DOMString autocapitalize; [CEReactions] attribute DOMString autocapitalize;
[CEReactions] attribute [TreatNullAs=EmptyString] DOMString innerText; [CEReactions] attribute [TreatNullAs=EmptyString] DOMString innerText;
ElementInternals attachInternals();
}; };
HTMLElement includes GlobalEventHandlers; HTMLElement includes GlobalEventHandlers;
@ -178,6 +176,8 @@ interface HTMLLinkElement : HTMLElement {
[CEReactions] attribute DOMString hreflang; [CEReactions] attribute DOMString hreflang;
[CEReactions] attribute DOMString type; [CEReactions] attribute DOMString type;
[SameObject, PutForwards=value] readonly attribute DOMTokenList sizes; [SameObject, PutForwards=value] readonly attribute DOMTokenList sizes;
[CEReactions] attribute USVString imageSrcset;
[CEReactions] attribute DOMString imageSizes;
[CEReactions] attribute DOMString referrerPolicy; [CEReactions] attribute DOMString referrerPolicy;
}; };
HTMLLinkElement includes LinkStyle; HTMLLinkElement includes LinkStyle;
@ -1412,11 +1412,6 @@ dictionary ElementDefinitionOptions {
DOMString extends; DOMString extends;
}; };
[Exposed=Window]
interface ElementInternals {
};
dictionary FocusOptions { dictionary FocusOptions {
boolean preventScroll = false; boolean preventScroll = false;
}; };

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<title>Should not crash on foreignObject under clipPath</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>test(()=>{})</script>
<svg>
<clipPath>
<foreignObject>ABC</foreignObject>
</clipPath>
</svg>

View file

@ -25,7 +25,7 @@ job_path_map = {
"manifest_upload": [".*"], "manifest_upload": [".*"],
"resources_unittest": ["resources/", "tools/"], "resources_unittest": ["resources/", "tools/"],
"tools_unittest": ["tools/"], "tools_unittest": ["tools/"],
"wptrunner_unittest": ["tools/wptrunner/*"], "wptrunner_unittest": ["tools/"],
"build_css": ["css/"], "build_css": ["css/"],
"update_built": ["2dcontext/", "update_built": ["2dcontext/",
"html/", "html/",

View file

@ -74,7 +74,7 @@ def test_wptrunner_unittest():
assert jobs.get_jobs(["tools/wptrunner/wptrunner/wptrunner.py"], assert jobs.get_jobs(["tools/wptrunner/wptrunner/wptrunner.py"],
includes=["wptrunner_unittest"]) == set(["wptrunner_unittest"]) includes=["wptrunner_unittest"]) == set(["wptrunner_unittest"])
assert jobs.get_jobs(["tools/example.py"], assert jobs.get_jobs(["tools/example.py"],
includes=["wptrunner_unittest"]) == set() includes=["wptrunner_unittest"]) == set(["wptrunner_unittest"])
def test_build_css(): def test_build_css():

View file

@ -63,16 +63,12 @@ class URLManifestItem(ManifestItem):
def __init__(self, tests_root, path, url_base, url, **extras): def __init__(self, tests_root, path, url_base, url, **extras):
super(URLManifestItem, self).__init__(tests_root, path) super(URLManifestItem, self).__init__(tests_root, path)
assert url_base[0] == "/"
self.url_base = url_base self.url_base = url_base
assert url[0] != "/"
self._url = url self._url = url
self._extras = extras self._extras = extras
@property
def _source_file(self):
"""create a SourceFile for the item"""
from .sourcefile import SourceFile
return SourceFile(self._tests_root, self.path, self.url_base)
@property @property
def id(self): def id(self):
return self.url return self.url
@ -80,11 +76,6 @@ class URLManifestItem(ManifestItem):
@property @property
def url(self): def url(self):
# we can outperform urljoin, because we know we just have path relative URLs # we can outperform urljoin, because we know we just have path relative URLs
if self._url[0] == "/":
# TODO: MANIFEST6
# this is actually a bug in older generated manifests, _url shouldn't
# be an absolute path
return self._url
if self.url_base == "/": if self.url_base == "/":
return "/" + self._url return "/" + self._url
return urljoin(self.url_base, self._url) return urljoin(self.url_base, self._url)
@ -125,12 +116,7 @@ class TestharnessTest(URLManifestItem):
@property @property
def script_metadata(self): def script_metadata(self):
if "script_metadata" in self._extras: return self._extras.get("script_metadata")
return self._extras["script_metadata"]
else:
# TODO: MANIFEST6
# this branch should go when the manifest version is bumped
return self._source_file.script_metadata
def to_json(self): def to_json(self):
rv = super(TestharnessTest, self).to_json() rv = super(TestharnessTest, self).to_json()
@ -140,8 +126,7 @@ class TestharnessTest(URLManifestItem):
rv[-1]["testdriver"] = self.testdriver rv[-1]["testdriver"] = self.testdriver
if self.jsshell: if self.jsshell:
rv[-1]["jsshell"] = True rv[-1]["jsshell"] = True
if self.script_metadata is not None: if self.script_metadata:
# we store this even if it is [] to avoid having to read the source file
rv[-1]["script_metadata"] = self.script_metadata rv[-1]["script_metadata"] = self.script_metadata
return rv return rv

View file

@ -15,7 +15,7 @@ try:
except ImportError: except ImportError:
fast_json = json fast_json = json
CURRENT_VERSION = 5 CURRENT_VERSION = 6
class ManifestError(Exception): class ManifestError(Exception):
@ -68,8 +68,8 @@ class TypeData(object):
self.load(key) self.load(key)
return self.data[key] return self.data[key]
def __bool__(self): def __nonzero__(self):
return bool(self.data) return bool(self.data) or bool(self.json_data)
def __len__(self): def __len__(self):
rv = len(self.data) rv = len(self.data)
@ -86,6 +86,10 @@ class TypeData(object):
raise KeyError raise KeyError
def __setitem__(self, key, value): def __setitem__(self, key, value):
if self.json_data is not None:
path = from_os_path(key)
if path in self.json_data:
del self.json_data[path]
self.data[key] = value self.data[key] = value
def __contains__(self, key): def __contains__(self, key):

View file

@ -14,7 +14,7 @@ from ..item import URLManifestItem
"a.b.serviceworker.c.d", "a.b.serviceworker.c.d",
]) ])
def test_url_https(path): def test_url_https(path):
m = URLManifestItem("/foobar", "/" + path, "/", "/foo.bar/" + path) m = URLManifestItem("/foo", "bar/" + path, "/", "bar/" + path)
assert m.https is True assert m.https is True
@ -36,6 +36,6 @@ def test_url_https(path):
"a.serviceworkerb.c", "a.serviceworkerb.c",
]) ])
def test_url_not_https(path): def test_url_not_https(path):
m = URLManifestItem("/foobar", "/" + path, "/", "/foo.bar/" + path) m = URLManifestItem("/foo", "bar/" + path, "/", "bar/" + path)
assert m.https is False assert m.https is False

View file

@ -15,7 +15,7 @@ def SourceFileWithTest(path, hash, cls, **kwargs):
if cls == item.SupportFile: if cls == item.SupportFile:
test = cls("/foobar", path, **kwargs) test = cls("/foobar", path, **kwargs)
else: else:
test = cls("/foobar", path, "/", utils.rel_path_to_url(path), **kwargs) test = cls("/foobar", path, "/", utils.from_os_path(path), **kwargs)
s.manifest_items = mock.Mock(return_value=(cls.item_type, [test])) s.manifest_items = mock.Mock(return_value=(cls.item_type, [test]))
return s return s
@ -58,11 +58,11 @@ def sourcefile_strategy(draw):
ref_path = draw(rel_dir_file_path()) ref_path = draw(rel_dir_file_path())
h.assume(path != ref_path) h.assume(path != ref_path)
ref_eq = draw(hs.sampled_from(["==", "!="])) ref_eq = draw(hs.sampled_from(["==", "!="]))
test = cls("/foobar", path, "/", utils.rel_path_to_url(path), references=[(utils.rel_path_to_url(ref_path), ref_eq)]) test = cls("/foobar", path, "/", utils.from_os_path(path), references=[(utils.from_os_path(ref_path), ref_eq)])
elif cls is item.SupportFile: elif cls is item.SupportFile:
test = cls("/foobar", path) test = cls("/foobar", path)
else: else:
test = cls("/foobar", path, "/", utils.rel_path_to_url(path)) test = cls("/foobar", path, "/", utils.from_os_path(path))
s.manifest_items = mock.Mock(return_value=(cls.item_type, [test])) s.manifest_items = mock.Mock(return_value=(cls.item_type, [test]))
return s return s
@ -111,42 +111,36 @@ def test_manifest_to_json_forwardslash():
'paths': { 'paths': {
'a/b': ('0000000000000000000000000000000000000000', 'testharness') 'a/b': ('0000000000000000000000000000000000000000', 'testharness')
}, },
'version': 5, 'version': 6,
'url_base': '/', 'url_base': '/',
'items': { 'items': {
'testharness': { 'testharness': {
'a/b': [['/a/b', {}]] 'a/b': [['a/b', {}]]
} }
} }
} }
@pytest.mark.skipif(os.sep != "\\", reason="backslash path")
def test_manifest_to_json_backslash(): def test_manifest_to_json_backslash():
m = manifest.Manifest() m = manifest.Manifest()
s = SourceFileWithTest("a\\b", "0"*40, item.TestharnessTest) s = SourceFileWithTest("a\\b", "0"*40, item.TestharnessTest)
if os.path.sep == "\\": assert m.update([(s, True)]) is True
assert m.update([(s, True)]) is True
assert m.to_json() == { assert m.to_json() == {
'paths': { 'paths': {
'a/b': ('0000000000000000000000000000000000000000', 'testharness') 'a/b': ('0000000000000000000000000000000000000000', 'testharness')
}, },
'version': 5, 'version': 6,
'url_base': '/', 'url_base': '/',
'items': { 'items': {
'testharness': { 'testharness': {
'a/b': [['/a/b', {}]] 'a/b': [['a/b', {}]]
}
} }
} }
else: }
with pytest.raises(ValueError):
# one of these must raise ValueError
# the first must return True if it doesn't raise
assert m.update([(s, True)]) is True
m.to_json()
def test_manifest_from_json_backslash(): def test_manifest_from_json_backslash():
@ -154,11 +148,11 @@ def test_manifest_from_json_backslash():
'paths': { 'paths': {
'a\\b': ('0000000000000000000000000000000000000000', 'testharness') 'a\\b': ('0000000000000000000000000000000000000000', 'testharness')
}, },
'version': 5, 'version': 6,
'url_base': '/', 'url_base': '/',
'items': { 'items': {
'testharness': { 'testharness': {
'a\\b': [['/a/b', {}]] 'a\\b': [['a/b', {}]]
} }
} }
} }
@ -294,8 +288,8 @@ def test_iterpath():
m = manifest.Manifest() m = manifest.Manifest()
sources = [SourceFileWithTest("test1", "0"*40, item.RefTestNode, references=[("/test1-ref", "==")]), sources = [SourceFileWithTest("test1", "0"*40, item.RefTestNode, references=[("/test1-ref", "==")]),
SourceFileWithTests("test2", "1"*40, item.TestharnessTest, [("/test2-1.html",), SourceFileWithTests("test2", "1"*40, item.TestharnessTest, [("test2-1.html",),
("/test2-2.html",)]), ("test2-2.html",)]),
SourceFileWithTest("test3", "0"*40, item.TestharnessTest)] SourceFileWithTest("test3", "0"*40, item.TestharnessTest)]
m.update([(s, True) for s in sources]) m.update([(s, True) for s in sources])
@ -308,8 +302,8 @@ def test_filter():
m = manifest.Manifest() m = manifest.Manifest()
sources = [SourceFileWithTest("test1", "0"*40, item.RefTestNode, references=[("/test1-ref", "==")]), sources = [SourceFileWithTest("test1", "0"*40, item.RefTestNode, references=[("/test1-ref", "==")]),
SourceFileWithTests("test2", "0"*40, item.TestharnessTest, [("/test2-1.html",), SourceFileWithTests("test2", "0"*40, item.TestharnessTest, [("test2-1.html",),
("/test2-2.html",)]), ("test2-2.html",)]),
SourceFileWithTest("test3", "0"*40, item.TestharnessTest)] SourceFileWithTest("test3", "0"*40, item.TestharnessTest)]
m.update([(s, True) for s in sources]) m.update([(s, True) for s in sources])
@ -317,7 +311,7 @@ def test_filter():
def filter(it): def filter(it):
for test in it: for test in it:
if test[0] in ["/test2-2.html", "/test3"]: if test[0] in ["test2-2.html", "test3"]:
yield test yield test
filtered_manifest = manifest.Manifest.from_json("/", json, types=["testharness"], meta_filters=[filter]) filtered_manifest = manifest.Manifest.from_json("/", json, types=["testharness"], meta_filters=[filter])
@ -407,3 +401,26 @@ def test_update_from_json():
test1 = s1.manifest_items()[1][0] test1 = s1.manifest_items()[1][0]
assert list(m) == [("testharness", test1.path, {test1})] assert list(m) == [("testharness", test1.path, {test1})]
def test_update_from_json_modified():
# Create the original manifest
m = manifest.Manifest()
s1 = SourceFileWithTest("test1", "0"*40, item.TestharnessTest)
m.update([(s1, True)])
json_str = m.to_json()
# Reload it from JSON
m = manifest.Manifest.from_json("/", json_str)
# Update it with timeout="long"
s2 = SourceFileWithTest("test1", "1"*40, item.TestharnessTest, timeout="long")
m.update([(s2, True)])
json_str = m.to_json()
assert json_str == {
'items': {'testharness': {'test1': [['test1', {"timeout": "long"}]]}},
'paths': {'test1': ('1111111111111111111111111111111111111111',
'testharness')},
'url_base': '/',
'version': 6
}

View file

@ -33,7 +33,7 @@ def update_from_cli(**kwargs):
path = kwargs["path"] path = kwargs["path"]
assert tests_root is not None assert tests_root is not None
if kwargs["download"]: if not kwargs["rebuild"] and kwargs["download"]:
download_from_github(path, tests_root) download_from_github(path, tests_root)
manifest.load_and_update(tests_root, manifest.load_and_update(tests_root,

View file

@ -101,7 +101,7 @@ class Firefox(Browser):
product = { product = {
"nightly": "firefox-nightly-latest-ssl", "nightly": "firefox-nightly-latest-ssl",
"beta": "firefox-beta-latest-ssl", "beta": "firefox-beta-latest-ssl",
"stable": "firefox-beta-latest-ssl" "stable": "firefox-latest-ssl"
} }
os_builds = { os_builds = {
@ -267,7 +267,7 @@ class Firefox(Browser):
if version: if version:
dest = os.path.join(dest, version) dest = os.path.join(dest, version)
have_cache = False have_cache = False
if os.path.exists(dest): if os.path.exists(dest) and len(os.listdir(dest)) > 0:
if channel != "nightly": if channel != "nightly":
have_cache = True have_cache = True
else: else:

View file

@ -5,3 +5,4 @@ mozdebug==0.1.1
pillow==5.4.1 pillow==5.4.1
urllib3[secure]==1.24.1 urllib3[secure]==1.24.1
requests==2.21.0 requests==2.21.0
six>=1.8

View file

@ -2,7 +2,8 @@
xfail_strict=true xfail_strict=true
[tox] [tox]
envlist = py27-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo} envlist = py27-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo},py36-base
skip_missing_interpreters = true
[testenv] [testenv]
deps = deps =

View file

@ -1,4 +1,4 @@
import ConfigParser from six.moves.configparser import SafeConfigParser
import os import os
import sys import sys
from collections import OrderedDict from collections import OrderedDict
@ -20,7 +20,7 @@ class ConfigDict(dict):
def read(config_path): def read(config_path):
config_path = os.path.abspath(config_path) config_path = os.path.abspath(config_path)
config_root = os.path.split(config_path)[0] config_root = os.path.split(config_path)[0]
parser = ConfigParser.SafeConfigParser() parser = SafeConfigParser()
success = parser.read(config_path) success = parser.read(config_path)
assert config_path in success, success assert config_path in success, success

View file

@ -8,12 +8,16 @@ import time
from mozlog import get_default_logger, handlers, proxy from mozlog import get_default_logger, handlers, proxy
from wptlogging import LogLevelRewriter from .wptlogging import LogLevelRewriter
from wptserve.handlers import StringHandler
here = os.path.split(__file__)[0] here = os.path.split(__file__)[0]
repo_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir, os.pardir)) repo_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir, os.pardir))
sys.path.insert(0, repo_root)
from tools import localpaths # noqa: flake8
from wptserve.handlers import StringHandler
serve = None serve = None

View file

@ -1,5 +1,5 @@
# flake8: noqa (not ideal, but nicer than adding noqa: F401 to every line!) # flake8: noqa (not ideal, but nicer than adding noqa: F401 to every line!)
from base import (executor_kwargs, from .base import (executor_kwargs,
testharness_result_converter, testharness_result_converter,
reftest_result_converter, reftest_result_converter,
TestExecutor) TestExecutor)

View file

@ -1,18 +1,18 @@
import base64 import base64
import hashlib import hashlib
import httplib from six.moves.http_client import HTTPConnection
import io import io
import os import os
import threading import threading
import traceback import traceback
import socket import socket
import urlparse from six.moves.urllib.parse import urljoin, urlsplit, urlunsplit
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from PIL import Image, ImageChops, ImageStat from PIL import Image, ImageChops, ImageStat
from ..testrunner import Stop from ..testrunner import Stop
from protocol import Protocol, BaseProtocolPart from .protocol import Protocol, BaseProtocolPart
here = os.path.split(__file__)[0] here = os.path.split(__file__)[0]
@ -50,10 +50,10 @@ def strip_server(url):
e.g. http://example.org:8000/tests?id=1#2 becomes /tests?id=1#2""" e.g. http://example.org:8000/tests?id=1#2 becomes /tests?id=1#2"""
url_parts = list(urlparse.urlsplit(url)) url_parts = list(urlsplit(url))
url_parts[0] = "" url_parts[0] = ""
url_parts[1] = "" url_parts[1] = ""
return urlparse.urlunsplit(url_parts) return urlunsplit(url_parts)
class TestharnessResultConverter(object): class TestharnessResultConverter(object):
@ -213,7 +213,7 @@ class TestExecutor(object):
self.server_config["ports"][protocol][0]) self.server_config["ports"][protocol][0])
def test_url(self, test): def test_url(self, test):
return urlparse.urljoin(self.server_url(test.environment["protocol"]), test.url) return urljoin(self.server_url(test.environment["protocol"]), test.url)
@abstractmethod @abstractmethod
def do_test(self, test): def do_test(self, test):
@ -563,7 +563,7 @@ class WebDriverProtocol(Protocol):
An HTTP request to an invalid path that results in a 404 is An HTTP request to an invalid path that results in a 404 is
proof enough to us that the server is alive and kicking. proof enough to us that the server is alive and kicking.
""" """
conn = httplib.HTTPConnection(self.server.host, self.server.port) conn = HTTPConnection(self.server.host, self.server.port)
conn.request("HEAD", self.server.base_path + "invalid") conn.request("HEAD", self.server.base_path + "invalid")
res = conn.getresponse() res = conn.getresponse()
return res.status == 404 return res.status == 404

View file

@ -356,6 +356,20 @@ class WebDriverTestharnessExecutor(TestharnessExecutor):
while True: while True:
result = protocol.base.execute_script( result = protocol.base.execute_script(
self.script_resume % format_map, async=True) self.script_resume % format_map, async=True)
# As of 2019-03-29, WebDriver does not define expected behavior for
# cases where the browser crashes during script execution:
#
# https://github.com/w3c/webdriver/issues/1308
if not isinstance(result, list) or len(result) != 2:
try:
is_alive = self.is_alive()
except client.WebDriverException:
is_alive = False
if not is_alive:
raise Exception("Browser crashed during script execution.")
done, rv = handler(result) done, rv = handler(result)
if done: if done:
break break

View file

@ -1,7 +1,7 @@
import json import json
import sys import sys
from os.path import dirname, join from os.path import dirname, join
from StringIO import StringIO from six.moves import cStringIO as StringIO
from mozlog import handlers, structuredlog from mozlog import handlers, structuredlog

View file

@ -1,5 +1,5 @@
import os import os
import urlparse from six.moves.urllib.parse import urljoin
from collections import deque from collections import deque
from wptmanifest.backends import static from wptmanifest.backends import static
@ -236,8 +236,8 @@ class ExpectedManifest(ManifestItem):
@property @property
def url(self): def url(self):
return urlparse.urljoin(self.url_base, return urljoin(self.url_base,
"/".join(self.test_path.split(os.path.sep))) "/".join(self.test_path.split(os.path.sep)))
@property @property
def disabled(self): def disabled(self):
@ -364,7 +364,7 @@ class TestNode(ManifestItem):
@property @property
def id(self): def id(self):
return urlparse.urljoin(self.parent.url, self.name) return urljoin(self.parent.url, self.name)
@property @property
def disabled(self): def disabled(self):

View file

@ -6,7 +6,7 @@ be included or excluded.
""" """
import glob import glob
import os import os
import urlparse from six.moves.urllib.parse import urlparse, urlsplit
from wptmanifest.node import DataNode from wptmanifest.node import DataNode
from wptmanifest.backends import conditional from wptmanifest.backends import conditional
@ -68,7 +68,7 @@ class IncludeManifest(ManifestItem):
def _get_components(self, url): def _get_components(self, url):
rv = [] rv = []
url_parts = urlparse.urlsplit(url) url_parts = urlsplit(url)
variant = "" variant = ""
if url_parts.query: if url_parts.query:
variant += "?" + url_parts.query variant += "?" + url_parts.query
@ -103,7 +103,7 @@ class IncludeManifest(ManifestItem):
continue continue
url = test.url url = test.url
if query or fragment: if query or fragment:
parsed = urlparse.urlparse(url) parsed = urlparse(url)
if ((query and query != parsed.query) or if ((query and query != parsed.query) or
(fragment and fragment != parsed.fragment)): (fragment and fragment != parsed.fragment)):
continue continue

View file

@ -1,7 +1,7 @@
from __future__ import print_function from __future__ import print_function
import itertools import itertools
import os import os
import urlparse from six.moves.urllib.parse import urljoin
from collections import namedtuple, defaultdict from collections import namedtuple, defaultdict
from math import ceil from math import ceil
@ -114,8 +114,8 @@ class ExpectedManifest(ManifestItem):
@property @property
def url(self): def url(self):
return urlparse.urljoin(self.url_base, return urljoin(self.url_base,
"/".join(self.test_path.split(os.path.sep))) "/".join(self.test_path.split(os.path.sep)))
def set_lsan(self, run_info, result): def set_lsan(self, run_info, result):
"""Set the result of the test in a particular run """Set the result of the test in a particular run
@ -195,7 +195,7 @@ class TestNode(ManifestItem):
@property @property
def id(self): def id(self):
"""The id of the test represented by this TestNode""" """The id of the test represented by this TestNode"""
return urlparse.urljoin(self.parent.url, self.name) return urljoin(self.parent.url, self.name)
def disabled(self, run_info): def disabled(self, run_info):
"""Boolean indicating whether this test is disabled when run in an """Boolean indicating whether this test is disabled when run in an

View file

@ -8,12 +8,12 @@ from collections import defaultdict, namedtuple
from mozlog import structuredlog from mozlog import structuredlog
import manifestupdate from . import manifestupdate
import testloader from . import testloader
import wptmanifest from . import wptmanifest
import wpttest from . import wpttest
from expected import expected_path from .expected import expected_path
from vcs import git from .vcs import git
manifest = None # Module that will be imported relative to test_root manifest = None # Module that will be imported relative to test_root
manifestitem = None manifestitem = None

View file

@ -1,14 +1,14 @@
import hashlib import hashlib
import os import os
import urlparse from six.moves.urllib.parse import urlsplit
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from Queue import Empty from six.moves.queue import Empty
from collections import defaultdict, deque from collections import defaultdict, deque
from multiprocessing import Queue from multiprocessing import Queue
import manifestinclude from . import manifestinclude
import manifestexpected from . import manifestexpected
import wpttest from . import wpttest
from mozlog import structured from mozlog import structured
manifest = None manifest = None
@ -348,7 +348,7 @@ class PathGroupedSource(GroupedSource):
depth = kwargs.get("depth") depth = kwargs.get("depth")
if depth is True or depth == 0: if depth is True or depth == 0:
depth = None depth = None
path = urlparse.urlsplit(test.url).path.split("/")[1:-1][:depth] path = urlsplit(test.url).path.split("/")[1:-1][:depth]
rv = path != state.get("prev_path") rv = path != state.get("prev_path")
state["prev_path"] = path state["prev_path"] = path
return rv return rv

View file

@ -3,7 +3,7 @@ from __future__ import unicode_literals
import multiprocessing import multiprocessing
import threading import threading
import traceback import traceback
from Queue import Empty from six.moves.queue import Empty
from collections import namedtuple from collections import namedtuple
from multiprocessing import Process, current_process, Queue from multiprocessing import Process, current_process, Queue

View file

@ -7,7 +7,7 @@ import pytest
sys.path.insert(0, join(dirname(__file__), "..", "..")) sys.path.insert(0, join(dirname(__file__), "..", ".."))
from wptrunner import browsers from .. import browsers
_products = browsers.product_list _products = browsers.product_list

View file

@ -1,17 +1,13 @@
import json import json
import sys
import time import time
from os.path import dirname, join from six.moves import cStringIO as StringIO
from StringIO import StringIO
import mock import mock
from mozlog import handlers, structuredlog from mozlog import handlers, structuredlog
sys.path.insert(0, join(dirname(__file__), "..", "..")) from ..formatters import wptreport
from ..formatters.wptreport import WptreportFormatter
from wptrunner.formatters import wptreport
from wptrunner.formatters.wptreport import WptreportFormatter
def test_wptreport_runtime(capfd): def test_wptreport_runtime(capfd):

View file

@ -1,14 +1,13 @@
import os
import sys import sys
from io import BytesIO from io import BytesIO
import pytest import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..")) from .. import manifestexpected
from wptrunner import manifestexpected
@pytest.mark.xfail(sys.version[0] == "3",
reason="bytes/text confusion in py3")
@pytest.mark.parametrize("fuzzy, expected", [ @pytest.mark.parametrize("fuzzy, expected", [
(b"ref.html:1;200", [("ref.html", ((1, 1), (200, 200)))]), (b"ref.html:1;200", [("ref.html", ((1, 1), (200, 200)))]),
(b"ref.html:0-1;100-200", [("ref.html", ((0, 1), (100, 200)))]), (b"ref.html:0-1;100-200", [("ref.html", ((0, 1), (100, 200)))]),

View file

@ -1,17 +1,12 @@
import sys
from os.path import join, dirname from os.path import join, dirname
import mock import mock
import pytest import pytest
import sys
from .base import all_products, active_products from .base import all_products, active_products
from .. import environment
sys.path.insert(0, join(dirname(__file__), "..", "..", "..", "..")) # repo root from .. import products
from tools import localpaths # noqa: flake8
from wptrunner import environment
from wptrunner import products
test_paths = {"/": {"tests_path": join(dirname(__file__), "..", "..", "..", "..")}} # repo root test_paths = {"/": {"tests_path": join(dirname(__file__), "..", "..", "..", "..")}} # repo root
environment.do_delayed_imports(None, test_paths) environment.do_delayed_imports(None, test_paths)
@ -24,7 +19,9 @@ def test_load_active_product(product):
# test passes if it doesn't throw # test passes if it doesn't throw
@all_products("product") @all_products("product", marks={
"firefox": pytest.mark.xfail(sys.version[0] == "3", reason="mozinfo 0.10 doesn't support py3"),
})
def test_load_all_products(product): def test_load_all_products(product):
"""test every product either loads or throws ImportError""" """test every product either loads or throws ImportError"""
try: try:

View file

@ -1,9 +1,4 @@
import sys from .. import stability
from os.path import dirname, join
sys.path.insert(0, join(dirname(__file__), "..", ".."))
from wptrunner import stability
def test_is_inconsistent(): def test_is_inconsistent():

View file

@ -1,15 +1,12 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import os
import sys import sys
import tempfile import tempfile
import pytest import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from mozlog import structured from mozlog import structured
from wptrunner.testloader import TestFilter as Filter from ..testloader import TestFilter as Filter
from .test_wpttest import make_mock_manifest from .test_wpttest import make_mock_manifest
structured.set_default_logger(structured.structuredlog.StructuredLogger("TestLoader")) structured.set_default_logger(structured.structuredlog.StructuredLogger("TestLoader"))
@ -23,6 +20,8 @@ skip: true
@pytest.mark.xfail(sys.platform == "win32", @pytest.mark.xfail(sys.platform == "win32",
reason="NamedTemporaryFile cannot be reopened on Win32") reason="NamedTemporaryFile cannot be reopened on Win32")
@pytest.mark.xfail(sys.version[0] == "3",
reason="wptmanifest.parser doesn't support py3")
def test_filter_unicode(): def test_filter_unicode():
tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10), tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10),
("test", "c", 10)) ("test", "c", 10))

View file

@ -1,6 +1,7 @@
import json import json
import mock import mock
import os import os
import pytest
import sys import sys
from io import BytesIO from io import BytesIO
@ -13,18 +14,14 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
from manifest import manifest, item as manifest_item from manifest import manifest, item as manifest_item
def rel_path_to_url(rel_path, url_base="/"): def rel_path_to_test_url(rel_path):
assert not os.path.isabs(rel_path) assert not os.path.isabs(rel_path)
if url_base[0] != "/": return rel_path.replace(os.sep, "/")
url_base = "/" + url_base
if url_base[-1] != "/":
url_base += "/"
return url_base + rel_path.replace(os.sep, "/")
def SourceFileWithTest(path, hash, cls, *args): def SourceFileWithTest(path, hash, cls, *args):
s = mock.Mock(rel_path=path, hash=hash) s = mock.Mock(rel_path=path, hash=hash)
test = cls("/foobar", path, "/", rel_path_to_url(path), *args) test = cls("/foobar", path, "/", rel_path_to_test_url(path), *args)
s.manifest_items = mock.Mock(return_value=(cls.item_type, [test])) s.manifest_items = mock.Mock(return_value=(cls.item_type, [test]))
return s return s
@ -101,6 +98,8 @@ def create_test_manifest(tests, url_base="/"):
return m return m
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_0(): def test_update_0():
tests = [("path/to/test.htm", ["/path/to/test.htm"], "testharness", tests = [("path/to/test.htm", ["/path/to/test.htm"], "testharness",
"""[test.htm] """[test.htm]
@ -121,6 +120,8 @@ def test_update_0():
assert updated[0][1].is_empty assert updated[0][1].is_empty
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_1(): def test_update_1():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", tests = [("path/to/test.htm", [test_id], "testharness",
@ -143,6 +144,8 @@ def test_update_1():
assert new_manifest.get_test(test_id).children[0].get("expected") == "FAIL" assert new_manifest.get_test(test_id).children[0].get("expected") == "FAIL"
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_skip_0(): def test_skip_0():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", tests = [("path/to/test.htm", [test_id], "testharness",
@ -162,6 +165,8 @@ def test_skip_0():
assert not updated assert not updated
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_new_subtest(): def test_new_subtest():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -186,6 +191,8 @@ def test_new_subtest():
assert new_manifest.get_test(test_id).children[1].get("expected") == "FAIL" assert new_manifest.get_test(test_id).children[1].get("expected") == "FAIL"
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_multiple_0(): def test_update_multiple_0():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -220,6 +227,8 @@ def test_update_multiple_0():
"expected", {"debug": False, "os": "linux"}) == "TIMEOUT" "expected", {"debug": False, "os": "linux"}) == "TIMEOUT"
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_multiple_1(): def test_update_multiple_1():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -256,6 +265,8 @@ def test_update_multiple_1():
"expected", {"debug": False, "os": "windows"}) == "FAIL" "expected", {"debug": False, "os": "windows"}) == "FAIL"
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_multiple_2(): def test_update_multiple_2():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -290,6 +301,8 @@ def test_update_multiple_2():
"expected", {"debug": True, "os": "osx"}) == "TIMEOUT" "expected", {"debug": True, "os": "osx"}) == "TIMEOUT"
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_multiple_3(): def test_update_multiple_3():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -326,6 +339,8 @@ def test_update_multiple_3():
"expected", {"debug": True, "os": "osx"}) == "TIMEOUT" "expected", {"debug": True, "os": "osx"}) == "TIMEOUT"
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_ignore_existing(): def test_update_ignore_existing():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -362,6 +377,8 @@ def test_update_ignore_existing():
"expected", {"debug": False, "os": "osx"}) == "NOTRUN" "expected", {"debug": False, "os": "osx"}) == "NOTRUN"
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_assertion_count_0(): def test_update_assertion_count_0():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -385,6 +402,8 @@ def test_update_assertion_count_0():
assert new_manifest.get_test(test_id).get("min-asserts") == 2 assert new_manifest.get_test(test_id).get("min-asserts") == 2
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_assertion_count_1(): def test_update_assertion_count_1():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -408,6 +427,8 @@ def test_update_assertion_count_1():
assert new_manifest.get_test(test_id).has_key("min-asserts") is False assert new_manifest.get_test(test_id).has_key("min-asserts") is False
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_assertion_count_2(): def test_update_assertion_count_2():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -427,6 +448,8 @@ def test_update_assertion_count_2():
assert not updated assert not updated
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_assertion_count_3(): def test_update_assertion_count_3():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]
@ -460,6 +483,8 @@ def test_update_assertion_count_3():
assert new_manifest.get_test(test_id).get("min-asserts") == 2 assert new_manifest.get_test(test_id).get("min-asserts") == 2
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_assertion_count_4(): def test_update_assertion_count_4():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]""")] tests = [("path/to/test.htm", [test_id], "testharness", """[test.htm]""")]
@ -490,6 +515,8 @@ def test_update_assertion_count_4():
assert new_manifest.get_test(test_id).has_key("min-asserts") is False assert new_manifest.get_test(test_id).has_key("min-asserts") is False
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_lsan_0(): def test_update_lsan_0():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -507,6 +534,8 @@ def test_update_lsan_0():
assert new_manifest.get("lsan-allowed") == ["foo"] assert new_manifest.get("lsan-allowed") == ["foo"]
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_lsan_1(): def test_update_lsan_1():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -527,6 +556,8 @@ lsan-allowed: [foo]""")]
assert new_manifest.get("lsan-allowed") == ["baz", "foo"] assert new_manifest.get("lsan-allowed") == ["baz", "foo"]
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_lsan_2(): def test_update_lsan_2():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -549,6 +580,8 @@ lsan-allowed: [foo]"""),
assert new_manifest.get("lsan-allowed") == ["baz"] assert new_manifest.get("lsan-allowed") == ["baz"]
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_lsan_3(): def test_update_lsan_3():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -571,6 +604,8 @@ def test_update_lsan_3():
assert new_manifest.get("lsan-allowed") == ["baz", "foo"] assert new_manifest.get("lsan-allowed") == ["baz", "foo"]
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_wptreport_0(): def test_update_wptreport_0():
tests = [("path/to/test.htm", ["/path/to/test.htm"], "testharness", tests = [("path/to/test.htm", ["/path/to/test.htm"], "testharness",
"""[test.htm] """[test.htm]
@ -591,6 +626,8 @@ def test_update_wptreport_0():
assert updated[0][1].is_empty assert updated[0][1].is_empty
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_wptreport_1(): def test_update_wptreport_1():
tests = [("path/to/test.htm", ["/path/to/test.htm"], "testharness", ""), tests = [("path/to/test.htm", ["/path/to/test.htm"], "testharness", ""),
("path/to/__dir__", ["path/to/__dir__"], None, "")] ("path/to/__dir__", ["path/to/__dir__"], None, "")]
@ -606,6 +643,8 @@ def test_update_wptreport_1():
assert updated[0][1].get("lsan-allowed") == ["baz"] assert updated[0][1].get("lsan-allowed") == ["baz"]
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_leak_total_0(): def test_update_leak_total_0():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -625,6 +664,8 @@ def test_update_leak_total_0():
assert new_manifest.get("leak-threshold") == ['default:51200'] assert new_manifest.get("leak-threshold") == ['default:51200']
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_leak_total_1(): def test_update_leak_total_1():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -641,6 +682,8 @@ def test_update_leak_total_1():
assert not updated assert not updated
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_leak_total_2(): def test_update_leak_total_2():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -658,6 +701,8 @@ leak-total: 110""")]
assert not updated assert not updated
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_leak_total_3(): def test_update_leak_total_3():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -678,6 +723,8 @@ leak-total: 100""")]
assert new_manifest.get("leak-threshold") == ['default:51200'] assert new_manifest.get("leak-threshold") == ['default:51200']
@pytest.mark.xfail(sys.version[0] == "3",
reason="metadata doesn't support py3")
def test_update_leak_total_4(): def test_update_leak_total_4():
test_id = "/path/to/test.htm" test_id = "/path/to/test.htm"
dir_id = "path/to/__dir__" dir_id = "path/to/__dir__"
@ -710,6 +757,8 @@ class TestStep(Step):
class UpdateRunner(StepRunner): class UpdateRunner(StepRunner):
steps = [TestStep] steps = [TestStep]
@pytest.mark.xfail(sys.version[0] == "3",
reason="update.state doesn't support py3")
def test_update_pickle(): def test_update_pickle():
logger = structuredlog.StructuredLogger("expected_test") logger = structuredlog.StructuredLogger("expected_test")
args = { args = {

View file

@ -1,14 +1,11 @@
import os import pytest
import sys import sys
from io import BytesIO from io import BytesIO
from mock import Mock from mock import Mock
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from manifest import manifest as wptmanifest from manifest import manifest as wptmanifest
from manifest.item import TestharnessTest from manifest.item import TestharnessTest
from wptrunner import manifestexpected, wpttest from .. import manifestexpected, wpttest
dir_ini_0 = """\ dir_ini_0 = """\
prefs: [a:b] prefs: [a:b]
@ -69,6 +66,8 @@ def make_mock_manifest(*items):
return rv return rv
@pytest.mark.xfail(sys.version[0] == "3",
reason="bytes/text confusion in py3")
def test_metadata_inherit(): def test_metadata_inherit():
tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10), tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10),
("test", "c", 10)) ("test", "c", 10))
@ -93,6 +92,8 @@ def test_metadata_inherit():
assert test_obj.tags == {"a", "dir:a"} assert test_obj.tags == {"a", "dir:a"}
@pytest.mark.xfail(sys.version[0] == "3",
reason="bytes/text confusion in py3")
def test_conditional(): def test_conditional():
tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10), tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10),
("test", "c", 10)) ("test", "c", 10))
@ -109,6 +110,8 @@ def test_conditional():
assert test_obj.expected() == "FAIL" assert test_obj.expected() == "FAIL"
@pytest.mark.xfail(sys.version[0] == "3",
reason="bytes/text confusion in py3")
def test_metadata_lsan_stack_depth(): def test_metadata_lsan_stack_depth():
tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10)) tests = make_mock_manifest(("test", "a", 10), ("test", "a/b", 10))
@ -147,14 +150,16 @@ def test_metadata_lsan_stack_depth():
assert test_obj.lsan_max_stack_depth == 42 assert test_obj.lsan_max_stack_depth == 42
@pytest.mark.xfail(sys.version[0] == "3",
reason="bytes/text confusion in py3")
def test_metadata_fuzzy(): def test_metadata_fuzzy():
manifest_data = { manifest_data = {
"items": {"reftest": {"a/fuzzy.html": [["/a/fuzzy.html", "items": {"reftest": {"a/fuzzy.html": [["a/fuzzy.html",
[["/a/fuzzy-ref.html", "=="]], [["/a/fuzzy-ref.html", "=="]],
{"fuzzy": [[["/a/fuzzy.html", '/a/fuzzy-ref.html', '=='], {"fuzzy": [[["/a/fuzzy.html", '/a/fuzzy-ref.html', '=='],
[[2, 3], [10, 15]]]]}]]}}, [[2, 3], [10, 15]]]]}]]}},
"paths": {"a/fuzzy.html": ["0"*40, "reftest"]}, "paths": {"a/fuzzy.html": ["0"*40, "reftest"]},
"version": wptmanifest.CURRENT_VERSION, "version": 6,
"url_base": "/"} "url_base": "/"}
manifest = wptmanifest.Manifest.from_json(".", manifest_data) manifest = wptmanifest.Manifest.from_json(".", manifest_data)
test_metadata = manifestexpected.static.compile(BytesIO(test_fuzzy), test_metadata = manifestexpected.static.compile(BytesIO(test_fuzzy),

View file

@ -4,7 +4,7 @@ from mozlog.structured import structuredlog, commandline
from .. import wptcommandline from .. import wptcommandline
from update import WPTUpdate from .update import WPTUpdate
def remove_logging_args(args): def remove_logging_args(args):
"""Take logging args out of the dictionary of command line arguments so """Take logging args out of the dictionary of command line arguments so

View file

@ -2,7 +2,7 @@ import os
from .. import metadata, products from .. import metadata, products
from base import Step, StepRunner from .base import Step, StepRunner
class GetUpdatePropertyList(Step): class GetUpdatePropertyList(Step):

View file

@ -1,5 +1,5 @@
import os import os
import cPickle as pickle from six.moves import cPickle as pickle # noqa: N813
here = os.path.abspath(os.path.split(__file__)[0]) here = os.path.abspath(os.path.split(__file__)[0])

View file

@ -5,8 +5,8 @@ import shutil
import sys import sys
import uuid import uuid
from base import Step, StepRunner from .base import Step, StepRunner
from tree import Commit from .tree import Commit
here = os.path.abspath(os.path.split(__file__)[0]) here = os.path.abspath(os.path.split(__file__)[0])

View file

@ -1,12 +1,12 @@
import os import os
import sys import sys
from metadata import MetadataUpdateRunner from .metadata import MetadataUpdateRunner
from sync import SyncFromUpstreamRunner from .sync import SyncFromUpstreamRunner
from tree import GitTree, HgTree, NoVCSTree from .tree import GitTree, HgTree, NoVCSTree
from base import Step, StepRunner, exit_clean, exit_unclean from .base import Step, StepRunner, exit_clean, exit_unclean
from state import SavedState, UnsavedState from .state import SavedState, UnsavedState
def setup_paths(sync_path): def setup_paths(sync_path):
sys.path.insert(0, os.path.abspath(sync_path)) sys.path.insert(0, os.path.abspath(sync_path))

View file

@ -6,9 +6,9 @@ from collections import OrderedDict
from distutils.spawn import find_executable from distutils.spawn import find_executable
from datetime import timedelta from datetime import timedelta
import config from . import config
import wpttest from . import wpttest
from formatters import chromium, wptreport, wptscreenshot from .formatters import chromium, wptreport, wptscreenshot
def abs_path(path): def abs_path(path):
return os.path.abspath(os.path.expanduser(path)) return os.path.abspath(os.path.expanduser(path))

View file

@ -1,7 +1,7 @@
import logging import logging
import sys import sys
import threading import threading
from StringIO import StringIO from six import StringIO
from multiprocessing import Queue from multiprocessing import Queue
from mozlog import commandline, stdadapter, set_default_logger from mozlog import commandline, stdadapter, set_default_logger

View file

@ -1,5 +1,5 @@
# flake8: noqa (not ideal, but nicer than adding noqa: F401 to every line!) # flake8: noqa (not ideal, but nicer than adding noqa: F401 to every line!)
from serializer import serialize from .serializer import serialize
from parser import parse from .parser import parse
from backends.static import compile as compile_static from .backends.static import compile as compile_static
from backends.conditional import compile as compile_condition from .backends.conditional import compile as compile_condition

View file

@ -14,12 +14,12 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from cStringIO import StringIO from six.moves import cStringIO as StringIO
from node import (AtomNode, BinaryExpressionNode, BinaryOperatorNode, from .node import (AtomNode, BinaryExpressionNode, BinaryOperatorNode,
ConditionalNode, DataNode, IndexNode, KeyValueNode, ListNode, ConditionalNode, DataNode, IndexNode, KeyValueNode, ListNode,
NumberNode, StringNode, UnaryExpressionNode, NumberNode, StringNode, UnaryExpressionNode,
UnaryOperatorNode, ValueNode, VariableNode) UnaryOperatorNode, ValueNode, VariableNode)
class ParseError(Exception): class ParseError(Exception):

View file

@ -1,7 +1,7 @@
from node import NodeVisitor, ValueNode, ListNode, BinaryExpressionNode from .node import NodeVisitor, ValueNode, ListNode, BinaryExpressionNode
from parser import atoms, precedence from .parser import atoms, precedence
atom_names = {v:"@%s" % k for (k,v) in atoms.iteritems()} atom_names = {v:"@%s" % k for (k,v) in atoms.items()}
named_escapes = set(["\a", "\b", "\f", "\n", "\r", "\t", "\v"]) named_escapes = set(["\a", "\b", "\f", "\n", "\r", "\t", "\v"])

View file

@ -1,9 +1,13 @@
import pytest
import sys
import unittest import unittest
from ..backends import conditional from ..backends import conditional
from ..node import BinaryExpressionNode, BinaryOperatorNode, VariableNode, NumberNode from ..node import BinaryExpressionNode, BinaryOperatorNode, VariableNode, NumberNode
@pytest.mark.xfail(sys.version[0] == "3",
reason="wptmanifest.parser doesn't support py3")
class TestConditional(unittest.TestCase): class TestConditional(unittest.TestCase):
def compile(self, input_text): def compile(self, input_text):
return conditional.compile(input_text) return conditional.compile(input_text)

View file

@ -1,6 +1,8 @@
import pytest
import sys
import unittest import unittest
from cStringIO import StringIO from six.moves import cStringIO as StringIO
from .. import parser from .. import parser
@ -8,6 +10,8 @@ from .. import parser
# use test_serializer for the majority of cases # use test_serializer for the majority of cases
@pytest.mark.xfail(sys.version[0] == "3",
reason="wptmanifest.parser doesn't support py3")
class TestExpression(unittest.TestCase): class TestExpression(unittest.TestCase):
def setUp(self): def setUp(self):
self.parser = parser.Parser() self.parser = parser.Parser()

View file

@ -6,6 +6,8 @@ import pytest
from .. import parser, serializer from .. import parser, serializer
@pytest.mark.xfail(sys.version[0] == "3",
reason="wptmanifest.parser doesn't support py3")
class TokenizerTest(unittest.TestCase): class TokenizerTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.serializer = serializer.ManifestSerializer() self.serializer = serializer.ManifestSerializer()

View file

@ -1,3 +1,5 @@
import pytest
import sys
import unittest import unittest
from ..backends import static from ..backends import static
@ -6,6 +8,8 @@ from ..backends import static
# use test_serializer for the majority of cases # use test_serializer for the majority of cases
@pytest.mark.xfail(sys.version[0] == "3",
reason="wptmanifest.parser doesn't support py3")
class TestStatic(unittest.TestCase): class TestStatic(unittest.TestCase):
def compile(self, input_text, input_data): def compile(self, input_text, input_data):
return static.compile(input_text, input_data) return static.compile(input_text, input_data)

View file

@ -1,14 +1,15 @@
import sys import sys
import os import pytest
import unittest import unittest
sys.path.insert(0, os.path.abspath("..")) from six.moves import cStringIO as StringIO
from cStringIO import StringIO
from .. import parser from .. import parser
from ..parser import token_types from ..parser import token_types
@pytest.mark.xfail(sys.version[0] == "3",
reason="Tokenizer doesn't support py3")
class TokenizerTest(unittest.TestCase): class TokenizerTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.tokenizer = parser.Tokenizer() self.tokenizer = parser.Tokenizer()

View file

@ -1,9 +1,9 @@
import os import os
import subprocess import subprocess
import urlparse from six.moves.urllib.parse import urljoin
from collections import defaultdict from collections import defaultdict
from wptmanifest.parser import atoms from .wptmanifest.parser import atoms
atom_reset = atoms["Reset"] atom_reset = atoms["Reset"]
enabled_tests = set(["testharness", "reftest", "wdspec"]) enabled_tests = set(["testharness", "reftest", "wdspec"])
@ -473,11 +473,11 @@ class ReftestTest(Test):
values = {} values = {}
for key, data in value: for key, data in value:
if len(key) == 3: if len(key) == 3:
key[0] = urlparse.urljoin(self.url, key[0]) key[0] = urljoin(self.url, key[0])
key[1] = urlparse.urljoin(self.url, key[1]) key[1] = urljoin(self.url, key[1])
else: else:
# Key is just a relative url to a ref # Key is just a relative url to a ref
key = urlparse.urljoin(self.url, key) key = urljoin(self.url, key)
values[key] = data values[key] = data
return values return values

View file

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<title>DedicatedWorker: WorkerOptions 'credentials'</title> <title>DedicatedWorker: WorkerOptions 'credentials'</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script> <script src="/common/get-host-info.sub.js"></script>

View file

@ -46954,5 +46954,5 @@
] ]
}, },
"url_base": "/_webgl/", "url_base": "/_webgl/",
"version": 5 "version": 6
} }