diff options
author | bors-servo <servo-ops@mozilla.com> | 2020-05-21 07:14:40 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-21 07:14:40 -0400 |
commit | 87bf24139c6f7f271a7906bb3d28fbad095e21c4 (patch) | |
tree | 2b23bea4ad3fd9d7df696ce8fdac0359c4251f6a | |
parent | b22e34fb74ae5353e2fa2abe171cbbb6ee77931b (diff) | |
parent | bc7c10c2ceb71b1a0ea086aee8c0f720415fa85f (diff) | |
download | servo-87bf24139c6f7f271a7906bb3d28fbad095e21c4.tar.gz servo-87bf24139c6f7f271a7906bb3d28fbad095e21c4.zip |
Auto merge of #26605 - servo-wpt-sync:wpt_update_21-05-2020, r=servo-wpt-sync
Sync WPT with upstream (21-05-2020)
Automated downstream sync of changes from upstream as of 21-05-2020.
[no-wpt-sync]
r? @servo-wpt-sync
150 files changed, 5687 insertions, 3449 deletions
diff --git a/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-002.html.ini b/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-002.html.ini deleted file mode 100644 index f64b45fea6b..00000000000 --- a/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-002.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[hit-test-floats-002.html] - [Hit test float] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-scale-hittest.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-scale-hittest.html.ini index 4a1e8110f6f..f8e7e539aae 100644 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-scale-hittest.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-scale-hittest.html.ini @@ -2,3 +2,6 @@ [Hit test intersecting scaled box] expected: FAIL + [Hit test within unscaled box] + expected: FAIL + diff --git a/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-001.html.ini b/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-001.html.ini index 48b9e143850..5d20389c8e9 100644 --- a/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-001.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-001.html.ini @@ -1,982 +1,58 @@ [properties-value-inherit-001.html] - [top length(pt) / events] - expected: FAIL - - [border-right-width length(mm) / events] - expected: FAIL - [background-position length(pt) / values] expected: FAIL - [width length(pt) / events] - expected: FAIL - [background-position length(pt) / events] expected: FAIL - [border-bottom-width length(pc) / events] - expected: FAIL - - [height length(ex) / events] - expected: FAIL - - [padding-bottom length(mm) / events] - expected: FAIL - - [border-top-width length(px) / events] - expected: FAIL - - [border-top-width length(pt) / events] - expected: FAIL - - [padding-top length(em) / events] - expected: FAIL - - [outline-width length(pc) / events] - expected: FAIL - - [max-width length(in) / events] - expected: FAIL - - [margin-top length(cm) / events] - expected: FAIL - - [margin-right length(pt) / events] - expected: FAIL - - [right length(ex) / events] - expected: FAIL - - [vertical-align length(px) / events] - expected: FAIL - - [max-height length(em) / events] - expected: FAIL - - [width length(ex) / events] - expected: FAIL - - [border-bottom-color color(rgba) / events] - expected: FAIL - - [width percentage(%) / events] - expected: FAIL - [background-position length(px) / values] expected: FAIL - [margin-top length(ex) / events] - expected: FAIL - - [border-top-width length(in) / events] - expected: FAIL - - [right length(em) / events] - expected: FAIL - - [top length(ex) / events] - expected: FAIL - - [padding-left length(px) / events] - expected: FAIL - - [margin-top length(em) / events] - expected: FAIL - - [left length(em) / events] - expected: FAIL - - [margin-left length(px) / events] - expected: FAIL - [background-position length(cm) / events] expected: FAIL - [max-height percentage(%) / events] - expected: FAIL - - [bottom length(ex) / events] - expected: FAIL - - [padding-left length(mm) / events] - expected: FAIL - - [right length(mm) / events] - expected: FAIL - - [margin-top length(pc) / events] - expected: FAIL - [background-position length(mm) / values] expected: FAIL - [border-left-width length(pt) / events] - expected: FAIL - - [outline-offset length(mm) / events] - expected: FAIL - - [vertical-align length(in) / events] - expected: FAIL - - [border-bottom-width length(pt) / events] - expected: FAIL - - [border-bottom-width length(in) / events] - expected: FAIL - - [margin-bottom length(pc) / events] - expected: FAIL - - [border-left-width length(mm) / events] - expected: FAIL - - [height length(em) / events] - expected: FAIL - [background-position length(in) / events] expected: FAIL - [height length(cm) / events] - expected: FAIL - - [padding-top length(in) / events] - expected: FAIL - - [max-width length(ex) / events] - expected: FAIL - - [padding-top length(px) / events] - expected: FAIL - - [border-top-width length(pc) / events] - expected: FAIL - - [top length(cm) / events] - expected: FAIL - - [left length(ex) / events] - expected: FAIL - - [min-width length(ex) / events] - expected: FAIL - - [left length(pc) / events] - expected: FAIL - - [vertical-align length(em) / events] - expected: FAIL - - [left length(in) / events] - expected: FAIL - - [left length(px) / events] - expected: FAIL - - [border-bottom-width length(mm) / events] - expected: FAIL - - [min-width length(cm) / events] - expected: FAIL - - [vertical-align length(cm) / events] - expected: FAIL - - [padding-bottom length(px) / events] - expected: FAIL - - [max-width percentage(%) / events] - expected: FAIL - - [outline-offset length(cm) / events] - expected: FAIL - - [top length(in) / events] - expected: FAIL - - [border-left-color color(rgba) / events] - expected: FAIL - - [margin-left length(mm) / events] - expected: FAIL - - [margin-top length(pt) / events] - expected: FAIL - - [min-height length(cm) / events] - expected: FAIL - - [max-height length(cm) / events] - expected: FAIL - - [width length(mm) / events] - expected: FAIL - - [width length(pc) / events] - expected: FAIL - [background-position length(em) / events] expected: FAIL - [vertical-align length(mm) / events] - expected: FAIL - - [height length(px) / events] - expected: FAIL - - [right percentage(%) / events] - expected: FAIL - - [border-top-color color(rgba) / events] - expected: FAIL - - [outline-offset length(em) / events] - expected: FAIL - - [z-index integer(integer) / events] - expected: FAIL - - [padding-right length(px) / events] - expected: FAIL - - [vertical-align length(ex) / events] - expected: FAIL - - [outline-width length(em) / events] - expected: FAIL - - [width length(cm) / events] - expected: FAIL - - [margin-right length(ex) / events] - expected: FAIL - - [border-right-width length(cm) / events] - expected: FAIL - - [margin-right length(em) / events] - expected: FAIL - - [border-left-width length(ex) / events] - expected: FAIL - - [min-width length(mm) / events] - expected: FAIL - - [margin-right length(pc) / events] - expected: FAIL - - [margin-left length(pt) / events] - expected: FAIL - - [border-right-width length(pc) / events] - expected: FAIL - - [height length(in) / events] - expected: FAIL - - [border-left-width length(in) / events] - expected: FAIL - - [min-height length(ex) / events] - expected: FAIL - - [bottom length(em) / events] - expected: FAIL - - [border-right-color color(rgba) / events] - expected: FAIL - - [right length(in) / events] - expected: FAIL - - [padding-top length(pt) / events] - expected: FAIL - - [min-width length(em) / events] - expected: FAIL - - [border-right-width length(pt) / events] - expected: FAIL - - [opacity number[0,1\](zero-to-one) / events] - expected: FAIL - - [padding-bottom length(cm) / events] - expected: FAIL - - [margin-right length(in) / events] - expected: FAIL - - [margin-top length(px) / events] - expected: FAIL - - [padding-top length(ex) / events] - expected: FAIL - - [margin-left length(ex) / events] - expected: FAIL - - [top length(px) / events] - expected: FAIL - - [bottom length(cm) / events] - expected: FAIL - - [border-bottom-width length(px) / events] - expected: FAIL - - [margin-bottom length(ex) / events] - expected: FAIL - - [max-width length(mm) / events] - expected: FAIL - - [height percentage(%) / events] - expected: FAIL - - [border-right-width length(px) / events] - expected: FAIL - - [border-top-width length(mm) / events] - expected: FAIL - - [border-left-width length(em) / events] - expected: FAIL - - [max-width length(pc) / events] - expected: FAIL - [visibility visibility(keyword) / values] expected: FAIL - [padding-bottom length(em) / events] - expected: FAIL - - [min-width length(pt) / events] - expected: FAIL - - [outline-width length(cm) / events] - expected: FAIL - - [border-right-width length(in) / events] - expected: FAIL - - [bottom length(in) / events] - expected: FAIL - - [padding-right length(mm) / events] - expected: FAIL - - [border-left-width length(px) / events] - expected: FAIL - - [left length(cm) / events] - expected: FAIL - [background-position length(ex) / values] expected: FAIL - [margin-right length(px) / events] - expected: FAIL - - [clip rectangle(rectangle) / events] - expected: FAIL - - [margin-left length(cm) / events] - expected: FAIL - - [background-color color(rgba) / events] - expected: FAIL - - [min-width length(in) / events] - expected: FAIL - - [padding-right length(cm) / events] - expected: FAIL - - [width length(em) / events] - expected: FAIL - [background-position length(cm) / values] expected: FAIL - [margin-left length(em) / events] - expected: FAIL - - [margin-right length(cm) / events] - expected: FAIL - - [border-bottom-width length(cm) / events] - expected: FAIL - - [bottom length(pc) / events] - expected: FAIL - - [top percentage(%) / events] - expected: FAIL - - [padding-left length(pt) / events] - expected: FAIL - - [min-width percentage(%) / events] - expected: FAIL - - [right length(px) / events] - expected: FAIL - - [padding-right length(in) / events] - expected: FAIL - - [left length(mm) / events] - expected: FAIL - - [bottom length(px) / events] - expected: FAIL - - [padding-left length(pc) / events] - expected: FAIL - - [outline-width length(ex) / events] - expected: FAIL - - [padding-left length(cm) / events] - expected: FAIL - - [left length(pt) / events] - expected: FAIL - - [outline-width length(mm) / events] - expected: FAIL - - [padding-left length(ex) / events] - expected: FAIL - - [margin-bottom length(cm) / events] - expected: FAIL - - [max-width length(pt) / events] - expected: FAIL - - [border-right-width length(em) / events] - expected: FAIL - - [margin-left length(in) / events] - expected: FAIL - - [top length(em) / events] - expected: FAIL - - [padding-right length(pt) / events] - expected: FAIL - - [padding-top length(pc) / events] - expected: FAIL - - [border-top-width length(ex) / events] - expected: FAIL - - [min-height length(pt) / events] - expected: FAIL - - [width length(in) / events] - expected: FAIL - - [min-width length(pc) / events] - expected: FAIL - - [margin-bottom length(mm) / events] - expected: FAIL - - [height length(pc) / events] - expected: FAIL - [background-position length(ex) / events] expected: FAIL - [max-width length(px) / events] - expected: FAIL - - [bottom length(pt) / events] - expected: FAIL - - [padding-right length(ex) / events] - expected: FAIL - - [border-top-width length(em) / events] - expected: FAIL - - [max-height length(pt) / events] - expected: FAIL - - [vertical-align percentage(%) / events] - expected: FAIL - - [margin-left length(pc) / events] - expected: FAIL - - [min-height percentage(%) / events] - expected: FAIL - - [padding-bottom length(ex) / events] - expected: FAIL - - [padding-left length(em) / events] - expected: FAIL - - [bottom percentage(%) / events] - expected: FAIL - - [min-height length(pc) / events] - expected: FAIL - - [border-left-width length(pc) / events] - expected: FAIL - - [margin-bottom length(in) / events] - expected: FAIL - - [outline-width length(pt) / events] - expected: FAIL - - [margin-bottom length(em) / events] - expected: FAIL - - [top length(mm) / events] - expected: FAIL - - [outline-color color(rgba) / events] - expected: FAIL - [background-position length(pc) / events] expected: FAIL - [bottom length(mm) / events] - expected: FAIL - - [padding-top length(mm) / events] - expected: FAIL - - [border-right-width length(ex) / events] - expected: FAIL - - [border-top-width length(cm) / events] - expected: FAIL - - [outline-width length(in) / events] - expected: FAIL - - [right length(pt) / events] - expected: FAIL - - [width length(px) / events] - expected: FAIL - - [height length(pt) / events] - expected: FAIL - [background-position length(in) / values] expected: FAIL - [padding-left length(in) / events] - expected: FAIL - - [min-height length(em) / events] - expected: FAIL - - [left percentage(%) / events] - expected: FAIL - - [padding-bottom length(pc) / events] - expected: FAIL - - [max-height length(ex) / events] - expected: FAIL - - [border-left-width length(cm) / events] - expected: FAIL - - [outline-offset length(ex) / events] - expected: FAIL - - [max-height length(pc) / events] - expected: FAIL - - [padding-right length(pc) / events] - expected: FAIL - - [top length(pc) / events] - expected: FAIL - - [vertical-align length(pc) / events] - expected: FAIL - - [min-height length(px) / events] - expected: FAIL - - [margin-right length(mm) / events] - expected: FAIL - - [max-height length(mm) / events] - expected: FAIL - [background-position length(pc) / values] expected: FAIL - [right length(pc) / events] - expected: FAIL - [background-position percentage(%) / values] expected: FAIL - [vertical-align length(pt) / events] - expected: FAIL - - [padding-top length(cm) / events] - expected: FAIL - - [right length(cm) / events] - expected: FAIL - - [outline-offset length(pt) / events] - expected: FAIL - [background-position length(mm) / events] expected: FAIL - [min-height length(in) / events] - expected: FAIL - - [max-width length(cm) / events] - expected: FAIL - - [border-bottom-width length(ex) / events] - expected: FAIL - - [max-height length(px) / events] - expected: FAIL - - [min-width length(px) / events] - expected: FAIL - - [outline-offset length(px) / events] - expected: FAIL - - [margin-top length(in) / events] - expected: FAIL - [background-position length(em) / values] expected: FAIL - [outline-offset length(in) / events] - expected: FAIL - - [margin-bottom length(pt) / events] - expected: FAIL - - [max-width length(em) / events] - expected: FAIL - - [padding-bottom length(pt) / events] - expected: FAIL - - [min-height length(mm) / events] - expected: FAIL - - [padding-bottom length(in) / events] - expected: FAIL - - [margin-bottom length(px) / events] - expected: FAIL - - [max-height length(in) / events] - expected: FAIL - - [outline-width length(px) / events] - expected: FAIL - [background-position percentage(%) / events] expected: FAIL - [padding-right length(em) / events] - expected: FAIL - - [height length(mm) / events] - expected: FAIL - - [margin-top length(mm) / events] - expected: FAIL - [background-position length(px) / events] expected: FAIL - [outline-offset length(pc) / events] - expected: FAIL - - [border-bottom-width length(em) / events] - expected: FAIL - - [outline-width length(px) / values] - expected: FAIL - - [letter-spacing length(em) / events] - expected: FAIL - - [letter-spacing length(ex) / events] - expected: FAIL - - [text-indent length(pc) / values] - expected: FAIL - - [outline-offset length(px) / values] - expected: FAIL - - [letter-spacing length(mm) / events] - expected: FAIL - - [line-height length(in) / events] - expected: FAIL - - [vertical-align length(in) / values] - expected: FAIL - - [font-size percentage(%) / events] - expected: FAIL - - [text-indent percentage(%) / events] - expected: FAIL - - [text-shadow shadow(shadow) / events] - expected: FAIL - - [letter-spacing length(cm) / events] - expected: FAIL - - [vertical-align percentage(%) / values] - expected: FAIL - - [letter-spacing length(px) / events] - expected: FAIL - - [text-indent length(ex) / values] - expected: FAIL - - [text-indent length(mm) / events] - expected: FAIL - - [font-size length(px) / events] - expected: FAIL - - [vertical-align length(em) / values] - expected: FAIL - - [text-indent length(px) / values] - expected: FAIL - - [clip rectangle(rectangle) / values] - expected: FAIL - - [text-indent length(ex) / events] - expected: FAIL - - [line-height length(em) / events] - expected: FAIL - - [font-size length(pt) / events] - expected: FAIL - - [font-size length(in) / events] - expected: FAIL - - [text-indent length(in) / events] - expected: FAIL - - [outline-offset length(ex) / values] - expected: FAIL - - [letter-spacing length(in) / events] - expected: FAIL - - [vertical-align length(pc) / values] - expected: FAIL - - [vertical-align length(cm) / values] - expected: FAIL - - [letter-spacing length(pc) / events] - expected: FAIL - - [visibility visibility(keyword) / events] - expected: FAIL - - [vertical-align length(ex) / values] - expected: FAIL - - [text-indent length(pc) / events] - expected: FAIL - - [text-indent length(em) / events] - expected: FAIL - - [font-size length(pc) / events] - expected: FAIL - - [outline-offset length(mm) / values] - expected: FAIL - - [line-height length(pc) / events] - expected: FAIL - - [outline-offset length(pt) / values] - expected: FAIL - - [text-indent length(px) / events] - expected: FAIL - - [text-indent length(cm) / events] - expected: FAIL - - [vertical-align length(pt) / values] - expected: FAIL - - [font-weight font-weight(keyword) / events] - expected: FAIL - - [font-weight font-weight(numeric) / events] - expected: FAIL - - [line-height length(mm) / events] - expected: FAIL - - [line-height length(cm) / events] - expected: FAIL - - [word-spacing length(pt) / events] - expected: FAIL - - [line-height length(pt) / events] - expected: FAIL - - [word-spacing length(ex) / events] - expected: FAIL - - [color color(rgba) / events] - expected: FAIL - - [text-indent length(mm) / values] - expected: FAIL - - [word-spacing percentage(%) / events] - expected: FAIL - - [line-height percentage(%) / events] - expected: FAIL - - [text-indent length(pt) / events] - expected: FAIL - - [line-height length(ex) / events] - expected: FAIL - - [outline-offset length(in) / values] - expected: FAIL - - [outline-width length(pt) / values] - expected: FAIL - - [line-height number(integer) / events] - expected: FAIL - - [word-spacing length(cm) / events] - expected: FAIL - - [font-size length(mm) / events] - expected: FAIL - - [word-spacing length(mm) / events] - expected: FAIL - - [font-size length(cm) / events] - expected: FAIL - - [outline-width length(in) / values] - expected: FAIL - - [text-indent length(cm) / values] - expected: FAIL - - [outline-color color(rgba) / values] - expected: FAIL - - [text-indent length(pt) / values] - expected: FAIL - - [word-spacing length(em) / events] - expected: FAIL - - [line-height number(decimal) / events] - expected: FAIL - - [letter-spacing length(pt) / events] - expected: FAIL - - [text-shadow shadow(shadow) / values] - expected: FAIL - - [outline-width length(ex) / values] - expected: FAIL - - [word-spacing length(in) / events] - expected: FAIL - - [outline-width length(cm) / values] - expected: FAIL - - [word-spacing length(px) / events] - expected: FAIL - - [outline-width length(mm) / values] - expected: FAIL - - [outline-width length(pc) / values] - expected: FAIL - - [vertical-align length(px) / values] - expected: FAIL - - [text-indent length(in) / values] - expected: FAIL - - [text-indent length(em) / values] - expected: FAIL - - [line-height length(px) / events] - expected: FAIL - - [word-spacing length(pc) / events] - expected: FAIL - - [outline-width length(em) / values] - expected: FAIL - - [font-size length(em) / events] - expected: FAIL - - [outline-offset length(em) / values] - expected: FAIL - - [font-size length(ex) / events] - expected: FAIL - - [outline-offset length(cm) / values] - expected: FAIL - - [vertical-align length(mm) / values] - expected: FAIL - - [text-indent percentage(%) / values] - expected: FAIL - - [outline-offset length(pc) / values] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-003.html.ini b/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-003.html.ini index 2e184ee1047..681c017a2ee 100644 --- a/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-003.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-transitions/properties-value-inherit-003.html.ini @@ -1,106 +1,7 @@ [properties-value-inherit-003.html] - [line-height length-em(em) / events] - expected: FAIL - - [padding-left length-em(em) / events] - expected: FAIL - - [min-width length-em(em) / events] - expected: FAIL - - [right length-em(em) / events] - expected: FAIL - - [max-width length-em(em) / events] - expected: FAIL - - [text-indent length-em(em) / events] - expected: FAIL - - [margin-left length-em(em) / events] - expected: FAIL - - [word-spacing length-em(em) / events] - expected: FAIL - - [letter-spacing length-em(em) / events] - expected: FAIL - - [width length-em(em) / events] - expected: FAIL - - [padding-top length-em(em) / events] - expected: FAIL - - [margin-right length-em(em) / events] - expected: FAIL - - [vertical-align length-em(em) / values] - expected: FAIL - - [max-height length-em(em) / events] - expected: FAIL - - [padding-bottom length-em(em) / events] - expected: FAIL - - [border-top-width length-em(em) / events] - expected: FAIL - - [height length-em(em) / events] - expected: FAIL - - [border-bottom-width length-em(em) / events] - expected: FAIL - [background-position length-em(em) / events] expected: FAIL - [border-left-width length-em(em) / events] - expected: FAIL - - [margin-bottom length-em(em) / events] - expected: FAIL - - [min-height length-em(em) / events] - expected: FAIL - - [outline-width length-em(em) / values] - expected: FAIL - - [outline-offset length-em(em) / events] - expected: FAIL - - [padding-right length-em(em) / events] - expected: FAIL - [background-position length-em(em) / values] expected: FAIL - [top length-em(em) / events] - expected: FAIL - - [outline-width length-em(em) / events] - expected: FAIL - - [bottom length-em(em) / events] - expected: FAIL - - [text-indent length-em(em) / values] - expected: FAIL - - [outline-offset length-em(em) / values] - expected: FAIL - - [vertical-align length-em(em) / events] - expected: FAIL - - [left length-em(em) / events] - expected: FAIL - - [margin-top length-em(em) / events] - expected: FAIL - - [border-right-width length-em(em) / events] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/cssom-view/elementFromPoint-001.html.ini b/tests/wpt/metadata-layout-2020/css/cssom-view/elementFromPoint-001.html.ini deleted file mode 100644 index e38782d8c85..00000000000 --- a/tests/wpt/metadata-layout-2020/css/cssom-view/elementFromPoint-001.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[elementFromPoint-001.html] - [CSSOM View - 5 - extensions to the Document interface] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/cssom-view/elementsFromPoint-invalid-cases.html.ini b/tests/wpt/metadata-layout-2020/css/cssom-view/elementsFromPoint-invalid-cases.html.ini deleted file mode 100644 index e181af5397f..00000000000 --- a/tests/wpt/metadata-layout-2020/css/cssom-view/elementsFromPoint-invalid-cases.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[elementsFromPoint-invalid-cases.html] - [The root element is the last element returned for otherwise empty queries within the viewport] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini b/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini index e63f488f0eb..4ba015fc3a6 100644 --- a/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini +++ b/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini @@ -312,18 +312,21 @@ [Response: combined response Content-Type: text/html;" \\" text/plain ";charset=GBK] expected: NOTRUN - [<iframe>: combined response Content-Type: text/html;" text/plain] + [<iframe>: combined response Content-Type: text/html */*;charset=gbk] expected: FAIL - [<iframe>: combined response Content-Type: text/html */*;charset=gbk] + [<iframe>: separate response Content-Type: text/html;x=" text/plain] expected: FAIL - [<iframe>: combined response Content-Type: text/plain;charset=gbk text/html] + [<iframe>: combined response Content-Type: */* text/html] expected: FAIL - [<iframe>: separate response Content-Type: text/html;x=" text/plain] + [<iframe>: separate response Content-Type: text/html */*] + expected: FAIL + + [<iframe>: separate response Content-Type: text/html;" \\" text/plain] expected: FAIL - [<iframe>: combined response Content-Type: text/html;" \\" text/plain] + [<iframe>: combined response Content-Type: text/html;x=" text/plain] expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/fetch/content-type/script.window.js.ini b/tests/wpt/metadata-layout-2020/fetch/content-type/script.window.js.ini index e67f0406fc3..d2df9b78483 100644 --- a/tests/wpt/metadata-layout-2020/fetch/content-type/script.window.js.ini +++ b/tests/wpt/metadata-layout-2020/fetch/content-type/script.window.js.ini @@ -53,3 +53,6 @@ [combined text/javascript ] expected: FAIL + [separate text/javascript x/x] + expected: FAIL + diff --git a/tests/wpt/metadata-layout-2020/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini b/tests/wpt/metadata-layout-2020/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini new file mode 100644 index 00000000000..87b07c3e670 --- /dev/null +++ b/tests/wpt/metadata-layout-2020/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini @@ -0,0 +1,4 @@ +[traverse_the_history_1.html] + [Multiple history traversals from the same task] + expected: FAIL + diff --git a/tests/wpt/metadata-layout-2020/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini b/tests/wpt/metadata-layout-2020/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini new file mode 100644 index 00000000000..75d75b4cda2 --- /dev/null +++ b/tests/wpt/metadata-layout-2020/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini @@ -0,0 +1,4 @@ +[traverse_the_history_2.html] + [Multiple history traversals, last would be aborted] + expected: FAIL + diff --git a/tests/wpt/metadata-layout-2020/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html.ini b/tests/wpt/metadata-layout-2020/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html.ini new file mode 100644 index 00000000000..7966c1f09d9 --- /dev/null +++ b/tests/wpt/metadata-layout-2020/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html.ini @@ -0,0 +1,47 @@ +[blob-data.https.html] + expected: ERROR + [blob worker: self.crossOriginIsolated] + expected: FAIL + + [data frame: self.crossOriginIsolated] + expected: FAIL + + [blob frame: self.isSecureContext] + expected: FAIL + + [data worker: postMessaging to a dedicated blob sub-worker allows them to see each others' modifications] + expected: TIMEOUT + + [blob worker: self.isSecureContext] + expected: FAIL + + [blob frame: self.crossOriginIsolated] + expected: FAIL + + [blob worker: postMessaging to a dedicated HTTP sub-worker allows them to see each others' modifications] + expected: FAIL + + [data worker: self.crossOriginIsolated] + expected: FAIL + + [data worker: self.origin] + expected: FAIL + + [data frame: self.isSecureContext] + expected: FAIL + + [blob frame: postMessaging to a dedicated blob sub-worker allows them to see each others' modifications] + expected: TIMEOUT + + [data frame: postMessaging to a dedicated blob sub-worker allows them to see each others' modifications] + expected: TIMEOUT + + [data worker: self.isSecureContext] + expected: FAIL + + [blob worker: postMessaging to a dedicated blob sub-worker allows them to see each others' modifications] + expected: TIMEOUT + + [blob frame: postMessaging to a dedicated HTTP sub-worker allows them to see each others' modifications] + expected: FAIL + diff --git a/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini b/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini index 93673c2a0db..338d283eb0e 100644 --- a/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini +++ b/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini @@ -1,5 +1,4 @@ [iframe_sandbox_popups_escaping-3.html] - expected: CRASH [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini b/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini index 3080be9afc0..d913fcbb129 100644 --- a/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini +++ b/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini @@ -1,5 +1,5 @@ [iframe_sandbox_popups_nonescaping-1.html] - expected: CRASH + expected: TIMEOUT [Check that popups from a sandboxed iframe do not escape the sandbox] expected: NOTRUN diff --git a/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini b/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini index 0fbc49ea1c1..f4f994c5d6f 100644 --- a/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini +++ b/tests/wpt/metadata-layout-2020/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini @@ -1,5 +1,5 @@ [iframe_sandbox_popups_nonescaping-3.html] - expected: CRASH + expected: TIMEOUT [Check that popups from a sandboxed iframe do not escape the sandbox] expected: NOTRUN diff --git a/tests/wpt/metadata-layout-2020/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini b/tests/wpt/metadata-layout-2020/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini index 58c9d7f8c0c..57744023f73 100644 --- a/tests/wpt/metadata-layout-2020/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini +++ b/tests/wpt/metadata-layout-2020/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini @@ -1,5 +1,5 @@ [ignore-opens-during-unload.window.html] - expected: TIMEOUT + expected: CRASH [document.open should bail out when ignore-opens-during-unload is greater than 0 during visibilitychange event (open(parent) while unloading parent and child)] expected: TIMEOUT diff --git a/tests/wpt/metadata-layout-2020/webmessaging/without-ports/018.html.ini b/tests/wpt/metadata-layout-2020/webmessaging/without-ports/018.html.ini deleted file mode 100644 index 663a1f8fa30..00000000000 --- a/tests/wpt/metadata-layout-2020/webmessaging/without-ports/018.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[018.html] - expected: TIMEOUT - [origin of the script that invoked the method, javascript:] - expected: TIMEOUT - diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 930c35cc34c..5116a261dd9 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -113,6 +113,13 @@ {} ] ], + "negative-item-margins-002-crash.html": [ + "97b450df9a014bb309adec4c68b1bf5aca3314a5", + [ + null, + {} + ] + ], "negative-item-margins-crash.html": [ "d5f9365b5ec1be0e62435651a70d1baeb6d8083a", [ @@ -13334,14 +13341,14 @@ ] ], "focus-visible-003-manual.html": [ - "eeb2904d7d33ebab283c37925db90f6fab7c1328", + "ccc916a952854cc357ba7a5af73f4e1b476ef97d", [ null, {} ] ], "focus-visible-004-manual.html": [ - "dba057cc9c8641a96c65b0bb90cccbdd3d596dc3", + "4d7878e751ecd5487eecd9f40477fa4a7ff03484", [ null, {} @@ -123179,6 +123186,45 @@ {} ] ], + "tall-float-pushed-to-next-fragmentainer-000.html": [ + "a5f02184687fd21337c935d0ecc7ae07d6ae3bda", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "tall-float-pushed-to-next-fragmentainer-001.html": [ + "d172f935744ee3d44fdeb0c2f5f758321af4172a", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "tall-float-pushed-to-next-fragmentainer-002.html": [ + "1ba22353c0754a1e52224adae491971a7f86645c", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], "widows-orphans-001.html": [ "8da27f0b6594fc7ddd90bdb160be8f80a9479038", [ @@ -229339,6 +229385,60 @@ ] ] }, + "manual": { + "unclosed-canvas-1.htm": [ + "5e0c914755b672ae3427f2e433120176494bebf0", + [ + null, + [ + [ + "/html/canvas/element/manual/unclosed-canvas-1-expected.htm", + "==" + ] + ], + {} + ] + ], + "unclosed-canvas-2.htm": [ + "fb329e73d6f3a37410cad745e37bb2539f683edf", + [ + null, + [ + [ + "/html/canvas/element/manual/unclosed-canvas-2-expected.htm", + "==" + ] + ], + {} + ] + ], + "unclosed-canvas-3.htm": [ + "8ffaa0f9eb5b0025029fc45c7585c601bff3f60f", + [ + null, + [ + [ + "/html/canvas/element/manual/unclosed-canvas-3-expected.htm", + "==" + ] + ], + {} + ] + ], + "unclosed-canvas-4.htm": [ + "aa5fd144381dbbdbc71afc7350e9aa6187a728ef", + [ + null, + [ + [ + "/html/canvas/element/manual/unclosed-canvas-4-expected.htm", + "==" + ] + ], + {} + ] + ] + }, "shadows": { "canvas_shadows_002.htm": [ "908fffea13bfac5a5cd40413797928848cd34dcf", @@ -239529,6 +239629,40 @@ } } }, + "webgpu": { + "webgpu": { + "web-platform": { + "reftests": { + "canvas_clear.html": [ + "86a3da939dbe94efbeec04e5d366a40736ca4560", + [ + null, + [ + [ + "/webgpu/webgpu/web-platform/reftests/ref/canvas_clear-ref.html", + "==" + ] + ], + {} + ] + ], + "canvas_complex_bgra8unorm.html": [ + "1310543648e4fd640b0deb227000731af7b88b00", + [ + null, + [ + [ + "/webgpu/webgpu/web-platform/reftests/ref/canvas_complex-ref.html", + "==" + ] + ], + {} + ] + ] + } + } + } + }, "webvtt": { "rendering": { "cues-with-video": { @@ -242781,7 +242915,7 @@ }, "support": { ".azure-pipelines.yml": [ - "8c8a15d4ef438d21786fb62e5c7ca99475e80c45", + "8c39de66f4890b8507aaba8325a7fb7da176bc17", [] ], ".codecov.yml": [ @@ -316445,7 +316579,7 @@ [] ], "safari.md": [ - "0ff8fe5d95e8aed678e3f1d0e357f6518011537b", + "eed52254718922b000abd30273a50d56ce84d35a", [] ], "webkitgtk_minibrowser.md": [ @@ -323097,6 +323231,24 @@ [] ] }, + "manual": { + "unclosed-canvas-1-expected.htm": [ + "3272f32fb88030747608ce4b794a5bdbeeda5634", + [] + ], + "unclosed-canvas-2-expected.htm": [ + "fd48cd0db18f9eb46d435aa499bdeaa40504cd9f", + [] + ], + "unclosed-canvas-3-expected.htm": [ + "efd239b4fb33304da0a47473111d5e9ebf7fb54f", + [] + ], + "unclosed-canvas-4-expected.htm": [ + "492449261e722ebaa78196db579656d9b0ec5a34", + [] + ] + }, "path-objects": { "2d.path.fill.overlap.png": [ "e2a35d48d4c4363294aec671a38cbd4b39c9a53c", @@ -333563,10 +333715,6 @@ "b5481216729526387722a6c733ea529f5d1f831a", [] ], - "screen-wake-lock.idl": [ - "1eb30a06024713e5aab435610a8fc62841db8a50", - [] - ], "scroll-animations.idl": [ "00d0bae68126aa67d6714694422a098100eb7e71", [] @@ -333643,6 +333791,10 @@ "ef8fd6342a59c3584536e6ec491ad20c2208c51d", [] ], + "wake-lock.idl": [ + "1eb30a06024713e5aab435610a8fc62841db8a50", + [] + ], "wasm-js-api.idl": [ "cc943610145dec2346e7ec9d6891cf32859f9d59", [] @@ -340944,11 +341096,11 @@ [] ], "fetch-request-resources-iframe.https.html": [ - "fca57220235838939d04a10b5266c89eb3f9c17c", + "b9783071e12515b7e9cb683ce33970a31304ce2d", [] ], "fetch-request-resources-worker.js": [ - "d85f7143c3333933fcedb2ddc24ba6aaed019d9a", + "5c9e86d66846605a96a9fd61889e71b7ad4b7d00", [] ], "fetch-request-xhr-iframe.https.html": [ @@ -343408,13 +343560,17 @@ [] ], "install_safari.yml": [ - "5cbad0d00b9b7d268c5fa969172b8910ac73a3dd", + "d0660d152bbdfc89f308bfc048cd2221e9ea7524", [] ], "pip_install.yml": [ "18d1879e971613532fac5673d9a804acc1bc8673", [] ], + "publish_logs.yml": [ + "a49397a91ad7ca424864c5326b5fe7b4a3685a41", + [] + ], "safari-technology-preview.rb": [ "eae03474a49ff7bece32daf482390025c3ce9e2a", [] @@ -343895,11 +344051,11 @@ [] ], "manifest.py": [ - "19d1bbed0334b938d765fda6738f409a9793b306", + "345eeb6d2b0beeb3ce3c1390949cb9e2d19a435a", [] ], "sourcefile.py": [ - "c374ba050434e89b5c915d21da42550d16ed3b7d", + "b324bf22dd382515220d3a78d9f2710430030aee", [] ], "testpaths.py": [ @@ -343997,7 +344153,7 @@ [] ], "quic_transport_server.py": [ - "10d81743693b431acba1eaa082e03f73124e050a", + "9a04ad17f195c6e5d233e84a9b23904cccfeccd6", [] ], "requirements.txt": [ @@ -352157,7 +352313,7 @@ ], "common": { "constants.js": [ - "9d3dd1a32defa22fd3a0cd0e17504cb4727b9622", + "69496b1b23bf8a37bce0c4da0f121dd1810d334d", [] ], "framework": { @@ -352169,8 +352325,12 @@ "dc5a9caf850b967ea0779fee6b7c725376c0bbbb", [] ], + "file_loader.js": [ + "1b77a4e85953b7f0d85345b2f4f8d4f38ce7ed29", + [] + ], "fixture.js": [ - "55f8ec48b22acdd553c093eaba8a568b0d8f1f56", + "ef23f06596bd7cc244484102008db8ca9485c2c8", [] ], "generate_minimal_query_list.js": [ @@ -352178,6 +352338,10 @@ [] ], "gpu": { + "device_pool.js": [ + "848e5802817b43e26c8e25ecfec48c0ea9fe8816", + [] + ], "implementation.js": [ "670872b5d6e32ebf3815935fdd9fec605056a30c", [] @@ -352199,14 +352363,66 @@ "3f624a86e325daaadd1990e1aa11804ea2ab16d2", [] ], + "logging": { + "log_message.js": [ + "11f352f892e76eb0140f0fe36249f41e103e1e05", + [] + ], + "logger.js": [ + "8d66c554c5ad8b48df127d914883fc8f4578bc38", + [] + ], + "result.js": [ + "813e781ba28ce0471d17d439c0fc20ed400f68ac", + [] + ], + "test_case_recorder.js": [ + "d16af0f2b861421cb77050648440ae4e4fbd3d39", + [] + ] + }, "params.js": [ "f8e46b62dbaf0039903a0496d333de5c84315820", [] ], + "params_builder.js": [ + "10dd239df93c6ce1a9ae8559586c6c304b3243e2", + [] + ], "params_utils.js": [ - "cde89843f9e67d7f7e01914823fc807df2f40a66", + "161feb5d4306ea30ae56c7ba6f76ac81f90a25ba", [] ], + "query": { + "compare.js": [ + "2cbe6cc80c9f35d1c70dc08fa1a4eea7b577d2bf", + [] + ], + "encode_selectively.js": [ + "d67f10422334a14747285c5dfc1672d0553fa05f", + [] + ], + "parseQuery.js": [ + "758227cc520f486f4a0662d0935eaa86a1aa937b", + [] + ], + "query.js": [ + "b80b6904f17e1b9e4341f1e926fc27de5ce86362", + [] + ], + "separators.js": [ + "4782fe457b877850899ce45c7fe7eab0d8f5970c", + [] + ], + "stringify_params.js": [ + "b5503ffb54ead8677dfb5189aecd9e46fcf30cad", + [] + ], + "validQueryPart.js": [ + "f51ebade76a3442e80fdffd789af12aa56e8db40", + [] + ] + }, "test_filter": { "filter_by_group.js": [ "b43749f9c5d700d1085b6402a086e38dcc4f2e24", @@ -352230,11 +352446,15 @@ ] }, "test_group.js": [ - "8837b1e924a412e8fb706d2f0601b72a7a79a28a", + "ef34b5fd51ccd1196240310f1fac7ed0e0b95407", + [] + ], + "test_suite_listing.js": [ + "99c900217c1463e09faefd01e0db96498db7ca92", [] ], "tree.js": [ - "8f96c98074942127cd7b781778e5a17eb36f1d0d", + "2f4329c164d843c8ff18f5115f439106065853d3", [] ], "url_query.js": [ @@ -352246,8 +352466,12 @@ "cb900605bcfe77bae785c207419787e317bf1d73", [] ], + "collect_garbage.js": [ + "83b797a0cc48e3f7de5a7b51cdcbf82b531fe025", + [] + ], "stack.js": [ - "3d0ec636d853d7b150cf921a931ce2e59963dcbc", + "99653f888066181e5fbac7a7a4331f6cb4fe3ecb", [] ], "timeout.js": [ @@ -352255,12 +352479,12 @@ [] ], "util.js": [ - "ca64026916c1a7319674daf254c5eeb7df5c7699", + "b64379982a60f7b4551b7611feb7fdcf288d560e", [] ] }, "version.js": [ - "159b3cf420e59692ad87875ce7d760b5a8c956f8", + "f1fe61edc7f491e64eb8a768fb03b0f36c76a2e0", [] ] }, @@ -352271,16 +352495,16 @@ [] ], "test_worker-worker.js": [ - "dd078c313a6287e500c902ee301c310b0c81e81f", + "be3f4952f0542e5be2c45e4882416576cb685a07", [] ], "test_worker.js": [ - "a67030056f5b8d5ed7665f9e06f9735d0e26b287", + "7e8b9a47c077261e8dcacb21487989edbd146e2c", [] ] }, "wpt.js": [ - "fd02f09471bc656a900714dd586101d6acb28c46", + "0648a0dc7ee923ee37b676b77d97105776f378b9", [] ] } @@ -352290,19 +352514,19 @@ "operation": { "buffers": { "create_mapped.spec.js": [ - "7b2bc39aa3defbd14c1ad2dfa938ca4df6ee495d", + "1c3b1254d503727d9efd189ec6b9eba5bac3a79b", [] ], "map.spec.js": [ - "1c73d62a95ff82ed211a8dc6bf9b74b4c2a41fae", + "842421dd5ce0321554b39aaae31ce42cd0b944ba", [] ], "map_detach.spec.js": [ - "14d5be5a6311cd4eba637d679c7275be811aafb6", + "8ae0be0b197ac1ae1a6bac48dacd00ecc8ec2a9e", [] ], "map_oom.spec.js": [ - "ee642a5c3b34177b815bbac26228567e25f62e37", + "a04347ffd4f7af75514c11326c6ef704849ca46d", [] ], "mapping_test.js": [ @@ -352312,115 +352536,173 @@ }, "command_buffer": { "basic.spec.js": [ - "bc4020bfeb53afcaa19ccf5f155e358886ffbc29", + "547a08683f7318d5aceb2e26096166c1c994c579", [] ], "copies.spec.js": [ - "c330415d8511b9a548706b6019e1a6614804d432", + "cc2ea6deae161d2025119beda183dfb767b63795", [] ], "render": { "basic.spec.js": [ - "88710e8aa09287dfd612acf26976406c2576cba5", + "815eb5b70b0092c096fe385ad94729f62ef44761", [] ] } }, "fences.spec.js": [ - "386530e08523bdfc9da2a4827d8a04760cab6678", + "f9f079b6241fa99a6895250329b18fb88d895ac3", [] - ] + ], + "resource_init": { + "copied_texture_clear.spec.js": [ + "22a71bf725ced2b9e3b53569ff25798aa9761968", + [] + ], + "texture_zero_init_test.js": [ + "5dc3c227232b0fc3140b30be26ccb38071622fcd", + [] + ] + } }, "validation": { "createBindGroup.spec.js": [ - "97683cf75a92d574147a000e29a69b70e7fb97a1", + "1eb8f959f333b7680ce81c1e449a02bde25cf188", [] ], "createBindGroupLayout.spec.js": [ - "b03e01591133aa7fd641b805a598cca328d16157", + "3961ba3a81a5e0b4c95db861fae12ace1aa97ec9", [] ], "createPipelineLayout.spec.js": [ - "f1582c4478a2074cbb37b99c32f8e4c5242116d0", + "262581e8714ce7c5a1f165cfac7749b240b52df8", [] ], "createTexture.spec.js": [ - "ab4c6f866b4df74315c69f3cb8bfd483540e54ea", + "2ef8d19523311d64519af8ecff18d27ac9695749", [] ], "createView.spec.js": [ - "d23af58387440bf7b5d6953a240110a179e8379d", + "524d921adaa7002187faa306eaf9d78aa5b98aef", [] ], "error_scope.spec.js": [ - "fd69c4e13c0382d95eb2fc5dd535b48b5543c022", + "3edbec2dc417fc4cb95ab67baefc1d0f1a798154", [] ], "fences.spec.js": [ - "7747b5e9dc8592dde77167c2696da0582e1573f0", + "2ab0691e3ce6cadb532a94a43d568b8a111a8430", [] ], "queue_submit.spec.js": [ - "dbe0bb4d31ed68eec197d7a556e6f9e097b5eeb5", + "24e386b9d22c2bbea0fca8e8b5c94c770e8ed7d5", [] ], "render_pass_descriptor.spec.js": [ - "7c887a1c0fd112b7d5648edc2698e0376e5f2ae5", + "3c1b111fea4a79aab8cd8defbc61152e7e5302ea", [] ], "setBindGroup.spec.js": [ - "baf590746c33c04c9fedd75b11de7873d4eeec91", + "95786a8f78d3a6fe230d6a08c3cfb83c93a97666", [] ], "setBlendColor.spec.js": [ - "b8905453ac952131698a5b67d9b3a1f6270c9e83", + "469641df04341795efdad946ea65eb517a51265c", [] ], "setScissorRect.spec.js": [ - "e12c90d7cdae1c2271b9b97df8a85816c6e5e5a7", + "8381865a6938c4a32d81744fb1bbaaf41ae309fb", [] ], "setStencilReference.spec.js": [ - "cbd48aeaad532724977752e524dd106c38cd14df", + "f205239d86142ea08880f226f9d9ae052a385aa1", [] ], "setViewport.spec.js": [ - "9a3009f38ac020893f78cc5f7ad33defaa93101d", + "f1168c11086fd4fa7114c36b9895bab49b66a410", [] ], "validation_test.js": [ - "92d8a0699c4f2c7f1002537c97dd30bf93137b9d", + "17eb97bcc63daafbda34a661bafd0da688d7bb8b", [] ] } }, "capability_info.js": [ - "0e336b979f8290152b0ec0e9c7993768106a2fed", + "b2d9353b04d7c9f4616b22c9a235ddaf41827131", [] ], "examples.spec.js": [ - "add23f7250ee70a1f80b7ee1ca2c292e7ae3c0d6", + "28b9ae47f2c25183ba68b1bcb7303a033541213b", [] ], "gpu_test.js": [ - "0202f34fcf7429a3eb671f786c45efbacae36871", + "d2528c8d84b5eaa1fcb218fbb9452c4f9f0ae0a9", [] ], "listing.js": [ - "5b9ef1afb0184599c0b6f33468356f21677315d5", + "ea23ab2832834983efe327c5adffc8cf1ac0cefe", [] ], + "util": { + "conversion.js": [ + "73c04fe56badcff5aee3bf665465b24c81d4f3bf", + [] + ], + "math.js": [ + "19720d631c55590bfbfc223e9c6409eded4d6232", + [] + ], + "texture": { + "layout.js": [ + "db9d5dbb4352b9c29581ff5d1b7bbadb1d8753e6", + [] + ], + "subresource.js": [ + "04a8e7221a8ad8a9f76369d4e3f2ffa4fe21a056", + [] + ], + "texelData.js": [ + "2ea7275e710a5e47a59480ca2a56c1026172e6bf", + [] + ] + } + }, "web-platform": { "canvas": { "context_creation.spec.js": [ - "fd8593b642ed84440706ca4b1b29dc4f2e1660d5", + "427b15fced447160db36ca3d6f829211f5080206", [] ] }, "copyImageBitmapToTexture.spec.js": [ - "5e84113b95ad6940517a9c3dc3339ae233b52a10", + "de978550acccc3c1b876eb99fdfabd1ed8c1c56a", [] - ] + ], + "reftests": { + "canvas_clear.js": [ + "52ffaedad84c7552fd13cbac89cd800c09a012c0", + [] + ], + "canvas_complex.js": [ + "1e63a0ab20233e9db7e9c628493af178edd386c9", + [] + ], + "gpu_ref_test.js": [ + "f45f232557cdd05406317b3a521d06e3e1bbd960", + [] + ], + "ref": { + "canvas_clear-ref.html": [ + "2e0781186273ac49d6c70b5e5a9c68103aa5f173", + [] + ], + "canvas_complex-ref.html": [ + "3d5b3b3376d23cfdcda57f0c53fc3192e8a77bb6", + [] + ] + } + } } } }, @@ -352960,7 +353242,7 @@ [] ], "client-indication.quic.py": [ - "da0701cc04b17b461344879a62631d65326c167b", + "56238c7514c065f9933bf3b1f10eff24503ad73e", [] ] } @@ -374345,6 +374627,13 @@ {} ] ], + "blocked-iframe-are-cross-origin.html": [ + "9fedc4e930e923fbb58c684fb55acbecb951e0bd", + [ + null, + {} + ] + ], "idlharness.window.js": [ "2845f82c955139e5a5640195af49ece555fe3faa", [ @@ -376042,7 +376331,7 @@ ] ], "reporting-api-sends-reports-on-violation.https.sub.html": [ - "23337ae8d077e33fcec38fec6baa59778a39e0f8", + "ba4df62bf6f1c658d6dfed48fe1f6f62201b942f", [ null, {} @@ -382700,6 +382989,20 @@ {} ] ], + "viewport-user-scalable-no-clamp-to-max.tentative.html": [ + "c2c341245b528bc375bd8aa2d14e273fda492207", + [ + null, + {} + ] + ], + "viewport-user-scalable-no-clamp-to-min.tentative.html": [ + "89d7bb2f8ceb4d3da08ca7c98a7b37d311bbce3f", + [ + null, + {} + ] + ], "viewport-user-scalable-no-wide-content.tentative.html": [ "6cf0bfa236a0cb5806c5deeeb7d45c07afb9f16f", [ @@ -391440,6 +391743,13 @@ {} ] ], + "position-change-heuristic-in-nested-scroll-box.html": [ + "58c88001d53683c3f3a146c13141436b56514c96", + [ + null, + {} + ] + ], "position-change-heuristic.html": [ "b36b211f586782a7616c222fce04aa98817f35c4", [ @@ -404573,14 +404883,14 @@ ] }, "is-nested.html": [ - "7c3973ae058edfcead691242479777aab1f5d35a", + "0658f9030d1303e46184741b5e4114c4ce7b40a4", [ null, {} ] ], "is-specificity.html": [ - "bf3dbc6bb9fc105d87a63ddbef65ade931f223f0", + "541b0406d347e5ade0474024ba208ba222dc2d29", [ null, {} @@ -426942,6 +427252,15 @@ ] ], "rendering": { + "fullscreen-css-invalidation.html": [ + "e855d0c19352ccfec41a54fc20300c2b9323e39b", + [ + null, + { + "testdriver": true + } + ] + ], "fullscreen-css-transition.html": [ "b494dc04e6d900ce3fcb6ece31dd987095f4cfdb", [ @@ -448880,7 +449199,7 @@ ], "shared-array-buffers": { "blob-data.https.html": [ - "8fe2ee46cb35e41029b545cef4865c3e852995af", + "dbc73e98f578111757e5b82a8d6f5197249871a9", [ null, {} @@ -487468,7 +487787,7 @@ ] ], "path-absolute-endpoint.https.sub.html": [ - "ec06a368e97bdbad1e1df00a9aff55e807d9dd4d", + "144fcb024e39178e318e5b820efc5958b2a200b1", [ null, {} @@ -488383,7 +488702,7 @@ }, "screen-wake-lock": { "idlharness.https.window.js": [ - "370696e90b3579e9b0960942c1cc9269850f3f6b", + "275454248f5792b89883d67944ba5f46158c58a1", [ "screen-wake-lock/idlharness.https.window.html", { @@ -490506,7 +490825,7 @@ ] ], "fetch-request-resources.https.html": [ - "e0ddac74dbf8bd308a8942d925e1f9139c5f5685", + "fe227d9ce2f4943ec8a2aa936882f7b46daca28f", [ null, {} @@ -502262,7 +502581,7 @@ ] ], "trusted-types-reporting.tentative.html": [ - "5003fc7fad5fab912e678c6fe0ec60e7935d0613", + "5cefedb7b8ad5d9be8c3611df3aa3aee8ced29df", [ null, { @@ -502271,7 +502590,7 @@ ] ], "trusted-types-svg-script.tentative.html": [ - "903490e2f3d7f43f017bd843f912b99acba47c8e", + "946f825fa3eecd05247e1a2b16396ee4d3f7af11", [ null, {} @@ -502330,8 +502649,8 @@ } ] ], - "mouse-dblclick-event.html": [ - "31a600b3cb715e408cd4aa8920fb54fd77064e57", + "dblclick_event_mouse.html": [ + "50324f6dfdf7785db66d9af031f779d0189e0e57", [ null, { @@ -505319,15 +505638,22 @@ } ] ], + "request-video-frame-callback-dom.html": [ + "0277d7297883c4cd4f472b08c4399806280fe8eb", + [ + null, + {} + ] + ], "request-video-frame-callback-parallel.html": [ - "3407786c052b1844568c2f8512aecb3e2c7e3063", + "14c5de1adf55ba0016ab9985776c568e49f5956d", [ null, {} ] ], "request-video-frame-callback-repeating.html": [ - "bfdedb4bec00fe99f01ab6225e8b85a47617b3dd", + "e637a0872cb0d0c151e0a80a6a569449fd222a1b", [ null, {} @@ -505341,7 +505667,7 @@ ] ], "request-video-frame-callback.html": [ - "6660fadeaf47460fb274e2801ff2b2528147e010", + "afc6b834d44b3e1e400c09f1c74dbfbb159fea3d", [ null, {} @@ -511813,105 +512139,109 @@ }, "webgpu": { "cts.html": [ - "62340be400ed172b3997a68680e7f6c9e36dfeca", + "a06ad795899a57e544da016360a70c0050511eca", + [ + "webgpu/cts.html?q=webgpu:api,operation,buffers,create_mapped:*", + {} + ], [ - "webgpu/cts.html?q=webgpu:api/operation/buffers/create_mapped", + "webgpu/cts.html?q=webgpu:api,operation,buffers,map:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/operation/buffers/map", + "webgpu/cts.html?q=webgpu:api,operation,buffers,map_detach:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/operation/buffers/map_detach", + "webgpu/cts.html?q=webgpu:api,operation,buffers,map_oom:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/operation/buffers/map_oom", + "webgpu/cts.html?q=webgpu:api,operation,command_buffer,basic:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/operation/command_buffer/basic", + "webgpu/cts.html?q=webgpu:api,operation,command_buffer,copies:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/operation/command_buffer/copies", + "webgpu/cts.html?q=webgpu:api,operation,command_buffer,render,basic:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/operation/command_buffer/render/basic", + "webgpu/cts.html?q=webgpu:api,operation,fences:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/operation/fences", + "webgpu/cts.html?q=webgpu:api,operation,resource_init,copied_texture_clear:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/createBindGroup", + "webgpu/cts.html?q=webgpu:api,validation,createBindGroup:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/createBindGroupLayout", + "webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/createPipelineLayout", + "webgpu/cts.html?q=webgpu:api,validation,createPipelineLayout:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/createTexture", + "webgpu/cts.html?q=webgpu:api,validation,createTexture:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/createView", + "webgpu/cts.html?q=webgpu:api,validation,createView:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/error_scope", + "webgpu/cts.html?q=webgpu:api,validation,error_scope:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/fences", + "webgpu/cts.html?q=webgpu:api,validation,fences:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/queue_submit", + "webgpu/cts.html?q=webgpu:api,validation,queue_submit:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/render_pass_descriptor", + "webgpu/cts.html?q=webgpu:api,validation,render_pass_descriptor:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/setBindGroup", + "webgpu/cts.html?q=webgpu:api,validation,setBindGroup:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/setBlendColor", + "webgpu/cts.html?q=webgpu:api,validation,setBlendColor:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/setScissorRect", + "webgpu/cts.html?q=webgpu:api,validation,setScissorRect:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/setStencilReference", + "webgpu/cts.html?q=webgpu:api,validation,setStencilReference:*", {} ], [ - "webgpu/cts.html?q=webgpu:api/validation/setViewport", + "webgpu/cts.html?q=webgpu:api,validation,setViewport:*", {} ], [ - "webgpu/cts.html?q=webgpu:examples", + "webgpu/cts.html?q=webgpu:examples:*", {} ], [ - "webgpu/cts.html?q=webgpu:web-platform/canvas/context_creation", + "webgpu/cts.html?q=webgpu:web-platform,canvas,context_creation:*", {} ], [ - "webgpu/cts.html?q=webgpu:web-platform/copyImageBitmapToTexture", + "webgpu/cts.html?q=webgpu:web-platform,copyImageBitmapToTexture:*", {} ] ] diff --git a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini deleted file mode 100644 index f64b45fea6b..00000000000 --- a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[hit-test-floats-002.html] - [Hit test float] - expected: FAIL - diff --git a/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini b/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini index 4a1e8110f6f..f8e7e539aae 100644 --- a/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini +++ b/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini @@ -2,3 +2,6 @@ [Hit test intersecting scaled box] expected: FAIL + [Hit test within unscaled box] + expected: FAIL + diff --git a/tests/wpt/metadata/css/css-transitions/properties-value-inherit-001.html.ini b/tests/wpt/metadata/css/css-transitions/properties-value-inherit-001.html.ini index 4a5621565cb..5d20389c8e9 100644 --- a/tests/wpt/metadata/css/css-transitions/properties-value-inherit-001.html.ini +++ b/tests/wpt/metadata/css/css-transitions/properties-value-inherit-001.html.ini @@ -56,663 +56,3 @@ [background-position length(px) / events] expected: FAIL - [top length(pt) / events] - expected: FAIL - - [border-right-width length(mm) / events] - expected: FAIL - - [width length(pt) / events] - expected: FAIL - - [border-bottom-width length(pc) / events] - expected: FAIL - - [height length(ex) / events] - expected: FAIL - - [padding-bottom length(mm) / events] - expected: FAIL - - [border-top-width length(px) / events] - expected: FAIL - - [border-top-width length(pt) / events] - expected: FAIL - - [padding-top length(em) / events] - expected: FAIL - - [outline-width length(pc) / events] - expected: FAIL - - [max-width length(in) / events] - expected: FAIL - - [margin-top length(cm) / events] - expected: FAIL - - [margin-right length(pt) / events] - expected: FAIL - - [right length(ex) / events] - expected: FAIL - - [vertical-align length(px) / events] - expected: FAIL - - [max-height length(em) / events] - expected: FAIL - - [width length(ex) / events] - expected: FAIL - - [border-bottom-color color(rgba) / events] - expected: FAIL - - [width percentage(%) / events] - expected: FAIL - - [margin-top length(ex) / events] - expected: FAIL - - [border-top-width length(in) / events] - expected: FAIL - - [right length(em) / events] - expected: FAIL - - [top length(ex) / events] - expected: FAIL - - [padding-left length(px) / events] - expected: FAIL - - [margin-top length(em) / events] - expected: FAIL - - [left length(em) / events] - expected: FAIL - - [margin-left length(px) / events] - expected: FAIL - - [max-height percentage(%) / events] - expected: FAIL - - [bottom length(ex) / events] - expected: FAIL - - [padding-left length(mm) / events] - expected: FAIL - - [right length(mm) / events] - expected: FAIL - - [margin-top length(pc) / events] - expected: FAIL - - [border-left-width length(pt) / events] - expected: FAIL - - [outline-offset length(mm) / events] - expected: FAIL - - [vertical-align length(in) / events] - expected: FAIL - - [border-bottom-width length(pt) / events] - expected: FAIL - - [border-bottom-width length(in) / events] - expected: FAIL - - [margin-bottom length(pc) / events] - expected: FAIL - - [border-left-width length(mm) / events] - expected: FAIL - - [height length(em) / events] - expected: FAIL - - [height length(cm) / events] - expected: FAIL - - [padding-top length(in) / events] - expected: FAIL - - [max-width length(ex) / events] - expected: FAIL - - [padding-top length(px) / events] - expected: FAIL - - [border-top-width length(pc) / events] - expected: FAIL - - [top length(cm) / events] - expected: FAIL - - [left length(ex) / events] - expected: FAIL - - [min-width length(ex) / events] - expected: FAIL - - [left length(pc) / events] - expected: FAIL - - [vertical-align length(em) / events] - expected: FAIL - - [left length(in) / events] - expected: FAIL - - [left length(px) / events] - expected: FAIL - - [border-bottom-width length(mm) / events] - expected: FAIL - - [min-width length(cm) / events] - expected: FAIL - - [vertical-align length(cm) / events] - expected: FAIL - - [padding-bottom length(px) / events] - expected: FAIL - - [max-width percentage(%) / events] - expected: FAIL - - [outline-offset length(cm) / events] - expected: FAIL - - [top length(in) / events] - expected: FAIL - - [border-left-color color(rgba) / events] - expected: FAIL - - [margin-left length(mm) / events] - expected: FAIL - - [margin-top length(pt) / events] - expected: FAIL - - [min-height length(cm) / events] - expected: FAIL - - [max-height length(cm) / events] - expected: FAIL - - [width length(mm) / events] - expected: FAIL - - [width length(pc) / events] - expected: FAIL - - [vertical-align length(mm) / events] - expected: FAIL - - [height length(px) / events] - expected: FAIL - - [right percentage(%) / events] - expected: FAIL - - [border-top-color color(rgba) / events] - expected: FAIL - - [outline-offset length(em) / events] - expected: FAIL - - [padding-right length(px) / events] - expected: FAIL - - [vertical-align length(ex) / events] - expected: FAIL - - [outline-width length(em) / events] - expected: FAIL - - [width length(cm) / events] - expected: FAIL - - [margin-right length(ex) / events] - expected: FAIL - - [border-right-width length(cm) / events] - expected: FAIL - - [margin-right length(em) / events] - expected: FAIL - - [border-left-width length(ex) / events] - expected: FAIL - - [min-width length(mm) / events] - expected: FAIL - - [margin-right length(pc) / events] - expected: FAIL - - [margin-left length(pt) / events] - expected: FAIL - - [border-right-width length(pc) / events] - expected: FAIL - - [height length(in) / events] - expected: FAIL - - [border-left-width length(in) / events] - expected: FAIL - - [min-height length(ex) / events] - expected: FAIL - - [bottom length(em) / events] - expected: FAIL - - [border-right-color color(rgba) / events] - expected: FAIL - - [right length(in) / events] - expected: FAIL - - [padding-top length(pt) / events] - expected: FAIL - - [min-width length(em) / events] - expected: FAIL - - [border-right-width length(pt) / events] - expected: FAIL - - [opacity number[0,1\](zero-to-one) / events] - expected: FAIL - - [padding-bottom length(cm) / events] - expected: FAIL - - [margin-right length(in) / events] - expected: FAIL - - [margin-top length(px) / events] - expected: FAIL - - [padding-top length(ex) / events] - expected: FAIL - - [margin-left length(ex) / events] - expected: FAIL - - [top length(px) / events] - expected: FAIL - - [bottom length(cm) / events] - expected: FAIL - - [border-bottom-width length(px) / events] - expected: FAIL - - [margin-bottom length(ex) / events] - expected: FAIL - - [max-width length(mm) / events] - expected: FAIL - - [height percentage(%) / events] - expected: FAIL - - [border-right-width length(px) / events] - expected: FAIL - - [border-top-width length(mm) / events] - expected: FAIL - - [border-left-width length(em) / events] - expected: FAIL - - [max-width length(pc) / events] - expected: FAIL - - [padding-bottom length(em) / events] - expected: FAIL - - [min-width length(pt) / events] - expected: FAIL - - [outline-width length(cm) / events] - expected: FAIL - - [border-right-width length(in) / events] - expected: FAIL - - [bottom length(in) / events] - expected: FAIL - - [padding-right length(mm) / events] - expected: FAIL - - [border-left-width length(px) / events] - expected: FAIL - - [left length(cm) / events] - expected: FAIL - - [margin-right length(px) / events] - expected: FAIL - - [clip rectangle(rectangle) / events] - expected: FAIL - - [margin-left length(cm) / events] - expected: FAIL - - [background-color color(rgba) / events] - expected: FAIL - - [min-width length(in) / events] - expected: FAIL - - [padding-right length(cm) / events] - expected: FAIL - - [width length(em) / events] - expected: FAIL - - [margin-left length(em) / events] - expected: FAIL - - [margin-right length(cm) / events] - expected: FAIL - - [border-bottom-width length(cm) / events] - expected: FAIL - - [bottom length(pc) / events] - expected: FAIL - - [top percentage(%) / events] - expected: FAIL - - [padding-left length(pt) / events] - expected: FAIL - - [min-width percentage(%) / events] - expected: FAIL - - [right length(px) / events] - expected: FAIL - - [padding-right length(in) / events] - expected: FAIL - - [left length(mm) / events] - expected: FAIL - - [bottom length(px) / events] - expected: FAIL - - [padding-left length(pc) / events] - expected: FAIL - - [outline-width length(ex) / events] - expected: FAIL - - [padding-left length(cm) / events] - expected: FAIL - - [left length(pt) / events] - expected: FAIL - - [outline-width length(mm) / events] - expected: FAIL - - [padding-left length(ex) / events] - expected: FAIL - - [margin-bottom length(cm) / events] - expected: FAIL - - [max-width length(pt) / events] - expected: FAIL - - [border-right-width length(em) / events] - expected: FAIL - - [margin-left length(in) / events] - expected: FAIL - - [top length(em) / events] - expected: FAIL - - [padding-right length(pt) / events] - expected: FAIL - - [padding-top length(pc) / events] - expected: FAIL - - [border-top-width length(ex) / events] - expected: FAIL - - [min-height length(pt) / events] - expected: FAIL - - [width length(in) / events] - expected: FAIL - - [min-width length(pc) / events] - expected: FAIL - - [margin-bottom length(mm) / events] - expected: FAIL - - [height length(pc) / events] - expected: FAIL - - [max-width length(px) / events] - expected: FAIL - - [bottom length(pt) / events] - expected: FAIL - - [padding-right length(ex) / events] - expected: FAIL - - [border-top-width length(em) / events] - expected: FAIL - - [max-height length(pt) / events] - expected: FAIL - - [vertical-align percentage(%) / events] - expected: FAIL - - [margin-left length(pc) / events] - expected: FAIL - - [min-height percentage(%) / events] - expected: FAIL - - [padding-bottom length(ex) / events] - expected: FAIL - - [padding-left length(em) / events] - expected: FAIL - - [bottom percentage(%) / events] - expected: FAIL - - [min-height length(pc) / events] - expected: FAIL - - [border-left-width length(pc) / events] - expected: FAIL - - [margin-bottom length(in) / events] - expected: FAIL - - [outline-width length(pt) / events] - expected: FAIL - - [margin-bottom length(em) / events] - expected: FAIL - - [top length(mm) / events] - expected: FAIL - - [outline-color color(rgba) / events] - expected: FAIL - - [bottom length(mm) / events] - expected: FAIL - - [padding-top length(mm) / events] - expected: FAIL - - [border-right-width length(ex) / events] - expected: FAIL - - [border-top-width length(cm) / events] - expected: FAIL - - [outline-width length(in) / events] - expected: FAIL - - [right length(pt) / events] - expected: FAIL - - [width length(px) / events] - expected: FAIL - - [height length(pt) / events] - expected: FAIL - - [padding-left length(in) / events] - expected: FAIL - - [min-height length(em) / events] - expected: FAIL - - [left percentage(%) / events] - expected: FAIL - - [padding-bottom length(pc) / events] - expected: FAIL - - [max-height length(ex) / events] - expected: FAIL - - [border-left-width length(cm) / events] - expected: FAIL - - [outline-offset length(ex) / events] - expected: FAIL - - [max-height length(pc) / events] - expected: FAIL - - [padding-right length(pc) / events] - expected: FAIL - - [top length(pc) / events] - expected: FAIL - - [vertical-align length(pc) / events] - expected: FAIL - - [min-height length(px) / events] - expected: FAIL - - [margin-right length(mm) / events] - expected: FAIL - - [max-height length(mm) / events] - expected: FAIL - - [right length(pc) / events] - expected: FAIL - - [vertical-align length(pt) / events] - expected: FAIL - - [padding-top length(cm) / events] - expected: FAIL - - [right length(cm) / events] - expected: FAIL - - [outline-offset length(pt) / events] - expected: FAIL - - [min-height length(in) / events] - expected: FAIL - - [max-width length(cm) / events] - expected: FAIL - - [border-bottom-width length(ex) / events] - expected: FAIL - - [max-height length(px) / events] - expected: FAIL - - [min-width length(px) / events] - expected: FAIL - - [outline-offset length(px) / events] - expected: FAIL - - [margin-top length(in) / events] - expected: FAIL - - [outline-offset length(in) / events] - expected: FAIL - - [margin-bottom length(pt) / events] - expected: FAIL - - [max-width length(em) / events] - expected: FAIL - - [padding-bottom length(pt) / events] - expected: FAIL - - [min-height length(mm) / events] - expected: FAIL - - [padding-bottom length(in) / events] - expected: FAIL - - [margin-bottom length(px) / events] - expected: FAIL - - [max-height length(in) / events] - expected: FAIL - - [outline-width length(px) / events] - expected: FAIL - - [padding-right length(em) / events] - expected: FAIL - - [height length(mm) / events] - expected: FAIL - - [margin-top length(mm) / events] - expected: FAIL - - [outline-offset length(pc) / events] - expected: FAIL - - [border-bottom-width length(em) / events] - expected: FAIL - - [z-index integer(integer) / events] - expected: FAIL - diff --git a/tests/wpt/metadata/css/css-transitions/properties-value-inherit-003.html.ini b/tests/wpt/metadata/css/css-transitions/properties-value-inherit-003.html.ini index f2ba77c14c2..681c017a2ee 100644 --- a/tests/wpt/metadata/css/css-transitions/properties-value-inherit-003.html.ini +++ b/tests/wpt/metadata/css/css-transitions/properties-value-inherit-003.html.ini @@ -5,90 +5,3 @@ [background-position length-em(em) / values] expected: FAIL - [line-height length-em(em) / events] - expected: FAIL - - [padding-left length-em(em) / events] - expected: FAIL - - [min-width length-em(em) / events] - expected: FAIL - - [right length-em(em) / events] - expected: FAIL - - [max-width length-em(em) / events] - expected: FAIL - - [text-indent length-em(em) / events] - expected: FAIL - - [margin-left length-em(em) / events] - expected: FAIL - - [word-spacing length-em(em) / events] - expected: FAIL - - [letter-spacing length-em(em) / events] - expected: FAIL - - [width length-em(em) / events] - expected: FAIL - - [padding-top length-em(em) / events] - expected: FAIL - - [margin-right length-em(em) / events] - expected: FAIL - - [max-height length-em(em) / events] - expected: FAIL - - [padding-bottom length-em(em) / events] - expected: FAIL - - [border-top-width length-em(em) / events] - expected: FAIL - - [height length-em(em) / events] - expected: FAIL - - [border-bottom-width length-em(em) / events] - expected: FAIL - - [border-left-width length-em(em) / events] - expected: FAIL - - [margin-bottom length-em(em) / events] - expected: FAIL - - [min-height length-em(em) / events] - expected: FAIL - - [outline-offset length-em(em) / events] - expected: FAIL - - [padding-right length-em(em) / events] - expected: FAIL - - [top length-em(em) / events] - expected: FAIL - - [outline-width length-em(em) / events] - expected: FAIL - - [bottom length-em(em) / events] - expected: FAIL - - [vertical-align length-em(em) / events] - expected: FAIL - - [left length-em(em) / events] - expected: FAIL - - [margin-top length-em(em) / events] - expected: FAIL - - [border-right-width length-em(em) / events] - expected: FAIL - diff --git a/tests/wpt/metadata/css/cssom-view/elementFromPoint-001.html.ini b/tests/wpt/metadata/css/cssom-view/elementFromPoint-001.html.ini deleted file mode 100644 index e38782d8c85..00000000000 --- a/tests/wpt/metadata/css/cssom-view/elementFromPoint-001.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[elementFromPoint-001.html] - [CSSOM View - 5 - extensions to the Document interface] - expected: FAIL - diff --git a/tests/wpt/metadata/css/cssom-view/elementsFromPoint-invalid-cases.html.ini b/tests/wpt/metadata/css/cssom-view/elementsFromPoint-invalid-cases.html.ini deleted file mode 100644 index e181af5397f..00000000000 --- a/tests/wpt/metadata/css/cssom-view/elementsFromPoint-invalid-cases.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[elementsFromPoint-invalid-cases.html] - [The root element is the last element returned for otherwise empty queries within the viewport] - expected: FAIL - diff --git a/tests/wpt/metadata/fetch/content-type/response.window.js.ini b/tests/wpt/metadata/fetch/content-type/response.window.js.ini index 1b1e9817153..196b87868f4 100644 --- a/tests/wpt/metadata/fetch/content-type/response.window.js.ini +++ b/tests/wpt/metadata/fetch/content-type/response.window.js.ini @@ -312,18 +312,21 @@ [fetch(): separate response Content-Type: text/plain ] expected: NOTRUN - [<iframe>: combined response Content-Type: text/html;" text/plain] + [<iframe>: combined response Content-Type: text/html */*;charset=gbk] expected: FAIL - [<iframe>: combined response Content-Type: text/html */*;charset=gbk] + [<iframe>: separate response Content-Type: text/html;x=" text/plain] expected: FAIL - [<iframe>: combined response Content-Type: text/plain;charset=gbk text/html] + [<iframe>: combined response Content-Type: */* text/html] expected: FAIL - [<iframe>: separate response Content-Type: text/html;x=" text/plain] + [<iframe>: separate response Content-Type: text/html */*] + expected: FAIL + + [<iframe>: separate response Content-Type: text/html;" \\" text/plain] expected: FAIL - [<iframe>: combined response Content-Type: text/html;" \\" text/plain] + [<iframe>: combined response Content-Type: text/html;x=" text/plain] expected: FAIL diff --git a/tests/wpt/metadata/fetch/content-type/script.window.js.ini b/tests/wpt/metadata/fetch/content-type/script.window.js.ini index e67f0406fc3..d2df9b78483 100644 --- a/tests/wpt/metadata/fetch/content-type/script.window.js.ini +++ b/tests/wpt/metadata/fetch/content-type/script.window.js.ini @@ -53,3 +53,6 @@ [combined text/javascript ] expected: FAIL + [separate text/javascript x/x] + expected: FAIL + diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini new file mode 100644 index 00000000000..87b07c3e670 --- /dev/null +++ b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini @@ -0,0 +1,4 @@ +[traverse_the_history_1.html] + [Multiple history traversals from the same task] + expected: FAIL + diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini new file mode 100644 index 00000000000..75d75b4cda2 --- /dev/null +++ b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini @@ -0,0 +1,4 @@ +[traverse_the_history_2.html] + [Multiple history traversals, last would be aborted] + expected: FAIL + diff --git a/tests/wpt/metadata/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html.ini b/tests/wpt/metadata/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html.ini index 042c6d3e4ae..063a11ac21f 100644 --- a/tests/wpt/metadata/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html.ini +++ b/tests/wpt/metadata/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html.ini @@ -24,3 +24,24 @@ [blob frame: postMessaging to a dedicated HTTP sub-worker allows them to see each others' modifications] expected: FAIL + [data frame: self.crossOriginIsolated] + expected: FAIL + + [data worker: postMessaging to a dedicated blob sub-worker allows them to see each others' modifications] + expected: TIMEOUT + + [data worker: self.crossOriginIsolated] + expected: FAIL + + [data worker: self.origin] + expected: FAIL + + [data frame: self.isSecureContext] + expected: FAIL + + [data frame: postMessaging to a dedicated blob sub-worker allows them to see each others' modifications] + expected: TIMEOUT + + [data worker: self.isSecureContext] + expected: FAIL + diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini index cb0211f1d21..f6a7aca3306 100644 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini +++ b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini @@ -1,6 +1,5 @@ [iframe_sandbox_popups_escaping-3.html] type: testharness - expected: CRASH [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini index 963d4cd20ef..9df1ac56f2a 100644 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini +++ b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini @@ -1,6 +1,6 @@ [iframe_sandbox_popups_nonescaping-1.html] type: testharness - expected: CRASH + expected: TIMEOUT [Check that popups from a sandboxed iframe do not escape the sandbox] expected: NOTRUN diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini index 71edac2c5ed..e440b1e38c6 100644 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini +++ b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html.ini @@ -1,6 +1,6 @@ [iframe_sandbox_popups_nonescaping-3.html] type: testharness - expected: CRASH + expected: TIMEOUT [Check that popups from a sandboxed iframe do not escape the sandbox] expected: NOTRUN diff --git a/tests/wpt/metadata/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini b/tests/wpt/metadata/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini index 69bd952d756..910c88d3e81 100644 --- a/tests/wpt/metadata/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini +++ b/tests/wpt/metadata/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini @@ -1,5 +1,5 @@ [ignore-opens-during-unload.window.html] - expected: TIMEOUT + expected: CRASH [ignore-opens-during-unload] expected: FAIL diff --git a/tests/wpt/metadata/webmessaging/without-ports/018.html.ini b/tests/wpt/metadata/webmessaging/without-ports/018.html.ini deleted file mode 100644 index 663a1f8fa30..00000000000 --- a/tests/wpt/metadata/webmessaging/without-ports/018.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[018.html] - expected: TIMEOUT - [origin of the script that invoked the method, javascript:] - expected: TIMEOUT - diff --git a/tests/wpt/web-platform-tests/.azure-pipelines.yml b/tests/wpt/web-platform-tests/.azure-pipelines.yml index 8c8a15d4ef4..8c39de66f48 100644 --- a/tests/wpt/web-platform-tests/.azure-pipelines.yml +++ b/tests/wpt/web-platform-tests/.azure-pipelines.yml @@ -25,6 +25,11 @@ trigger: - triggers/safari_stable - triggers/safari_preview +# Set safaridriver_diagnose to true to enable safaridriver diagnostics. The +# logs won't appear in `./wpt run` output but will be uploaded as an artifact. +variables: + safaridriver_diagnose: false + jobs: # The affected tests jobs are unconditional for speed, as most PRs have one or # more affected tests: https://github.com/web-platform-tests/wpt/issues/13936. @@ -108,11 +113,7 @@ jobs: displayName: 'Run tests (Firefox Nightly)' - script: no_proxy='*' ./wpt run --yes --no-manifest-update --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-mach - --log-mach-level info --channel preview safari infrastructure/ displayName: 'Run tests (Safari Technology Preview)' - - task: PublishBuildArtifacts@1 - displayName: 'Publish results' - inputs: - artifactName: 'infrastructure' - condition: always() + - template: tools/ci/azure/publish_logs.yml - job: tools_unittest_mac displayName: 'tools/ unittests: macOS' @@ -616,6 +617,7 @@ jobs: displayName: 'Publish results' inputs: artifactName: 'safari-results' + - template: tools/ci/azure/publish_logs.yml - template: tools/ci/azure/fyi_hook.yml parameters: dependsOn: results_safari @@ -651,6 +653,7 @@ jobs: displayName: 'Publish results' inputs: artifactName: 'safari-preview-results' + - template: tools/ci/azure/publish_logs.yml - template: tools/ci/azure/fyi_hook.yml parameters: dependsOn: results_safari_preview diff --git a/tests/wpt/web-platform-tests/content-security-policy/embedded-enforcement/blocked-iframe-are-cross-origin.html b/tests/wpt/web-platform-tests/content-security-policy/embedded-enforcement/blocked-iframe-are-cross-origin.html new file mode 100644 index 00000000000..9fedc4e930e --- /dev/null +++ b/tests/wpt/web-platform-tests/content-security-policy/embedded-enforcement/blocked-iframe-are-cross-origin.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> + <title>Embedded Enforcement: blocked iframe are cross-origin.</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/testharness-helper.sub.js"></script> +</head> +<body> +<script> + +let SecurityError = 18; + +let tests = [ + {name: "Same-origin" , origin: getOrigin()}, + {name: "Cross-origin", origin: getCrossOrigin()}, +]; + +for(test of tests) { + promise_test(async () => { + let iframe = document.createElement("iframe"); + let loaded = new Promise(r => iframe.onload = r); + iframe.csp = "script-src 'none'"; + iframe.src = test.origin + "common/blank.html"; + document.body.appendChild(iframe); + await loaded; + assert_throws_dom(SecurityError, () => iframe.contentWindow.document); + }, `${test.name} document blocked by embedded enforcement must appear cross-origin`); +} + +</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub.html b/tests/wpt/web-platform-tests/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub.html index 23337ae8d07..ba4df62bf6f 100644 --- a/tests/wpt/web-platform-tests/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub.html +++ b/tests/wpt/web-platform-tests/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub.html @@ -27,14 +27,14 @@ assert_equals(reports[0].type, "csp-violation"); assert_equals(reports[0].url, document_url); assert_equals(reports[0].body.documentURL, document_url); - assert_equals(reports[0].body.referrer, null); + assert_equals(reports[0].body.referrer, ""); assert_equals(reports[0].body.blockedURL, base_url + "support/fail.png"); assert_equals(reports[0].body.effectiveDirective, "img-src"); assert_equals(reports[0].body.originalPolicy, "script-src 'self' 'unsafe-inline'; img-src 'none'; report-to csp-group"); assert_equals(reports[0].body.sourceFile, document_url); - assert_equals(reports[0].body.sample, null); + assert_equals(reports[0].body.sample, ""); assert_equals(reports[0].body.disposition, "enforce"); assert_equals(reports[0].body.statusCode, 0); assert_equals(reports[0].body.lineNumber, 53); diff --git a/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-000.html b/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-000.html new file mode 100644 index 00000000000..a5f02184687 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-000.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-break-3/#parallel-flows"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<meta name="assert" content="A float that doesn't fit in the current fragmentainer will be pushed to next fragmentainer, while subsequent content may still fit in the former fragmentainer, without being affected by the float"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:3; column-fill:auto; height:100px;"> + <div style="width:100px; background:red;"> + <div style="width:200px;"> + <div style="width:100px; height:50px; background:green;"></div> + <div style="float:left; width:50px; line-height:60px;"><br></div> + <div style="clear:right; width:100px; height:50px; display:flow-root; background:green;"></div> + </div> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-001.html b/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-001.html new file mode 100644 index 00000000000..d172f935744 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-001.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-break-3/#parallel-flows"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<meta name="assert" content="A float that doesn't fit in the current fragmentainer will be pushed to next fragmentainer, while subsequent content may still fit in the former fragmentainer, without being affected by the float"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:3; column-fill:auto; column-gap:0; width:150px; height:100px;"> + <div style="background:red;"> + <div style="width:50px; height:50px; background:green;"></div> + <div style="float:left; width:50px; line-height:70px; background:green;"><br></div> + <div style="float:left; width:50px; line-height:30px; background:green;"><br></div> + <div style="width:50px; height:50px; display:flow-root; background:green;"></div> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-002.html b/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-002.html new file mode 100644 index 00000000000..1ba22353c07 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-break/tall-float-pushed-to-next-fragmentainer-002.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-break-3/#parallel-flows"> +<link rel="match" href="../reference/ref-filled-green-100px-square-only.html"> +<meta name="assert" content="A float that doesn't fit in the current fragmentainer will be pushed to next fragmentainer, while subsequent content may still fit in the former fragmentainer, but it still needs to apply clearance as needed."> +<p>Test passes if there is a filled green square.</p> +<div style="columns:3; column-fill:auto; column-gap:0; width:150px; height:120px;"> + <div style="height:100px; background:green;"></div> + <div style="float:right; width:10px; line-height:100px; background:green;"><br></div> + <div style="float:left; width:40px; line-height:60px; background:green;"><br></div> + <div style="clear:left; height:40px;background:green;"></div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-device-adapt/viewport-user-scalable-no-clamp-to-max.tentative.html b/tests/wpt/web-platform-tests/css/css-device-adapt/viewport-user-scalable-no-clamp-to-max.tentative.html new file mode 100644 index 00000000000..c2c341245b5 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-device-adapt/viewport-user-scalable-no-clamp-to-max.tentative.html @@ -0,0 +1,29 @@ +<!doctype html> +<meta charset=utf-8> +<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=device-width, maximum-scale=1.0"> +<link rel="help" href="https://drafts.csswg.org/css-device-adapt/"> +<link rel="help" href="https://webcompat.com/issues/52856"> +<style> +body { + margin: 0; +} +#content { + width: 100px; + height: 100px; + background: green; +} +</style> + +<div id="content">Content</div> + +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +'use strict'; +test(() => { + assert_equals(window.visualViewport.scale, 1.0, + 'visual viewport scale should be 1.0'); +}, 'Page with meta viewport "width=device-width, user-scalable=no, ' + + 'initial-scale=device-width, maximum-scale=1.0" ' + + 'should scale to 1.0.'); +</script> diff --git a/tests/wpt/web-platform-tests/css/css-device-adapt/viewport-user-scalable-no-clamp-to-min.tentative.html b/tests/wpt/web-platform-tests/css/css-device-adapt/viewport-user-scalable-no-clamp-to-min.tentative.html new file mode 100644 index 00000000000..89d7bb2f8ce --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-device-adapt/viewport-user-scalable-no-clamp-to-min.tentative.html @@ -0,0 +1,29 @@ +<!doctype html> +<meta charset=utf-8> +<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=0.25, minimum-scale=1.0"> +<link rel="help" href="https://drafts.csswg.org/css-device-adapt/"> +<link rel="help" href="https://webcompat.com/issues/52856"> +<style> +body { + margin: 0; +} +#content { + width: 100px; + height: 100px; + background: green; +} +</style> + +<div id="content">Content</div> + +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +'use strict'; +test(() => { + assert_equals(window.visualViewport.scale, 1.0, + 'visual viewport scale should be 1.0'); +}, 'Page with meta viewport "width=device-width, user-scalable=no, ' + + 'initial-scale=0.25, minimum-scale=1.0" ' + + 'should scale to 1.0.'); +</script> diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/negative-item-margins-002-crash.html b/tests/wpt/web-platform-tests/css/css-flexbox/negative-item-margins-002-crash.html new file mode 100644 index 00000000000..97b450df9a0 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-flexbox/negative-item-margins-002-crash.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<title>Negative item margins</title> +<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org" /> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths" /> + +<p>Test passes if it doesn't crash.</p> + +<div style="display: flex; flex-flow: column;"> + <div style="margin: -10px;"></div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-scroll-anchoring/position-change-heuristic-in-nested-scroll-box.html b/tests/wpt/web-platform-tests/css/css-scroll-anchoring/position-change-heuristic-in-nested-scroll-box.html new file mode 100644 index 00000000000..58c88001d53 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-scroll-anchoring/position-change-heuristic-in-nested-scroll-box.html @@ -0,0 +1,85 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/#suppression-triggers"> +<style> +#space { + height: 4000px; + overflow: hidden; +} +#header { + background-color: #F5B335; + height: 50px; + width: 100%; +} +#content { + background-color: #D3D3D3; + height: 400px; +} +.scroller { + overflow: scroll; + position: relative; + width: 600px; + height: 600px; +} +body { + overflow: hidden; +} +</style> +<div id="maybeScroller"> + <div id="space"> + <div id="header"></div> + <div id="before"></div> + <div id="content"></div> + </div> +</div> +<script> + +// Tests that scroll anchoring is suppressed when an element in the scroller +// changes its in-flow state. + +var scroller; + +function runCase(oldPos, newPos, expectSuppression, skipInverse) { + var header = document.querySelector("#header"); + var before = document.querySelector("#before"); + + header.style.position = oldPos; + before.style.height = "0"; + scroller.scrollTop = 200; + + header.style.position = newPos; + before.style.height = "25px"; + + var expectedTop = expectSuppression ? 200 : 225; + assert_equals(scroller.scrollTop, expectedTop); + + if (!skipInverse) + runCase(newPos, oldPos, expectSuppression, true); +} + +test(() => { + scroller = document.scrollingElement; + document.querySelector("#maybeScroller").className = ""; + + runCase("static", "fixed", true); + runCase("static", "absolute", true); + runCase("static", "relative", false); + runCase("fixed", "absolute", false); + runCase("fixed", "relative", true); + runCase("absolute", "relative", true); +}, "Position changes in document scroller."); + +test(() => { + scroller = document.querySelector("#maybeScroller"); + scroller.className = "scroller"; + + runCase("static", "fixed", true); + runCase("static", "absolute", true); + runCase("static", "relative", false); + runCase("fixed", "absolute", false); + runCase("fixed", "relative", true); + runCase("absolute", "relative", true); +}, "Position changes in scrollable <div>."); + +</script> diff --git a/tests/wpt/web-platform-tests/css/selectors/focus-visible-003-manual.html b/tests/wpt/web-platform-tests/css/selectors/focus-visible-003-manual.html index eeb2904d7d3..ccc916a9528 100644 --- a/tests/wpt/web-platform-tests/css/selectors/focus-visible-003-manual.html +++ b/tests/wpt/web-platform-tests/css/selectors/focus-visible-003-manual.html @@ -58,15 +58,16 @@ <label><input data-tested="false" id="el-10" type="radio"></input> Focus me.</label> </div> <div> - <label><input data-tested="false" id="el-11" type="color"></input> Focus me.</label> - </div> - <div> <!-- Focusing file input triggers a modal, so only test manually --> <input id="el-12" type="file" value="Focus me."></input> </div> <div> <label><input data-tested="false" id="el-13" type="range"></input> Focus me.</label> </div> + <div> + <!-- Ensure the color input is last, as it has a pop-up which obscures other elements --> + <label><input data-tested="false" id="el-11" type="color"></input> Focus me.</label> + </div> <script> async_test(function(t) { document.querySelectorAll("[data-tested]").forEach((el) => { diff --git a/tests/wpt/web-platform-tests/css/selectors/focus-visible-004-manual.html b/tests/wpt/web-platform-tests/css/selectors/focus-visible-004-manual.html index dba057cc9c8..4d7878e751e 100644 --- a/tests/wpt/web-platform-tests/css/selectors/focus-visible-004-manual.html +++ b/tests/wpt/web-platform-tests/css/selectors/focus-visible-004-manual.html @@ -58,15 +58,18 @@ <label><input data-tested="false" id="el-10" type="radio"></input> Focus me.</label> </div> <div> - <label><input data-tested="false" id="el-11" type="color"></input> Focus me.</label> - </div> - <div> <!-- Focusing file input triggers a modal, so only test manually --> <input id="el-12" type="file" value="Focus me."></input> </div> <div> <label><input data-tested="false" id="el-13" type="range"></input> Focus me.</label> </div> + <div> + <!-- Ensure the color input is last, as it has a pop-up which obscures other elements, + causing the `mouseClickInTarget` method to fail and the test to hang waiting for + a click event.--> + <label><input data-tested="false" id="el-11" type="color"></input> Focus me.</label> + </div> <script> async_test(function(t) { document.querySelectorAll("[data-tested]").forEach((el) => { diff --git a/tests/wpt/web-platform-tests/css/selectors/is-nested.html b/tests/wpt/web-platform-tests/css/selectors/is-nested.html index 7c3973ae058..0658f9030d1 100644 --- a/tests/wpt/web-platform-tests/css/selectors/is-nested.html +++ b/tests/wpt/web-platform-tests/css/selectors/is-nested.html @@ -14,7 +14,7 @@ font-size: 10px; width: 10px; } - .a+:is(.b+.f, .b+:is(*, .c>.e, .g, *))+.d { + .e:is(.b+.f, .e:is(*, .c>.e, .g, *))+.d { color: red; font-size: 20px; } @@ -25,7 +25,7 @@ .a+.c>.e { color: black; } - .a+:is(.b+.f, :is(.c>.e, .g)) { + .e:is(.b+.f, :is(.c>.e, .g)) { color: red; } .c>.e { @@ -69,4 +69,4 @@ </script> </body> -</html>
\ No newline at end of file +</html> diff --git a/tests/wpt/web-platform-tests/css/selectors/is-specificity.html b/tests/wpt/web-platform-tests/css/selectors/is-specificity.html index bf3dbc6bb9f..541b0406d34 100644 --- a/tests/wpt/web-platform-tests/css/selectors/is-specificity.html +++ b/tests/wpt/web-platform-tests/css/selectors/is-specificity.html @@ -13,7 +13,7 @@ height: 10px; width: 10px; } - :is(.a, .b.c + .d, .e) + :is(* + .p, .q.r + .s, * + .t) + #target { + :is(.a, .b.c + .d, .q) + :is(* + .p, .q.r + .s, * + .t) + #target { height: 20px; width: 20px; } diff --git a/tests/wpt/web-platform-tests/docs/running-tests/safari.md b/tests/wpt/web-platform-tests/docs/running-tests/safari.md index 0ff8fe5d95e..eed52254718 100644 --- a/tests/wpt/web-platform-tests/docs/running-tests/safari.md +++ b/tests/wpt/web-platform-tests/docs/running-tests/safari.md @@ -42,3 +42,6 @@ argument: The logs will be in `~/Library/Logs/com.apple.WebDriver/`. See `man safaridriver` for more information. + +To enable safaridriver diagnostics in Azure Pipelines, set +`safaridriver_diagnose` to `true` in `.azure-pipelines.yml`. diff --git a/tests/wpt/web-platform-tests/fullscreen/rendering/fullscreen-css-invalidation.html b/tests/wpt/web-platform-tests/fullscreen/rendering/fullscreen-css-invalidation.html new file mode 100644 index 00000000000..e855d0c1935 --- /dev/null +++ b/tests/wpt/web-platform-tests/fullscreen/rendering/fullscreen-css-invalidation.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Invalidate :fullscreen based style</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<style> + #pass { + color: red; + } + :root:fullscreen #pass { + color: green; + } +</style> +<div id="pass">Should be green</div> +<script> + async_test(t => { + document.onfullscreenchange = t.step_func_done(() => { + assert_equals(document.fullscreenElement, document.documentElement); + assert_equals(getComputedStyle(pass).color, "rgb(0, 128, 0)", "Green when :root is fullscreened."); + }); + document.documentElement.addEventListener('click', t.step_func(() => { + document.documentElement.requestFullscreen(); + }), {once: true}); + assert_equals(getComputedStyle(pass).color, "rgb(255, 0, 0)", "Initially red."); + test_driver.click(document.documentElement); + }); +</script> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-1-expected.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-1-expected.htm new file mode 100644 index 00000000000..3272f32fb88 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-1-expected.htm @@ -0,0 +1,10 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + </head> + <body> + <p>There should be no text below this, because the text is inside a canvas element. + The canvas is never closed, and the rest of the body ends up inside it.</p> + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-1.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-1.htm new file mode 100644 index 00000000000..5e0c914755b --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-1.htm @@ -0,0 +1,14 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + <link rel="match" href="unclosed-canvas-1-expected.htm"> + <meta name="assert" content="Test what if canvas tag is unclosed in tag p" /> + <script type="text/javascript"></script> + </head> + <body> + <p>There should be no text below this, because the text is inside a canvas element. + The canvas is never closed, and the rest of the body ends up inside it. </p> + <canvas>This text should NOT be visible if JavaScript is enabled. + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-2-expected.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-2-expected.htm new file mode 100644 index 00000000000..fd48cd0db18 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-2-expected.htm @@ -0,0 +1,14 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + </head> + <body> + <div><canvas></canvas></div> + <p>This text should be visible, even though it's preceded by an unclosed canvas tag, + because of the </div> that closes an element opened before the canvas. + There's nothing special about div; we get the same results with other types of + elements. + </p> + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-2.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-2.htm new file mode 100644 index 00000000000..fb329e73d6f --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-2.htm @@ -0,0 +1,15 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + <link rel="match" href="unclosed-canvas-2-expected.htm"> + <meta name="assert" content="Test what if canvas tag is unclosed in tag div" /> + <script type="text/javascript"></script> + </head> + <body> + <div><canvas></div> + <p>This text should be visible, even though it's preceded by an unclosed canvas tag, + because of the </div> that closes an element opened before the canvas. + There's nothing special about div; we get the same results with other types of elements.</p> + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-3-expected.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-3-expected.htm new file mode 100644 index 00000000000..efd239b4fb3 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-3-expected.htm @@ -0,0 +1,13 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + </head> + <body> + <p>There should be no text below this, because the text is inside a canvas element + and the </div> that's also inside the canvas element does not close an open + element. The canvas is never closed, and the rest of the body ends up inside it. + There's nothing special about div; we get the same results with other types of + elements.</p> + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-3.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-3.htm new file mode 100644 index 00000000000..8ffaa0f9eb5 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-3.htm @@ -0,0 +1,16 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + <link rel="match" href="unclosed-canvas-3-expected.htm"> + <meta name="assert" content="Test what if canvas tag is unclosed in unclosed div" /> + <script type="text/javascript"></script> + </head> + <body> + <p>There should be no text below this, because the text is inside a canvas element + and the </div> that's also inside the canvas element does not close an open element. + The canvas is never closed, and the rest of the body ends up inside it. + There's nothing special about div; we get the same results with other types of elements.</p> + <canvas></div>This text should NOT be visible if JavaScript is enabled. + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-4-expected.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-4-expected.htm new file mode 100644 index 00000000000..492449261e7 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-4-expected.htm @@ -0,0 +1,14 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + </head> + <body> + <p>There should be no text below this, because the text is inside a canvas element + and the </div> that's also inside the canvas element does not close an open + element. The canvas is never closed, and the rest of the body ends up inside it. + There's nothing special about div; we get the same results with other types of + elements. The fact that the canvas tag uses XML self-closing syntax has no effect. + </p> + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-4.htm b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-4.htm new file mode 100644 index 00000000000..aa5fd144381 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/canvas/element/manual/unclosed-canvas-4.htm @@ -0,0 +1,17 @@ +<!doctype HTML> +<html> + <head> + <title>unclosed canvas tag in body</title> + <link rel="match" href="unclosed-canvas-4-expected.htm"> + <meta name="assert" content="Test what if canvas tag is unclosed in body" /> + <script type="text/javascript"></script> + </head> + <body> + <p>There should be no text below this, because the text is inside a canvas element + and the </div> that's also inside the canvas element does not close an open element. + The canvas is never closed, and the rest of the body ends up inside it. + There's nothing special about div; we get the same results with other types of elements. + The fact that the canvas tag uses XML self-closing syntax has no effect.</p> + <canvas/></div>This text should NOT be visible if JavaScript is enabled. + </body> +</html> diff --git a/tests/wpt/web-platform-tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html b/tests/wpt/web-platform-tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html index 8fe2ee46cb3..dbc73e98f57 100644 --- a/tests/wpt/web-platform-tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html +++ b/tests/wpt/web-platform-tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/blob-data.https.html @@ -29,9 +29,10 @@ self.postMessage({ origin: self.origin, view }); \`], { type: "text/javascript" }))); return new Promise((resolve, reject) => { - // Initially the sub-worker gives us an object containing an origin and a view on a shared + /* Initially the sub-worker gives us an object containing an origin and a view on a shared // buffer. We then modify the shared buffer through the buffer and tell the sub-worker to // "continue". The sub-worker verifies the modification and relays whether it succeeded. + */ worker.onmessage = t.step_func(({ data }) => { if ("succeeded" in data) { assert_true(data.succeeded); @@ -101,7 +102,7 @@ fetch_tests_from_window(frame.contentWindow); const dataWorkerScript = ` importScripts("${url.origin}/resources/testharness.js?pipe=header(Cross-Origin-Resource-Policy,cross-origin)"); -// Cannot use httpWorkerIncrementerTest() here as the HTTP URL is not same origin. +/* Cannot use httpWorkerIncrementerTest() here as the HTTP URL is not same origin. */ ${blobWorkerIncrementerTest("data worker")} @@ -116,7 +117,7 @@ const dataFrameScript = ` <!doctype html> <script src=${url.origin}/resources/testharness.js?pipe=header(Cross-Origin-Resource-Policy,cross-origin)><\/script> <script> -// Cannot use httpWorkerIncrementerTest() here as the HTTP URL is not same origin. +/* Cannot use httpWorkerIncrementerTest() here as the HTTP URL is not same origin. */ ${blobWorkerIncrementerTest("data frame")} diff --git a/tests/wpt/web-platform-tests/interfaces/screen-wake-lock.idl b/tests/wpt/web-platform-tests/interfaces/wake-lock.idl index 1eb30a06024..1eb30a06024 100644 --- a/tests/wpt/web-platform-tests/interfaces/screen-wake-lock.idl +++ b/tests/wpt/web-platform-tests/interfaces/wake-lock.idl diff --git a/tests/wpt/web-platform-tests/reporting/path-absolute-endpoint.https.sub.html b/tests/wpt/web-platform-tests/reporting/path-absolute-endpoint.https.sub.html index ec06a368e97..144fcb024e3 100644 --- a/tests/wpt/web-platform-tests/reporting/path-absolute-endpoint.https.sub.html +++ b/tests/wpt/web-platform-tests/reporting/path-absolute-endpoint.https.sub.html @@ -28,14 +28,14 @@ assert_equals(reports[0].type, "csp-violation"); assert_equals(reports[0].url, location.href); assert_equals(reports[0].body.documentURL, location.href); - assert_equals(reports[0].body.referrer, null); + assert_equals(reports[0].body.referrer, ""); assert_equals(reports[0].body.blockedURL, `${base_url}/reporting/resources/fail.png`); assert_equals(reports[0].body.effectiveDirective, "img-src"); assert_equals(reports[0].body.originalPolicy, "script-src 'self' 'unsafe-inline'; img-src 'none'; report-to csp-group"); assert_equals(reports[0].body.sourceFile, location.href); - assert_equals(reports[0].body.sample, null); + assert_equals(reports[0].body.sample, ""); assert_equals(reports[0].body.disposition, "enforce"); assert_equals(reports[0].body.statusCode, 0); assert_equals(reports[0].body.lineNumber, 66); diff --git a/tests/wpt/web-platform-tests/screen-wake-lock/idlharness.https.window.js b/tests/wpt/web-platform-tests/screen-wake-lock/idlharness.https.window.js index 370696e90b3..275454248f5 100644 --- a/tests/wpt/web-platform-tests/screen-wake-lock/idlharness.https.window.js +++ b/tests/wpt/web-platform-tests/screen-wake-lock/idlharness.https.window.js @@ -8,7 +8,7 @@ 'use strict'; idl_test( - ['screen-wake-lock'], + ['wake-lock'], ['dom', 'html'], async idl_array => { idl_array.add_objects({ Navigator: ['navigator'] }); diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-resources.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-resources.https.html index e0ddac74dbf..fe227d9ce2f 100644 --- a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-resources.https.html +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-resources.https.html @@ -5,12 +5,12 @@ <script src="/common/get-host-info.sub.js"></script> <script src="resources/test-helpers.sub.js"></script> <script> -var url_count = 0; -var expected_results = {}; +let url_count = 0; +const expected_results = {}; function add_promise_to_test(url) { - var expected = expected_results[url]; + const expected = expected_results[url]; return new Promise((resolve) => { expected.resolve = resolve; }); @@ -18,7 +18,7 @@ function add_promise_to_test(url) function image_test(frame, url, cross_origin, expected_mode, expected_credentials) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { cross_origin: cross_origin, mode: expected_mode, @@ -26,8 +26,7 @@ function image_test(frame, url, cross_origin, expected_mode, redirect: 'follow', integrity: '', destination: 'image', - message: 'Image load (url:' + - actual_url + ' cross_origin:' + cross_origin + ')' + message: `Image load (url:${actual_url} cross_origin:${cross_origin})` }; frame.contentWindow.load_image(actual_url, cross_origin); return add_promise_to_test(actual_url); @@ -35,7 +34,7 @@ function image_test(frame, url, cross_origin, expected_mode, function script_test(frame, url, cross_origin, expected_mode, expected_credentials) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { cross_origin: cross_origin, mode: expected_mode, @@ -43,8 +42,7 @@ function script_test(frame, url, cross_origin, expected_mode, redirect: 'follow', integrity: '', destination: 'script', - message: 'Script load (url:' + - actual_url + ' cross_origin:' + cross_origin + ')' + message: `Script load (url:${actual_url} cross_origin:${cross_origin})` }; frame.contentWindow.load_script(actual_url, cross_origin); return add_promise_to_test(actual_url); @@ -52,7 +50,7 @@ function script_test(frame, url, cross_origin, expected_mode, function css_test(frame, url, cross_origin, expected_mode, expected_credentials) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { cross_origin: cross_origin, mode: expected_mode, @@ -60,15 +58,14 @@ function css_test(frame, url, cross_origin, expected_mode, redirect: 'follow', integrity: '', destination: 'style', - message: 'CSS load (url:' + - actual_url + ' cross_origin:' + cross_origin + ')' + message: `CSS load (url:${actual_url} cross_origin:${cross_origin})` }; frame.contentWindow.load_css(actual_url, cross_origin); return add_promise_to_test(actual_url); } function font_face_test(frame, url, expected_mode, expected_credentials) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { url: actual_url, mode: expected_mode, @@ -76,14 +73,14 @@ function font_face_test(frame, url, expected_mode, expected_credentials) { redirect: 'follow', integrity: '', destination: 'font', - message: 'FontFace load (url:' + actual_url + ')' + message: `FontFace load (url: ${actual_url})` }; frame.contentWindow.load_font(actual_url); return add_promise_to_test(actual_url); } function script_integrity_test(frame, url, integrity, expected_integrity) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { url: actual_url, mode: 'no-cors', @@ -91,14 +88,14 @@ function script_integrity_test(frame, url, integrity, expected_integrity) { redirect: 'follow', integrity: expected_integrity, destination: 'script', - message: 'Script load (url:' + actual_url + ')' + message: `Script load (url:${actual_url})` }; frame.contentWindow.load_script_with_integrity(actual_url, integrity); return add_promise_to_test(actual_url); } function css_integrity_test(frame, url, integrity, expected_integrity) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { url: actual_url, mode: 'no-cors', @@ -106,7 +103,7 @@ function css_integrity_test(frame, url, integrity, expected_integrity) { redirect: 'follow', integrity: expected_integrity, destination: 'style', - message: 'CSS load (url:' + actual_url + ')' + message: `CSS load (url:${actual_url})` }; frame.contentWindow.load_css_with_integrity(actual_url, integrity); return add_promise_to_test(actual_url); @@ -114,33 +111,31 @@ function css_integrity_test(frame, url, integrity, expected_integrity) { function fetch_test(frame, url, mode, credentials, expected_mode, expected_credentials) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { mode: expected_mode, credentials: expected_credentials, redirect: 'follow', integrity: '', destination: 'empty', - message: 'fetch (url:' + actual_url + ' mode:' + mode + ' credentials:' + - credentials + ')' + message: `fetch (url:${actual_url} mode:${mode} ` + + `credentials:${credentials})` }; frame.contentWindow.fetch( - new Request(actual_url, {mode: mode, credentials: credentials})).then(() => { - }, () => { }); + new Request(actual_url, {mode: mode, credentials: credentials})); return add_promise_to_test(actual_url); } function audio_test(frame, url, cross_origin, expected_mode, expected_credentials) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { mode: expected_mode, credentials: expected_credentials, redirect: 'follow', integrity: '', destination: 'audio', - message: 'Audio load (url:' + actual_url + ' cross_origin:' + - cross_origin + ')' + message: `Audio load (url:${actual_url} cross_origin:${cross_origin})` }; frame.contentWindow.load_audio(actual_url, cross_origin); return add_promise_to_test(actual_url); @@ -149,163 +144,159 @@ function audio_test(frame, url, cross_origin, function video_test(frame, url, cross_origin, expected_mode, expected_credentials) { - var actual_url = url + (++url_count); + const actual_url = url + (++url_count); expected_results[actual_url] = { mode: expected_mode, credentials: expected_credentials, redirect: 'follow', integrity: '', destination: 'video', - message: 'Video load (url:' + actual_url + ' cross_origin:' + - cross_origin + ')' + message: `Video load (url:${actual_url} cross_origin:${cross_origin})` }; frame.contentWindow.load_video(actual_url, cross_origin); return add_promise_to_test(actual_url); } -promise_test(function(t) { - var SCOPE = 'resources/fetch-request-resources-iframe.https.html'; - var SCRIPT = 'resources/fetch-request-resources-worker.js'; - var host_info = get_host_info(); - var LOCAL_URL = +promise_test(async t => { + const SCOPE = 'resources/fetch-request-resources-iframe.https.html'; + const SCRIPT = 'resources/fetch-request-resources-worker.js'; + const host_info = get_host_info(); + const LOCAL_URL = host_info['HTTPS_ORIGIN'] + base_path() + 'resources/dummy?test'; - var REMOTE_URL = + const REMOTE_URL = host_info['HTTPS_REMOTE_ORIGIN'] + base_path() + 'resources/dummy?test'; - var worker; - var frame; - return service_worker_unregister_and_register(t, SCRIPT, SCOPE) - .then(function(registration) { - worker = registration.installing; - return wait_for_state(t, worker, 'activated'); - }) - .then(function() { - return new Promise(function(resolve, reject) { - var channel = new MessageChannel(); - channel.port1.onmessage = t.step_func(function(msg) { - if (msg.data.ready) { - resolve(); - return; - } - var result = msg.data; - var expected = expected_results[result.url]; - if (!expected) { - return; - } - test(() => { - assert_equals( - result.mode, expected.mode, - 'mode of ' + expected.message + ' must be ' + - expected.mode + '.'); - assert_equals( - result.credentials, expected.credentials, - 'credentials of ' + expected.message + ' must be ' + - expected.credentials + '.'); - assert_equals( - result.redirect, expected.redirect, - 'redirect mode of ' + expected.message + ' must be ' + - expected.redirect + '.'); - assert_equals( - result.integrity, expected.integrity, - 'integrity of ' + expected.message + ' must be ' + - expected.integrity + '.'); - assert_equals( - result.destination, expected.destination, - 'destination of ' + expected.message + ' must be ' + - expected.destination + '.'); - }, expected.message); - expected.resolve(); - delete expected_results[result.url]; - }); - worker.postMessage( - {port: channel.port2}, [channel.port2]); - }); - }) - .then(function() { return with_iframe(SCOPE); }) - .then(async function(f) { - frame = f; - await image_test(f, LOCAL_URL, '', 'no-cors', 'include'); - await image_test(f, REMOTE_URL, '', 'no-cors', 'include'); - await css_test(f, LOCAL_URL, '', 'no-cors', 'include'); - await css_test(f, REMOTE_URL, '', 'no-cors', 'include'); + const registration = + await service_worker_unregister_and_register(t, SCRIPT, SCOPE); + t.add_cleanup(() => registration.unregister()); + const worker = registration.installing; + await wait_for_state(t, worker, 'activated'); - await image_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); - await image_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); - await image_test(f, REMOTE_URL, '', 'no-cors', 'include'); - await image_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); - await image_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); + await new Promise((resolve, reject) => { + const channel = new MessageChannel(); + channel.port1.onmessage = t.step_func(msg => { + if (msg.data.ready) { + resolve(); + return; + } + const result = msg.data; + const expected = expected_results[result.url]; + if (!expected) { + return; + } + test(() => { + assert_equals( + result.mode, expected.mode, + `mode of must be ${expected.mode}.`); + assert_equals( + result.credentials, expected.credentials, + `credentials of ${expected.message} must be ` + + `${expected.credentials}.`); + assert_equals( + result.redirect, expected.redirect, + `redirect mode of ${expected.message} must be ` + + `${expected.redirect}.`); + assert_equals( + result.integrity, expected.integrity, + `integrity of ${expected.message} must be ` + + `${expected.integrity}.`); + assert_equals( + result.destination, expected.destination, + `destination of ${expected.message} must be ` + + `${expected.destination}.`); + }, expected.message); + expected.resolve(); + delete expected_results[result.url]; + }); + worker.postMessage({port: channel.port2}, [channel.port2]); + }); + + const f = await with_iframe(SCOPE); + t.add_cleanup(() => f.remove()); + + await image_test(f, LOCAL_URL, '', 'no-cors', 'include'); + await image_test(f, REMOTE_URL, '', 'no-cors', 'include'); + await css_test(f, LOCAL_URL, '', 'no-cors', 'include'); + await css_test(f, REMOTE_URL, '', 'no-cors', 'include'); - await script_test(f, LOCAL_URL, '', 'no-cors', 'include'); - await script_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); - await script_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); - await script_test(f, REMOTE_URL, '', 'no-cors', 'include'); - await script_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); - await script_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); + await image_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); + await image_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); + await image_test(f, REMOTE_URL, '', 'no-cors', 'include'); + await image_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); + await image_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); - await css_test(f, LOCAL_URL, '', 'no-cors', 'include'); - await css_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); - await css_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); - await css_test(f, REMOTE_URL, '', 'no-cors', 'include'); - await css_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); - await css_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); + await script_test(f, LOCAL_URL, '', 'no-cors', 'include'); + await script_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); + await script_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); + await script_test(f, REMOTE_URL, '', 'no-cors', 'include'); + await script_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); + await script_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); - await font_face_test(f, LOCAL_URL, 'cors', 'same-origin'); - await font_face_test(f, REMOTE_URL, 'cors', 'same-origin'); + await css_test(f, LOCAL_URL, '', 'no-cors', 'include'); + await css_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); + await css_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); + await css_test(f, REMOTE_URL, '', 'no-cors', 'include'); + await css_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); + await css_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); - await script_integrity_test(f, LOCAL_URL, ' ', ' '); - await script_integrity_test(f, LOCAL_URL, - 'This is not a valid integrity because it has no dashes', - 'This is not a valid integrity because it has no dashes'); - await script_integrity_test(f, LOCAL_URL, 'sha256-', 'sha256-'); - await script_integrity_test(f, LOCAL_URL, 'sha256-foo?123', 'sha256-foo?123'); - await script_integrity_test(f, LOCAL_URL, 'sha256-foo sha384-abc ', 'sha256-foo sha384-abc '); - await script_integrity_test(f, LOCAL_URL, 'sha256-foo sha256-abc', 'sha256-foo sha256-abc'); + await font_face_test(f, LOCAL_URL, 'cors', 'same-origin'); + await font_face_test(f, REMOTE_URL, 'cors', 'same-origin'); - await css_integrity_test(f, LOCAL_URL, ' ', ' '); - await css_integrity_test(f, LOCAL_URL, - 'This is not a valid integrity because it has no dashes', - 'This is not a valid integrity because it has no dashes'); - await css_integrity_test(f, LOCAL_URL, 'sha256-', 'sha256-'); - await css_integrity_test(f, LOCAL_URL, 'sha256-foo?123', 'sha256-foo?123'); - await css_integrity_test(f, LOCAL_URL, 'sha256-foo sha384-abc ', 'sha256-foo sha384-abc '); - await css_integrity_test(f, LOCAL_URL, 'sha256-foo sha256-abc', 'sha256-foo sha256-abc'); + await script_integrity_test(f, LOCAL_URL, ' ', ' '); + await script_integrity_test( + f, LOCAL_URL, + 'This is not a valid integrity because it has no dashes', + 'This is not a valid integrity because it has no dashes'); + await script_integrity_test(f, LOCAL_URL, 'sha256-', 'sha256-'); + await script_integrity_test(f, LOCAL_URL, 'sha256-foo?123', 'sha256-foo?123'); + await script_integrity_test(f, LOCAL_URL, 'sha256-foo sha384-abc ', + 'sha256-foo sha384-abc '); + await script_integrity_test(f, LOCAL_URL, 'sha256-foo sha256-abc', + 'sha256-foo sha256-abc'); - await fetch_test(f, LOCAL_URL, 'same-origin', 'omit', 'same-origin', 'omit'); - await fetch_test(f, LOCAL_URL, 'same-origin', 'same-origin', - 'same-origin', 'same-origin'); - await fetch_test(f, LOCAL_URL, 'same-origin', 'include', - 'same-origin', 'include'); - await fetch_test(f, LOCAL_URL, 'no-cors', 'omit', 'no-cors', 'omit'); - await fetch_test(f, LOCAL_URL, 'no-cors', 'same-origin', - 'no-cors', 'same-origin'); - await fetch_test(f, LOCAL_URL, 'no-cors', 'include', 'no-cors', 'include'); - await fetch_test(f, LOCAL_URL, 'cors', 'omit', 'cors', 'omit'); - await fetch_test(f, LOCAL_URL, 'cors', 'same-origin', 'cors', 'same-origin'); - await fetch_test(f, LOCAL_URL, 'cors', 'include', 'cors', 'include'); - await fetch_test(f, REMOTE_URL, 'no-cors', 'omit', 'no-cors', 'omit'); - await fetch_test(f, REMOTE_URL, 'no-cors', 'same-origin', - 'no-cors', 'same-origin'); - await fetch_test(f, REMOTE_URL, 'no-cors', 'include', 'no-cors', 'include'); - await fetch_test(f, REMOTE_URL, 'cors', 'omit', 'cors', 'omit'); - await fetch_test(f, REMOTE_URL, 'cors', 'same-origin', 'cors', 'same-origin'); - await fetch_test(f, REMOTE_URL, 'cors', 'include', 'cors', 'include'); + await css_integrity_test(f, LOCAL_URL, ' ', ' '); + await css_integrity_test( + f, LOCAL_URL, + 'This is not a valid integrity because it has no dashes', + 'This is not a valid integrity because it has no dashes'); + await css_integrity_test(f, LOCAL_URL, 'sha256-', 'sha256-'); + await css_integrity_test(f, LOCAL_URL, 'sha256-foo?123', 'sha256-foo?123'); + await css_integrity_test(f, LOCAL_URL, 'sha256-foo sha384-abc ', + 'sha256-foo sha384-abc '); + await css_integrity_test(f, LOCAL_URL, 'sha256-foo sha256-abc', + 'sha256-foo sha256-abc'); - await audio_test(f, LOCAL_URL, '', 'no-cors', 'include'); - await audio_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); - await audio_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); - await audio_test(f, REMOTE_URL, '', 'no-cors', 'include'); - await audio_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); - await audio_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); + await fetch_test(f, LOCAL_URL, 'same-origin', 'omit', 'same-origin', 'omit'); + await fetch_test(f, LOCAL_URL, 'same-origin', 'same-origin', + 'same-origin', 'same-origin'); + await fetch_test(f, LOCAL_URL, 'same-origin', 'include', + 'same-origin', 'include'); + await fetch_test(f, LOCAL_URL, 'no-cors', 'omit', 'no-cors', 'omit'); + await fetch_test(f, LOCAL_URL, 'no-cors', 'same-origin', + 'no-cors', 'same-origin'); + await fetch_test(f, LOCAL_URL, 'no-cors', 'include', 'no-cors', 'include'); + await fetch_test(f, LOCAL_URL, 'cors', 'omit', 'cors', 'omit'); + await fetch_test(f, LOCAL_URL, 'cors', 'same-origin', 'cors', 'same-origin'); + await fetch_test(f, LOCAL_URL, 'cors', 'include', 'cors', 'include'); + await fetch_test(f, REMOTE_URL, 'no-cors', 'omit', 'no-cors', 'omit'); + await fetch_test(f, REMOTE_URL, 'no-cors', 'same-origin', 'no-cors', 'same-origin'); + await fetch_test(f, REMOTE_URL, 'no-cors', 'include', 'no-cors', 'include'); + await fetch_test(f, REMOTE_URL, 'cors', 'omit', 'cors', 'omit'); + await fetch_test(f, REMOTE_URL, 'cors', 'same-origin', 'cors', 'same-origin'); + await fetch_test(f, REMOTE_URL, 'cors', 'include', 'cors', 'include'); - await video_test(f, LOCAL_URL, '', 'no-cors', 'include'); - await video_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); - await video_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); - await video_test(f, REMOTE_URL, '', 'no-cors', 'include'); - await video_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); - await video_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); + await audio_test(f, LOCAL_URL, '', 'no-cors', 'include'); + await audio_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); + await audio_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); + await audio_test(f, REMOTE_URL, '', 'no-cors', 'include'); + await audio_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); + await audio_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); - frame.remove(); - service_worker_unregister(t, SCOPE); - }).catch(unreached_rejection(t)); - }, 'Verify FetchEvent for resources.'); + await video_test(f, LOCAL_URL, '', 'no-cors', 'include'); + await video_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin'); + await video_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include'); + await video_test(f, REMOTE_URL, '', 'no-cors', 'include'); + await video_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin'); + await video_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include'); +}, 'Verify FetchEvent for resources.'); </script> diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-iframe.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-iframe.https.html index fca57220235..b9783071e12 100644 --- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-iframe.https.html +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-iframe.https.html @@ -3,7 +3,7 @@ <script> function load_image(url, cross_origin) { - var img = document.createElement('img'); + const img = document.createElement('img'); if (cross_origin != '') { img.crossOrigin = cross_origin; } @@ -11,7 +11,7 @@ function load_image(url, cross_origin) { } function load_script(url, cross_origin) { - var script = document.createElement('script'); + const script = document.createElement('script'); script.src = url; if (cross_origin != '') { script.crossOrigin = cross_origin; @@ -20,7 +20,7 @@ function load_script(url, cross_origin) { } function load_css(url, cross_origin) { - var link = document.createElement('link'); + const link = document.createElement('link'); link.rel = 'stylesheet' link.href = url; link.type = 'text/css'; @@ -31,31 +31,31 @@ function load_css(url, cross_origin) { } function load_font(url) { - var fontFace = new FontFace('test', 'url(' + url + ')'); + const fontFace = new FontFace('test', 'url(' + url + ')'); fontFace.load(); } function load_css_image(url, type) { - var div = document.createElement('div'); + const div = document.createElement('div'); document.body.appendChild(div); div.style[type] = 'url(' + url + ')'; } function load_css_image_set(url, type) { - var div = document.createElement('div'); + const div = document.createElement('div'); document.body.appendChild(div); div.style[type] = '-webkit-image-set(url(' + url + ') 1x)'; } function load_script_with_integrity(url, integrity) { - var script = document.createElement('script'); + const script = document.createElement('script'); script.src = url; script.integrity = integrity; document.body.appendChild(script); } function load_css_with_integrity(url, integrity) { - var link = document.createElement('link'); + const link = document.createElement('link'); link.rel = 'stylesheet' link.href = url; link.type = 'text/css'; @@ -64,7 +64,7 @@ function load_css_with_integrity(url, integrity) { } function load_audio(url, cross_origin) { - var audio = document.createElement('audio'); + const audio = document.createElement('audio'); if (cross_origin != '') { audio.crossOrigin = cross_origin; } @@ -73,7 +73,7 @@ function load_audio(url, cross_origin) { } function load_video(url, cross_origin) { - var video = document.createElement('video'); + const video = document.createElement('video'); if (cross_origin != '') { video.crossOrigin = cross_origin; } diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-worker.js index d85f7143c33..5c9e86d6684 100644 --- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-worker.js +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-resources-worker.js @@ -1,26 +1,26 @@ -var requests = []; -var port = undefined; +const requests = []; +let port = undefined; -self.onmessage = function(e) { - var message = e.data; +self.onmessage = e => { + const message = e.data; if ('port' in message) { port = message.port; port.postMessage({ready: true}); } }; -self.addEventListener('fetch', function(event) { - var url = event.request.url; - if (url.indexOf('dummy?test') == -1) { - return; - } - port.postMessage({ - url: url, - mode: event.request.mode, - redirect: event.request.redirect, - credentials: event.request.credentials, - integrity: event.request.integrity, - destination: event.request.destination - }); - event.respondWith(Promise.reject()); +self.addEventListener('fetch', e => { + const url = e.request.url; + if (!url.includes('dummy?test')) { + return; + } + port.postMessage({ + url: url, + mode: e.request.mode, + redirect: e.request.redirect, + credentials: e.request.credentials, + integrity: e.request.integrity, + destination: e.request.destination }); + e.respondWith(Promise.reject()); +}); diff --git a/tests/wpt/web-platform-tests/tools/ci/azure/install_safari.yml b/tests/wpt/web-platform-tests/tools/ci/azure/install_safari.yml index 5cbad0d00b9..d0660d152bb 100644 --- a/tests/wpt/web-platform-tests/tools/ci/azure/install_safari.yml +++ b/tests/wpt/web-platform-tests/tools/ci/azure/install_safari.yml @@ -3,6 +3,9 @@ parameters: # Should match https://web-platform-tests.org/running-tests/safari.html steps: +- script: defaults write com.apple.WebDriver DiagnosticsEnabled 1 + displayName: 'Enable safaridriver diagnostics' + condition: eq(variables['safaridriver_diagnose'], true) - ${{ if eq(parameters.channel, 'preview') }}: - script: | HOMEBREW_NO_AUTO_UPDATE=1 brew cask install tools/ci/azure/safari-technology-preview.rb diff --git a/tests/wpt/web-platform-tests/tools/ci/azure/publish_logs.yml b/tests/wpt/web-platform-tests/tools/ci/azure/publish_logs.yml new file mode 100644 index 00000000000..a49397a91ad --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/ci/azure/publish_logs.yml @@ -0,0 +1,7 @@ +steps: +- task: PublishBuildArtifacts@1 + displayName: 'Publish safaridriver logs' + inputs: + pathtoPublish: /Users/runner/Library/Logs/com.apple.WebDriver/ + artifactName: safaridriver-logs + condition: eq(variables['safaridriver_diagnose'], true) diff --git a/tests/wpt/web-platform-tests/tools/manifest/manifest.py b/tests/wpt/web-platform-tests/tools/manifest/manifest.py index 19d1bbed033..345eeb6d2b0 100644 --- a/tests/wpt/web-platform-tests/tools/manifest/manifest.py +++ b/tests/wpt/web-platform-tests/tools/manifest/manifest.py @@ -7,6 +7,7 @@ from multiprocessing import Pool, cpu_count from six import ( PY3, binary_type, + ensure_text, iteritems, itervalues, string_types, @@ -175,12 +176,14 @@ class Manifest(object): to_update = [] - for source_file, update in tree: + for source_file_or_path, update in tree: if not update: - assert isinstance(source_file, (binary_type, text_type)) - deleted.remove(tuple(source_file.split(os.path.sep))) + assert isinstance(source_file_or_path, (binary_type, text_type)) + path = ensure_text(source_file_or_path) + deleted.remove(tuple(path.split(os.path.sep))) else: - assert not isinstance(source_file, bytes) + assert not isinstance(source_file_or_path, (binary_type, text_type)) + source_file = source_file_or_path rel_path_parts = source_file.rel_path_parts assert isinstance(rel_path_parts, tuple) diff --git a/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py index c374ba05043..b324bf22dd3 100644 --- a/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py +++ b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py @@ -2,7 +2,7 @@ import hashlib import re import os from collections import deque -from six import binary_type, iteritems, text_type +from six import binary_type, ensure_text, iteritems, text_type from six.moves.urllib.parse import urljoin from fnmatch import fnmatch @@ -190,24 +190,21 @@ class SourceFile(object): ("css", "CSS2", "archive"), ("css", "common")} # type: Set[Tuple[bytes, ...]] - def __init__(self, tests_root, rel_path, url_base, hash=None, contents=None): + def __init__(self, tests_root, rel_path_str, url_base, hash=None, contents=None): # type: (AnyStr, AnyStr, Text, Optional[Text], Optional[bytes]) -> None """Object representing a file in a source tree. :param tests_root: Path to the root of the source tree - :param rel_path: File path relative to tests_root + :param rel_path_str: File path relative to tests_root :param url_base: Base URL used when converting file paths to urls :param contents: Byte array of the contents of the file or ``None``. """ + rel_path = ensure_text(rel_path_str) assert not os.path.isabs(rel_path), rel_path - if os.name == "nt": # do slash normalization on Windows - if isinstance(rel_path, binary_type): - rel_path = rel_path.replace(b"/", b"\\") - else: - rel_path = rel_path.replace(u"/", u"\\") + rel_path = rel_path.replace(u"/", u"\\") dir_path, filename = os.path.split(rel_path) name, ext = os.path.splitext(filename) @@ -218,13 +215,13 @@ class SourceFile(object): meta_flags = name.split(".")[1:] - self.tests_root = tests_root # type: Union[bytes, Text] - self.rel_path = rel_path # type: Union[bytes, Text] - self.dir_path = dir_path # type: Union[bytes, Text] - self.filename = filename # type: Union[bytes, Text] - self.name = name # type: Union[bytes, Text] - self.ext = ext # type: Union[bytes, Text] - self.type_flag = type_flag # type: Optional[Union[bytes, Text]] + self.tests_root = ensure_text(tests_root) # type: Text + self.rel_path = rel_path # type: Text + self.dir_path = dir_path # type: Text + self.filename = filename # type: Text + self.name = name # type: Text + self.ext = ext # type: Text + self.type_flag = type_flag # type: Optional[Text] self.meta_flags = meta_flags # type: Union[List[bytes], List[Text]] self.url_base = url_base self.contents = contents @@ -282,7 +279,7 @@ class SourceFile(object): @cached_property def path(self): - # type: () -> Union[bytes, Text] + # type: () -> Text return os.path.join(self.tests_root, self.rel_path) @cached_property diff --git a/tests/wpt/web-platform-tests/tools/quic/quic_transport_server.py b/tests/wpt/web-platform-tests/tools/quic/quic_transport_server.py index 10d81743693..9a04ad17f19 100644 --- a/tests/wpt/web-platform-tests/tools/quic/quic_transport_server.py +++ b/tests/wpt/web-platform-tests/tools/quic/quic_transport_server.py @@ -56,9 +56,11 @@ class QuicTransportProtocol(QuicConnectionProtocol): isinstance(event, StreamDataReceived) and event.stream_id == 2): # client indication process + prefix = 'Client indication error: ' self.client_indication_data += event.data + if len(self.client_indication_data) > 65535: + raise Exception('too large data for client indication') if event.end_stream: - prefix = 'Client inditation error: ' self.process_client_indication() if self.is_closing_or_closed(): return diff --git a/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.html b/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.html index 5003fc7fad5..5cefedb7b8a 100644 --- a/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.html +++ b/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.html @@ -190,34 +190,32 @@ // TODO(lyf): https://crbug.com/1066791 Following tests which related to svg // script element cause a flaky timeout in `linux-blink-rel`, following tests // should be added back after the bug fix. - // - // TODO(lyf): https://crbug.com/1064598 - // promise_test(t => { - // let p = Promise.resolve() - // .then(promise_violation("require-trusted-types-for 'script'")) - // .then(expect_blocked_uri("trusted-types-sink")) - // .then(expect_sample("SVGScriptElement href")); - // expect_throws(_ => { document.getElementById("svgscript").href.baseVal = "" }); - // return p; - // }, "Trusted Type violation report: sample for SVGScriptElement href assignment"); - // - // promise_test(t => { - // let p = Promise.resolve() - // .then(promise_violation("require-trusted-types-for 'script'")) - // .then(expect_blocked_uri("trusted-types-sink")) - // .then(expect_sample("Element setAttribute")); - // expect_throws(_ => { document.getElementById("svgscript").setAttribute('href', "test"); }); - // return p; - // }, "Trusted Type violation report: sample for SVGScriptElement href assignment by setAttribute"); - // - // promise_test(t => { - // let p = Promise.resolve() - // .then(promise_violation("require-trusted-types-for 'script'")) - // .then(expect_blocked_uri("trusted-types-sink")) - // .then(expect_sample("SVGScriptElement text")); - // expect_throws(_ => { document.getElementById("svgscript").insertBefore(document.createTextNode("Hello"), null) }); - // return p; - // }, "Trusted Type violation report: sample for SVGScriptElement text assignment"); + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("require-trusted-types-for 'script'")) + .then(expect_blocked_uri("trusted-types-sink")) + .then(expect_sample("SVGAnimatedString baseVal")); + expect_throws(_ => { document.getElementById("svgscript").href.baseVal = "" }); + return p; + }, "Trusted Type violation report: sample for SVGScriptElement href assignment"); + + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("require-trusted-types-for 'script'")) + .then(expect_blocked_uri("trusted-types-sink")) + .then(expect_sample("Element setAttribute")); + expect_throws(_ => { document.getElementById("svgscript").setAttribute('href', "test"); }); + return p; + }, "Trusted Type violation report: sample for SVGScriptElement href assignment by setAttribute"); + + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("require-trusted-types-for 'script'")) + .then(expect_blocked_uri("trusted-types-sink")) + .then(expect_sample("SVGScriptElement text")); + expect_throws(_ => { document.getElementById("svgscript").insertBefore(document.createTextNode("Hello"), null) }); + return p; + }, "Trusted Type violation report: sample for SVGScriptElement text assignment"); promise_test(t => { let p = Promise.resolve() diff --git a/tests/wpt/web-platform-tests/trusted-types/trusted-types-svg-script.tentative.html b/tests/wpt/web-platform-tests/trusted-types/trusted-types-svg-script.tentative.html index 903490e2f3d..946f825fa3e 100644 --- a/tests/wpt/web-platform-tests/trusted-types/trusted-types-svg-script.tentative.html +++ b/tests/wpt/web-platform-tests/trusted-types/trusted-types-svg-script.tentative.html @@ -53,13 +53,11 @@ promise_test(t => { const elem = document.createElementNS( "http://www.w3.org/2000/svg", "script"); - elem.href.baseVal = "about:blank"; + assert_throws_js(TypeError, _ => { + elem.href.baseVal = "about:blank"; + }); document.getElementById("svg").appendChild(elem); - - // TODO(1066791): This should be rejected and throw an SPV event, but - // doesn't until the issue is fixed. - // return promise_spv(); - return Promise.resolve(); + return promise_spv(); }, "Assign string to SVGScriptElement.href.baseVal."); promise_test(t => { diff --git a/tests/wpt/web-platform-tests/uievents/click/dblclick_event_mouse.html b/tests/wpt/web-platform-tests/uievents/click/dblclick_event_mouse.html new file mode 100644 index 00000000000..50324f6dfdf --- /dev/null +++ b/tests/wpt/web-platform-tests/uievents/click/dblclick_event_mouse.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>dblclick event for the mouse pointer type</title> + <link rel="author" title="Google" href="http://www.google.com/" /> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> + <style> + #target + { + background-color: green; + width: 200px; + height: 200px; + } + </style> + </head> + <body> + <p>Double-click on the green box with the left mouse button.</p> + <div id="target"></div> + <script> + promise_test(async (t) => { + const target = document.getElementById("target"); + const event_watcher = new EventWatcher(t, target, ["click", "dblclick"]); + const actions_promise = new test_driver.Actions() + .pointerMove(0, 0, {origin: target}) + .pointerDown() + .pointerUp() + .pointerDown() + .pointerUp() + .send(); + // Make sure the test finishes after all the input actions are completed. + t.add_cleanup(() => actions_promise); + const event = await event_watcher.wait_for(["click", "click", "dblclick"]); + assert_equals(event.type, "dblclick"); + assert_equals(event.target, target); + assert_equals(event.detail, 2); + }); + </script> + </body> +</html> diff --git a/tests/wpt/web-platform-tests/uievents/click/mouse-dblclick-event.html b/tests/wpt/web-platform-tests/uievents/click/mouse-dblclick-event.html deleted file mode 100644 index 31a600b3cb7..00000000000 --- a/tests/wpt/web-platform-tests/uievents/click/mouse-dblclick-event.html +++ /dev/null @@ -1,55 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Double Click</title> - <link rel="author" title="Google" href="http://www.google.com/" /> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="/resources/testdriver.js"></script> - <script src="/resources/testdriver-actions.js"></script> - <script src="/resources/testdriver-vendor.js"></script> - <style type="text/css"> - .textarea - { - background: red; - width: 100px; - height: 100px; - color: white; - text-align: center; - font-family: monospace; - } - </style> - <script type="text/javascript"> - // Send two continuous clicks. - function run() { - var testDoubleClick = async_test('Tests that the double click event is correctly generated by sending pointerDown, pointerUp, pointerDown and pointerUp for the mouse type.'); - var elem = document.getElementById("click_area"); - var actions_promise; - elem.addEventListener('dblclick', function(e) { - testDoubleClick.step(function () { - assert_equals(e.target.id, "click_area"); - assert_equals(e.detail, 2); - }); - // Make sure the test finishes after all the input actions are completed. - actions_promise.then( () => { - testDoubleClick.done(); - }); - }); - - actions_promise = new test_driver.Actions() - .pointerMove(0, 0, {origin: elem}) - .pointerDown() - .pointerUp() - .pointerDown() - .pointerUp() - .send(); - } - </script> - </head> - <body onload="run()"> - <h1>Double Click</h1> - <p>Double-click on the text area and check if the "dblclick" event is received.</p> - <div id="click_area" class="textarea"></div> - </body> -</html>
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-dom.html b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-dom.html new file mode 100644 index 00000000000..0277d729788 --- /dev/null +++ b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-dom.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html> +<title>Test the video.requestVideoFrameCallback() API for non visible video elements.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/media.js"></script> +<body> +</body> +<script> +var testVideo = { + url: getVideoURI('/media/movie_5'), + height: 240, + width: 320, +} + +async_test(function(t) { + let video = document.createElement('video'); + + video.requestVideoFrameCallback(t.step_func_done()); + video.src = testVideo.url; + video.play(); + +}, 'Test a video outside of the DOM can still use video.rVFC.'); + +function rvfcStyleTest(applyStyle, description) { + async_test(function(t) { + let video = document.createElement('video'); + document.body.appendChild(video); + applyStyle(video); + + video.requestVideoFrameCallback( + t.step_func( _ => { + // Make sure we can receive more than one callback. + video.requestVideoFrameCallback(t.step_func_done()); + }) + ); + + video.src = testVideo.url; + video.play(); + }, description); +} + +rvfcStyleTest((video) => { video.style.display = "none"}, + 'Test video.rVFC works with "display:none".'); + +rvfcStyleTest((video) => { video.style.visibility = "hidden"}, + 'Test video.rVFC works with "visibility:hidden".'); + +</script> +</html> diff --git a/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html index 3407786c052..14c5de1adf5 100644 --- a/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html +++ b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html @@ -1,6 +1,7 @@ <!DOCTYPE html> <html> <title>Test having multiple video.rVFC callbacks in flight for a single element.</title> +<body></body> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/media.js"></script> @@ -8,6 +9,7 @@ async_test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); let firstTime; let firstMetadata; @@ -29,6 +31,7 @@ async_test(function(t) { async_test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); let secondCallbackId; diff --git a/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html index bfdedb4bec0..e637a0872cb 100644 --- a/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html +++ b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html @@ -1,6 +1,7 @@ <!DOCTYPE html> <html> <title>Test repeatedly chaining video.rVFC() callbacks.</title> +<body></body> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/media.js"></script> @@ -8,6 +9,7 @@ async_test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); let firstTime; video.requestVideoFrameCallback(t.step_func((time) => { @@ -35,6 +37,7 @@ async_test(function(t) { async_test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); let maxNumberOfCalls = 10; let currentCallNumber = 0; diff --git a/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback.html b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback.html index 6660fadeaf4..afc6b834d44 100644 --- a/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback.html +++ b/tests/wpt/web-platform-tests/video-rvfc/request-video-frame-callback.html @@ -1,6 +1,7 @@ <!DOCTYPE html> <html> <title>Test the basics of the video.requestVideoFrameCallback() API.</title> +<body></body> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/media.js"></script> @@ -13,6 +14,7 @@ var testVideo = { async_test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); let id = video.requestVideoFrameCallback( t.step_func_done((time, metadata) => { @@ -31,6 +33,7 @@ async_test(function(t) { async_test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); video.requestVideoFrameCallback( t.step_func(video_now => { @@ -50,6 +53,7 @@ async_test(function(t) { async_test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); let id = video.requestVideoFrameCallback( t.step_func(_ => { @@ -74,6 +78,7 @@ async_test(function(t) { test(function(t) { let video = document.createElement('video'); + document.body.appendChild(video); // requestVideoFrameCallback() expects 1 function as a parameter. assert_throws_js(TypeError, _ => { video.requestVideoFrameCallback() } ); diff --git a/tests/wpt/web-platform-tests/webgpu/common/constants.js b/tests/wpt/web-platform-tests/webgpu/common/constants.js index 9d3dd1a32de..69496b1b23b 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/constants.js +++ b/tests/wpt/web-platform-tests/webgpu/common/constants.js @@ -3,6 +3,7 @@ **/ // https://github.com/gpuweb/gpuweb/blob/0a48816412b5d08a5fb8b89005e019165a1a2c63/spec/index.bs +// tslint:disable:variable-name // String enums export let ExtensionName; @@ -180,7 +181,7 @@ export let TextureFormat; TextureFormat["BGRA8Unorm"] = "bgra8unorm"; TextureFormat["BGRA8UnormSRGB"] = "bgra8unorm-srgb"; TextureFormat["RGB10A2Unorm"] = "rgb10a2unorm"; - TextureFormat["RGB11B10Float"] = "rg11b10float"; + TextureFormat["RG11B10Float"] = "rg11b10float"; TextureFormat["RG32Uint"] = "rg32uint"; TextureFormat["RG32Sint"] = "rg32sint"; TextureFormat["RG32Float"] = "rg32float"; diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/file_loader.js b/tests/wpt/web-platform-tests/webgpu/common/framework/file_loader.js new file mode 100644 index 00000000000..1b77a4e8595 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/file_loader.js @@ -0,0 +1,36 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { parseQuery } from './query/parseQuery.js'; +import { loadTreeForQuery } from './tree.js'; // A listing file, e.g. either of: +// - `src/webgpu/listing.ts` (which is dynamically computed, has a Promise<TestSuiteListing>) +// - `out/webgpu/listing.js` (which is pre-baked, has a TestSuiteListing) + +// Base class for DefaultTestFileLoader and FakeTestFileLoader. +export class TestFileLoader { + importSpecFile(suite, path) { + return this.import(`${suite}/${path.join('/')}.spec.js`); + } + + async loadTree(query, subqueriesToExpand = []) { + return loadTreeForQuery(this, parseQuery(query), subqueriesToExpand.map(q => parseQuery(q))); + } + + async loadTests(query) { + const tree = await this.loadTree(query); + return tree.iterateLeaves(); + } + +} +export class DefaultTestFileLoader extends TestFileLoader { + async listing(suite) { + return (await import(`../../${suite}/listing.js`)).listing; + } + + import(path) { + return import(`../../${path}`); + } + +} +//# sourceMappingURL=file_loader.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/fixture.js b/tests/wpt/web-platform-tests/webgpu/common/framework/fixture.js index 55f8ec48b22..ef23f06596b 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/framework/fixture.js +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/fixture.js @@ -45,7 +45,7 @@ export class Fixture { } fail(msg) { - this.rec.fail(new Error(msg)); + this.rec.expectationFailed(new Error(msg)); } async immediateAsyncExpectation(fn) { @@ -63,18 +63,18 @@ export class Fixture { expectErrorValue(expectedName, ex, niceStack) { if (!(ex instanceof Error)) { - niceStack.message = 'THREW non-error value, of type ' + typeof ex + niceStack.message; - this.rec.fail(niceStack); + niceStack.message = `THREW non-error value, of type ${typeof ex}: ${ex}`; + this.rec.expectationFailed(niceStack); return; } const actualName = ex.name; if (actualName !== expectedName) { - niceStack.message = `THREW ${actualName}, instead of ${expectedName}` + niceStack.message; - this.rec.fail(niceStack); + niceStack.message = `THREW ${actualName}, instead of ${expectedName}: ${ex}`; + this.rec.expectationFailed(niceStack); } else { - niceStack.message = 'OK: threw ' + actualName + niceStack.message; + niceStack.message = `OK: threw ${actualName}${ex.message}`; this.rec.debug(niceStack); } } @@ -85,8 +85,8 @@ export class Fixture { try { await p; - niceStack.message = 'DID NOT THROW' + m; - this.rec.fail(niceStack); + niceStack.message = 'DID NOT REJECT' + m; + this.rec.expectationFailed(niceStack); } catch (ex) { niceStack.message = m; this.expectErrorValue(expectedName, ex, niceStack); @@ -99,7 +99,7 @@ export class Fixture { try { fn(); - this.rec.fail(new Error('DID NOT THROW' + m)); + this.rec.expectationFailed(new Error('DID NOT THROW' + m)); } catch (ex) { this.expectErrorValue(expectedName, ex, new Error(m)); } @@ -110,7 +110,7 @@ export class Fixture { const m = msg ? ': ' + msg : ''; this.rec.debug(new Error('expect OK' + m)); } else { - this.rec.fail(new Error(msg)); + this.rec.expectationFailed(new Error(msg)); } return cond; diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/gpu/device_pool.js b/tests/wpt/web-platform-tests/webgpu/common/framework/gpu/device_pool.js new file mode 100644 index 00000000000..848e5802817 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/gpu/device_pool.js @@ -0,0 +1,132 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import { assert, raceWithRejectOnTimeout, unreachable, assertReject } from '../util/util.js'; +import { getGPU } from './implementation.js'; + +class TestFailedButDeviceReusable extends Error {} + +export class TestOOMedShouldAttemptGC extends Error {} +const kPopErrorScopeTimeoutMS = 5000; +export class DevicePool { + constructor() { + _defineProperty(this, "failed", false); + + _defineProperty(this, "holder", undefined); + } + + // undefined if "uninitialized" (not yet initialized, or lost) + async acquire() { + assert(!this.failed, 'WebGPU device previously failed to initialize; not retrying'); + + if (this.holder === undefined) { + try { + this.holder = await DevicePool.makeHolder(); + } catch (ex) { + this.failed = true; + throw ex; + } + } + + assert(!this.holder.acquired, 'Device was in use on DevicePool.acquire'); + this.holder.acquired = true; + this.beginErrorScopes(); + return this.holder.device; + } // When a test is done using a device, it's released back into the pool. + // This waits for error scopes, checks their results, and checks for various error conditions. + + + async release(device) { + const holder = this.holder; + assert(holder !== undefined, 'trying to release a device while pool is uninitialized'); + assert(holder.acquired, 'trying to release a device while already released'); + assert(device === holder.device, 'Released device was the wrong device'); + + try { + // Time out if popErrorScope never completes. This could happen due to a browser bug - e.g., + // as of this writing, on Chrome GPU process crash, popErrorScope just hangs. + await raceWithRejectOnTimeout(this.endErrorScopes(), kPopErrorScopeTimeoutMS, 'finalization popErrorScope timed out'); // (Hopefully if the device was lost, it has been reported by the time endErrorScopes() + // has finished (or timed out). If not, it could cause a finite number of extra test + // failures following this one (but should recover eventually).) + + const lostReason = holder.lostReason; + + if (lostReason !== undefined) { + // Fail the current test. + unreachable(`Device was lost: ${lostReason}`); + } + } catch (ex) { + // Any error that isn't explicitly TestFailedButDeviceReusable forces a new device to be + // created for the next test. + if (!(ex instanceof TestFailedButDeviceReusable)) { + this.holder = undefined; + } + + throw ex; + } finally { + // TODO: device.destroy() + // Mark the holder as free. (This only has an effect if the pool still has the holder.) + // This could be done at the top but is done here to guard against async-races during release. + holder.acquired = false; + } + } // Gets a device and creates a DeviceHolder. + // If the device is lost, DeviceHolder.lostReason gets set. + + + static async makeHolder() { + const gpu = getGPU(); + const adapter = await gpu.requestAdapter(); + const holder = { + acquired: false, + device: await adapter.requestDevice(), + lostReason: undefined + }; + holder.device.lost.then(ev => { + holder.lostReason = ev.message; + }); + return holder; + } // Create error scopes that wrap the entire test. + + + beginErrorScopes() { + assert(this.holder !== undefined); + this.holder.device.pushErrorScope('out-of-memory'); + this.holder.device.pushErrorScope('validation'); + } // End the whole-test error scopes. Check that there are no extra error scopes, and that no + // otherwise-uncaptured errors occurred during the test. + + + async endErrorScopes() { + assert(this.holder !== undefined); + let gpuValidationError; + let gpuOutOfMemoryError; + + try { + // May reject if the device was lost. + gpuValidationError = await this.holder.device.popErrorScope(); + gpuOutOfMemoryError = await this.holder.device.popErrorScope(); + } catch (ex) { + assert(this.holder.lostReason !== undefined, "popErrorScope failed, but device.lost hasn't fired (yet)"); + throw ex; + } + + await assertReject(this.holder.device.popErrorScope(), 'There was an extra error scope on the stack after a test'); + + if (gpuValidationError !== null) { + assert(gpuValidationError instanceof GPUValidationError); // Allow the device to be reused. + + throw new TestFailedButDeviceReusable(`Unexpected validation error occurred: ${gpuValidationError.message}`); + } + + if (gpuOutOfMemoryError !== null) { + assert(gpuOutOfMemoryError instanceof GPUOutOfMemoryError); // Don't allow the device to be reused; unexpected OOM could break the device. + + throw new TestOOMedShouldAttemptGC('Unexpected out-of-memory error occurred'); + } + } + +} +//# sourceMappingURL=device_pool.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/logging/log_message.js b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/log_message.js new file mode 100644 index 00000000000..11f352f892e --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/log_message.js @@ -0,0 +1,50 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import { extractImportantStackTrace } from '../util/stack.js'; +export class LogMessageWithStack extends Error { + constructor(name, ex) { + super(ex.message); + + _defineProperty(this, "stackHidden", false); + + _defineProperty(this, "timesSeen", 1); + + this.name = name; + this.stack = ex.stack; + } + /** Set a flag so the stack is not printed in toJSON(). */ + + + setStackHidden() { + this.stackHidden = true; + } + /** Increment the "seen x times" counter. */ + + + incrementTimesSeen() { + this.timesSeen++; + } + + toJSON() { + let m = this.name + ': '; + + if (!this.stackHidden && this.stack) { + // this.message is already included in this.stack + m += extractImportantStackTrace(this); + } else { + m += this.message; + } + + if (this.timesSeen > 1) { + m += `\n(seen ${this.timesSeen} times with identical stack)`; + } + + return m; + } + +} +//# sourceMappingURL=log_message.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/logging/logger.js b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/logger.js new file mode 100644 index 00000000000..8d66c554c5a --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/logger.js @@ -0,0 +1,35 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import { version } from '../version.js'; +import { TestCaseRecorder } from './test_case_recorder.js'; +export class Logger { + constructor(debug) { + _defineProperty(this, "debug", void 0); + + _defineProperty(this, "results", new Map()); + + this.debug = debug; + } + + record(name) { + const result = { + status: 'running', + timems: -1 + }; + this.results.set(name, result); + return [new TestCaseRecorder(result, this.debug), result]; + } + + asJSON(space) { + return JSON.stringify({ + version, + results: Array.from(this.results) + }, undefined, space); + } + +} +//# sourceMappingURL=logger.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/logging/result.js b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/result.js new file mode 100644 index 00000000000..813e781ba28 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/result.js @@ -0,0 +1,4 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ +//# sourceMappingURL=result.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/logging/test_case_recorder.js b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/test_case_recorder.js new file mode 100644 index 00000000000..d16af0f2b86 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/logging/test_case_recorder.js @@ -0,0 +1,137 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import { SkipTestCase } from '../fixture.js'; +import { now, assert } from '../util/util.js'; +import { LogMessageWithStack } from './log_message.js'; +var LogSeverity; + +(function (LogSeverity) { + LogSeverity[LogSeverity["Pass"] = 0] = "Pass"; + LogSeverity[LogSeverity["Skip"] = 1] = "Skip"; + LogSeverity[LogSeverity["Warn"] = 2] = "Warn"; + LogSeverity[LogSeverity["ExpectFailed"] = 3] = "ExpectFailed"; + LogSeverity[LogSeverity["ValidationFailed"] = 4] = "ValidationFailed"; + LogSeverity[LogSeverity["ThrewException"] = 5] = "ThrewException"; +})(LogSeverity || (LogSeverity = {})); + +const kMaxLogStacks = 2; +/** Holds onto a LiveTestCaseResult owned by the Logger, and writes the results into it. */ + +export class TestCaseRecorder { + /** Used to dedup log messages which have identical stacks. */ + constructor(result, debugging) { + _defineProperty(this, "result", void 0); + + _defineProperty(this, "maxLogSeverity", LogSeverity.Pass); + + _defineProperty(this, "startTime", -1); + + _defineProperty(this, "logs", []); + + _defineProperty(this, "logLinesAtCurrentSeverity", 0); + + _defineProperty(this, "debugging", false); + + _defineProperty(this, "messagesForPreviouslySeenStacks", new Map()); + + this.result = result; + this.debugging = debugging; + } + + start() { + assert(this.startTime < 0, 'TestCaseRecorder cannot be reused'); + this.startTime = now(); + } + + finish() { + assert(this.startTime >= 0, 'finish() before start()'); + const timeMilliseconds = now() - this.startTime; // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results. + + this.result.timems = Math.ceil(timeMilliseconds * 1000) / 1000; // Convert numeric enum back to string (but expose 'exception' as 'fail') + + this.result.status = this.maxLogSeverity === LogSeverity.Pass ? 'pass' : this.maxLogSeverity === LogSeverity.Skip ? 'skip' : this.maxLogSeverity === LogSeverity.Warn ? 'warn' : 'fail'; // Everything else is an error + + this.result.logs = this.logs; + } + + injectResult(injectedResult) { + Object.assign(this.result, injectedResult); + } + + debug(ex) { + if (!this.debugging) { + return; + } + + const logMessage = new LogMessageWithStack('DEBUG', ex); + logMessage.setStackHidden(); + this.logImpl(LogSeverity.Pass, logMessage); + } + + skipped(ex) { + this.logImpl(LogSeverity.Skip, new LogMessageWithStack('SKIP', ex)); + } + + warn(ex) { + this.logImpl(LogSeverity.Warn, new LogMessageWithStack('WARN', ex)); + } + + expectationFailed(ex) { + this.logImpl(LogSeverity.ExpectFailed, new LogMessageWithStack('EXPECTATION FAILED', ex)); + } + + validationFailed(ex) { + this.logImpl(LogSeverity.ValidationFailed, new LogMessageWithStack('VALIDATION FAILED', ex)); + } + + threw(ex) { + if (ex instanceof SkipTestCase) { + this.skipped(ex); + return; + } + + this.logImpl(LogSeverity.ThrewException, new LogMessageWithStack('EXCEPTION', ex)); + } + + logImpl(level, logMessage) { + // Deduplicate errors with the exact same stack + if (logMessage.stack) { + const seen = this.messagesForPreviouslySeenStacks.get(logMessage.stack); + + if (seen) { + seen.incrementTimesSeen(); + return; + } + + this.messagesForPreviouslySeenStacks.set(logMessage.stack, logMessage); + } // Mark printStack=false for all logs except 2 at the highest severity + + + if (level > this.maxLogSeverity) { + this.logLinesAtCurrentSeverity = 0; + this.maxLogSeverity = level; + + if (!this.debugging) { + // Go back and turn off printStack for everything of a lower log level + for (const log of this.logs) { + log.setStackHidden(); + } + } + } + + if (level < this.maxLogSeverity || this.logLinesAtCurrentSeverity >= kMaxLogStacks) { + if (!this.debugging) { + logMessage.setStackHidden(); + } + } + + this.logs.push(logMessage); + this.logLinesAtCurrentSeverity++; + } + +} +//# sourceMappingURL=test_case_recorder.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/params_builder.js b/tests/wpt/web-platform-tests/webgpu/common/framework/params_builder.js new file mode 100644 index 00000000000..10dd239df93 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/params_builder.js @@ -0,0 +1,111 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +let _Symbol$iterator; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import { publicParamsEquals } from './params_utils.js'; +import { assert } from './util/util.js'; // https://stackoverflow.com/a/56375136 + +export function poptions(name, values) { + const iter = makeReusableIterable(function* () { + for (const value of values) { + yield { + [name]: value + }; + } + }); + return iter; +} +export function pbool(name) { + return poptions(name, [false, true]); +} +export function params() { + return new ParamsBuilder(); +} +_Symbol$iterator = Symbol.iterator; +export class ParamsBuilder { + constructor() { + _defineProperty(this, "paramSpecs", [{}]); + } + + [_Symbol$iterator]() { + const iter = this.paramSpecs[Symbol.iterator](); + return iter; + } + + combine(newParams) { + const paramSpecs = this.paramSpecs; + this.paramSpecs = makeReusableIterable(function* () { + for (const a of paramSpecs) { + for (const b of newParams) { + yield mergeParams(a, b); + } + } + }); + return this; + } + + expand(expander) { + const paramSpecs = this.paramSpecs; + this.paramSpecs = makeReusableIterable(function* () { + for (const a of paramSpecs) { + for (const b of expander(a)) { + yield mergeParams(a, b); + } + } + }); + return this; + } + + filter(pred) { + const paramSpecs = this.paramSpecs; + this.paramSpecs = makeReusableIterable(function* () { + for (const p of paramSpecs) { + if (pred(p)) { + yield p; + } + } + }); + return this; + } + + unless(pred) { + return this.filter(x => !pred(x)); + } + + exclude(exclude) { + const excludeArray = Array.from(exclude); + const paramSpecs = this.paramSpecs; + this.paramSpecs = makeReusableIterable(function* () { + for (const p of paramSpecs) { + if (excludeArray.every(e => !publicParamsEquals(p, e))) { + yield p; + } + } + }); + return this; + } + +} // If you create an Iterable by calling a generator function (e.g. in IIFE), it is exhausted after +// one use. This just wraps a generator function in an object so it be iterated multiple times. + +function makeReusableIterable(generatorFn) { + return { + [Symbol.iterator]: generatorFn + }; +} + +// (keyof A & keyof B) is not empty, so they overlapped +function mergeParams(a, b) { + for (const key of Object.keys(a)) { + assert(!(key in b), 'Duplicate key: ' + key); + } + + return { ...a, + ...b + }; +} +//# sourceMappingURL=params_builder.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/params_utils.js b/tests/wpt/web-platform-tests/webgpu/common/framework/params_utils.js index cde89843f9e..161feb5d430 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/framework/params_utils.js +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/params_utils.js @@ -2,71 +2,25 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -import { objectEquals } from './util/util.js'; +import { comparePublicParamsPaths, Ordering } from './query/compare.js'; +import { kWildcard, kParamSeparator, kParamKVSeparator } from './query/separators.js'; // Consider adding more types here if needed + +export function paramKeyIsPublic(key) { + return !key.startsWith('_'); +} export function extractPublicParams(params) { const publicParams = {}; for (const k of Object.keys(params)) { - if (!k.startsWith('_')) { + if (paramKeyIsPublic(k)) { publicParams[k] = params[k]; } } return publicParams; } -export function stringifyPublicParams(p) { - if (p === null || paramsEquals(p, {})) { - return ''; - } - - return JSON.stringify(extractPublicParams(p)); -} -export function paramsEquals(x, y) { - if (x === y) { - return true; - } - - if (x === null) { - x = {}; - } - - if (y === null) { - y = {}; - } - - for (const xk of Object.keys(x)) { - if (x[xk] !== undefined && !y.hasOwnProperty(xk)) { - return false; - } - - if (!objectEquals(x[xk], y[xk])) { - return false; - } - } - - for (const yk of Object.keys(y)) { - if (y[yk] !== undefined && !x.hasOwnProperty(yk)) { - return false; - } - } - - return true; -} -export function paramsSupersets(sup, sub) { - if (sub === null) { - return true; - } - - if (sup === null) { - sup = {}; - } - - for (const k of Object.keys(sub)) { - if (!sup.hasOwnProperty(k) || sup[k] !== sub[k]) { - return false; - } - } - - return true; +export const badParamValueChars = new RegExp('[' + kParamKVSeparator + kParamSeparator + kWildcard + ']'); +export function publicParamsEquals(x, y) { + return comparePublicParamsPaths(x, y) === Ordering.Equal; } //# sourceMappingURL=params_utils.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/query/compare.js b/tests/wpt/web-platform-tests/webgpu/common/framework/query/compare.js new file mode 100644 index 00000000000..2cbe6cc80c9 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/query/compare.js @@ -0,0 +1,96 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { paramKeyIsPublic } from '../params_utils.js'; +import { assert, objectEquals } from '../util/util.js'; +export let Ordering; // Compares two queries for their ordering (which is used to build the tree). +// See src/unittests/query_compare.spec.ts for examples. + +(function (Ordering) { + Ordering[Ordering["Unordered"] = 0] = "Unordered"; + Ordering[Ordering["StrictSuperset"] = 1] = "StrictSuperset"; + Ordering[Ordering["Equal"] = 2] = "Equal"; + Ordering[Ordering["StrictSubset"] = 3] = "StrictSubset"; +})(Ordering || (Ordering = {})); + +export function compareQueries(a, b) { + if (a.suite !== b.suite) { + return Ordering.Unordered; + } + + const filePathOrdering = comparePaths(a.filePathParts, b.filePathParts); + + if (filePathOrdering !== Ordering.Equal || a.isMultiFile || b.isMultiFile) { + return compareOneLevel(filePathOrdering, a.isMultiFile, b.isMultiFile); + } + + assert('testPathParts' in a && 'testPathParts' in b); + const testPathOrdering = comparePaths(a.testPathParts, b.testPathParts); + + if (testPathOrdering !== Ordering.Equal || a.isMultiTest || b.isMultiTest) { + return compareOneLevel(testPathOrdering, a.isMultiTest, b.isMultiTest); + } + + assert('params' in a && 'params' in b); + const paramsPathOrdering = comparePublicParamsPaths(a.params, b.params); + + if (paramsPathOrdering !== Ordering.Equal || a.isMultiCase || b.isMultiCase) { + return compareOneLevel(paramsPathOrdering, a.isMultiCase, b.isMultiCase); + } + + return Ordering.Equal; +} // Compares a single level of a query. +// "IsBig" means the query is big relative to the level, e.g. for test-level: +// anything >= suite:a,* is big +// anything <= suite:a:* is small + +function compareOneLevel(ordering, aIsBig, bIsBig) { + assert(ordering !== Ordering.Equal || aIsBig || bIsBig); + if (ordering === Ordering.Unordered) return Ordering.Unordered; + if (aIsBig && bIsBig) return ordering; + if (!aIsBig && !bIsBig) return Ordering.Unordered; // Equal case is already handled + // Exactly one of (a, b) is big. + + if (aIsBig && ordering !== Ordering.StrictSubset) return Ordering.StrictSuperset; + if (bIsBig && ordering !== Ordering.StrictSuperset) return Ordering.StrictSubset; + return Ordering.Unordered; +} + +function comparePaths(a, b) { + const shorter = Math.min(a.length, b.length); + + for (let i = 0; i < shorter; ++i) { + if (a[i] !== b[i]) { + return Ordering.Unordered; + } + } + + if (a.length === b.length) { + return Ordering.Equal; + } else if (a.length < b.length) { + return Ordering.StrictSuperset; + } else { + return Ordering.StrictSubset; + } +} + +export function comparePublicParamsPaths(a, b) { + const aKeys = Object.keys(a).filter(k => paramKeyIsPublic(k)); + const commonKeys = new Set(aKeys.filter(k => k in b)); + + for (const k of commonKeys) { + if (!objectEquals(a[k], b[k])) { + return Ordering.Unordered; + } + } + + const bKeys = Object.keys(b).filter(k => paramKeyIsPublic(k)); + const aRemainingKeys = aKeys.length - commonKeys.size; + const bRemainingKeys = bKeys.length - commonKeys.size; + if (aRemainingKeys === 0 && bRemainingKeys === 0) return Ordering.Equal; + if (aRemainingKeys === 0) return Ordering.StrictSuperset; + if (bRemainingKeys === 0) return Ordering.StrictSubset; + return Ordering.Unordered; +} +//# sourceMappingURL=compare.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/query/encode_selectively.js b/tests/wpt/web-platform-tests/webgpu/common/framework/query/encode_selectively.js new file mode 100644 index 00000000000..d67f1042233 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/query/encode_selectively.js @@ -0,0 +1,28 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +// Encodes a stringified TestQuery so that it can be placed in a `?q=` parameter in a URL. +// encodeURIComponent encodes in accordance with `application/x-www-form-urlencoded`, but URLs don't +// actually have to be as strict as HTML form encoding (we interpret this purely from JavaScript). +// So we encode the component, then selectively convert some %-encoded escape codes back to their +// original form for readability/copyability. +export function encodeURIComponentSelectively(s) { + let ret = encodeURIComponent(s); + ret = ret.replace(/%22/g, '"'); // for JSON strings + + ret = ret.replace(/%2C/g, ','); // for path separator, and JSON arrays + + ret = ret.replace(/%3A/g, ':'); // for big separator + + ret = ret.replace(/%3B/g, ';'); // for param separator + + ret = ret.replace(/%3D/g, '='); // for params (k=v) + + ret = ret.replace(/%5B/g, '['); // for JSON arrays + + ret = ret.replace(/%5D/g, ']'); // for JSON arrays + + return ret; +} +//# sourceMappingURL=encode_selectively.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/query/parseQuery.js b/tests/wpt/web-platform-tests/webgpu/common/framework/query/parseQuery.js new file mode 100644 index 00000000000..758227cc520 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/query/parseQuery.js @@ -0,0 +1,122 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { badParamValueChars, paramKeyIsPublic } from '../params_utils.js'; +import { assert } from '../util/util.js'; +import { TestQueryMultiFile, TestQueryMultiTest, TestQueryMultiCase, TestQuerySingleCase } from './query.js'; +import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js'; +import { validQueryPart } from './validQueryPart.js'; +export function parseQuery(s) { + try { + return parseQueryImpl(s); + } catch (ex) { + ex.message += '\n on: ' + s; + throw ex; + } +} + +function parseQueryImpl(s) { + // Undo encodeURIComponentSelectively + s = decodeURIComponent(s); // bigParts are: suite, group, test, params (note kBigSeparator could appear in params) + + const [suite, fileString, testString, paramsString] = s.split(kBigSeparator, 4); + assert(fileString !== undefined, `filter string must have at least one ${kBigSeparator}`); + const { + parts: file, + wildcard: filePathHasWildcard + } = parseBigPart(fileString, kPathSeparator); + + if (testString === undefined) { + // Query is file-level + assert(filePathHasWildcard, `File-level query without wildcard ${kWildcard}. Did you want a file-level query \ +(append ${kPathSeparator}${kWildcard}) or test-level query (append ${kBigSeparator}${kWildcard})?`); + return new TestQueryMultiFile(suite, file); + } + + assert(!filePathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`); + const { + parts: test, + wildcard: testPathHasWildcard + } = parseBigPart(testString, kPathSeparator); + + if (paramsString === undefined) { + // Query is test-level + assert(testPathHasWildcard, `Test-level query without wildcard ${kWildcard}; did you want a test-level query \ +(append ${kPathSeparator}${kWildcard}) or case-level query (append ${kBigSeparator}${kWildcard})?`); + assert(file.length > 0, 'File part of test-level query was empty (::)'); + return new TestQueryMultiTest(suite, file, test); + } // Query is case-level + + + assert(!testPathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`); + const { + parts: paramsParts, + wildcard: paramsHasWildcard + } = parseBigPart(paramsString, kParamSeparator); + assert(test.length > 0, 'Test part of case-level query was empty (::)'); + const params = {}; + + for (const paramPart of paramsParts) { + const [k, v] = parseSingleParam(paramPart); + assert(validQueryPart.test(k), 'param key names must match ' + validQueryPart); + params[k] = v; + } + + if (paramsHasWildcard) { + return new TestQueryMultiCase(suite, file, test, params); + } else { + return new TestQuerySingleCase(suite, file, test, params); + } +} // webgpu:a,b,* or webgpu:a,b,c:* + + +const kExampleQueries = `\ +webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}${kWildcard} or \ +webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}c${kBigSeparator}${kWildcard}`; + +function parseBigPart(s, separator) { + if (s === '') { + return { + parts: [], + wildcard: false + }; + } + + const parts = s.split(separator); + let endsWithWildcard = false; + + for (const [i, part] of parts.entries()) { + if (i === parts.length - 1) { + endsWithWildcard = part === kWildcard; + } + + assert(part.indexOf(kWildcard) === -1 || endsWithWildcard, `Wildcard ${kWildcard} must be complete last part of a path (e.g. ${kExampleQueries})`); + } + + if (endsWithWildcard) { + // Remove the last element of the array (which is just the wildcard). + parts.length = parts.length - 1; + } + + return { + parts, + wildcard: endsWithWildcard + }; +} + +function parseSingleParam(paramSubstring) { + assert(paramSubstring !== '', 'Param in a query must not be blank (is there a trailing comma?)'); + const i = paramSubstring.indexOf('='); + assert(i !== -1, 'Param in a query must be of form key=value'); + const k = paramSubstring.substring(0, i); + assert(paramKeyIsPublic(k), 'Param in a query must not be private (start with _)'); + const v = paramSubstring.substring(i + 1); + return [k, parseSingleParamValue(v)]; +} + +function parseSingleParamValue(s) { + assert(!badParamValueChars.test(s), `param value must not match ${badParamValueChars} - was ${s}`); + return s === 'undefined' ? undefined : JSON.parse(s); +} +//# sourceMappingURL=parseQuery.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/query/query.js b/tests/wpt/web-platform-tests/webgpu/common/framework/query/query.js new file mode 100644 index 00000000000..b80b6904f17 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/query/query.js @@ -0,0 +1,89 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import { assert } from '../util/util.js'; +import { encodeURIComponentSelectively } from './encode_selectively.js'; +import { kBigSeparator, kPathSeparator, kWildcard, kParamSeparator } from './separators.js'; +import { stringifyPublicParams } from './stringify_params.js'; +export class TestQueryMultiFile { + constructor(suite, file) { + _defineProperty(this, "isMultiFile", true); + + _defineProperty(this, "suite", void 0); + + _defineProperty(this, "filePathParts", void 0); + + this.suite = suite; + this.filePathParts = [...file]; + } + + toString() { + return encodeURIComponentSelectively(this.toStringHelper().join(kBigSeparator)); + } + + toHTML() { + return this.toStringHelper().join(kBigSeparator + '<wbr>'); + } + + toStringHelper() { + return [this.suite, [...this.filePathParts, kWildcard].join(kPathSeparator)]; + } + +} +export class TestQueryMultiTest extends TestQueryMultiFile { + constructor(suite, file, test) { + super(suite, file); + + _defineProperty(this, "isMultiFile", false); + + _defineProperty(this, "isMultiTest", true); + + _defineProperty(this, "testPathParts", void 0); + + assert(file.length > 0, 'multi-test (or finer) query must have file-path'); + this.testPathParts = [...test]; + } + + toStringHelper() { + return [this.suite, this.filePathParts.join(kPathSeparator), [...this.testPathParts, kWildcard].join(kPathSeparator)]; + } + +} +export class TestQueryMultiCase extends TestQueryMultiTest { + constructor(suite, file, test, params) { + super(suite, file, test); + + _defineProperty(this, "isMultiTest", false); + + _defineProperty(this, "isMultiCase", true); + + _defineProperty(this, "params", void 0); + + assert(test.length > 0, 'multi-case (or finer) query must have test-path'); + this.params = { ...params + }; + } + + toStringHelper() { + const paramsParts = stringifyPublicParams(this.params); + return [this.suite, this.filePathParts.join(kPathSeparator), this.testPathParts.join(kPathSeparator), [...paramsParts, kWildcard].join(kParamSeparator)]; + } + +} +export class TestQuerySingleCase extends TestQueryMultiCase { + constructor(...args) { + super(...args); + + _defineProperty(this, "isMultiCase", false); + } + + toStringHelper() { + const paramsParts = stringifyPublicParams(this.params); + return [this.suite, this.filePathParts.join(kPathSeparator), this.testPathParts.join(kPathSeparator), paramsParts.join(kParamSeparator)]; + } + +} +//# sourceMappingURL=query.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/query/separators.js b/tests/wpt/web-platform-tests/webgpu/common/framework/query/separators.js new file mode 100644 index 00000000000..4782fe457b8 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/query/separators.js @@ -0,0 +1,14 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +export const kBigSeparator = ':'; // Separator between big parts: suite:file:test:case + +export const kPathSeparator = ','; // Separator between path,to,file or path,to,test + +export const kParamSeparator = ';'; // Separator between k=v;k=v + +export const kParamKVSeparator = '='; // Separator between key and value in k=v + +export const kWildcard = '*'; // Final wildcard, if query is not single-case +//# sourceMappingURL=separators.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/query/stringify_params.js b/tests/wpt/web-platform-tests/webgpu/common/framework/query/stringify_params.js new file mode 100644 index 00000000000..b5503ffb54e --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/query/stringify_params.js @@ -0,0 +1,20 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { badParamValueChars, paramKeyIsPublic } from '../params_utils.js'; +import { assert } from '../util/util.js'; +import { kParamKVSeparator } from './separators.js'; +export function stringifyPublicParams(p) { + return Object.keys(p).filter(k => paramKeyIsPublic(k)).map(k => stringifySingleParam(k, p[k])); +} +export function stringifySingleParam(k, v) { + return `${k}${kParamKVSeparator}${stringifySingleParamValue(v)}`; +} + +function stringifySingleParamValue(v) { + const s = v === undefined ? 'undefined' : JSON.stringify(v); + assert(!badParamValueChars.test(s), `JSON.stringified param value must not match ${badParamValueChars} - was ${s}`); + return s; +} +//# sourceMappingURL=stringify_params.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/query/validQueryPart.js b/tests/wpt/web-platform-tests/webgpu/common/framework/query/validQueryPart.js new file mode 100644 index 00000000000..f51ebade76a --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/query/validQueryPart.js @@ -0,0 +1,7 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +// Applies to group parts, test parts, params keys. +export const validQueryPart = /^[a-zA-Z0-9_]+$/; +//# sourceMappingURL=validQueryPart.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/test_group.js b/tests/wpt/web-platform-tests/webgpu/common/framework/test_group.js index 8837b1e924a..ef34b5fd51c 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/framework/test_group.js +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/test_group.js @@ -4,12 +4,20 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -import { allowedTestNameCharacters } from './allowed_characters.js'; -import { extractPublicParams, paramsEquals } from './params_utils.js'; -import { checkPublicParamType } from './url_query.js'; +import { extractPublicParams, publicParamsEquals } from './params_utils.js'; +import { kPathSeparator } from './query/separators.js'; +import { stringifyPublicParams } from './query/stringify_params.js'; +import { validQueryPart } from './query/validQueryPart.js'; import { assert } from './util/util.js'; -const validNames = new RegExp('^[' + allowedTestNameCharacters + ']+$'); -export class TestGroup { +export function makeTestGroup(fixture) { + return new TestGroup(fixture); +} // Interface for running tests + +export function makeTestGroupForUnitTesting(fixture) { + return new TestGroup(fixture); +} + +class TestGroup { constructor(fixture) { _defineProperty(this, "fixture", void 0); @@ -20,14 +28,13 @@ export class TestGroup { this.fixture = fixture; } - *iterate(log) { + *iterate() { for (const test of this.tests) { - yield* test.iterate(log); + yield* test.iterate(); } } checkName(name) { - assert(validNames.test(name), `Invalid test name ${name}; must match [${validNames}]+`); assert( // Shouldn't happen due to the rule above. Just makes sure that treated // unencoded strings as encoded strings is OK. name === decodeURIComponent(name), `Not decodeURIComponent-idempotent: ${name} !== ${decodeURIComponent(name)}`); @@ -36,86 +43,98 @@ export class TestGroup { } // TODO: This could take a fixture, too, to override the one for the group. - test(name, fn) { - // Replace spaces with underscores for readability. - assert(name.indexOf('_') === -1, 'Invalid test name ${name}: contains underscore (use space)'); - name = name.replace(/ /g, '_'); + test(name) { this.checkName(name); - const test = new Test(name, this.fixture, fn); + const parts = name.split(kPathSeparator); + + for (const p of parts) { + assert(validQueryPart.test(p), `Invalid test name part ${p}; must match ${validQueryPart}`); + } + + const test = new TestBuilder(parts, this.fixture); this.tests.push(test); return test; } -} // This test is created when it's inserted, but may be parameterized afterward (.params()). + checkCaseNamesAndDuplicates() { + for (const test of this.tests) { + test.checkCaseNamesAndDuplicates(); + } + } + +} -class Test { - constructor(name, fixture, fn) { - _defineProperty(this, "name", void 0); +class TestBuilder { + constructor(testPath, fixture) { + _defineProperty(this, "testPath", void 0); _defineProperty(this, "fixture", void 0); - _defineProperty(this, "fn", void 0); + _defineProperty(this, "testFn", void 0); - _defineProperty(this, "cases", null); + _defineProperty(this, "cases", undefined); - this.name = name; + this.testPath = testPath; this.fixture = fixture; - this.fn = fn; } - params(specs) { - assert(this.cases === null, 'test case is already parameterized'); - const cases = Array.from(specs); - const seen = []; // This is n^2. + fn(fn) { + this.testFn = fn; + } - for (const spec of cases) { - const publicParams = extractPublicParams(spec); // Check type of public params: can only be (currently): - // number, string, boolean, undefined, number[] + checkCaseNamesAndDuplicates() { + if (this.cases === undefined) { + return; + } // This is n^2. - for (const v of Object.values(publicParams)) { - checkPublicParamType(v); - } - assert(!seen.some(x => paramsEquals(x, publicParams)), 'Duplicate test case params'); - seen.push(publicParams); + const seen = []; + + for (const testcase of this.cases) { + // stringifyPublicParams also checks for invalid params values + const testcaseString = stringifyPublicParams(testcase); + assert(!seen.some(x => publicParamsEquals(x, testcase)), `Duplicate public test case params: ${testcaseString}`); + seen.push(testcase); } + } - this.cases = cases; + params(casesIterable) { + assert(this.cases === undefined, 'test case is already parameterized'); + this.cases = Array.from(casesIterable); + return this; } - *iterate(rec) { - for (const params of this.cases || [null]) { - yield new RunCaseSpecific(rec, this.name, params, this.fixture, this.fn); + *iterate() { + assert(this.testFn !== undefined, 'internal error'); + + for (const params of this.cases || [{}]) { + yield new RunCaseSpecific(this.testPath, params, this.fixture, this.testFn); } } } class RunCaseSpecific { - constructor(recorder, test, params, fixture, fn) { + constructor(testPath, params, fixture, fn) { _defineProperty(this, "id", void 0); _defineProperty(this, "params", void 0); - _defineProperty(this, "recorder", void 0); - _defineProperty(this, "fixture", void 0); _defineProperty(this, "fn", void 0); this.id = { - test, - params: params ? extractPublicParams(params) : null + test: testPath, + params: extractPublicParams(params) }; this.params = params; - this.recorder = recorder; this.fixture = fixture; this.fn = fn; } - async run(debug) { - const [rec, res] = this.recorder.record(this.id.test, this.id.params); - rec.start(debug); + async run(rec) { + rec.start(); try { const inst = new this.fixture(rec, this.params || {}); @@ -130,17 +149,12 @@ class RunCaseSpecific { } catch (ex) { // There was an exception from constructor, init, test, or finalize. // An error from init or test may have been a SkipTestCase. - // An error from finalize may have been an eventualAsyncExpectation failure. + // An error from finalize may have been an eventualAsyncExpectation failure + // or unexpected validation/OOM error from the GPUDevice. rec.threw(ex); } rec.finish(); - return res; - } - - injectResult(result) { - const [, res] = this.recorder.record(this.id.test, this.id.params); - Object.assign(res, result); } } diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/test_suite_listing.js b/tests/wpt/web-platform-tests/webgpu/common/framework/test_suite_listing.js new file mode 100644 index 00000000000..99c900217c1 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/test_suite_listing.js @@ -0,0 +1,4 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ +//# sourceMappingURL=test_suite_listing.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/tree.js b/tests/wpt/web-platform-tests/webgpu/common/framework/tree.js index 8f96c980749..2f4329c164d 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/framework/tree.js +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/tree.js @@ -2,91 +2,301 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -import { stringifyPublicParams } from './params_utils.js'; +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -// e.g. iteratePath('a/b/c/d', ':') yields ['a/', 'a/b/', 'a/b/c/', 'a/b/c/d:'] -function* iteratePath(path, terminator) { - const parts = path.split('/'); +import { compareQueries, Ordering } from './query/compare.js'; +import { TestQueryMultiCase, TestQuerySingleCase, TestQueryMultiFile, TestQueryMultiTest } from './query/query.js'; +import { stringifySingleParam } from './query/stringify_params.js'; +import { assert } from './util/util.js'; // `loadTreeForQuery()` loads a TestTree for a given queryToLoad. +// The resulting tree is a linked-list all the way from `suite:*` to queryToLoad, +// and under queryToLoad is a tree containing every case matched by queryToLoad. +// +// `subqueriesToExpand` influences the `collapsible` flag on nodes in the resulting tree. +// A node is considered "collapsible" if none of the subqueriesToExpand is a StrictSubset +// of that node. +// +// In WebKit/Blink-style web_tests, an expectation file marks individual cts.html "variants" as +// "Failure", "Crash", etc. +// By passing in the list of expectations as the subqueriesToExpand, we can programmatically +// subdivide the cts.html "variants" list to be able to implement arbitrarily-fine suppressions +// (instead of having to suppress entire test files, which would lose a lot of coverage). +// +// `iterateCollapsedQueries()` produces the list of queries for the variants list. +// +// Though somewhat complicated, this system has important benefits: +// - Avoids having to suppress entire test files, which would cause large test coverage loss. +// - Minimizes the number of page loads needed for fine-grained suppressions. +// (In the naive case, we could do one page load per test case - but the test suite would +// take impossibly long to run.) +// - Enables developers to put any number of tests in one file as appropriate, without worrying +// about expectation granularity. - if (parts.length > 1) { - let partial = parts[0] + '/'; - yield partial; +export class TestTree { + constructor(root) { + _defineProperty(this, "root", void 0); - for (let i = 1; i < parts.length - 1; ++i) { - partial += parts[i] + '/'; - yield partial; - } // Path ends in '/' (so is a README). + this.root = root; + } + iterateCollapsedQueries() { + return TestTree.iterateSubtreeCollapsedQueries(this.root); + } - if (parts[parts.length - 1] === '') { - return; + iterateLeaves() { + return TestTree.iterateSubtreeLeaves(this.root); + } + + toString() { + return TestTree.subtreeToString('(root)', this.root, ''); + } + + static *iterateSubtreeCollapsedQueries(subtree) { + for (const [, child] of subtree.children) { + if ('children' in child && !child.collapsible) { + yield* TestTree.iterateSubtreeCollapsedQueries(child); + } else { + yield child.query; + } } } - yield path + terminator; -} + static *iterateSubtreeLeaves(subtree) { + for (const [, child] of subtree.children) { + if ('children' in child) { + yield* TestTree.iterateSubtreeLeaves(child); + } else { + yield child; + } + } + } -export function treeFromFilterResults(log, listing) { - function getOrInsert(n, k) { - const children = n.children; + static subtreeToString(name, tree, indent) { + const collapsible = 'run' in tree ? '>' : tree.collapsible ? '+' : '-'; + let s = indent + `${collapsible} ${JSON.stringify(name)} => ` + `${tree.query} ${JSON.stringify(tree.query)}`; - if (children.has(k)) { - return children.get(k); + if ('children' in tree) { + if (tree.description !== undefined) { + s += indent + `\n | ${JSON.stringify(tree.description)}`; + } + + for (const [name, child] of tree.children) { + s += '\n' + TestTree.subtreeToString(name, child, indent + ' '); + } } - const v = { - children: new Map() - }; - children.set(k, v); - return v; + return s; } - const tree = { - children: new Map() - }; +} // TODO: Consider having subqueriesToExpand actually impact the depth-order of params in the tree. - for (const f of listing) { - const files = getOrInsert(tree, f.id.suite + ':'); +export async function loadTreeForQuery(loader, queryToLoad, subqueriesToExpand) { + const suite = queryToLoad.suite; + const specs = await loader.listing(suite); + const subqueriesToExpandEntries = Array.from(subqueriesToExpand.entries()); + const seenSubqueriesToExpand = new Array(subqueriesToExpand.length); + seenSubqueriesToExpand.fill(false); + + const isCollapsible = subquery => subqueriesToExpandEntries.every(([i, toExpand]) => { + const ordering = compareQueries(toExpand, subquery); // If toExpand == subquery, no expansion is needed (but it's still "seen"). + + if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true; + return ordering !== Ordering.StrictSubset; + }); // L0 = suite-level, e.g. suite:* + // L1 = file-level, e.g. suite:a,b:* + // L2 = test-level, e.g. suite:a,b:c,d:* + // L3 = case-level, e.g. suite:a,b:c,d: - if (f.id.path === '') { - // This is a suite README. - files.description = f.spec.description.trim(); - continue; - } - let tests = files; + let foundCase = false; // L0 is suite:* - for (const path of iteratePath(f.id.path, ':')) { - tests = getOrInsert(tests, f.id.suite + ':' + path); + const subtreeL0 = makeTreeForSuite(suite); + isCollapsible(subtreeL0.query); // mark seenSubqueriesToExpand + + for (const entry of specs) { + if (entry.file.length === 0 && 'readme' in entry) { + // Suite-level readme. + assert(subtreeL0.description === undefined); + subtreeL0.description = entry.readme.trim(); + continue; } - if (f.spec.description) { - // This is a directory README or spec file. - tests.description = f.spec.description.trim(); + { + const queryL1 = new TestQueryMultiFile(suite, entry.file); + const orderingL1 = compareQueries(queryL1, queryToLoad); + + if (orderingL1 === Ordering.Unordered) { + // File path is not matched by this query. + continue; + } } - if (!('g' in f.spec)) { - // This is a directory README. + if ('readme' in entry) { + // Entry is a README that is an ancestor or descendant of the query. + // (It's included for display in the standalone runner.) + // readmeSubtree is suite:a,b,* + // (This is always going to dedup with a file path, if there are any test spec files under + // the directory that has the README). + const readmeSubtree = addSubtreeForDirPath(subtreeL0, entry.file); + assert(readmeSubtree.description === undefined); + readmeSubtree.description = entry.readme.trim(); continue; - } + } // Entry is a spec file. - const [tRec] = log.record(f.id); - const fId = f.id.suite + ':' + f.id.path; - for (const t of f.spec.g.iterate(tRec)) { - let cases = tests; + const spec = await loader.importSpecFile(queryToLoad.suite, entry.file); + const description = spec.description.trim(); // subtreeL1 is suite:a,b:* - for (const path of iteratePath(t.id.test, '~')) { - cases = getOrInsert(cases, fId + ':' + path); - } + const subtreeL1 = addSubtreeForFilePath(subtreeL0, entry.file, description, isCollapsible); // TODO: If tree generation gets too slow, avoid actually iterating the cases in a file + // if there's no need to (based on the subqueriesToExpand). - const p = stringifyPublicParams(t.id.params); - cases.children.set(fId + ':' + t.id.test + '=' + p, { - runCase: t - }); + for (const t of spec.g.iterate()) { + { + const queryL3 = new TestQuerySingleCase(suite, entry.file, t.id.test, t.id.params); + const orderingL3 = compareQueries(queryL3, queryToLoad); + + if (orderingL3 === Ordering.Unordered || orderingL3 === Ordering.StrictSuperset) { + // Case is not matched by this query. + continue; + } + } // subtreeL2 is suite:a,b:c,d:* + + const subtreeL2 = addSubtreeForTestPath(subtreeL1, t.id.test, isCollapsible); // Leaf for case is suite:a,b:c,d:x=1;y=2 + + addLeafForCase(subtreeL2, t, isCollapsible); + foundCase = true; } } + const tree = new TestTree(subtreeL0); + + for (const [i, sq] of subqueriesToExpandEntries) { + const seen = seenSubqueriesToExpand[i]; + assert(seen, `subqueriesToExpand entry did not match anything \ +(can happen due to overlap with another subquery): ${sq.toString()}`); + } + + assert(foundCase, 'Query does not match any cases'); // TODO: Contains lots of single-child subtrees. Consider cleaning those up (as postprocess?). + + return tree; +} + +function makeTreeForSuite(suite) { + return { + query: new TestQueryMultiFile(suite, []), + children: new Map(), + collapsible: false + }; +} + +function addSubtreeForDirPath(tree, file) { + const subqueryFile = []; // To start, tree is suite:* + // This loop goes from that -> suite:a,* -> suite:a,b,* + + for (const part of file) { + subqueryFile.push(part); + tree = getOrInsertSubtree(part, tree, () => { + const query = new TestQueryMultiFile(tree.query.suite, subqueryFile); + return { + query, + collapsible: false + }; + }); + } + return tree; } + +function addSubtreeForFilePath(tree, file, description, checkCollapsible) { + // To start, tree is suite:* + // This goes from that -> suite:a,* -> suite:a,b,* + tree = addSubtreeForDirPath(tree, file); // This goes from that -> suite:a,b:* + + const subtree = getOrInsertSubtree('', tree, () => { + const query = new TestQueryMultiTest(tree.query.suite, tree.query.filePathParts, []); + return { + query, + description, + collapsible: checkCollapsible(query) + }; + }); + return subtree; +} + +function addSubtreeForTestPath(tree, test, isCollapsible) { + const subqueryTest = []; // To start, tree is suite:a,b:* + // This loop goes from that -> suite:a,b:c,* -> suite:a,b:c,d,* + + for (const part of test) { + subqueryTest.push(part); + tree = getOrInsertSubtree(part, tree, () => { + const query = new TestQueryMultiTest(tree.query.suite, tree.query.filePathParts, subqueryTest); + return { + query, + collapsible: isCollapsible(query) + }; + }); + } // This goes from that -> suite:a,b:c,d:* + + + return getOrInsertSubtree('', tree, () => { + const query = new TestQueryMultiCase(tree.query.suite, tree.query.filePathParts, subqueryTest, {}); + return { + query, + collapsible: isCollapsible(query) + }; + }); +} + +function addLeafForCase(tree, t, checkCollapsible) { + const query = tree.query; + let name = ''; + const subqueryParams = {}; // To start, tree is suite:a,b:c,d:* + // This loop goes from that -> suite:a,b:c,d:x=1;* -> suite:a,b:c,d:x=1;y=2;* + + for (const [k, v] of Object.entries(t.id.params)) { + name = stringifySingleParam(k, v); + subqueryParams[k] = v; + tree = getOrInsertSubtree(name, tree, () => { + const subquery = new TestQueryMultiCase(query.suite, query.filePathParts, query.testPathParts, subqueryParams); + return { + query: subquery, + collapsible: checkCollapsible(subquery) + }; + }); + } // This goes from that -> suite:a,b:c,d:x=1;y=2 + + + const subquery = new TestQuerySingleCase(query.suite, query.filePathParts, query.testPathParts, subqueryParams); + checkCollapsible(subquery); // mark seenSubqueriesToExpand + + insertLeaf(tree, subquery, t); +} + +function getOrInsertSubtree(key, parent, createSubtree) { + let v; + const child = parent.children.get(key); + + if (child !== undefined) { + assert('children' in child); // Make sure cached subtree is not actually a leaf + + v = child; + } else { + v = { ...createSubtree(), + children: new Map() + }; + parent.children.set(key, v); + } + + return v; +} + +function insertLeaf(parent, query, t) { + const key = ''; + const leaf = { + query, + run: rec => t.run(rec) + }; + assert(!parent.children.has(key)); + parent.children.set(key, leaf); +} //# sourceMappingURL=tree.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/util/collect_garbage.js b/tests/wpt/web-platform-tests/webgpu/common/framework/util/collect_garbage.js new file mode 100644 index 00000000000..83b797a0cc4 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/util/collect_garbage.js @@ -0,0 +1,51 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { resolveOnTimeout } from './util.js'; +export async function attemptGarbageCollection() { + const w = self; + + if (w.GCController) { + w.GCController.collect(); + return; + } + + if (w.opera && w.opera.collect) { + w.opera.collect(); + return; + } + + try { + w.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils).garbageCollect(); + return; + } catch (e) {} + + if (w.gc) { + w.gc(); + return; + } + + if (w.CollectGarbage) { + w.CollectGarbage(); + return; + } + + let i; + + function gcRec(n) { + if (n < 1) return; + let temp = { + i: 'ab' + i + i / 100000 + }; + temp = temp + 'foo'; + gcRec(n - 1); + } + + for (i = 0; i < 1000; i++) { + gcRec(10); + } + + return resolveOnTimeout(35); // Let the event loop run a few frames in case it helps. +} +//# sourceMappingURL=collect_garbage.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/util/stack.js b/tests/wpt/web-platform-tests/webgpu/common/framework/util/stack.js index 3d0ec636d85..99653f88806 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/framework/util/stack.js +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/util/stack.js @@ -2,40 +2,24 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -// Takes a stack trace, and extracts only the first continuous range of lines -// containing '/(webgpu|unittests)/', which should provide only the useful part -// of the stack to the caller (for logging). -export function getStackTrace(e) { +// Returns the stack trace of an Error, but without the extra boilerplate at the bottom +// (e.g. RunCaseSpecific, processTicksAndRejections, etc.), for logging. +export function extractImportantStackTrace(e) { if (!e.stack) { return ''; } - const parts = e.stack.split('\n'); - const stack = []; - const moreStack = []; - let found = false; - const commonRegex = /[\/\\](webgpu|unittests)[\/\\]/; + const lines = e.stack.split('\n'); - for (let i = 0; i < parts.length; ++i) { - const part = parts[i].trim(); - const isSuites = commonRegex.test(part); // approximate + for (let i = lines.length - 1; i >= 0; --i) { + const line = lines[i]; - if (found && !isSuites) { - moreStack.push(part); - } - - if (isSuites) { - if (moreStack.length) { - stack.push(...moreStack); - moreStack.length = 0; - } - - stack.push(part); - found = true; + if (line.indexOf('.spec.') !== -1) { + return lines.slice(0, i + 1).join('\n'); } } - return stack.join('\n'); + return e.stack; } // *** Examples *** // // Node fail() diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/util/util.js b/tests/wpt/web-platform-tests/webgpu/common/framework/util/util.js index ca64026916c..b64379982a6 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/framework/util/util.js +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/util/util.js @@ -5,7 +5,14 @@ import { timeout } from './timeout.js'; export function assert(condition, msg) { if (!condition) { - throw new Error(msg); + throw new Error(msg && (typeof msg === 'string' ? msg : msg())); + } +} +export async function assertReject(p, msg) { + try { + await p; + unreachable(msg); + } catch (ex) {// Assertion OK } } export function unreachable(msg) { @@ -16,10 +23,18 @@ const perf = typeof performance !== 'undefined' ? performance : require('perf_ho export function now() { return perf.now(); } +export function resolveOnTimeout(ms) { + return new Promise(resolve => { + timeout(() => { + resolve(); + }, ms); + }); +} +export class PromiseTimeoutError extends Error {} export function rejectOnTimeout(ms, msg) { - return new Promise((resolve, reject) => { + return new Promise((_resolve, reject) => { timeout(() => { - reject(new Error(msg)); + reject(new PromiseTimeoutError(msg)); }, ms); }); } diff --git a/tests/wpt/web-platform-tests/webgpu/common/framework/version.js b/tests/wpt/web-platform-tests/webgpu/common/framework/version.js index 159b3cf420e..f1fe61edc7f 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/framework/version.js +++ b/tests/wpt/web-platform-tests/webgpu/common/framework/version.js @@ -1,3 +1,3 @@ // AUTO-GENERATED - DO NOT EDIT. See tools/gen_version. -export const version = '8b01e69c5c7447d2560323f8d2da319db580e733'; +export const version = 'd8d0ca524c80a0086ab70e155b80589a6be2b6f6'; diff --git a/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker-worker.js b/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker-worker.js index dd078c313a6..be3f4952f05 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker-worker.js +++ b/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker-worker.js @@ -2,27 +2,21 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -import { TestLoader } from '../../framework/loader.js'; -import { Logger } from '../../framework/logger.js'; +import { DefaultTestFileLoader } from '../../framework/file_loader.js'; +import { Logger } from '../../framework/logging/logger.js'; import { assert } from '../../framework/util/util.js'; // should be DedicatedWorkerGlobalScope -const log = new Logger(); -const loader = new TestLoader(); +const loader = new DefaultTestFileLoader(); self.onmessage = async ev => { - const { - query, - debug - } = ev.data; - const files = Array.from((await loader.loadTests([query]))); - assert(files.length === 1, 'worker query resulted in != 1 files'); - const f = files[0]; - const [rec] = log.record(f.id); - assert('g' in f.spec, 'worker query resulted in README'); - const cases = Array.from(f.spec.g.iterate(rec)); - assert(cases.length === 1, 'worker query resulted in != 1 cases'); - const c = cases[0]; - const result = await c.run(debug); + const query = ev.data.query; + const debug = ev.data.debug; + const log = new Logger(debug); + const testcases = Array.from((await loader.loadTests(query))); + assert(testcases.length === 1, 'worker query resulted in != 1 cases'); + const testcase = testcases[0]; + const [rec, result] = log.record(testcase.query.toString()); + await testcase.run(rec); self.postMessage({ query, result diff --git a/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker.js b/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker.js index a67030056f5..7e8b9a47c07 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker.js +++ b/tests/wpt/web-platform-tests/webgpu/common/runtime/helper/test_worker.js @@ -4,13 +4,16 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -import { LogMessageWithStack } from '../../framework/logger.js'; +import { LogMessageWithStack } from '../../framework/logging/log_message.js'; export class TestWorker { - constructor() { + constructor(debug) { + _defineProperty(this, "debug", void 0); + _defineProperty(this, "worker", void 0); _defineProperty(this, "resolvers", new Map()); + this.debug = debug; const selfPath = import.meta.url; const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/')); const workerPath = selfPathDir + '/test_worker-worker.js'; @@ -33,14 +36,15 @@ export class TestWorker { }; } - run(query, debug = false) { + async run(rec, query) { this.worker.postMessage({ query, - debug + debug: this.debug }); - return new Promise(resolve => { + const workerResult = await new Promise(resolve => { this.resolvers.set(query, resolve); }); + rec.injectResult(workerResult); } } diff --git a/tests/wpt/web-platform-tests/webgpu/common/runtime/wpt.js b/tests/wpt/web-platform-tests/webgpu/common/runtime/wpt.js index fd02f09471b..0648a0dc7ee 100644 --- a/tests/wpt/web-platform-tests/webgpu/common/runtime/wpt.js +++ b/tests/wpt/web-platform-tests/webgpu/common/runtime/wpt.js @@ -2,58 +2,56 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -import { TestLoader } from '../framework/loader.js'; -import { Logger } from '../framework/logger.js'; -import { makeQueryString } from '../framework/url_query.js'; +import { DefaultTestFileLoader } from '../framework/file_loader.js'; +import { Logger } from '../framework/logging/logger.js'; import { AsyncMutex } from '../framework/util/async_mutex.js'; +import { assert } from '../framework/util/util.js'; import { optionEnabled } from './helper/options.js'; import { TestWorker } from './helper/test_worker.js'; (async () => { - const loader = new TestLoader(); - const files = await loader.loadTestsFromQuery(window.location.search); - const worker = optionEnabled('worker') ? new TestWorker() : undefined; - const log = new Logger(); + const loader = new DefaultTestFileLoader(); + const qs = new URLSearchParams(window.location.search).getAll('q'); + assert(qs.length === 1, 'currently, there must be exactly one ?q='); + const testcases = await loader.loadTests(qs[0]); + await addWPTTests(testcases); +})(); // Note: async_tests must ALL be added within the same task. This function *must not* be async. + + +function addWPTTests(testcases) { + const worker = optionEnabled('worker') ? new TestWorker(false) : undefined; + const log = new Logger(false); const mutex = new AsyncMutex(); const running = []; - for (const f of files) { - if (!('g' in f.spec)) { - continue; - } - - const [rec] = log.record(f.id); + for (const testcase of testcases) { + const name = testcase.query.toString(); - for (const t of f.spec.g.iterate(rec)) { - const name = makeQueryString(f.id, t.id); // Note: apparently, async_tests must ALL be added within the same task. + const wpt_fn = function () { + const p = mutex.with(async () => { + const [rec, res] = log.record(name); - async_test(function () { - const p = mutex.with(async () => { - let r; + if (worker) { + await worker.run(rec, name); + } else { + await testcase.run(rec); + } - if (worker) { - r = await worker.run(name); - t.injectResult(r); - } else { - r = await t.run(); + this.step(() => { + // Unfortunately, it seems not possible to surface any logs for warn/skip. + if (res.status === 'fail') { + throw (res.logs || []).map(s => s.toJSON()).join('\n\n'); } - - this.step(() => { - // Unfortunately, it seems not possible to surface any logs for warn/skip. - if (r.status === 'fail') { - throw (r.logs || []).map(s => s.toJSON()).join('\n\n'); - } - }); - this.done(); }); - running.push(p); - return p; - }, name); - } + this.done(); + }); + running.push(p); + return p; + }; + + async_test(wpt_fn, name); } - await Promise.all(running); - const resultsElem = document.getElementById('results'); - resultsElem.textContent = log.asJSON(2); -})(); + return Promise.all(running).then(() => log); +} //# sourceMappingURL=wpt.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/cts.html b/tests/wpt/web-platform-tests/webgpu/cts.html index 62340be400e..a06ad795899 100644 --- a/tests/wpt/web-platform-tests/webgpu/cts.html +++ b/tests/wpt/web-platform-tests/webgpu/cts.html @@ -26,49 +26,30 @@ <script src=/resources/testharness.js></script> <script src=/resources/testharnessreport.js></script> -<style> -#results { - font-family: monospace; - width: 100%; - height: 15em; -} - -/* Test Name column */ -#results > tbody > tr > td:nth-child(2) { - word-break: break-word; -} - -/* Message column */ -#results > tbody > tr > td:nth-child(3) { - white-space: pre-wrap; - word-break: break-word; -} -</style> - -<textarea id=results></textarea> <script type=module src=/webgpu/common/runtime/wpt.js></script> -<meta name=variant content='?q=webgpu:api/operation/buffers/create_mapped'> -<meta name=variant content='?q=webgpu:api/operation/buffers/map'> -<meta name=variant content='?q=webgpu:api/operation/buffers/map_detach'> -<meta name=variant content='?q=webgpu:api/operation/buffers/map_oom'> -<meta name=variant content='?q=webgpu:api/operation/command_buffer/basic'> -<meta name=variant content='?q=webgpu:api/operation/command_buffer/copies'> -<meta name=variant content='?q=webgpu:api/operation/command_buffer/render/basic'> -<meta name=variant content='?q=webgpu:api/operation/fences'> -<meta name=variant content='?q=webgpu:api/validation/createBindGroup'> -<meta name=variant content='?q=webgpu:api/validation/createBindGroupLayout'> -<meta name=variant content='?q=webgpu:api/validation/createPipelineLayout'> -<meta name=variant content='?q=webgpu:api/validation/createTexture'> -<meta name=variant content='?q=webgpu:api/validation/createView'> -<meta name=variant content='?q=webgpu:api/validation/error_scope'> -<meta name=variant content='?q=webgpu:api/validation/fences'> -<meta name=variant content='?q=webgpu:api/validation/queue_submit'> -<meta name=variant content='?q=webgpu:api/validation/render_pass_descriptor'> -<meta name=variant content='?q=webgpu:api/validation/setBindGroup'> -<meta name=variant content='?q=webgpu:api/validation/setBlendColor'> -<meta name=variant content='?q=webgpu:api/validation/setScissorRect'> -<meta name=variant content='?q=webgpu:api/validation/setStencilReference'> -<meta name=variant content='?q=webgpu:api/validation/setViewport'> -<meta name=variant content='?q=webgpu:examples'> -<meta name=variant content='?q=webgpu:web-platform/canvas/context_creation'> -<meta name=variant content='?q=webgpu:web-platform/copyImageBitmapToTexture'> +<meta name=variant content='?q=webgpu:api,operation,buffers,create_mapped:*'> +<meta name=variant content='?q=webgpu:api,operation,buffers,map:*'> +<meta name=variant content='?q=webgpu:api,operation,buffers,map_detach:*'> +<meta name=variant content='?q=webgpu:api,operation,buffers,map_oom:*'> +<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:*'> +<meta name=variant content='?q=webgpu:api,operation,command_buffer,copies:*'> +<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,basic:*'> +<meta name=variant content='?q=webgpu:api,operation,fences:*'> +<meta name=variant content='?q=webgpu:api,operation,resource_init,copied_texture_clear:*'> +<meta name=variant content='?q=webgpu:api,validation,createBindGroup:*'> +<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:*'> +<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:*'> +<meta name=variant content='?q=webgpu:api,validation,createTexture:*'> +<meta name=variant content='?q=webgpu:api,validation,createView:*'> +<meta name=variant content='?q=webgpu:api,validation,error_scope:*'> +<meta name=variant content='?q=webgpu:api,validation,fences:*'> +<meta name=variant content='?q=webgpu:api,validation,queue_submit:*'> +<meta name=variant content='?q=webgpu:api,validation,render_pass_descriptor:*'> +<meta name=variant content='?q=webgpu:api,validation,setBindGroup:*'> +<meta name=variant content='?q=webgpu:api,validation,setBlendColor:*'> +<meta name=variant content='?q=webgpu:api,validation,setScissorRect:*'> +<meta name=variant content='?q=webgpu:api,validation,setStencilReference:*'> +<meta name=variant content='?q=webgpu:api,validation,setViewport:*'> +<meta name=variant content='?q=webgpu:examples:*'> +<meta name=variant content='?q=webgpu:web-platform,canvas,context_creation:*'> +<meta name=variant content='?q=webgpu:web-platform,copyImageBitmapToTexture:*'> diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/create_mapped.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/create_mapped.spec.js index 7b2bc39aa3d..1c3b1254d50 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/create_mapped.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/create_mapped.spec.js @@ -2,18 +2,20 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -export const description = ``; -import { pbool, pcombine, poptions } from '../../../../common/framework/params.js'; -import { TestGroup } from '../../../../common/framework/test_group.js'; +export const description = ''; +import { params, pbool, poptions } from '../../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { MappingTest } from './mapping_test.js'; -export const g = new TestGroup(MappingTest); -g.test('createBufferMapped', async t => { - const size = t.params.size; +export const g = makeTestGroup(MappingTest); +g.test('createBufferMapped').params(params().combine(poptions('size', [12, 512 * 1024])).combine(pbool('mappable'))).fn(t => { + const { + size, + mappable + } = t.params; const [buffer, arrayBuffer] = t.device.createBufferMapped({ size, - usage: GPUBufferUsage.COPY_SRC | (t.params.mappable ? GPUBufferUsage.MAP_WRITE : 0) + usage: GPUBufferUsage.COPY_SRC | (mappable ? GPUBufferUsage.MAP_WRITE : 0) }); t.checkMapWrite(buffer, arrayBuffer, size); -}).params(pcombine(poptions('size', [12, 512 * 1024]), // -pbool('mappable'))); +}); //# sourceMappingURL=create_mapped.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map.spec.js index 1c73d62a95f..842421dd5ce 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map.spec.js @@ -2,22 +2,26 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -export const description = ``; -import { pbool, pcombine, poptions } from '../../../../common/framework/params.js'; -import { TestGroup } from '../../../../common/framework/test_group.js'; +export const description = ''; +import { pbool, poptions, params } from '../../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { MappingTest } from './mapping_test.js'; -export const g = new TestGroup(MappingTest); -g.test('mapWriteAsync', async t => { - const size = t.params.size; +export const g = makeTestGroup(MappingTest); +g.test('mapWriteAsync').params(poptions('size', [12, 512 * 1024])).fn(async t => { + const { + size + } = t.params; const buffer = t.device.createBuffer({ size, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE }); const arrayBuffer = await buffer.mapWriteAsync(); t.checkMapWrite(buffer, arrayBuffer, size); -}).params(poptions('size', [12, 512 * 1024])); -g.test('mapReadAsync', async t => { - const size = t.params.size; +}); +g.test('mapReadAsync').params(poptions('size', [12, 512 * 1024])).fn(async t => { + const { + size + } = t.params; const [buffer, init] = t.device.createBufferMapped({ size, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ @@ -32,14 +36,16 @@ g.test('mapReadAsync', async t => { buffer.unmap(); const actual = new Uint8Array((await buffer.mapReadAsync())); t.expectBuffer(actual, new Uint8Array(expected.buffer)); -}).params(poptions('size', [12, 512 * 1024])); -g.test('createBufferMapped', async t => { - const size = t.params.size; +}); +g.test('createBufferMapped').params(params().combine(poptions('size', [12, 512 * 1024])).combine(pbool('mappable'))).fn(async t => { + const { + size, + mappable + } = t.params; const [buffer, arrayBuffer] = t.device.createBufferMapped({ size, - usage: GPUBufferUsage.COPY_SRC | (t.params.mappable ? GPUBufferUsage.MAP_WRITE : 0) + usage: GPUBufferUsage.COPY_SRC | (mappable ? GPUBufferUsage.MAP_WRITE : 0) }); t.checkMapWrite(buffer, arrayBuffer, size); -}).params(pcombine(poptions('size', [12, 512 * 1024]), // -pbool('mappable'))); +}); //# sourceMappingURL=map.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js index 14d5be5a631..8ae0be0b197 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_detach.spec.js @@ -2,8 +2,8 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -export const description = ``; -import { TestGroup } from '../../../../common/framework/test_group.js'; +export const description = ''; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { GPUTest } from '../../../gpu_test.js'; class F extends GPUTest { @@ -19,15 +19,26 @@ class F extends GPUTest { } -export const g = new TestGroup(F); -g.test('mapWriteAsync', async t => { +export const g = makeTestGroup(F); +g.test('mapWriteAsync').params([{ + unmap: true, + destroy: false +}, // +{ + unmap: false, + destroy: true +}, { + unmap: true, + destroy: true +}]).fn(async t => { const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_WRITE }); const arrayBuffer = await buffer.mapWriteAsync(); t.checkDetach(buffer, arrayBuffer, t.params.unmap, t.params.destroy); -}).params([{ +}); +g.test('mapReadAsync').params([{ unmap: true, destroy: false }, // @@ -37,26 +48,24 @@ g.test('mapWriteAsync', async t => { }, { unmap: true, destroy: true -}]); -g.test('mapReadAsync', async t => { +}]).fn(async t => { const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_READ }); const arrayBuffer = await buffer.mapReadAsync(); t.checkDetach(buffer, arrayBuffer, t.params.unmap, t.params.destroy); -}).params([{ +}); +g.test('create_mapped').params([{ unmap: true, destroy: false -}, // -{ +}, { unmap: false, destroy: true }, { unmap: true, destroy: true -}]); -g.test('create mapped', async t => { +}]).fn(async t => { const desc = { size: 4, usage: GPUBufferUsage.MAP_WRITE @@ -69,14 +78,5 @@ g.test('create mapped', async t => { if (t.params.destroy) buffer.destroy(); t.expect(arrayBuffer.byteLength === 0, 'ArrayBuffer should be detached'); t.expect(view.byteLength === 0, 'ArrayBufferView should be detached'); -}).params([{ - unmap: true, - destroy: false -}, { - unmap: false, - destroy: true -}, { - unmap: true, - destroy: true -}]); +}); //# sourceMappingURL=map_detach.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js index ee642a5c3b3..a04347ffd4f 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/buffers/map_oom.spec.js @@ -2,8 +2,8 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -export const description = ``; -import { TestGroup } from '../../../../common/framework/test_group.js'; +export const description = ''; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { GPUTest } from '../../../gpu_test.js'; function getBufferDesc() { @@ -13,16 +13,16 @@ function getBufferDesc() { }; } -export const g = new TestGroup(GPUTest); -g.test('mapWriteAsync', async t => { +export const g = makeTestGroup(GPUTest); +g.test('mapWriteAsync').fn(async t => { const buffer = t.device.createBuffer(getBufferDesc()); t.shouldReject('RangeError', buffer.mapWriteAsync()); }); -g.test('mapReadAsync', async t => { +g.test('mapReadAsync').fn(async t => { const buffer = t.device.createBuffer(getBufferDesc()); t.shouldReject('RangeError', buffer.mapReadAsync()); }); -g.test('createBufferMapped', async t => { +g.test('createBufferMapped').fn(async t => { t.shouldThrow('RangeError', () => { t.device.createBufferMapped(getBufferDesc()); }); diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js index bc4020bfeb5..547a08683f7 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/basic.spec.js @@ -5,10 +5,10 @@ export const description = ` Basic tests. `; -import { TestGroup } from '../../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { GPUTest } from '../../../gpu_test.js'; -export const g = new TestGroup(GPUTest); -g.test('empty', async t => { +export const g = makeTestGroup(GPUTest); +g.test('empty').fn(async t => { const encoder = t.device.createCommandEncoder(); const cmd = encoder.finish(); t.device.defaultQueue.submit([cmd]); diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/copies.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/copies.spec.js index c330415d851..cc2ea6deae1 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/copies.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/copies.spec.js @@ -5,10 +5,10 @@ export const description = ` copy{Buffer,Texture}To{Buffer,Texture} tests. `; -import { TestGroup } from '../../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { GPUTest } from '../../../gpu_test.js'; -export const g = new TestGroup(GPUTest); -g.test('b2b', async t => { +export const g = makeTestGroup(GPUTest); +g.test('b2b').fn(async t => { const data = new Uint32Array([0x01020304]); const [src, map] = t.device.createBufferMapped({ size: 4, @@ -25,7 +25,7 @@ g.test('b2b', async t => { t.device.defaultQueue.submit([encoder.finish()]); t.expectContents(dst, data); }); -g.test('b2t2b', async t => { +g.test('b2t2b').fn(async t => { const data = new Uint32Array([0x01020304]); const [src, map] = t.device.createBufferMapped({ size: 4, @@ -82,7 +82,7 @@ g.test('b2t2b', async t => { t.device.defaultQueue.submit([encoder.finish()]); t.expectContents(dst, data); }); -g.test('b2t2t2b', async t => { +g.test('b2t2t2b').fn(async t => { const data = new Uint32Array([0x01020304]); const [src, map] = t.device.createBufferMapped({ size: 4, diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/render/basic.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/render/basic.spec.js index 88710e8aa09..815eb5b70b0 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/render/basic.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/command_buffer/render/basic.spec.js @@ -5,10 +5,10 @@ export const description = ` Basic command buffer rendering tests. `; -import { TestGroup } from '../../../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../gpu_test.js'; -export const g = new TestGroup(GPUTest); -g.test('clear', async t => { +export const g = makeTestGroup(GPUTest); +g.test('clear').fn(async t => { const dst = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/fences.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/fences.spec.js index 386530e0852..f9f079b6241 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/fences.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/fences.spec.js @@ -2,42 +2,42 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -export const description = ``; -import { attemptGarbageCollection } from '../../../common/framework/collect_garbage.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; +export const description = ''; +import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { attemptGarbageCollection } from '../../../common/framework/util/collect_garbage.js'; import { raceWithRejectOnTimeout } from '../../../common/framework/util/util.js'; import { GPUTest } from '../../gpu_test.js'; -export const g = new TestGroup(GPUTest); -g.test('initial/no descriptor', t => { +export const g = makeTestGroup(GPUTest); +g.test('initial,no_descriptor').fn(t => { const fence = t.queue.createFence(); t.expect(fence.getCompletedValue() === 0); }); -g.test('initial/empty descriptor', t => { +g.test('initial,empty_descriptor').fn(t => { const fence = t.queue.createFence({}); t.expect(fence.getCompletedValue() === 0); }); -g.test('initial/descriptor with initialValue', t => { +g.test('initial,descriptor_with_initialValue').fn(t => { const fence = t.queue.createFence({ initialValue: 2 }); t.expect(fence.getCompletedValue() === 2); }); // Promise resolves when onCompletion value is less than signal value. -g.test('wait/less than signaled', async t => { +g.test('wait,less_than_signaled').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 2); await fence.onCompletion(1); t.expect(fence.getCompletedValue() === 2); }); // Promise resolves when onCompletion value is equal to signal value. -g.test('wait/equal to signaled', async t => { +g.test('wait,equal_to_signaled').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 2); await fence.onCompletion(2); t.expect(fence.getCompletedValue() === 2); }); // All promises resolve when signal is called once. -g.test('wait/signaled once', async t => { +g.test('wait,signaled_once').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 20); const promises = []; @@ -51,7 +51,7 @@ g.test('wait/signaled once', async t => { await Promise.all(promises); }); // Promise resolves when signal is called multiple times. -g.test('wait/signaled multiple times', async t => { +g.test('wait,signaled_multiple_times').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 1); t.queue.signal(fence, 2); @@ -59,7 +59,7 @@ g.test('wait/signaled multiple times', async t => { t.expect(fence.getCompletedValue() === 2); }); // Promise resolves if fence has already completed. -g.test('wait/already completed', async t => { +g.test('wait,already_completed').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 2); // Wait for value to update. @@ -74,7 +74,7 @@ g.test('wait/already completed', async t => { t.expect(fence.getCompletedValue() === 2); }); // Test many calls to signal and wait on fence values one at a time. -g.test('wait/many/serially', async t => { +g.test('wait,many,serially').fn(async t => { const fence = t.queue.createFence(); for (let i = 1; i <= 20; ++i) { @@ -84,7 +84,7 @@ g.test('wait/many/serially', async t => { } }); // Test many calls to signal and wait on all fence values. -g.test('wait/many/parallel', async t => { +g.test('wait,many,parallel').fn(async t => { const fence = t.queue.createFence(); const promises = []; @@ -99,7 +99,7 @@ g.test('wait/many/parallel', async t => { t.expect(fence.getCompletedValue() === 20); }); // Test onCompletion promise resolves within a time limit. -g.test('wait/resolves within timeout', t => { +g.test('wait,resolves_within_timeout').fn(t => { const fence = t.queue.createFence(); t.queue.signal(fence, 2); return raceWithRejectOnTimeout((async () => { @@ -108,23 +108,23 @@ g.test('wait/resolves within timeout', t => { })(), 100, 'The fence has not been resolved within time limit.'); }); // Test dropping references to the fence and onCompletion promise does not crash. -g.test('drop/fence and promise', t => { +g.test('drop,fence_and_promise').fn(async t => { { const fence = t.queue.createFence(); t.queue.signal(fence, 2); fence.onCompletion(2); } - attemptGarbageCollection(); + await attemptGarbageCollection(); }); // Test dropping references to the fence and holding the promise does not crash. -g.test('drop/promise', async t => { +g.test('drop,promise').fn(async t => { let promise; { const fence = t.queue.createFence(); t.queue.signal(fence, 2); promise = fence.onCompletion(2); } - attemptGarbageCollection(); + await attemptGarbageCollection(); await promise; }); //# sourceMappingURL=fences.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/resource_init/copied_texture_clear.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/resource_init/copied_texture_clear.spec.js new file mode 100644 index 00000000000..22a71bf725c --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/resource_init/copied_texture_clear.spec.js @@ -0,0 +1,86 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +export const description = 'Test uninitialized textures are initialized to zero when copied.'; +import * as C from '../../../../common/constants.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { assert, unreachable } from '../../../../common/framework/util/util.js'; +import { ReadMethod, TextureZeroInitTest } from './texture_zero_init_test.js'; + +class CopiedTextureClearTest extends TextureZeroInitTest { + checkContentsByBufferCopy(texture, state, subresourceRange) { + for (const { + level: mipLevel, + slice + } of subresourceRange.each()) { + assert(this.params.dimension === '2d'); + this.expectSingleColor(texture, this.params.format, { + size: [this.textureWidth, this.textureHeight, 1], + dimension: this.params.dimension, + slice, + layout: { + mipLevel + }, + exp: this.stateToTexelComponents[state] + }); + } + } + + checkContentsByTextureCopy(texture, state, subresourceRange) { + for (const { + level, + slice + } of subresourceRange.each()) { + assert(this.params.dimension === '2d'); + const width = this.textureWidth >> level; + const height = this.textureHeight >> level; + const dst = this.device.createTexture({ + size: [width, height, 1], + format: this.params.format, + usage: C.TextureUsage.CopyDst | C.TextureUsage.CopySrc + }); + const commandEncoder = this.device.createCommandEncoder(); + commandEncoder.copyTextureToTexture({ + texture, + mipLevel: level, + arrayLayer: slice + }, { + texture: dst, + mipLevel: 0, + arrayLayer: 0 + }, { + width, + height, + depth: 1 + }); + this.queue.submit([commandEncoder.finish()]); + this.expectSingleColor(dst, this.params.format, { + size: [width, height, 1], + exp: this.stateToTexelComponents[state] + }); + } + } + + checkContents(texture, state, subresourceRange) { + switch (this.params.readMethod) { + case ReadMethod.CopyToBuffer: + this.checkContentsByBufferCopy(texture, state, subresourceRange); + break; + + case ReadMethod.CopyToTexture: + this.checkContentsByTextureCopy(texture, state, subresourceRange); + break; + + default: + unreachable(); + } + } + +} + +export const g = makeTestGroup(CopiedTextureClearTest); +g.test('uninitialized_texture_is_zero').params(TextureZeroInitTest.generateParams([ReadMethod.CopyToBuffer, ReadMethod.CopyToTexture])).fn(t => { + t.run(); +}); +//# sourceMappingURL=copied_texture_clear.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/resource_init/texture_zero_init_test.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/resource_init/texture_zero_init_test.js new file mode 100644 index 00000000000..5dc3c227232 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/operation/resource_init/texture_zero_init_test.js @@ -0,0 +1,563 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import * as C from '../../../../common/constants.js'; +import { params, poptions, pbool } from '../../../../common/framework/params_builder.js'; +import { assert, unreachable } from '../../../../common/framework/util/util.js'; +import { kTextureAspects, kTextureFormatInfo, kTextureFormats } from '../../../capability_info.js'; +import { GPUTest } from '../../../gpu_test.js'; +import { createTextureUploadBuffer } from '../../../util/texture/layout.js'; +import { SubresourceRange } from '../../../util/texture/subresource.js'; +import { getTexelDataRepresentation } from '../../../util/texture/texelData.js'; +var UninitializeMethod; + +(function (UninitializeMethod) { + UninitializeMethod["Creation"] = "Creation"; + UninitializeMethod["StoreOpClear"] = "StoreOpClear"; +})(UninitializeMethod || (UninitializeMethod = {})); + +const kUninitializeMethods = Object.keys(UninitializeMethod); +export let ReadMethod; + +(function (ReadMethod) { + ReadMethod["Sample"] = "Sample"; + ReadMethod["CopyToBuffer"] = "CopyToBuffer"; + ReadMethod["CopyToTexture"] = "CopyToTexture"; + ReadMethod["DepthTest"] = "DepthTest"; + ReadMethod["StencilTest"] = "StencilTest"; + ReadMethod["ColorBlending"] = "ColorBlending"; + ReadMethod["Storage"] = "Storage"; +})(ReadMethod || (ReadMethod = {})); + +const kMipLevelCounts = [1, 5]; // For each mip level count, define the mip ranges to leave uninitialized. + +const kUninitializedMipRangesToTest = { + 1: [{ + begin: 0, + end: 1 + }], + // Test the only mip + 5: [{ + begin: 0, + end: 2 + }, { + begin: 3, + end: 4 + }] // Test a range and a single mip + +}; // Test with these sample counts. + +const kSampleCounts = [1, 4]; // Test with these slice counts. This means the depth of a 3d texture or the number +// or layers in a 2D or a 1D texture array. + +// For each slice count, define the slices to leave uninitialized. +const kUninitializedSliceRangesToTest = { + 1: [{ + begin: 0, + end: 1 + }], + // Test the only slice + 7: [{ + begin: 2, + end: 4 + }, { + begin: 6, + end: 7 + }] // Test a range and a single slice + +}; // Test with these combinations of texture dimension and sliceCount. + +const kCreationSizes = [// { dimension: '1d', sliceCount: 7 }, // TODO: 1d textures +{ + dimension: '2d', + sliceCount: 1 +}, // 2d textures +{ + dimension: '2d', + sliceCount: 7 +} // 2d array textures +// { dimension: '3d', sliceCount: 7 }, // TODO: 3d textures +]; // Enums to abstract over color / depth / stencil values in textures. Depending on the texture format, +// the data for each value may have a different representation. These enums are converted to a +// representation such that their values can be compared. ex.) An integer is needed to upload to an +// unsigned normalized format, but its value is read as a float in the shader. + +export let InitializedState; + +(function (InitializedState) { + InitializedState[InitializedState["Canary"] = 0] = "Canary"; + InitializedState[InitializedState["Zero"] = 1] = "Zero"; +})(InitializedState || (InitializedState = {})); + +export function initializedStateAsFloat(state) { + switch (state) { + case InitializedState.Zero: + return 0; + + case InitializedState.Canary: + return 1; + + default: + unreachable(); + } +} +export function initializedStateAsUint(state) { + switch (state) { + case InitializedState.Zero: + return 0; + + case InitializedState.Canary: + return 255; + + default: + unreachable(); + } +} +export function initializedStateAsSint(state) { + switch (state) { + case InitializedState.Zero: + return 0; + + case InitializedState.Canary: + return -1; + + default: + unreachable(); + } +} +export function initializedStateAsColor(state, format) { + let value; + + if (format.indexOf('uint') !== -1) { + value = initializedStateAsUint(state); + } else if (format.indexOf('sint') !== -1) { + value = initializedStateAsSint(state); + } else { + value = initializedStateAsFloat(state); + } + + return [value, value, value, value]; +} +export function initializedStateAsDepth(state) { + switch (state) { + case InitializedState.Zero: + return 0; + + case InitializedState.Canary: + return 1; + + default: + unreachable(); + } +} +export function initializedStateAsStencil(state) { + switch (state) { + case InitializedState.Zero: + return 0; + + case InitializedState.Canary: + return 42; + + default: + unreachable(); + } +} + +function getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod) { + let usage = C.TextureUsage.CopyDst; + + switch (uninitializeMethod) { + case UninitializeMethod.Creation: + break; + + case UninitializeMethod.StoreOpClear: + usage |= C.TextureUsage.OutputAttachment; + break; + + default: + unreachable(); + } + + switch (readMethod) { + case ReadMethod.CopyToBuffer: + case ReadMethod.CopyToTexture: + usage |= C.TextureUsage.CopySrc; + break; + + case ReadMethod.Sample: + usage |= C.TextureUsage.Sampled; + break; + + case ReadMethod.Storage: + usage |= C.TextureUsage.Storage; + break; + + case ReadMethod.DepthTest: + case ReadMethod.StencilTest: + case ReadMethod.ColorBlending: + usage |= C.TextureUsage.OutputAttachment; + break; + + default: + unreachable(); + } + + if (sampleCount > 1) { + // Copies to multisampled textures are not allowed. We need OutputAttachment to initialize + // canary data in multisampled textures. + usage |= C.TextureUsage.OutputAttachment; + } + + if (!kTextureFormatInfo[format].copyable) { + // Copies are not possible. We need OutputAttachment to initialize + // canary data. + assert(kTextureFormatInfo[format].renderable); + usage |= C.TextureUsage.OutputAttachment; + } + + return usage; +} + +export class TextureZeroInitTest extends GPUTest { + constructor(rec, params) { + super(rec, params); + + _defineProperty(this, "stateToTexelComponents", void 0); + + const stateToTexelComponents = state => { + const [R, G, B, A] = initializedStateAsColor(state, this.params.format); + return { + R, + G, + B, + A, + Depth: initializedStateAsDepth(state), + Stencil: initializedStateAsStencil(state) + }; + }; + + this.stateToTexelComponents = { + [InitializedState.Zero]: stateToTexelComponents(InitializedState.Zero), + [InitializedState.Canary]: stateToTexelComponents(InitializedState.Canary) + }; + } + + get params() { + return super.params; + } + + get textureWidth() { + let width = 1 << this.params.mipLevelCount; + + if (this.params.nonPowerOfTwo) { + width = 2 * width - 1; + } + + return width; + } + + get textureHeight() { + let height = 1 << this.params.mipLevelCount; + + if (this.params.nonPowerOfTwo) { + height = 2 * height - 1; + } + + return height; + } // Used to iterate subresources and check that their uninitialized contents are zero when accessed + + + *iterateUninitializedSubresources() { + for (const mipRange of kUninitializedMipRangesToTest[this.params.mipLevelCount]) { + for (const sliceRange of kUninitializedSliceRangesToTest[this.params.sliceCount]) { + yield new SubresourceRange({ + mipRange, + sliceRange + }); + } + } + } // Used to iterate and initialize other subresources not checked for zero-initialization. + // Zero-initialization of uninitialized subresources should not have side effects on already + // initialized subresources. + + + *iterateInitializedSubresources() { + const uninitialized = new Array(this.params.mipLevelCount); + + for (let level = 0; level < uninitialized.length; ++level) { + uninitialized[level] = new Array(this.params.sliceCount); + } + + for (const subresources of this.iterateUninitializedSubresources()) { + for (const { + level, + slice + } of subresources.each()) { + uninitialized[level][slice] = true; + } + } + + for (let level = 0; level < uninitialized.length; ++level) { + for (let slice = 0; slice < uninitialized[level].length; ++slice) { + if (!uninitialized[level][slice]) { + yield new SubresourceRange({ + mipRange: { + begin: level, + count: 1 + }, + sliceRange: { + begin: slice, + count: 1 + } + }); + } + } + } + } + + *generateTextureViewDescriptorsForRendering(aspect, subresourceRange) { + const viewDescriptor = { + dimension: '2d', + aspect + }; + + if (subresourceRange === undefined) { + return viewDescriptor; + } + + for (const { + level, + slice + } of subresourceRange.each()) { + yield { ...viewDescriptor, + baseMipLevel: level, + mipLevelCount: 1, + baseArrayLayer: slice, + arrayLayerCount: 1 + }; + } + } + + initializeWithStoreOp(state, texture, subresourceRange) { + const commandEncoder = this.device.createCommandEncoder(); + + for (const viewDescriptor of this.generateTextureViewDescriptorsForRendering(this.params.aspect, subresourceRange)) { + if (kTextureFormatInfo[this.params.format].color) { + commandEncoder.beginRenderPass({ + colorAttachments: [{ + attachment: texture.createView(viewDescriptor), + storeOp: 'store', + loadValue: initializedStateAsColor(state, this.params.format) + }] + }).endPass(); + } else { + commandEncoder.beginRenderPass({ + colorAttachments: [], + depthStencilAttachment: { + attachment: texture.createView(viewDescriptor), + depthStoreOp: 'store', + depthLoadValue: initializedStateAsDepth(state), + stencilStoreOp: 'store', + stencilLoadValue: initializedStateAsStencil(state) + } + }).endPass(); + } + } + + this.queue.submit([commandEncoder.finish()]); + } + + initializeWithCopy(texture, state, subresourceRange) { + if (this.params.dimension === '1d' || this.params.dimension === '3d') { + // TODO: https://github.com/gpuweb/gpuweb/issues/69 + // Copies with 1D and 3D textures are not yet specified + unreachable(); + } + + const firstSubresource = subresourceRange.each().next().value; + assert(typeof firstSubresource !== 'undefined'); + const largestWidth = this.textureWidth >> firstSubresource.level; + const largestHeight = this.textureHeight >> firstSubresource.level; + const texelData = new Uint8Array(getTexelDataRepresentation(this.params.format).getBytes(this.stateToTexelComponents[state])); + const { + buffer, + bytesPerRow, + rowsPerImage + } = createTextureUploadBuffer(texelData, this.device, this.params.format, this.params.dimension, [largestWidth, largestHeight, 1]); + const commandEncoder = this.device.createCommandEncoder(); + + for (const { + level, + slice + } of subresourceRange.each()) { + const width = this.textureWidth >> level; + const height = this.textureHeight >> level; + commandEncoder.copyBufferToTexture({ + buffer, + bytesPerRow, + rowsPerImage + }, { + texture, + mipLevel: level, + arrayLayer: slice + }, { + width, + height, + depth: 1 + }); + } + + this.queue.submit([commandEncoder.finish()]); + buffer.destroy(); + } + + initializeTexture(texture, state, subresourceRange) { + if (this.params.sampleCount > 1 || !kTextureFormatInfo[this.params.format].copyable) { + // Copies to multisampled textures not yet specified. + // Use a storeOp for now. + assert(kTextureFormatInfo[this.params.format].renderable); + this.initializeWithStoreOp(state, texture, subresourceRange); + } else { + this.initializeWithCopy(texture, state, subresourceRange); + } + } + + discardTexture(texture, subresourceRange) { + const commandEncoder = this.device.createCommandEncoder(); + + for (const desc of this.generateTextureViewDescriptorsForRendering(this.params.aspect, subresourceRange)) { + if (kTextureFormatInfo[this.params.format].color) { + commandEncoder.beginRenderPass({ + colorAttachments: [{ + attachment: texture.createView(desc), + storeOp: 'clear', + loadValue: 'load' + }] + }).endPass(); + } else { + commandEncoder.beginRenderPass({ + colorAttachments: [], + depthStencilAttachment: { + attachment: texture.createView(desc), + depthStoreOp: 'clear', + depthLoadValue: 'load', + stencilStoreOp: 'clear', + stencilLoadValue: 'load' + } + }).endPass(); + } + } + + this.queue.submit([commandEncoder.finish()]); + } + + static generateParams(readMethods) { + return (// TODO: Consider making a list of "valid" texture descriptors in capability_info. + params().combine(poptions('format', kTextureFormats)).combine(poptions('aspect', kTextureAspects)).unless(({ + format, + aspect + }) => aspect === 'depth-only' && !kTextureFormatInfo[format].depth || aspect === 'stencil-only' && !kTextureFormatInfo[format].stencil).combine(poptions('mipLevelCount', kMipLevelCounts)).combine(poptions('sampleCount', kSampleCounts)) // Multisampled textures may only have one mip + .unless(({ + sampleCount, + mipLevelCount + }) => sampleCount > 1 && mipLevelCount > 1).combine(poptions('uninitializeMethod', kUninitializeMethods)).combine(poptions('readMethod', readMethods)).unless(({ + readMethod, + format + }) => // It doesn't make sense to copy from a packed depth format. + // This is not specified yet, but it will probably be disallowed as the bits may + // be vendor-specific. + // TODO: Test copying out of the stencil aspect. + (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) && (format === 'depth24plus' || format === 'depth24plus-stencil8')).unless(({ + readMethod, + format + }) => readMethod === ReadMethod.DepthTest && !kTextureFormatInfo[format].depth || readMethod === ReadMethod.StencilTest && !kTextureFormatInfo[format].stencil || readMethod === ReadMethod.ColorBlending && !kTextureFormatInfo[format].color || // TODO: Test with depth sampling + readMethod === ReadMethod.Sample && kTextureFormatInfo[format].depth).unless(({ + readMethod, + sampleCount + }) => // We can only read from multisampled textures by sampling. + sampleCount > 1 && (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture)).combine(kCreationSizes) // Multisampled 3D / 2D array textures not supported. + .unless(({ + sampleCount, + sliceCount + }) => sampleCount > 1 && sliceCount > 1).filter(({ + format, + sampleCount, + uninitializeMethod, + readMethod + }) => { + const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod); + + if (usage & C.TextureUsage.OutputAttachment && !kTextureFormatInfo[format].renderable) { + return false; + } + + if (usage & C.TextureUsage.Storage && !kTextureFormatInfo[format].storage) { + return false; + } + + return true; + }).combine(pbool('nonPowerOfTwo')) + ); + } + + run() { + const { + format, + dimension, + mipLevelCount, + sliceCount, + sampleCount, + uninitializeMethod, + readMethod + } = this.params; + const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod); + const texture = this.device.createTexture({ + size: [this.textureWidth, this.textureHeight, sliceCount], + format, + dimension, + usage, + mipLevelCount, + sampleCount + }); // Initialize some subresources with canary values + + for (const subresourceRange of this.iterateInitializedSubresources()) { + this.initializeTexture(texture, InitializedState.Canary, subresourceRange); + } + + switch (uninitializeMethod) { + case UninitializeMethod.Creation: + break; + + case UninitializeMethod.StoreOpClear: + // Initialize the rest of the resources. + for (const subresourceRange of this.iterateUninitializedSubresources()) { + this.initializeTexture(texture, InitializedState.Canary, subresourceRange); + } // Then use a store op to discard their contents. + + + for (const subresourceRange of this.iterateUninitializedSubresources()) { + this.discardTexture(texture, subresourceRange); + } + + break; + + default: + unreachable(); + } // Check that all uninitialized resources are zero. + + + for (const subresourceRange of this.iterateUninitializedSubresources()) { + this.checkContents(texture, InitializedState.Zero, subresourceRange); + } // Check the all other resources are unchanged. + + + for (const subresourceRange of this.iterateInitializedSubresources()) { + this.checkContents(texture, InitializedState.Canary, subresourceRange); + } + } + +} +//# sourceMappingURL=texture_zero_init_test.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroup.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroup.spec.js index 97683cf75a9..1eb8f959f33 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroup.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroup.spec.js @@ -6,18 +6,18 @@ export const description = ` createBindGroup validation tests. `; import * as C from '../../../common/constants.js'; -import { pcombine, poptions } from '../../../common/framework/params.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { poptions, params } from '../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { unreachable } from '../../../common/framework/util/util.js'; -import { kBindingTypes } from '../../capability_info.js'; -import { BindingResourceType, ValidationTest, resourceBindingMatches } from './validation_test.js'; +import { kBindingTypes, kBindingTypeInfo, kBindableResources, kTextureUsages, kTextureBindingTypes, kTextureBindingTypeInfo } from '../../capability_info.js'; +import { ValidationTest } from './validation_test.js'; function clone(descriptor) { return JSON.parse(JSON.stringify(descriptor)); } -export const g = new TestGroup(ValidationTest); -g.test('binding count mismatch', async t => { +export const g = makeTestGroup(ValidationTest); +g.test('binding_count_mismatch').fn(async t => { const bindGroupLayout = t.device.createBindGroupLayout({ entries: [{ binding: 0, @@ -56,7 +56,7 @@ g.test('binding count mismatch', async t => { t.device.createBindGroup(badDescriptor); }); }); -g.test('binding must be present in layout', async t => { +g.test('binding_must_be_present_in_layout').fn(async t => { const bindGroupLayout = t.device.createBindGroupLayout({ entries: [{ binding: 0, @@ -89,18 +89,23 @@ g.test('binding must be present in layout', async t => { t.device.createBindGroup(badDescriptor); }); }); -g.test('buffer binding must contain exactly one buffer of its type', t => { - const bindingType = t.params.bindingType; - const resourceType = t.params.resourceType; +g.test('buffer_binding_must_contain_exactly_one_buffer_of_its_type').params(params().combine(poptions('bindingType', kBindingTypes)).combine(poptions('resourceType', kBindableResources))).fn(t => { + const { + bindingType, + resourceType + } = t.params; + const info = kBindingTypeInfo[bindingType]; + const storageTextureFormat = info.resource === 'storageTex' ? 'rgba8unorm' : undefined; const layout = t.device.createBindGroupLayout({ entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, - type: bindingType + type: bindingType, + storageTextureFormat }] }); const resource = t.getBindingResource(resourceType); - const shouldError = !resourceBindingMatches(bindingType, resourceType); + const resourceBindingMatches = info.resource === resourceType; t.expectValidationError(() => { t.device.createBindGroup({ layout, @@ -109,73 +114,44 @@ g.test('buffer binding must contain exactly one buffer of its type', t => { resource }] }); - }, shouldError); -}).params(pcombine(poptions('bindingType', kBindingTypes), poptions('resourceType', Object.keys(BindingResourceType)))); -g.test('texture binding must have correct usage', async t => { - const type = t.params.type; - const usage = t.params._usage; + }, !resourceBindingMatches); +}); +g.test('texture_binding_must_have_correct_usage').params(params().combine(poptions('type', kTextureBindingTypes)).combine(poptions('usage', kTextureUsages))).fn(async t => { + const { + type, + usage + } = t.params; + const info = kTextureBindingTypeInfo[type]; + const storageTextureFormat = info.resource === 'storageTex' ? 'rgba8unorm' : undefined; const bindGroupLayout = t.device.createBindGroupLayout({ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, - type + type, + storageTextureFormat }] }); - const goodDescriptor = { + const descriptor = { size: { width: 16, height: 16, depth: 1 }, - format: C.TextureFormat.R8Unorm, + format: C.TextureFormat.RGBA8Unorm, usage - }; // Control case - - t.device.createBindGroup({ - entries: [{ - binding: 0, - resource: t.device.createTexture(goodDescriptor).createView() - }], - layout: bindGroupLayout - }); - - function* mismatchedTextureUsages() { - yield GPUTextureUsage.COPY_SRC; - yield GPUTextureUsage.COPY_DST; - - if (type !== 'sampled-texture') { - yield GPUTextureUsage.SAMPLED; - } - - if (type !== 'readonly-storage-texture' && type !== 'writeonly-storage-texture') { - yield GPUTextureUsage.STORAGE; - } - - yield GPUTextureUsage.OUTPUT_ATTACHMENT; - } // Mismatched texture binding usages are not valid. - - - for (const mismatchedTextureUsage of mismatchedTextureUsages()) { - const badDescriptor = clone(goodDescriptor); - badDescriptor.usage = mismatchedTextureUsage; - t.expectValidationError(() => { - t.device.createBindGroup({ - entries: [{ - binding: 0, - resource: t.device.createTexture(badDescriptor).createView() - }], - layout: bindGroupLayout - }); + }; + const shouldError = usage !== info.usage; + t.expectValidationError(() => { + t.device.createBindGroup({ + entries: [{ + binding: 0, + resource: t.device.createTexture(descriptor).createView() + }], + layout: bindGroupLayout }); - } -}).params([{ - type: 'sampled-texture', - _usage: C.TextureUsage.Sampled -}, { - type: 'storage-texture', - _usage: C.TextureUsage.Storage -}]); -g.test('texture must have correct component type', async t => { + }, shouldError); +}); +g.test('texture_must_have_correct_component_type').params(poptions('textureComponentType', [C.TextureComponentType.Float, C.TextureComponentType.Sint, C.TextureComponentType.Uint])).fn(async t => { const { textureComponentType } = t.params; @@ -246,9 +222,9 @@ g.test('texture must have correct component type', async t => { }); }); } -}).params(poptions('textureComponentType', ['float', 'sint', 'uint'])); // TODO: Write test for all dimensions. +}); // TODO: Write test for all dimensions. -g.test('texture must have correct dimension', async t => { +g.test('texture_must_have_correct_dimension').fn(async t => { const bindGroupLayout = t.device.createBindGroupLayout({ entries: [{ binding: 0, @@ -287,45 +263,7 @@ g.test('texture must have correct dimension', async t => { }); }); }); -g.test('buffer offset and size for bind groups match', async t => { - const { - offset, - size, - _success - } = t.params; - const bindGroupLayout = t.device.createBindGroupLayout({ - entries: [{ - binding: 0, - visibility: GPUShaderStage.COMPUTE, - type: 'storage-buffer' - }] - }); - const buffer = t.device.createBuffer({ - size: 1024, - usage: GPUBufferUsage.STORAGE - }); - const descriptor = { - entries: [{ - binding: 0, - resource: { - buffer, - offset, - size - } - }], - layout: bindGroupLayout - }; - - if (_success) { - // Control case - t.device.createBindGroup(descriptor); - } else { - // Buffer offset and/or size don't match in bind groups. - t.expectValidationError(() => { - t.device.createBindGroup(descriptor); - }); - } -}).params([{ +g.test('buffer_offset_and_size_for_bind_groups_match').params([{ offset: 0, size: 512, _success: true @@ -402,5 +340,43 @@ g.test('buffer offset and size for bind groups match', async t => { size: 1, _success: false } // offset+size is OOB -]); +]).fn(async t => { + const { + offset, + size, + _success + } = t.params; + const bindGroupLayout = t.device.createBindGroupLayout({ + entries: [{ + binding: 0, + visibility: GPUShaderStage.COMPUTE, + type: 'storage-buffer' + }] + }); + const buffer = t.device.createBuffer({ + size: 1024, + usage: GPUBufferUsage.STORAGE + }); + const descriptor = { + entries: [{ + binding: 0, + resource: { + buffer, + offset, + size + } + }], + layout: bindGroupLayout + }; + + if (_success) { + // Control case + t.device.createBindGroup(descriptor); + } else { + // Buffer offset and/or size don't match in bind groups. + t.expectValidationError(() => { + t.device.createBindGroup(descriptor); + }); + } +}); //# sourceMappingURL=createBindGroup.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js index b03e0159113..3961ba3a81a 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js @@ -6,17 +6,17 @@ export const description = ` createBindGroupLayout validation tests. `; import * as C from '../../../common/constants.js'; -import { poptions } from '../../../common/framework/params.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; -import { kBindingTypeInfo, kBindingTypes, kMaxBindingsPerBindGroup, kPerStageBindingLimits, kShaderStages } from '../../capability_info.js'; +import { poptions, params } from '../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { kBindingTypeInfo, kBindingTypes, kMaxBindingsPerBindGroup, kShaderStages } from '../../capability_info.js'; import { ValidationTest } from './validation_test.js'; function clone(descriptor) { return JSON.parse(JSON.stringify(descriptor)); } -export const g = new TestGroup(ValidationTest); -g.test('some binding index was specified more than once', async t => { +export const g = makeTestGroup(ValidationTest); +g.test('some_binding_index_was_specified_more_than_once').fn(async t => { const goodDescriptor = { entries: [{ binding: 0, @@ -37,7 +37,7 @@ g.test('some binding index was specified more than once', async t => { t.device.createBindGroupLayout(badDescriptor); }); }); -g.test('Visibility of bindings can be 0', async t => { +g.test('visibility_of_bindings_can_be_0').fn(async t => { t.device.createBindGroupLayout({ entries: [{ binding: 0, @@ -46,7 +46,13 @@ g.test('Visibility of bindings can be 0', async t => { }] }); }); -g.test('number of dynamic buffers exceeds the maximum value', async t => { +g.test('number_of_dynamic_buffers_exceeds_the_maximum_value').params([{ + type: C.BindingType.StorageBuffer, + maxDynamicBufferCount: 4 +}, { + type: C.BindingType.UniformBuffer, + maxDynamicBufferCount: 8 +}]).fn(async t => { const { type, maxDynamicBufferCount @@ -78,16 +84,12 @@ g.test('number of dynamic buffers exceeds the maximum value', async t => { t.expectValidationError(() => { t.device.createBindGroupLayout(badDescriptor); }); -}).params([{ - type: C.BindingType.StorageBuffer, - maxDynamicBufferCount: 4 -}, { - type: C.BindingType.UniformBuffer, - maxDynamicBufferCount: 8 -}]); -g.test('dynamic set to true is allowed only for buffers', async t => { - const type = t.params.type; - const success = kBindingTypeInfo[type].type === 'buffer'; +}); +g.test('dynamic_set_to_true_is_allowed_only_for_buffers').params(poptions('type', kBindingTypes)).fn(async t => { + const { + type + } = t.params; + const success = kBindingTypeInfo[type].perPipelineLimitClass.maxDynamic > 0; const descriptor = { entries: [{ binding: 0, @@ -99,71 +101,53 @@ g.test('dynamic set to true is allowed only for buffers', async t => { t.expectValidationError(() => { t.device.createBindGroupLayout(descriptor); }, !success); -}).params(poptions('type', kBindingTypes)); -let kCasesForMaxResourcesPerStageTests; -{ - // One bind group layout will be filled with kPerStageBindingLimit[...] of the type |type|. - // For each item in the array returned here, a case will be generated which tests a pipeline - // layout with one extra bind group layout with one extra binding. That extra binding will have: - // - // - If extraTypeSame, any of the binding types which counts toward the same limit as |type|. - // (i.e. 'storage-buffer' <-> 'readonly-storage-buffer'). - // - Otherwise, an arbitrary other type. - function* pickExtraBindingTypes(bindingType, extraTypeSame) { - const info = kBindingTypeInfo[bindingType]; - - if (extraTypeSame) { - for (const extraBindingType of kBindingTypes) { - if (info.perStageLimitType === kBindingTypeInfo[extraBindingType].perStageLimitType) { - yield extraBindingType; - } +}); // One bind group layout will be filled with kPerStageBindingLimit[...] of the type |type|. +// For each item in the array returned here, a case will be generated which tests a pipeline +// layout with one extra bind group layout with one extra binding. That extra binding will have: +// +// - If extraTypeSame, any of the binding types which counts toward the same limit as |type|. +// (i.e. 'storage-buffer' <-> 'readonly-storage-buffer'). +// - Otherwise, an arbitrary other type. + +function* pickExtraBindingTypes(bindingType, extraTypeSame) { + const info = kBindingTypeInfo[bindingType]; + + if (extraTypeSame) { + for (const extraBindingType of kBindingTypes) { + if (info.perStageLimitClass.class === kBindingTypeInfo[extraBindingType].perStageLimitClass.class) { + yield extraBindingType; } - } else { - yield info.perStageLimitType === 'sampler' ? 'sampled-texture' : 'sampler'; } + } else { + yield info.perStageLimitClass.class === 'sampler' ? 'sampled-texture' : 'sampler'; } +} - kCasesForMaxResourcesPerStageTests = []; - - for (const maxedType of kBindingTypes) { - for (const maxedVisibility of kShaderStages) { - // Don't generate a case where maxedType isn't valid in maxedVisibility. - if (!(kBindingTypeInfo[maxedType].validStages & maxedVisibility)) continue; - - for (const extraTypeSame of [true, false]) { - for (const extraType of pickExtraBindingTypes(maxedType, extraTypeSame)) { - for (const extraVisibility of kShaderStages) { - // Don't generate a case where extraType isn't valid in extraVisibility. - if (!(kBindingTypeInfo[extraType].validStages & extraVisibility)) continue; - kCasesForMaxResourcesPerStageTests.push({ - maxedType, - maxedVisibility, - extraType, - extraVisibility - }); - } - } - } - } +const kCasesForMaxResourcesPerStageTests = params().combine(poptions('maxedType', kBindingTypes)).combine(poptions('maxedVisibility', kShaderStages)).filter(p => (kBindingTypeInfo[p.maxedType].validStages & p.maxedVisibility) !== 0).expand(function* (p) { + for (const extraTypeSame of [true, false]) { + yield* poptions('extraType', pickExtraBindingTypes(p.maxedType, extraTypeSame)); } -} // Should never fail unless kMaxBindingsPerBindGroup is exceeded, because the validation for +}).combine(poptions('extraVisibility', kShaderStages)).filter(p => (kBindingTypeInfo[p.extraType].validStages & p.extraVisibility) !== 0); // Should never fail unless kMaxBindingsPerBindGroup is exceeded, because the validation for // resources-of-type-per-stage is in pipeline layout creation. -g.test('max resources per stage/in bind group layout', async t => { - const maxedType = t.params.maxedType; - const extraType = t.params.extraType; +g.test('max_resources_per_stage,in_bind_group_layout').params(kCasesForMaxResourcesPerStageTests).fn(async t => { const { + maxedType, + extraType, maxedVisibility, extraVisibility } = t.params; - const maxedCount = kPerStageBindingLimits[kBindingTypeInfo[maxedType].perStageLimitType]; + const maxedTypeInfo = kBindingTypeInfo[maxedType]; + const maxedCount = maxedTypeInfo.perStageLimitClass.max; + const extraTypeInfo = kBindingTypeInfo[extraType]; const maxResourceBindings = []; for (let i = 0; i < maxedCount; i++) { maxResourceBindings.push({ binding: i, visibility: maxedVisibility, - type: maxedType + type: maxedType, + storageTextureFormat: maxedTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined }); } @@ -176,31 +160,35 @@ g.test('max resources per stage/in bind group layout', async t => { newDescriptor.entries.push({ binding: maxedCount, visibility: extraVisibility, - type: extraType + type: extraType, + storageTextureFormat: extraTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined }); const shouldError = maxedCount >= kMaxBindingsPerBindGroup; t.expectValidationError(() => { t.device.createBindGroupLayout(newDescriptor); }, shouldError); -}).params(kCasesForMaxResourcesPerStageTests); // One pipeline layout can have a maximum number of each type of binding *per stage* (which is +}); // One pipeline layout can have a maximum number of each type of binding *per stage* (which is // different for each type). Test that the max works, then add one more binding of same-or-different // type and same-or-different visibility. -g.test('max resources per stage/in pipeline layout', async t => { - const maxedType = t.params.maxedType; - const extraType = t.params.extraType; +g.test('max_resources_per_stage,in_pipeline_layout').params(kCasesForMaxResourcesPerStageTests).fn(async t => { const { + maxedType, + extraType, maxedVisibility, extraVisibility } = t.params; - const maxedCount = kPerStageBindingLimits[kBindingTypeInfo[maxedType].perStageLimitType]; + const maxedTypeInfo = kBindingTypeInfo[maxedType]; + const maxedCount = maxedTypeInfo.perStageLimitClass.max; + const extraTypeInfo = kBindingTypeInfo[extraType]; const maxResourceBindings = []; for (let i = 0; i < maxedCount; i++) { maxResourceBindings.push({ binding: i, visibility: maxedVisibility, - type: maxedType + type: maxedType, + storageTextureFormat: maxedTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined }); } @@ -215,16 +203,17 @@ g.test('max resources per stage/in pipeline layout', async t => { entries: [{ binding: 0, visibility: extraVisibility, - type: extraType + type: extraType, + storageTextureFormat: extraTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined }] }); // Some binding types use the same limit, e.g. 'storage-buffer' and 'readonly-storage-buffer'. - const newBindingCountsTowardSamePerStageLimit = (maxedVisibility & extraVisibility) !== 0 && kBindingTypeInfo[maxedType].perStageLimitType === kBindingTypeInfo[extraType].perStageLimitType; + const newBindingCountsTowardSamePerStageLimit = (maxedVisibility & extraVisibility) !== 0 && kBindingTypeInfo[maxedType].perStageLimitClass.class === kBindingTypeInfo[extraType].perStageLimitClass.class; const layoutExceedsPerStageLimit = newBindingCountsTowardSamePerStageLimit; t.expectValidationError(() => { t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout, extraLayout] }); }, layoutExceedsPerStageLimit); -}).params(kCasesForMaxResourcesPerStageTests); +}); //# sourceMappingURL=createBindGroupLayout.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js index f1582c4478a..262581e8714 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createPipelineLayout.spec.js @@ -5,8 +5,9 @@ export const description = ` createPipelineLayout validation tests. `; -import { pbool, pcombine, poptions } from '../../../common/framework/params.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; +import * as C from '../../../common/constants.js'; +import { pbool, poptions, params } from '../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { kBindingTypeInfo, kBindingTypes, kShaderStageCombinations } from '../../capability_info.js'; import { ValidationTest } from './validation_test.js'; @@ -14,16 +15,18 @@ function clone(descriptor) { return JSON.parse(JSON.stringify(descriptor)); } -export const g = new TestGroup(ValidationTest); -g.test('number of dynamic buffers exceeds the maximum value', async t => { +export const g = makeTestGroup(ValidationTest); +g.test('number_of_dynamic_buffers_exceeds_the_maximum_value').params(params().combine(poptions('visibility', [0, 2, 4, 6])).combine(poptions('type', [C.BindingType.UniformBuffer, C.BindingType.StorageBuffer, C.BindingType.ReadonlyStorageBuffer]))).fn(async t => { const { type, visibility } = t.params; - const maxDynamicCount = kBindingTypeInfo[type].maxDynamicCount; + const { + maxDynamic + } = kBindingTypeInfo[type].perPipelineLimitClass; const maxDynamicBufferBindings = []; - for (let binding = 0; binding < maxDynamicCount; binding++) { + for (let binding = 0; binding < maxDynamic; binding++) { maxDynamicBufferBindings.push({ binding, visibility, @@ -57,12 +60,13 @@ g.test('number of dynamic buffers exceeds the maximum value', async t => { t.expectValidationError(() => { t.device.createPipelineLayout(badPipelineLayoutDescriptor); }); -}).params(pcombine(poptions('visibility', [0, 2, 4, 6]), // -poptions('type', ['uniform-buffer', 'storage-buffer', 'readonly-storage-buffer']))); -g.test('visibility and dynamic offsets', t => { - const hasDynamicOffset = t.params.hasDynamicOffset; - const type = t.params.type; - const visibility = t.params.visibility; +}); +g.test('visibility_and_dynamic_offsets').params(params().combine(poptions('type', kBindingTypes)).combine(pbool('hasDynamicOffset')).combine(poptions('visibility', kShaderStageCombinations))).fn(t => { + const { + type, + hasDynamicOffset, + visibility + } = t.params; const info = kBindingTypeInfo[type]; const descriptor = { entries: [{ @@ -72,17 +76,17 @@ g.test('visibility and dynamic offsets', t => { hasDynamicOffset }] }; + const supportsDynamicOffset = kBindingTypeInfo[type].perPipelineLimitClass.maxDynamic > 0; let success = true; - if (info.type !== 'buffer' && hasDynamicOffset) success = false; + if (!supportsDynamicOffset && hasDynamicOffset) success = false; if ((visibility & ~info.validStages) !== 0) success = false; t.expectValidationError(() => { t.device.createPipelineLayout({ bindGroupLayouts: [t.device.createBindGroupLayout(descriptor)] }); }, !success); -}).params(pcombine(poptions('type', kBindingTypes), // -pbool('hasDynamicOffset'), poptions('visibility', kShaderStageCombinations))); -g.test('number of bind group layouts exceeds the maximum value', async t => { +}); +g.test('number_of_bind_group_layouts_exceeds_the_maximum_value').fn(async t => { const bindGroupLayoutDescriptor = { entries: [] }; // 4 is the maximum number of bind group layouts. diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createTexture.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createTexture.spec.js index ab4c6f866b4..2ef8d195233 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createTexture.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createTexture.spec.js @@ -5,8 +5,8 @@ export const description = ` createTexture validation tests. `; -import { poptions } from '../../../common/framework/params.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { poptions } from '../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { kTextureFormatInfo, kTextureFormats } from '../../capability_info.js'; import { ValidationTest } from './validation_test.js'; @@ -36,23 +36,9 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('validation of sampleCount', async t => { - const { - sampleCount, - mipLevelCount, - arrayLayerCount, - _success - } = t.params; - const descriptor = t.getDescriptor({ - sampleCount, - mipLevelCount, - arrayLayerCount - }); - t.expectValidationError(() => { - t.device.createTexture(descriptor); - }, !_success); -}).params([{ +export const g = makeTestGroup(F); +g.test('validation_of_sampleCount').params([// TODO: Consider making a list of "valid"+"invalid" texture descriptors in capability_info. +{ sampleCount: 0, _success: false }, // sampleCount of 0 is not allowed @@ -84,29 +70,29 @@ g.test('validation of sampleCount', async t => { sampleCount: 4, mipLevelCount: 2, _success: false -}, // it is an error to create a multisampled texture with mipLevelCount > 1 +}, // multisampled multi-level not allowed { sampleCount: 4, arrayLayerCount: 2, - _success: true -} // multisampled 2D array texture is supported -]); -g.test('validation of mipLevelCount', async t => { + _success: false +} // multisampled multi-layer is not allowed +]).fn(async t => { const { - width, - height, + sampleCount, mipLevelCount, + arrayLayerCount, _success } = t.params; const descriptor = t.getDescriptor({ - width, - height, - mipLevelCount + sampleCount, + mipLevelCount, + arrayLayerCount }); t.expectValidationError(() => { t.device.createTexture(descriptor); }, !_success); -}).params([{ +}); +g.test('validation_of_mipLevelCount').params([{ width: 32, height: 32, mipLevelCount: 1, @@ -160,19 +146,46 @@ g.test('validation of mipLevelCount', async t => { mipLevelCount: 6, _success: true } // non square mip map halves the resolution until a 1x1 dimension. (Mip maps: 32 * 8, 16 * 4, 8 * 2, 4 * 1, 2 * 1, 1 * 1) -]); -g.test('it is valid to destroy a texture', t => { +]).fn(async t => { + const { + width, + height, + mipLevelCount, + _success + } = t.params; + const descriptor = t.getDescriptor({ + width, + height, + mipLevelCount + }); + t.expectValidationError(() => { + t.device.createTexture(descriptor); + }, !_success); +}); +g.test('it_is_valid_to_destroy_a_texture').fn(t => { const descriptor = t.getDescriptor(); const texture = t.device.createTexture(descriptor); texture.destroy(); }); -g.test('it is valid to destroy a destroyed texture', t => { +g.test('it_is_valid_to_destroy_a_destroyed_texture').fn(t => { const descriptor = t.getDescriptor(); const texture = t.device.createTexture(descriptor); texture.destroy(); texture.destroy(); }); -g.test('it is invalid to submit a destroyed texture before and after encode', async t => { +g.test('it_is_invalid_to_submit_a_destroyed_texture_before_and_after_encode').params([{ + destroyBeforeEncode: false, + destroyAfterEncode: false, + _success: true +}, { + destroyBeforeEncode: true, + destroyAfterEncode: false, + _success: false +}, { + destroyBeforeEncode: false, + destroyAfterEncode: true, + _success: false +}]).fn(async t => { const { destroyBeforeEncode, destroyAfterEncode, @@ -208,20 +221,8 @@ g.test('it is invalid to submit a destroyed texture before and after encode', as t.expectValidationError(() => { t.queue.submit([commandBuffer]); }, !_success); -}).params([{ - destroyBeforeEncode: false, - destroyAfterEncode: false, - _success: true -}, { - destroyBeforeEncode: true, - destroyAfterEncode: false, - _success: false -}, { - destroyBeforeEncode: false, - destroyAfterEncode: true, - _success: false -}]); -g.test('it is invalid to have an output attachment texture with non renderable format', async t => { +}); +g.test('it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format').params(poptions('format', kTextureFormats)).fn(async t => { const format = t.params.format; const info = kTextureFormatInfo[format]; const descriptor = t.getDescriptor({ @@ -232,5 +233,5 @@ g.test('it is invalid to have an output attachment texture with non renderable f t.expectValidationError(() => { t.device.createTexture(descriptor); }, !info.renderable); -}).params(poptions('format', kTextureFormats)); // TODO: Add tests for compressed texture formats +}); // TODO: Add tests for compressed texture formats //# sourceMappingURL=createTexture.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createView.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createView.spec.js index d23af583874..524d921adaa 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createView.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/createView.spec.js @@ -5,7 +5,8 @@ export const description = ` createView validation tests. `; -import { TestGroup } from '../../../common/framework/test_group.js'; +import * as C from '../../../common/constants.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; const ARRAY_LAYER_COUNT_2D = 6; const MIP_LEVEL_COUNT = 6; @@ -55,28 +56,8 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('creating texture view on a 2D non array texture', async t => { - const { - dimension = '2d', - arrayLayerCount, - mipLevelCount, - baseMipLevel, - _success - } = t.params; - const texture = t.createTexture({ - arrayLayerCount: 1 - }); - const descriptor = t.getDescriptor({ - dimension, - arrayLayerCount, - mipLevelCount, - baseMipLevel - }); - t.expectValidationError(() => { - texture.createView(descriptor); - }, !_success); -}).params([{ +export const g = makeTestGroup(F); +g.test('creating_texture_view_on_a_2D_non_array_texture').params([{ _success: true }, // default view works { @@ -88,7 +69,7 @@ g.test('creating texture view on a 2D non array texture', async t => { _success: false }, // it is an error to view a layer past the end of the texture { - dimension: '2d-array', + dimension: C.TextureViewDimension.E2dArray, arrayLayerCount: 1, _success: true }, // it is OK to create a 1-layer 2D array texture view on a 2D texture @@ -135,30 +116,32 @@ g.test('creating texture view on a 2D non array texture', async t => { mipLevelCount: 1, baseMipLevel: MIP_LEVEL_COUNT, _success: false -}]); -g.test('creating texture view on a 2D array texture', async t => { +}]).fn(async t => { const { - dimension = '2d-array', + dimension = '2d', arrayLayerCount, - baseArrayLayer, + mipLevelCount, + baseMipLevel, _success } = t.params; const texture = t.createTexture({ - arrayLayerCount: ARRAY_LAYER_COUNT_2D + arrayLayerCount: 1 }); const descriptor = t.getDescriptor({ dimension, arrayLayerCount, - baseArrayLayer + mipLevelCount, + baseMipLevel }); t.expectValidationError(() => { texture.createView(descriptor); }, !_success); -}).params([{ +}); +g.test('creating_texture_view_on_a_2D_array_texture').params([{ _success: true }, // default view works { - dimension: '2d', + dimension: C.TextureViewDimension.E2d, arrayLayerCount: 1, _success: true }, // it is OK to create a 2D texture view on a 2D array texture @@ -200,40 +183,38 @@ g.test('creating texture view on a 2D array texture', async t => { arrayLayerCount: 1, baseArrayLayer: ARRAY_LAYER_COUNT_2D, _success: false -}]); -g.test('Using defaults validates the same as setting values for more than 1 array layer', async t => { +}]).fn(async t => { const { - format, - dimension, + dimension = '2d-array', arrayLayerCount, - mipLevelCount, + baseArrayLayer, _success } = t.params; const texture = t.createTexture({ arrayLayerCount: ARRAY_LAYER_COUNT_2D }); - const descriptor = { - format, + const descriptor = t.getDescriptor({ dimension, arrayLayerCount, - mipLevelCount - }; + baseArrayLayer + }); t.expectValidationError(() => { texture.createView(descriptor); }, !_success); -}).params([{ +}); +g.test('Using_defaults_validates_the_same_as_setting_values_for_more_than_1_array_layer').params([{ _success: true }, { - format: 'rgba8unorm', + format: C.TextureFormat.RGBA8Unorm, _success: true }, { - format: 'r8unorm', + format: C.TextureFormat.R8Unorm, _success: false }, { - dimension: '2d-array', + dimension: C.TextureViewDimension.E2dArray, _success: true }, { - dimension: '2d', + dimension: C.TextureViewDimension.E2d, _success: false }, { arrayLayerCount: ARRAY_LAYER_COUNT_2D, @@ -241,15 +222,14 @@ g.test('Using defaults validates the same as setting values for more than 1 arra }, // setting array layers to non-0 means the dimensionality will default to 2D so by itself it causes an error. { arrayLayerCount: ARRAY_LAYER_COUNT_2D, - dimension: '2d-array', + dimension: C.TextureViewDimension.E2dArray, _success: true }, { arrayLayerCount: ARRAY_LAYER_COUNT_2D, - dimension: '2d-array', + dimension: C.TextureViewDimension.E2dArray, mipLevelCount: MIP_LEVEL_COUNT, _success: true -}]); -g.test('Using defaults validates the same as setting values for only 1 array layer', async t => { +}]).fn(async t => { const { format, dimension, @@ -258,7 +238,7 @@ g.test('Using defaults validates the same as setting values for only 1 array lay _success } = t.params; const texture = t.createTexture({ - arrayLayerCount: 1 + arrayLayerCount: ARRAY_LAYER_COUNT_2D }); const descriptor = { format, @@ -269,19 +249,20 @@ g.test('Using defaults validates the same as setting values for only 1 array lay t.expectValidationError(() => { texture.createView(descriptor); }, !_success); -}).params([{ +}); +g.test('Using_defaults_validates_the_same_as_setting_values_for_only_1_array_layer').params([{ _success: true }, { - format: 'rgba8unorm', + format: C.TextureFormat.RGBA8Unorm, _success: true }, { - format: 'r8unorm', + format: C.TextureFormat.R8Unorm, _success: false }, { - dimension: '2d-array', + dimension: C.TextureViewDimension.E2dArray, _success: true }, { - dimension: '2d', + dimension: C.TextureViewDimension.E2d, _success: true }, { arrayLayerCount: 0, @@ -298,60 +279,88 @@ g.test('Using defaults validates the same as setting values for only 1 array lay }, { mipLevelCount: 1, _success: true -}]); -g.test('creating cube map texture view', async t => { +}]).fn(async t => { const { - dimension = '2d-array', + format, + dimension, arrayLayerCount, + mipLevelCount, _success } = t.params; const texture = t.createTexture({ - arrayLayerCount: 16 + arrayLayerCount: 1 }); - const descriptor = t.getDescriptor({ + const descriptor = { + format, dimension, - arrayLayerCount - }); + arrayLayerCount, + mipLevelCount + }; t.expectValidationError(() => { texture.createView(descriptor); }, !_success); -}).params([{ - dimension: 'cube', +}); +g.test('creating_cube_map_texture_view').params([{ + dimension: C.TextureViewDimension.Cube, arrayLayerCount: 6, _success: true }, // it is OK to create a cube map texture view with arrayLayerCount == 6 // it is an error to create a cube map texture view with arrayLayerCount != 6 { - dimension: 'cube', + dimension: C.TextureViewDimension.Cube, arrayLayerCount: 3, _success: false }, { - dimension: 'cube', + dimension: C.TextureViewDimension.Cube, arrayLayerCount: 7, _success: false }, { - dimension: 'cube', + dimension: C.TextureViewDimension.Cube, arrayLayerCount: 12, _success: false }, { - dimension: 'cube', + dimension: C.TextureViewDimension.Cube, _success: false }, { - dimension: 'cube-array', + dimension: C.TextureViewDimension.CubeArray, arrayLayerCount: 12, _success: true }, // it is OK to create a cube map array texture view with arrayLayerCount % 6 == 0 // it is an error to create a cube map array texture view with arrayLayerCount % 6 != 0 { - dimension: 'cube-array', + dimension: C.TextureViewDimension.CubeArray, arrayLayerCount: 11, _success: false }, { - dimension: 'cube-array', + dimension: C.TextureViewDimension.CubeArray, arrayLayerCount: 13, _success: false -}]); -g.test('creating cube map texture view with a non square texture', async t => { +}]).fn(async t => { + const { + dimension = '2d-array', + arrayLayerCount, + _success + } = t.params; + const texture = t.createTexture({ + arrayLayerCount: 16 + }); + const descriptor = t.getDescriptor({ + dimension, + arrayLayerCount + }); + t.expectValidationError(() => { + texture.createView(descriptor); + }, !_success); +}); +g.test('creating_cube_map_texture_view_with_a_non_square_texture').params([{ + dimension: C.TextureViewDimension.Cube, + arrayLayerCount: 6 +}, // it is an error to create a cube map texture view with width != height. +{ + dimension: C.TextureViewDimension.CubeArray, + arrayLayerCount: 12 +} // it is an error to create a cube map array texture view with width != height. +]).fn(async t => { const { dimension, arrayLayerCount @@ -369,17 +378,9 @@ g.test('creating cube map texture view with a non square texture', async t => { t.expectValidationError(() => { nonSquareTexture.createView(descriptor); }); -}).params([{ - dimension: 'cube', - arrayLayerCount: 6 -}, // it is an error to create a cube map texture view with width != height. -{ - dimension: 'cube-array', - arrayLayerCount: 12 -} // it is an error to create a cube map array texture view with width != height. -]); // TODO: add more tests when rules are fully implemented. +}); // TODO: add more tests when rules are fully implemented. -g.test('test the format compatibility rules when creating a texture view', async t => { +g.test('test_the_format_compatibility_rules_when_creating_a_texture_view').fn(async t => { const texture = t.createTexture({ arrayLayerCount: 1 }); @@ -391,7 +392,7 @@ g.test('test the format compatibility rules when creating a texture view', async texture.createView(descriptor); }); }); -g.test('it is invalid to use a texture view created from a destroyed texture', async t => { +g.test('it_is_invalid_to_use_a_texture_view_created_from_a_destroyed_texture').fn(async t => { const texture = t.createTexture({ arrayLayerCount: 1 }); diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/error_scope.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/error_scope.spec.js index fd69c4e13c0..3edbec2dc41 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/error_scope.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/error_scope.spec.js @@ -9,7 +9,7 @@ error scope validation tests. `; import { Fixture } from '../../../common/framework/fixture.js'; import { getGPU } from '../../../common/framework/gpu/implementation.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { assert, raceWithRejectOnTimeout } from '../../../common/framework/util/util.js'; class F extends Fixture { @@ -64,14 +64,14 @@ class F extends Fixture { } -export const g = new TestGroup(F); -g.test('simple case where the error scope catches an error', async t => { +export const g = makeTestGroup(F); +g.test('simple_case_where_the_error_scope_catches_an_error').fn(async t => { t.device.pushErrorScope('validation'); t.createErrorBuffer(); const error = await t.device.popErrorScope(); t.expect(error instanceof GPUValidationError); }); -g.test('errors bubble to the parent scope if not handled by the current scope', async t => { +g.test('errors_bubble_to_the_parent_scope_if_not_handled_by_the_current_scope').fn(async t => { t.device.pushErrorScope('validation'); t.device.pushErrorScope('out-of-memory'); t.createErrorBuffer(); @@ -84,7 +84,7 @@ g.test('errors bubble to the parent scope if not handled by the current scope', t.expect(error instanceof GPUValidationError); } }); -g.test('if an error scope matches an error it does not bubble to the parent scope', async t => { +g.test('if_an_error_scope_matches_an_error_it_does_not_bubble_to_the_parent_scope').fn(async t => { t.device.pushErrorScope('validation'); t.device.pushErrorScope('validation'); t.createErrorBuffer(); @@ -97,7 +97,7 @@ g.test('if an error scope matches an error it does not bubble to the parent scop t.expect(error === null); } }); -g.test('if no error scope handles an error it fires an uncapturederror event', async t => { +g.test('if_no_error_scope_handles_an_error_it_fires_an_uncapturederror_event').fn(async t => { t.device.pushErrorScope('out-of-memory'); const uncapturedErrorEvent = await t.expectUncapturedError(() => { t.createErrorBuffer(); @@ -106,7 +106,7 @@ g.test('if no error scope handles an error it fires an uncapturederror event', a const error = await t.device.popErrorScope(); t.expect(error === null); }); -g.test('push/popping sibling error scopes must be balanced', async t => { +g.test('push,popping_sibling_error_scopes_must_be_balanced').fn(async t => { { const promise = t.device.popErrorScope(); t.shouldReject('OperationError', promise); @@ -125,7 +125,7 @@ g.test('push/popping sibling error scopes must be balanced', async t => { t.shouldReject('OperationError', promise); } }); -g.test('push/popping nested error scopes must be balanced', async t => { +g.test('push,popping_nested_error_scopes_must_be_balanced').fn(async t => { { const promise = t.device.popErrorScope(); t.shouldReject('OperationError', promise); diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/fences.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/fences.spec.js index 7747b5e9dc8..2ab0691e3ce 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/fences.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/fences.spec.js @@ -5,11 +5,11 @@ export const description = ` fences validation tests. `; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; -export const g = new TestGroup(ValidationTest); // TODO: Remove if https://github.com/gpuweb/gpuweb/issues/377 is decided +export const g = makeTestGroup(ValidationTest); // TODO: Remove if https://github.com/gpuweb/gpuweb/issues/377 is decided -g.test('wait on a fence without signaling the value is invalid', async t => { +g.test('wait_on_a_fence_without_signaling_the_value_is_invalid').fn(async t => { const fence = t.queue.createFence(); t.expectValidationError(() => { const promise = fence.onCompletion(2); @@ -17,7 +17,7 @@ g.test('wait on a fence without signaling the value is invalid', async t => { }); }); // TODO: Remove if https://github.com/gpuweb/gpuweb/issues/377 is decided -g.test('wait on a fence with a value greater than signaled value is invalid', async t => { +g.test('wait_on_a_fence_with_a_value_greater_than_signaled_value_is_invalid').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 2); t.expectValidationError(() => { @@ -25,7 +25,7 @@ g.test('wait on a fence with a value greater than signaled value is invalid', as t.shouldReject('OperationError', promise); }); }); -g.test('signal a value lower than signaled value is invalid', async t => { +g.test('signal_a_value_lower_than_signaled_value_is_invalid').fn(async t => { const fence = t.queue.createFence({ initialValue: 1 }); @@ -33,7 +33,7 @@ g.test('signal a value lower than signaled value is invalid', async t => { t.queue.signal(fence, 0); }); }); -g.test('signal a value equal to signaled value is invalid', async t => { +g.test('signal_a_value_equal_to_signaled_value_is_invalid').fn(async t => { const fence = t.queue.createFence({ initialValue: 1 }); @@ -41,14 +41,14 @@ g.test('signal a value equal to signaled value is invalid', async t => { t.queue.signal(fence, 1); }); }); -g.test('increasing fence value by more than 1 succeeds', async t => { +g.test('increasing_fence_value_by_more_than_1_succeeds').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 2); await fence.onCompletion(2); t.queue.signal(fence, 6); await fence.onCompletion(6); }); -g.test('signal a fence on a different device than it was created on is invalid', async t => { +g.test('signal_a_fence_on_a_different_device_than_it_was_created_on_is_invalid').fn(async t => { const fence = t.queue.createFence(); const anotherDevice = await t.device.adapter.requestDevice(); const anotherQueue = anotherDevice.defaultQueue; @@ -56,7 +56,7 @@ g.test('signal a fence on a different device than it was created on is invalid', anotherQueue.signal(fence, 2); }); }); -g.test('signal a fence on a different device does not update fence signaled value', async t => { +g.test('signal_a_fence_on_a_different_device_does_not_update_fence_signaled_value').fn(async t => { const fence = t.queue.createFence({ initialValue: 1 }); diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/queue_submit.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/queue_submit.spec.js index dbe0bb4d31e..24e386b9d22 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/queue_submit.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/queue_submit.spec.js @@ -5,10 +5,10 @@ export const description = ` queue submit validation tests. `; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; -export const g = new TestGroup(ValidationTest); -g.test('submitting with a mapped buffer is disallowed', async t => { +export const g = makeTestGroup(ValidationTest); +g.test('submitting_with_a_mapped_buffer_is_disallowed').fn(async t => { const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/render_pass_descriptor.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/render_pass_descriptor.spec.js index 7c887a1c0fd..3c1b111fea4 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/render_pass_descriptor.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/render_pass_descriptor.spec.js @@ -5,7 +5,7 @@ export const description = ` render pass descriptor validation tests. `; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; class F extends ValidationTest { @@ -67,8 +67,8 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('a render pass with only one color is ok', t => { +export const g = makeTestGroup(F); +g.test('a_render_pass_with_only_one_color_is_ok').fn(t => { const colorTexture = t.createTexture({ format: 'rgba8unorm' }); @@ -77,7 +77,7 @@ g.test('a render pass with only one color is ok', t => { }; t.tryRenderPass(true, descriptor); }); -g.test('a render pass with only one depth attachment is ok', t => { +g.test('a_render_pass_with_only_one_depth_attachment_is_ok').fn(t => { const depthStencilTexture = t.createTexture({ format: 'depth24plus-stencil8' }); @@ -87,7 +87,15 @@ g.test('a render pass with only one depth attachment is ok', t => { }; t.tryRenderPass(true, descriptor); }); -g.test('OOB color attachment indices are handled', async t => { +g.test('OOB_color_attachment_indices_are_handled').params([{ + colorAttachmentsCount: 4, + _success: true +}, // Control case +{ + colorAttachmentsCount: 5, + _success: false +} // Out of bounds +]).fn(async t => { const { colorAttachmentsCount, _success @@ -102,16 +110,8 @@ g.test('OOB color attachment indices are handled', async t => { await t.tryRenderPass(_success, { colorAttachments }); -}).params([{ - colorAttachmentsCount: 4, - _success: true -}, // Control case -{ - colorAttachmentsCount: 5, - _success: false -} // Out of bounds -]); -g.test('attachments must have the same size', async t => { +}); +g.test('attachments_must_have_the_same_size').fn(async t => { const colorTexture1x1A = t.createTexture({ width: 1, height: 1, @@ -161,7 +161,7 @@ g.test('attachments must have the same size', async t => { await t.tryRenderPass(false, descriptor); } }); -g.test('attachments must match whether they are used for color or depth stencil', async t => { +g.test('attachments_must_match_whether_they_are_used_for_color_or_depth_stencil').fn(async t => { const colorTexture = t.createTexture({ format: 'rgba8unorm' }); @@ -184,7 +184,22 @@ g.test('attachments must match whether they are used for color or depth stencil' await t.tryRenderPass(false, descriptor); } }); -g.test('check layer count for color or depth stencil', async t => { +g.test('check_layer_count_for_color_or_depth_stencil').params([{ + arrayLayerCount: 5, + baseArrayLayer: 0, + _success: false +}, // using 2D array texture view with arrayLayerCount > 1 is not allowed +{ + arrayLayerCount: 1, + baseArrayLayer: 0, + _success: true +}, // using 2D array texture view that covers the first layer of the texture is OK +{ + arrayLayerCount: 1, + baseArrayLayer: 9, + _success: true +} // using 2D array texture view that covers the last layer is OK for depth stencil +]).fn(async t => { const { arrayLayerCount, baseArrayLayer, @@ -236,23 +251,23 @@ g.test('check layer count for color or depth stencil', async t => { }; await t.tryRenderPass(_success, descriptor); } -}).params([{ - arrayLayerCount: 5, - baseArrayLayer: 0, +}); +g.test('check_mip_level_count_for_color_or_depth_stencil').params([{ + mipLevelCount: 2, + baseMipLevel: 0, _success: false -}, // using 2D array texture view with arrayLayerCount > 1 is not allowed +}, // using 2D texture view with mipLevelCount > 1 is not allowed { - arrayLayerCount: 1, - baseArrayLayer: 0, + mipLevelCount: 1, + baseMipLevel: 0, _success: true -}, // using 2D array texture view that covers the first layer of the texture is OK +}, // using 2D texture view that covers the first level of the texture is OK { - arrayLayerCount: 1, - baseArrayLayer: 9, + mipLevelCount: 1, + baseMipLevel: 3, _success: true -} // using 2D array texture view that covers the last layer is OK for depth stencil -]); -g.test('check mip level count for color or depth stencil', async t => { +} // using 2D texture view that covers the last level of the texture is OK +]).fn(async t => { const { mipLevelCount, baseMipLevel, @@ -304,23 +319,8 @@ g.test('check mip level count for color or depth stencil', async t => { }; await t.tryRenderPass(_success, descriptor); } -}).params([{ - mipLevelCount: 2, - baseMipLevel: 0, - _success: false -}, // using 2D texture view with mipLevelCount > 1 is not allowed -{ - mipLevelCount: 1, - baseMipLevel: 0, - _success: true -}, // using 2D texture view that covers the first level of the texture is OK -{ - mipLevelCount: 1, - baseMipLevel: 3, - _success: true -} // using 2D texture view that covers the last level of the texture is OK -]); -g.test('it is invalid to set resolve target if color attachment is non multisampled', async t => { +}); +g.test('it_is_invalid_to_set_resolve_target_if_color_attachment_is_non_multisampled').fn(async t => { const colorTexture = t.createTexture({ sampleCount: 1 }); @@ -341,7 +341,7 @@ g.test('it is invalid to set resolve target if color attachment is non multisamp }; await t.tryRenderPass(false, descriptor); }); -g.test('check the use of multisampled textures as color attachments', async t => { +g.test('check_the_use_of_multisampled_textures_as_color_attachments').fn(async t => { const colorTexture = t.createTexture({ sampleCount: 1 }); @@ -363,7 +363,7 @@ g.test('check the use of multisampled textures as color attachments', async t => await t.tryRenderPass(false, descriptor); } }); -g.test('it is invalid to use a multisampled resolve target', async t => { +g.test('it_is_invalid_to_use_a_multisampled_resolve_target').fn(async t => { const multisampledColorTexture = t.createTexture({ sampleCount: 4 }); @@ -377,7 +377,7 @@ g.test('it is invalid to use a multisampled resolve target', async t => { }; await t.tryRenderPass(false, descriptor); }); -g.test('it is invalid to use a resolve target with array layer count greater than 1', async t => { +g.test('it_is_invalid_to_use_a_resolve_target_with_array_layer_count_greater_than_1').fn(async t => { const multisampledColorTexture = t.createTexture({ sampleCount: 4 }); @@ -391,7 +391,7 @@ g.test('it is invalid to use a resolve target with array layer count greater tha }; await t.tryRenderPass(false, descriptor); }); -g.test('it is invalid to use a resolve target with mipmap level count greater than 1', async t => { +g.test('it_is_invalid_to_use_a_resolve_target_with_mipmap_level_count_greater_than_1').fn(async t => { const multisampledColorTexture = t.createTexture({ sampleCount: 4 }); @@ -405,7 +405,7 @@ g.test('it is invalid to use a resolve target with mipmap level count greater th }; await t.tryRenderPass(false, descriptor); }); -g.test('it is invalid to use a resolve target whose usage is not output attachment', async t => { +g.test('it_is_invalid_to_use_a_resolve_target_whose_usage_is_not_output_attachment').fn(async t => { const multisampledColorTexture = t.createTexture({ sampleCount: 4 }); @@ -419,7 +419,7 @@ g.test('it is invalid to use a resolve target whose usage is not output attachme }; await t.tryRenderPass(false, descriptor); }); -g.test('it is invalid to use a resolve target in error state', async t => { +g.test('it_is_invalid_to_use_a_resolve_target_in_error_state').fn(async t => { const ARRAY_LAYER_COUNT = 1; const multisampledColorTexture = t.createTexture({ sampleCount: 4 @@ -440,7 +440,7 @@ g.test('it is invalid to use a resolve target in error state', async t => { }; await t.tryRenderPass(false, descriptor); }); -g.test('use of multisampled attachment and non multisampled resolve target is allowed', async t => { +g.test('use_of_multisampled_attachment_and_non_multisampled_resolve_target_is_allowed').fn(async t => { const multisampledColorTexture = t.createTexture({ sampleCount: 4 }); @@ -454,7 +454,7 @@ g.test('use of multisampled attachment and non multisampled resolve target is al }; t.tryRenderPass(true, descriptor); }); -g.test('use a resolve target in a format different than the attachment is not allowed', async t => { +g.test('use_a_resolve_target_in_a_format_different_than_the_attachment_is_not_allowed').fn(async t => { const multisampledColorTexture = t.createTexture({ sampleCount: 4 }); @@ -468,7 +468,7 @@ g.test('use a resolve target in a format different than the attachment is not al }; await t.tryRenderPass(false, descriptor); }); -g.test('size of the resolve target must be the same as the color attachment', async t => { +g.test('size_of_the_resolve_target_must_be_the_same_as_the_color_attachment').fn(async t => { const size = 16; const multisampledColorTexture = t.createTexture({ width: size, @@ -504,7 +504,7 @@ g.test('size of the resolve target must be the same as the color attachment', as t.tryRenderPass(true, descriptor); } }); -g.test('check depth stencil attachment sample counts mismatch', async t => { +g.test('check_depth_stencil_attachment_sample_counts_mismatch').fn(async t => { const multisampledDepthStencilTexture = t.createTexture({ sampleCount: 4, format: 'depth24plus-stencil8' diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBindGroup.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBindGroup.spec.js index baf590746c3..95786a8f78d 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBindGroup.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBindGroup.spec.js @@ -5,8 +5,8 @@ export const description = ` setBindGroup validation tests. `; -import { pcombine, poptions } from '../../../common/framework/params.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { poptions, params } from '../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; class F extends ValidationTest { @@ -58,8 +58,8 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('dynamic offsets passed but not expected/compute pass', async t => { +export const g = makeTestGroup(F); +g.test('dynamic_offsets_passed_but_not_expected,compute_pass').params(poptions('type', ['compute', 'renderpass', 'renderbundle'])).fn(async t => { const bindGroupLayout = t.device.createBindGroupLayout({ entries: [] }); @@ -104,8 +104,46 @@ g.test('dynamic offsets passed but not expected/compute pass', async t => { t.fail(); } }); -}).params(poptions('type', ['compute', 'renderpass', 'renderbundle'])); -g.test('dynamic offsets match expectations in pass encoder', async t => { +}); +g.test('dynamic_offsets_match_expectations_in_pass_encoder').params(params().combine(poptions('type', ['compute', 'renderpass', 'renderbundle'])).combine([{ + dynamicOffsets: [256, 0], + _success: true +}, // Dynamic offsets aligned +{ + dynamicOffsets: [1, 2], + _success: false +}, // Dynamic offsets not aligned +// Wrong number of dynamic offsets +{ + dynamicOffsets: [256, 0, 0], + _success: false +}, { + dynamicOffsets: [256], + _success: false +}, { + dynamicOffsets: [], + _success: false +}, // Dynamic uniform buffer out of bounds because of binding size +{ + dynamicOffsets: [512, 0], + _success: false +}, { + dynamicOffsets: [1024, 0], + _success: false +}, { + dynamicOffsets: [0xffffffff, 0], + _success: false +}, // Dynamic storage buffer out of bounds because of binding size +{ + dynamicOffsets: [0, 512], + _success: false +}, { + dynamicOffsets: [0, 1024], + _success: false +}, { + dynamicOffsets: [0, 0xffffffff], + _success: false +}])).fn(async t => { // Dynamic buffer offsets require offset to be divisible by 256 const MIN_DYNAMIC_BUFFER_OFFSET_ALIGNMENT = 256; const BINDING_SIZE = 9; @@ -164,43 +202,5 @@ g.test('dynamic offsets match expectations in pass encoder', async t => { t.testComputePass(bindGroup, dynamicOffsets); }, !_success); -}).params(pcombine(poptions('type', ['compute', 'renderpass', 'renderbundle']), [{ - dynamicOffsets: [256, 0], - _success: true -}, // Dynamic offsets aligned -{ - dynamicOffsets: [1, 2], - _success: false -}, // Dynamic offsets not aligned -// Wrong number of dynamic offsets -{ - dynamicOffsets: [256, 0, 0], - _success: false -}, { - dynamicOffsets: [256], - _success: false -}, { - dynamicOffsets: [], - _success: false -}, // Dynamic uniform buffer out of bounds because of binding size -{ - dynamicOffsets: [512, 0], - _success: false -}, { - dynamicOffsets: [1024, 0], - _success: false -}, { - dynamicOffsets: [Number.MAX_SAFE_INTEGER, 0], - _success: false -}, // Dynamic storage buffer out of bounds because of binding size -{ - dynamicOffsets: [0, 512], - _success: false -}, { - dynamicOffsets: [0, 1024], - _success: false -}, { - dynamicOffsets: [0, Number.MAX_SAFE_INTEGER], - _success: false -}])); // TODO: test error bind group +}); // TODO: test error bind group //# sourceMappingURL=setBindGroup.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBlendColor.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBlendColor.spec.js index b8905453ac9..469641df043 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBlendColor.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setBlendColor.spec.js @@ -5,7 +5,7 @@ export const description = ` setBlendColor validation tests. `; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; // TODO: Move beginRenderPass to a Fixture class. class F extends ValidationTest { @@ -34,8 +34,8 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('basic use of setBlendColor', t => { +export const g = makeTestGroup(F); +g.test('basic_use_of_setBlendColor').fn(t => { const commandEncoder = t.device.createCommandEncoder(); const renderPass = t.beginRenderPass(commandEncoder); renderPass.setBlendColor({ @@ -47,7 +47,7 @@ g.test('basic use of setBlendColor', t => { renderPass.endPass(); commandEncoder.finish(); }); -g.test('setBlendColor allows any number value', t => { +g.test('setBlendColor_allows_any_number_value').fn(t => { const values = [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]; for (const value of values) { diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setScissorRect.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setScissorRect.spec.js index e12c90d7cda..8381865a693 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setScissorRect.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setScissorRect.spec.js @@ -5,7 +5,7 @@ export const description = ` setScissorRect validation tests. `; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; const TEXTURE_WIDTH = 16; const TEXTURE_HEIGHT = 16; // TODO: Move this fixture class to a common file. @@ -36,23 +36,8 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('use of setScissorRect', async t => { - const { - x, - y, - width, - height, - _success - } = t.params; - const commandEncoder = t.device.createCommandEncoder(); - const renderPass = t.beginRenderPass(commandEncoder); - renderPass.setScissorRect(x, y, width, height); - renderPass.endPass(); - t.expectValidationError(() => { - commandEncoder.finish(); - }, !_success); -}).params([{ +export const g = makeTestGroup(F); +g.test('use_of_setScissorRect').params([{ x: 0, y: 0, width: 1, @@ -87,5 +72,20 @@ g.test('use of setScissorRect', async t => { height: TEXTURE_HEIGHT + 1, _success: true } // Scissor larger than the framebuffer is allowed -]); +]).fn(async t => { + const { + x, + y, + width, + height, + _success + } = t.params; + const commandEncoder = t.device.createCommandEncoder(); + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setScissorRect(x, y, width, height); + renderPass.endPass(); + t.expectValidationError(() => { + commandEncoder.finish(); + }, !_success); +}); //# sourceMappingURL=setScissorRect.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setStencilReference.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setStencilReference.spec.js index cbd48aeaad5..f205239d861 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setStencilReference.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setStencilReference.spec.js @@ -5,8 +5,8 @@ export const description = ` setStencilReference validation tests. `; -import { poptions } from '../../../common/framework/params.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { poptions } from '../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; // TODO: Move this fixture class to a common file. class F extends ValidationTest { @@ -35,8 +35,8 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('use of setStencilReference', t => { +export const g = makeTestGroup(F); +g.test('use_of_setStencilReference').params(poptions('reference', [0, 0xffffffff])).fn(t => { const { reference } = t.params; @@ -45,5 +45,5 @@ g.test('use of setStencilReference', t => { renderPass.setStencilReference(reference); renderPass.endPass(); commandEncoder.finish(); -}).params(poptions('reference', [0, 0xffffffff])); +}); //# sourceMappingURL=setStencilReference.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setViewport.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setViewport.spec.js index 9a3009f38ac..f1168c11086 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setViewport.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/setViewport.spec.js @@ -5,7 +5,7 @@ export const description = ` setViewport validation tests. `; -import { TestGroup } from '../../../common/framework/test_group.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; import { ValidationTest } from './validation_test.js'; const TEXTURE_WIDTH = 16; const TEXTURE_HEIGHT = 16; // TODO: Move this fixture class to a common file. @@ -36,25 +36,8 @@ class F extends ValidationTest { } -export const g = new TestGroup(F); -g.test('use of setViewport', async t => { - const { - x, - y, - width, - height, - minDepth, - maxDepth, - _success - } = t.params; - const commandEncoder = t.device.createCommandEncoder(); - const renderPass = t.beginRenderPass(commandEncoder); - renderPass.setViewport(x, y, width, height, minDepth, maxDepth); - renderPass.endPass(); - t.expectValidationError(() => { - commandEncoder.finish(); - }, !_success); -}).params([{ +export const g = makeTestGroup(F); +g.test('use_of_setViewport').params([{ x: 0, y: 0, width: 1, @@ -189,5 +172,22 @@ g.test('use of setViewport', async t => { maxDepth: 1, _success: true } // Viewport larger than the framebuffer is allowed -]); +]).fn(async t => { + const { + x, + y, + width, + height, + minDepth, + maxDepth, + _success + } = t.params; + const commandEncoder = t.device.createCommandEncoder(); + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setViewport(x, y, width, height, minDepth, maxDepth); + renderPass.endPass(); + t.expectValidationError(() => { + commandEncoder.finish(); + }, !_success); +}); //# sourceMappingURL=setViewport.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/validation_test.js b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/validation_test.js index 92d8a0699c4..17eb97bcc63 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/validation_test.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/api/validation/validation_test.js @@ -4,42 +4,6 @@ import { unreachable } from '../../../common/framework/util/util.js'; import { GPUTest } from '../../gpu_test.js'; -export let BindingResourceType; - -(function (BindingResourceType) { - BindingResourceType["error-buffer"] = "error-buffer"; - BindingResourceType["error-sampler"] = "error-sampler"; - BindingResourceType["error-textureview"] = "error-textureview"; - BindingResourceType["uniform-buffer"] = "uniform-buffer"; - BindingResourceType["storage-buffer"] = "storage-buffer"; - BindingResourceType["sampler"] = "sampler"; - BindingResourceType["sampled-textureview"] = "sampled-textureview"; - BindingResourceType["storage-textureview"] = "storage-textureview"; -})(BindingResourceType || (BindingResourceType = {})); - -export function resourceBindingMatches(b, r) { - switch (b) { - case 'storage-buffer': - case 'readonly-storage-buffer': - return r === 'storage-buffer'; - - case 'sampled-texture': - return r === 'sampled-textureview'; - - case 'sampler': - return r === 'sampler'; - - case 'readonly-storage-texture': - case 'writeonly-storage-texture': - return r === 'storage-textureview'; - - case 'uniform-buffer': - return r === 'uniform-buffer'; - - default: - unreachable('unknown GPUBindingType'); - } -} export class ValidationTest extends GPUTest { getStorageBuffer() { return this.device.createBuffer({ @@ -70,6 +34,12 @@ export class ValidationTest extends GPUTest { return this.device.createSampler(); } + getComparisonSampler() { + return this.device.createSampler({ + compare: 'never' + }); + } + getErrorSampler() { this.device.pushErrorScope('validation'); const sampler = this.device.createSampler({ @@ -120,34 +90,37 @@ export class ValidationTest extends GPUTest { getBindingResource(bindingType) { switch (bindingType) { - case 'error-buffer': + case 'errorBuf': return { buffer: this.getErrorBuffer() }; - case 'error-sampler': + case 'errorSamp': return this.getErrorSampler(); - case 'error-textureview': + case 'errorTex': return this.getErrorTextureView(); - case 'uniform-buffer': + case 'uniformBuf': return { buffer: this.getUniformBuffer() }; - case 'storage-buffer': + case 'storageBuf': return { buffer: this.getStorageBuffer() }; - case 'sampler': + case 'plainSamp': return this.getSampler(); - case 'sampled-textureview': + case 'compareSamp': + return this.getComparisonSampler(); + + case 'sampledTex': return this.getSampledTexture().createView(); - case 'storage-textureview': + case 'storageTex': return this.getStorageTexture().createView(); default: @@ -170,7 +143,7 @@ export class ValidationTest extends GPUTest { if (!gpuValidationError) { niceStack.message = 'Validation error was expected.'; - this.rec.fail(niceStack); + this.rec.validationFailed(niceStack); } else if (gpuValidationError instanceof GPUValidationError) { niceStack.message = `Captured validation error - ${gpuValidationError.message}`; this.rec.debug(niceStack); diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/capability_info.js b/tests/wpt/web-platform-tests/webgpu/webgpu/capability_info.js index 0e336b979f8..b2d9353b04d 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/capability_info.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/capability_info.js @@ -2,7 +2,16 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -import * as C from '../common/constants.js'; // Textures +import * as C from '../common/constants.js'; + +function keysOf(obj) { + return Object.keys(obj); +} + +function numericKeysOf(obj) { + return Object.keys(obj).map(n => Number(n)); +} // Textures + export const kTextureFormatInfo = /* prettier-ignore */ @@ -12,230 +21,611 @@ export const kTextureFormatInfo = // 8-bit formats 'r8unorm': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 1, + blockWidth: 1, + blockHeight: 1 }, 'r8snorm': { renderable: false, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 1, + blockWidth: 1, + blockHeight: 1 }, 'r8uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 1, + blockWidth: 1, + blockHeight: 1 }, 'r8sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 1, + blockWidth: 1, + blockHeight: 1 }, // 16-bit formats 'r16uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 2, + blockWidth: 1, + blockHeight: 1 }, 'r16sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 2, + blockWidth: 1, + blockHeight: 1 }, 'r16float': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 2, + blockWidth: 1, + blockHeight: 1 }, 'rg8unorm': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 2, + blockWidth: 1, + blockHeight: 1 }, 'rg8snorm': { renderable: false, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 2, + blockWidth: 1, + blockHeight: 1 }, 'rg8uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 2, + blockWidth: 1, + blockHeight: 1 }, 'rg8sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 2, + blockWidth: 1, + blockHeight: 1 }, // 32-bit formats 'r32uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'r32sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'r32float': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rg16uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rg16sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rg16float': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rgba8unorm': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rgba8unorm-srgb': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rgba8snorm': { renderable: false, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rgba8uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rgba8sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'bgra8unorm': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'bgra8unorm-srgb': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, // Packed 32-bit formats 'rgb10a2unorm': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'rg11b10float': { renderable: false, - color: true + color: true, + depth: false, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, // 64-bit formats 'rg32uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 8, + blockWidth: 1, + blockHeight: 1 }, 'rg32sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 8, + blockWidth: 1, + blockHeight: 1 }, 'rg32float': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 8, + blockWidth: 1, + blockHeight: 1 }, 'rgba16uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 8, + blockWidth: 1, + blockHeight: 1 }, 'rgba16sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 8, + blockWidth: 1, + blockHeight: 1 }, 'rgba16float': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 8, + blockWidth: 1, + blockHeight: 1 }, // 128-bit formats 'rgba32uint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 16, + blockWidth: 1, + blockHeight: 1 }, 'rgba32sint': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 16, + blockWidth: 1, + blockHeight: 1 }, 'rgba32float': { renderable: true, - color: true + color: true, + depth: false, + stencil: false, + storage: true, + copyable: true, + bytesPerBlock: 16, + blockWidth: 1, + blockHeight: 1 }, // Depth/stencil formats 'depth32float': { renderable: true, - color: false + color: false, + depth: true, + stencil: false, + storage: false, + copyable: true, + bytesPerBlock: 4, + blockWidth: 1, + blockHeight: 1 }, 'depth24plus': { renderable: true, - color: false + color: false, + depth: true, + stencil: false, + storage: false, + copyable: false }, 'depth24plus-stencil8': { renderable: true, - color: false + color: false, + depth: true, + stencil: true, + storage: false, + copyable: false } }; -export const kTextureFormats = Object.keys(kTextureFormatInfo); // Bindings +export const kTextureFormats = keysOf(kTextureFormatInfo); +export const kTextureDimensionInfo = +/* prettier-ignore */ +{ + '1d': {}, + '2d': {}, + '3d': {} +}; +export const kTextureDimensions = keysOf(kTextureDimensionInfo); +export const kTextureAspectInfo = +/* prettier-ignore */ +{ + 'all': {}, + 'depth-only': {}, + 'stencil-only': {} +}; +export const kTextureAspects = keysOf(kTextureAspectInfo); +export const kTextureUsageInfo = { + [C.TextureUsage.CopySrc]: {}, + [C.TextureUsage.CopyDst]: {}, + [C.TextureUsage.Sampled]: {}, + [C.TextureUsage.Storage]: {}, + [C.TextureUsage.OutputAttachment]: {} +}; +export const kTextureUsages = numericKeysOf(kTextureUsageInfo); // Typedefs for bindings +// Bindings export const kMaxBindingsPerBindGroup = 16; export const kPerStageBindingLimits = /* prettier-ignore */ { - 'uniform-buffer': 12, - 'storage-buffer': 4, - 'sampler': 16, - 'sampled-texture': 16, - 'storage-texture': 4 + 'uniformBuf': { + class: 'uniformBuf', + max: 12 + }, + 'storageBuf': { + class: 'storageBuf', + max: 4 + }, + 'sampler': { + class: 'sampler', + max: 16 + }, + 'sampledTex': { + class: 'sampledTex', + max: 16 + }, + 'storageTex': { + class: 'storageTex', + max: 4 + } }; -const kStagesAll = C.ShaderStage.Vertex | C.ShaderStage.Fragment | C.ShaderStage.Compute; -const kStagesCompute = C.ShaderStage.Compute; -export const kBindingTypeInfo = +export const kPerPipelineBindingLimits = +/* prettier-ignore */ +{ + 'uniformBuf': { + class: 'uniformBuf', + maxDynamic: 8 + }, + 'storageBuf': { + class: 'storageBuf', + maxDynamic: 4 + }, + 'sampler': { + class: 'sampler', + maxDynamic: 0 + }, + 'sampledTex': { + class: 'sampledTex', + maxDynamic: 0 + }, + 'storageTex': { + class: 'storageTex', + maxDynamic: 0 + } +}; +const kBindableResource = +/* prettier-ignore */ +{ + uniformBuf: {}, + storageBuf: {}, + plainSamp: {}, + compareSamp: {}, + sampledTex: {}, + storageTex: {}, + errorBuf: {}, + errorSamp: {}, + errorTex: {} +}; +export const kBindableResources = keysOf(kBindableResource); +const kBindingKind = +/* prettier-ignore */ +{ + uniformBuf: { + resource: 'uniformBuf', + perStageLimitClass: kPerStageBindingLimits.uniformBuf, + perPipelineLimitClass: kPerPipelineBindingLimits.uniformBuf + }, + storageBuf: { + resource: 'storageBuf', + perStageLimitClass: kPerStageBindingLimits.storageBuf, + perPipelineLimitClass: kPerPipelineBindingLimits.storageBuf + }, + plainSamp: { + resource: 'plainSamp', + perStageLimitClass: kPerStageBindingLimits.sampler, + perPipelineLimitClass: kPerPipelineBindingLimits.sampler + }, + compareSamp: { + resource: 'compareSamp', + perStageLimitClass: kPerStageBindingLimits.sampler, + perPipelineLimitClass: kPerPipelineBindingLimits.sampler + }, + sampledTex: { + resource: 'sampledTex', + perStageLimitClass: kPerStageBindingLimits.sampledTex, + perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex + }, + storageTex: { + resource: 'storageTex', + perStageLimitClass: kPerStageBindingLimits.storageTex, + perPipelineLimitClass: kPerPipelineBindingLimits.storageTex + } +}; // Binding type info + +const kValidStagesAll = { + validStages: C.ShaderStage.Vertex | C.ShaderStage.Fragment | C.ShaderStage.Compute +}; +const kValidStagesStorageWrite = { + validStages: C.ShaderStage.Fragment | C.ShaderStage.Compute +}; +export const kBufferBindingTypeInfo = /* prettier-ignore */ { 'uniform-buffer': { - type: 'buffer', - validStages: kStagesAll, - perStageLimitType: 'uniform-buffer', - maxDynamicCount: 8 + usage: C.BufferUsage.Uniform, + ...kBindingKind.uniformBuf, + ...kValidStagesAll }, 'storage-buffer': { - type: 'buffer', - validStages: kStagesCompute, - perStageLimitType: 'storage-buffer', - maxDynamicCount: 4 + usage: C.BufferUsage.Storage, + ...kBindingKind.storageBuf, + ...kValidStagesStorageWrite }, 'readonly-storage-buffer': { - type: 'buffer', - validStages: kStagesAll, - perStageLimitType: 'storage-buffer', - maxDynamicCount: 4 - }, - 'sampler': { - type: 'sampler', - validStages: kStagesAll, - perStageLimitType: 'sampler', - maxDynamicCount: 0 - }, - 'comparison-sampler': { - type: 'sampler', - validStages: kStagesAll, - perStageLimitType: 'sampler', - maxDynamicCount: 0 + usage: C.BufferUsage.Storage, + ...kBindingKind.storageBuf, + ...kValidStagesAll + } +}; +export const kBufferBindingTypes = keysOf(kBufferBindingTypeInfo); +export const kSamplerBindingTypeInfo = +/* prettier-ignore */ +{ + 'sampler': { ...kBindingKind.plainSamp, + ...kValidStagesAll }, + 'comparison-sampler': { ...kBindingKind.compareSamp, + ...kValidStagesAll + } +}; +export const kSamplerBindingTypes = keysOf(kSamplerBindingTypeInfo); +export const kTextureBindingTypeInfo = +/* prettier-ignore */ +{ 'sampled-texture': { - type: 'texture', - validStages: kStagesAll, - perStageLimitType: 'sampled-texture', - maxDynamicCount: 0 + usage: C.TextureUsage.Sampled, + ...kBindingKind.sampledTex, + ...kValidStagesAll }, 'writeonly-storage-texture': { - type: 'texture', - validStages: kStagesCompute, - perStageLimitType: 'storage-texture', - maxDynamicCount: 0 + usage: C.TextureUsage.Storage, + ...kBindingKind.storageTex, + ...kValidStagesStorageWrite }, 'readonly-storage-texture': { - type: 'texture', - validStages: kStagesAll, - perStageLimitType: 'storage-texture', - maxDynamicCount: 0 + usage: C.TextureUsage.Storage, + ...kBindingKind.storageTex, + ...kValidStagesAll } }; -export const kBindingTypes = Object.keys(kBindingTypeInfo); +export const kTextureBindingTypes = keysOf(kTextureBindingTypeInfo); // All binding types (merged from above) + +export const kBindingTypeInfo = { ...kBufferBindingTypeInfo, + ...kSamplerBindingTypeInfo, + ...kTextureBindingTypeInfo +}; +export const kBindingTypes = keysOf(kBindingTypeInfo); export const kShaderStages = [C.ShaderStage.Vertex, C.ShaderStage.Fragment, C.ShaderStage.Compute]; export const kShaderStageCombinations = [0, 1, 2, 3, 4, 5, 6, 7]; //# sourceMappingURL=capability_info.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/examples.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/examples.spec.js index add23f7250e..28b9ae47f2c 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/examples.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/examples.spec.js @@ -7,7 +7,7 @@ Examples of writing CTS tests with various features. Start here when looking for examples of basic framework usage. `; -import { TestGroup } from '../common/framework/test_group.js'; +import { makeTestGroup } from '../common/framework/test_group.js'; import { GPUTest } from './gpu_test.js'; // To run these tests in the standalone runner, run `grunt build` or `grunt pre` then open: // - http://localhost:8080/?runnow=1&q=webgpu:examples: // To run in WPT, copy/symlink the out-wpt/ directory as the webgpu/ directory in WPT, then open: @@ -18,10 +18,10 @@ import { GPUTest } from './gpu_test.js'; // To run these tests in the standalone // - ?q=webgpu:examples:basic/ // - ?q=webgpu:examples: -export const g = new TestGroup(GPUTest); // Note: spaces in test names are replaced with underscores: webgpu:examples:test_name= +export const g = makeTestGroup(GPUTest); // Note: spaces in test names are replaced with underscores: webgpu:examples:test_name= -g.test('test name', t => {}); -g.test('basic', t => { +g.test('test_name').fn(t => {}); +g.test('basic').fn(t => { t.expect(true); t.expect(true, 'true should be true'); t.shouldThrow( // The expected '.name' of the thrown error. @@ -31,7 +31,7 @@ g.test('basic', t => { }, // Log message. 'function should throw Error'); }); -g.test('basic/async', async t => { +g.test('basic,async').fn(async t => { // shouldReject must be awaited to ensure it can wait for the promise before the test ends. t.shouldReject( // The expected '.name' of the thrown error. 'TypeError', // Promise expected to reject. @@ -50,9 +50,7 @@ g.test('basic/async', async t => { // - webgpu:examples:basic/params={"x":2,"y":4} runs with t.params = {x: 2, y: 5, _result: 6}. // - webgpu:examples:basic/params={"x":-10,"y":18} runs with t.params = {x: -10, y: 18, _result: 8}. -g.test('basic/params', t => { - t.expect(t.params.x + t.params.y === t.params._result); -}).params([{ +g.test('basic,params').params([{ x: 2, y: 4, _result: 6 @@ -61,15 +59,17 @@ g.test('basic/params', t => { x: -10, y: 18, _result: 8 -}]); // (note the blank comment above to enforce newlines on autoformat) +}]).fn(t => { + t.expect(t.params.x + t.params.y === t.params._result); +}); // (note the blank comment above to enforce newlines on autoformat) -g.test('gpu/async', async t => { +g.test('gpu,async').fn(async t => { const fence = t.queue.createFence(); t.queue.signal(fence, 2); await fence.onCompletion(1); t.expect(fence.getCompletedValue() === 2); }); -g.test('gpu/buffers', async t => { +g.test('gpu,buffers').fn(async t => { const data = new Uint32Array([0, 1234, 0]); const [src, map] = t.device.createBufferMapped({ size: 12, diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/gpu_test.js b/tests/wpt/web-platform-tests/webgpu/webgpu/gpu_test.js index 0202f34fcf7..d2528c8d84b 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/gpu_test.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/gpu_test.js @@ -5,49 +5,11 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } import { Fixture } from '../common/framework/fixture.js'; -import { getGPU } from '../common/framework/gpu/implementation.js'; -import { assert, unreachable } from '../common/framework/util/util.js'; - -class DevicePool { - constructor() { - _defineProperty(this, "device", undefined); - - _defineProperty(this, "state", 'uninitialized'); - } - - async initialize() { - try { - const gpu = getGPU(); - const adapter = await gpu.requestAdapter(); - this.device = await adapter.requestDevice(); - } catch (ex) { - this.state = 'failed'; - throw ex; - } - } - - async acquire() { - assert(this.state !== 'acquired', 'Device was in use'); - assert(this.state !== 'failed', 'Failed to initialize WebGPU device'); - const state = this.state; - this.state = 'acquired'; - - if (state === 'uninitialized') { - await this.initialize(); - } - - assert(!!this.device); - return this.device; - } - - release(device) { - assert(this.state === 'acquired'); - assert(device === this.device, 'Released device was the wrong device'); - this.state = 'free'; - } - -} - +import { DevicePool, TestOOMedShouldAttemptGC } from '../common/framework/gpu/device_pool.js'; +import { attemptGarbageCollection } from '../common/framework/util/collect_garbage.js'; +import { assert } from '../common/framework/util/util.js'; +import { fillTextureDataWithTexelValue, getTextureCopyLayout } from './util/texture/layout.js'; +import { getTexelDataRepresentation } from './util/texture/texelData.js'; const devicePool = new DevicePool(); export class GPUTest extends Fixture { constructor(...args) { @@ -76,40 +38,34 @@ export class GPUTest extends Fixture { device, queue }; + } // Note: finalize is called even if init was unsuccessful. - try { - await device.popErrorScope(); - unreachable('There was an error scope on the stack at the beginning of the test'); - } catch (ex) {} - - device.pushErrorScope('out-of-memory'); - device.pushErrorScope('validation'); - this.initialized = true; - } async finalize() { - // Note: finalize is called even if init was unsuccessful. await super.finalize(); - if (this.initialized) { - const gpuValidationError = await this.device.popErrorScope(); - - if (gpuValidationError !== null) { - assert(gpuValidationError instanceof GPUValidationError); - this.fail(`Unexpected validation error occurred: ${gpuValidationError.message}`); - } + if (this.objects) { + let threw; + { + const objects = this.objects; + this.objects = undefined; + + try { + await devicePool.release(objects.device); + } catch (ex) { + threw = ex; + } + } // The GPUDevice and GPUQueue should now have no outstanding references. - const gpuOutOfMemoryError = await this.device.popErrorScope(); + if (threw) { + if (threw instanceof TestOOMedShouldAttemptGC) { + // Try to clean up, in case there are stray GPU resources in need of collection. + await attemptGarbageCollection(); + } - if (gpuOutOfMemoryError !== null) { - assert(gpuOutOfMemoryError instanceof GPUOutOfMemoryError); - this.fail('Unexpected out-of-memory error occurred'); + throw threw; } } - - if (this.objects) { - devicePool.release(this.objects.device); - } } createCopyForMapRead(src, size) { @@ -125,15 +81,15 @@ export class GPUTest extends Fixture { expectContents(src, expected) { - const exp = new Uint8Array(expected.buffer, expected.byteOffset, expected.byteLength); const dst = this.createCopyForMapRead(src, expected.buffer.byteLength); this.eventualAsyncExpectation(async niceStack => { - const actual = new Uint8Array((await dst.mapReadAsync())); - const check = this.checkBuffer(actual, exp); + const constructor = expected.constructor; + const actual = new constructor((await dst.mapReadAsync())); + const check = this.checkBuffer(actual, expected); if (check !== undefined) { niceStack.message = check; - this.rec.fail(niceStack); + this.rec.expectationFailed(niceStack); } dst.destroy(); @@ -144,31 +100,43 @@ export class GPUTest extends Fixture { const check = this.checkBuffer(actual, exp); if (check !== undefined) { - this.rec.fail(new Error(check)); + this.rec.expectationFailed(new Error(check)); } } - checkBuffer(actual, exp) { + checkBuffer(actual, exp, tolerance = 0) { + assert(actual.constructor === exp.constructor); const size = exp.byteLength; if (actual.byteLength !== size) { return 'size mismatch'; } - const lines = []; - let failedPixels = 0; + const failedByteIndices = []; + const failedByteExpectedValues = []; + const failedByteActualValues = []; for (let i = 0; i < size; ++i) { - if (actual[i] !== exp[i]) { - if (failedPixels > 4) { - lines.push('... and more'); + const tol = typeof tolerance === 'function' ? tolerance(i) : tolerance; + + if (Math.abs(actual[i] - exp[i]) > tol) { + if (failedByteIndices.length >= 4) { + failedByteIndices.push('...'); + failedByteExpectedValues.push('...'); + failedByteActualValues.push('...'); break; } - failedPixels++; - lines.push(`at [${i}], expected ${exp[i]}, got ${actual[i]}`); + failedByteIndices.push(i.toString()); + failedByteExpectedValues.push(exp[i].toString()); + failedByteActualValues.push(actual[i].toString()); } - } // TODO: Could make a more convenient message, which could look like e.g.: + } + + const summary = `at [${failedByteIndices.join(', ')}], \ +expected [${failedByteExpectedValues.join(', ')}], \ +got [${failedByteActualValues.join(', ')}]`; + const lines = [summary]; // TODO: Could make a more convenient message, which could look like e.g.: // // Starting at offset 48, // got 22222222 ABCDABCD 99999999 @@ -183,20 +151,55 @@ export class GPUTest extends Fixture { // Or, maybe these diffs aren't actually very useful (given we have the prints just above here), // and we should remove them. More important will be logging of texture data in a visual format. - - if (size <= 256 && failedPixels > 0) { - const expHex = Array.from(exp).map(x => x.toString(16).padStart(2, '0')).join(''); - const actHex = Array.from(actual).map(x => x.toString(16).padStart(2, '0')).join(''); - lines.push('EXPECT: ' + expHex); - lines.push('ACTUAL: ' + actHex); + if (size <= 256 && failedByteIndices.length > 0) { + const expHex = Array.from(new Uint8Array(exp.buffer, exp.byteOffset, exp.byteLength)).map(x => x.toString(16).padStart(2, '0')).join(''); + const actHex = Array.from(new Uint8Array(actual.buffer, actual.byteOffset, actual.byteLength)).map(x => x.toString(16).padStart(2, '0')).join(''); + lines.push('EXPECT:\t ' + exp.join(' ')); + lines.push('\t0x' + expHex); + lines.push('ACTUAL:\t ' + actual.join(' ')); + lines.push('\t0x' + actHex); } - if (failedPixels) { + if (failedByteIndices.length) { return lines.join('\n'); } return undefined; } + expectSingleColor(src, format, { + size, + exp, + dimension = '2d', + slice = 0, + layout + }) { + const { + byteLength, + bytesPerRow, + rowsPerImage, + mipSize + } = getTextureCopyLayout(format, dimension, size, layout); + const expectedTexelData = getTexelDataRepresentation(format).getBytes(exp); + const buffer = this.device.createBuffer({ + size: byteLength, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST + }); + const commandEncoder = this.device.createCommandEncoder(); + commandEncoder.copyTextureToBuffer({ + texture: src, + mipLevel: layout?.mipLevel, + arrayLayer: slice + }, { + buffer, + bytesPerRow, + rowsPerImage + }, mipSize); + this.queue.submit([commandEncoder.finish()]); + const arrayBuffer = new ArrayBuffer(byteLength); + fillTextureDataWithTexelValue(expectedTexelData, format, dimension, arrayBuffer, size, layout); + this.expectContents(buffer, new Uint8Array(arrayBuffer)); + } + } //# sourceMappingURL=gpu_test.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/listing.js b/tests/wpt/web-platform-tests/webgpu/webgpu/listing.js index 5b9ef1afb01..ea23ab28328 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/listing.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/listing.js @@ -2,151 +2,295 @@ export const listing = [ { - "path": "", - "description": "WebGPU conformance test suite." + "file": [], + "readme": "WebGPU conformance test suite." }, { - "path": "api/", - "description": "Tests for full coverage of the Javascript API surface of WebGPU." + "file": [ + "api" + ], + "readme": "Tests for full coverage of the Javascript API surface of WebGPU." }, { - "path": "api/operation/", - "description": "Tests that check the result of performing valid WebGPU operations, taking advantage of\nparameterization to exercise interactions between features." + "file": [ + "api", + "operation" + ], + "readme": "Tests that check the result of performing valid WebGPU operations, taking advantage of\nparameterization to exercise interactions between features." }, { - "path": "api/operation/buffers/", - "description": "GPUBuffer tests." + "file": [ + "api", + "operation", + "buffers" + ], + "readme": "GPUBuffer tests." }, { - "path": "api/operation/buffers/create_mapped", + "file": [ + "api", + "operation", + "buffers", + "create_mapped" + ], "description": "" }, { - "path": "api/operation/buffers/map", + "file": [ + "api", + "operation", + "buffers", + "map" + ], "description": "" }, { - "path": "api/operation/buffers/map_detach", + "file": [ + "api", + "operation", + "buffers", + "map_detach" + ], "description": "" }, { - "path": "api/operation/buffers/map_oom", + "file": [ + "api", + "operation", + "buffers", + "map_oom" + ], "description": "" }, { - "path": "api/operation/command_buffer/basic", + "file": [ + "api", + "operation", + "command_buffer", + "basic" + ], "description": "Basic tests." }, { - "path": "api/operation/command_buffer/copies", + "file": [ + "api", + "operation", + "command_buffer", + "copies" + ], "description": "copy{Buffer,Texture}To{Buffer,Texture} tests." }, { - "path": "api/operation/command_buffer/render/basic", + "file": [ + "api", + "operation", + "command_buffer", + "render", + "basic" + ], "description": "Basic command buffer rendering tests." }, { - "path": "api/operation/fences", + "file": [ + "api", + "operation", + "fences" + ], "description": "" }, { - "path": "api/regression/", - "description": "One-off tests that reproduce API bugs found in implementations to prevent the bugs from\nappearing again." + "file": [ + "api", + "operation", + "resource_init", + "copied_texture_clear" + ], + "description": "Test uninitialized textures are initialized to zero when copied." }, { - "path": "api/validation/", - "description": "Positive and negative tests for all the validation rules of the API." + "file": [ + "api", + "regression" + ], + "readme": "One-off tests that reproduce API bugs found in implementations to prevent the bugs from\nappearing again." }, { - "path": "api/validation/createBindGroup", + "file": [ + "api", + "validation" + ], + "readme": "Positive and negative tests for all the validation rules of the API." + }, + { + "file": [ + "api", + "validation", + "createBindGroup" + ], "description": "createBindGroup validation tests." }, { - "path": "api/validation/createBindGroupLayout", + "file": [ + "api", + "validation", + "createBindGroupLayout" + ], "description": "createBindGroupLayout validation tests." }, { - "path": "api/validation/createPipelineLayout", + "file": [ + "api", + "validation", + "createPipelineLayout" + ], "description": "createPipelineLayout validation tests." }, { - "path": "api/validation/createTexture", + "file": [ + "api", + "validation", + "createTexture" + ], "description": "createTexture validation tests." }, { - "path": "api/validation/createView", + "file": [ + "api", + "validation", + "createView" + ], "description": "createView validation tests." }, { - "path": "api/validation/error_scope", + "file": [ + "api", + "validation", + "error_scope" + ], "description": "error scope validation tests." }, { - "path": "api/validation/fences", + "file": [ + "api", + "validation", + "fences" + ], "description": "fences validation tests." }, { - "path": "api/validation/queue_submit", + "file": [ + "api", + "validation", + "queue_submit" + ], "description": "queue submit validation tests." }, { - "path": "api/validation/render_pass_descriptor", + "file": [ + "api", + "validation", + "render_pass_descriptor" + ], "description": "render pass descriptor validation tests." }, { - "path": "api/validation/setBindGroup", + "file": [ + "api", + "validation", + "setBindGroup" + ], "description": "setBindGroup validation tests." }, { - "path": "api/validation/setBlendColor", + "file": [ + "api", + "validation", + "setBlendColor" + ], "description": "setBlendColor validation tests." }, { - "path": "api/validation/setScissorRect", + "file": [ + "api", + "validation", + "setScissorRect" + ], "description": "setScissorRect validation tests." }, { - "path": "api/validation/setStencilReference", + "file": [ + "api", + "validation", + "setStencilReference" + ], "description": "setStencilReference validation tests." }, { - "path": "api/validation/setViewport", + "file": [ + "api", + "validation", + "setViewport" + ], "description": "setViewport validation tests." }, { - "path": "examples", + "file": [ + "examples" + ], "description": "Examples of writing CTS tests with various features.\n\nStart here when looking for examples of basic framework usage." }, { - "path": "idl/", - "description": "Tests to check that the WebGPU IDL is correctly implemented, for examples that objects exposed\nexactly the correct members, and that methods throw when passed incomplete dictionaries." + "file": [ + "idl" + ], + "readme": "Tests to check that the WebGPU IDL is correctly implemented, for examples that objects exposed\nexactly the correct members, and that methods throw when passed incomplete dictionaries." }, { - "path": "shader/", - "description": "Tests for full coverage of the shaders that can be passed to WebGPU." + "file": [ + "shader" + ], + "readme": "Tests for full coverage of the shaders that can be passed to WebGPU." }, { - "path": "shader/execution/", - "description": "Tests that check the result of valid shader execution." + "file": [ + "shader", + "execution" + ], + "readme": "Tests that check the result of valid shader execution." }, { - "path": "shader/regression/", - "description": "One-off tests that reproduce shader bugs found in implementations to prevent the bugs from\nappearing again." + "file": [ + "shader", + "regression" + ], + "readme": "One-off tests that reproduce shader bugs found in implementations to prevent the bugs from\nappearing again." }, { - "path": "shader/validation/", - "description": "Positive and negative tests for all the validation rules of the shading language." + "file": [ + "shader", + "validation" + ], + "readme": "Positive and negative tests for all the validation rules of the shading language." }, { - "path": "web-platform/", - "description": "Tests for Web platform-specific interactions like GPUSwapChain and canvas, WebXR,\nImageBitmaps, and video APIs." + "file": [ + "web-platform" + ], + "readme": "Tests for Web platform-specific interactions like GPUSwapChain and canvas, WebXR,\nImageBitmaps, and video APIs." }, { - "path": "web-platform/canvas/context_creation", + "file": [ + "web-platform", + "canvas", + "context_creation" + ], "description": "" }, { - "path": "web-platform/copyImageBitmapToTexture", + "file": [ + "web-platform", + "copyImageBitmapToTexture" + ], "description": "copy imageBitmap To texture tests." } ]; diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/util/conversion.js b/tests/wpt/web-platform-tests/webgpu/webgpu/util/conversion.js new file mode 100644 index 00000000000..73c04fe56ba --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/util/conversion.js @@ -0,0 +1,61 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { assert } from '../../common/framework/util/util.js'; +export function floatAsNormalizedInteger(float, bits, signed) { + if (signed) { + assert(float >= -1 && float <= 1); + const max = Math.pow(2, bits - 1) - 1; + return Math.round(float * max); + } else { + assert(float >= 0 && float <= 1); + const max = Math.pow(2, bits) - 1; + return Math.round(float * max); + } +} // Does not handle clamping, underflow, overflow, denormalized numbers + +export function float32ToFloatBits(n, signBits, exponentBits, fractionBits, bias) { + assert(exponentBits <= 8); + assert(fractionBits <= 23); + assert(Number.isFinite(n)); + + if (n === 0) { + return 0; + } + + if (signBits === 0) { + assert(n >= 0); + } + + const buf = new DataView(new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT)); + buf.setFloat32(0, n, true); + const bits = buf.getUint32(0, true); // bits (32): seeeeeeeefffffffffffffffffffffff + + const fractionBitsToDiscard = 23 - fractionBits; // 0 or 1 + + const sign = bits >> 31 & signBits; // >> to remove fraction, & to remove sign, - 127 to remove bias. + + const exp = (bits >> 23 & 0xff) - 127; // Convert to the new biased exponent. + + const newBiasedExp = bias + exp; + assert(newBiasedExp >= 0 && newBiasedExp < 1 << exponentBits); // Mask only the fraction, and discard the lower bits. + + const newFraction = (bits & 0x7fffff) >> fractionBitsToDiscard; + return sign << exponentBits + fractionBits | newBiasedExp << fractionBits | newFraction; +} +export function assertInIntegerRange(n, bits, signed) { + if (signed) { + const min = -Math.pow(2, bits - 1); + const max = Math.pow(2, bits - 1) - 1; + assert(n >= min && n <= max); + } else { + const max = Math.pow(2, bits) - 1; + assert(n >= 0 && n <= max); + } +} +export function gammaCompress(n) { + n = n <= 0.0031308 ? 12.92 * n : 1.055 * Math.pow(n, 1 / 2.4) - 0.055; + return n < 0 ? 0 : n > 1 ? 1 : n; +} +//# sourceMappingURL=conversion.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/util/math.js b/tests/wpt/web-platform-tests/webgpu/webgpu/util/math.js new file mode 100644 index 00000000000..19720d631c5 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/util/math.js @@ -0,0 +1,11 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +export function align(n, alignment) { + return Math.ceil(n / alignment) * alignment; +} +export function isAligned(n, alignment) { + return n === align(n, alignment); +} +//# sourceMappingURL=math.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/layout.js b/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/layout.js new file mode 100644 index 00000000000..db9d5dbb435 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/layout.js @@ -0,0 +1,126 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import * as C from '../../../common/constants.js'; +import { assert, unreachable } from '../../../common/framework/util/util.js'; +import { kTextureFormatInfo } from '../../capability_info.js'; +import { align, isAligned } from '../math.js'; +export const kBytesPerRowAlignment = 256; +export const kBufferCopyAlignment = 4; +const kDefaultLayoutOptions = { + mipLevel: 0, + bytesPerRow: undefined, + rowsPerImage: undefined +}; +export function getMipSizePassthroughLayers(dimension, size, mipLevel) { + const shiftMinOne = n => Math.max(1, n >> mipLevel); + + switch (dimension) { + case '1d': + assert(size[2] === 1); + return [shiftMinOne(size[0]), size[1], size[2]]; + + case '2d': + return [shiftMinOne(size[0]), shiftMinOne(size[1]), size[2]]; + + case '3d': + return [shiftMinOne(size[0]), shiftMinOne(size[1]), shiftMinOne(size[2])]; + + default: + unreachable(); + } +} +export function getTextureCopyLayout(format, dimension, size, options = kDefaultLayoutOptions) { + const { + mipLevel + } = options; + let { + bytesPerRow, + rowsPerImage + } = options; + const mipSize = getMipSizePassthroughLayers(dimension, size, mipLevel); + const { + blockWidth, + blockHeight, + bytesPerBlock + } = kTextureFormatInfo[format]; + assert(!!bytesPerBlock && !!blockWidth && !!blockHeight); + assert(isAligned(mipSize[0], blockWidth)); + const minBytesPerRow = mipSize[0] / blockWidth * bytesPerBlock; + const alignedMinBytesPerRow = align(minBytesPerRow, kBytesPerRowAlignment); + + if (bytesPerRow !== undefined) { + assert(bytesPerRow >= alignedMinBytesPerRow); + assert(isAligned(bytesPerRow, kBytesPerRowAlignment)); + } else { + bytesPerRow = alignedMinBytesPerRow; + } + + if (rowsPerImage !== undefined) { + assert(rowsPerImage >= mipSize[1]); + } else { + rowsPerImage = mipSize[1]; + } + + assert(isAligned(rowsPerImage, blockHeight)); + const bytesPerSlice = bytesPerRow * (rowsPerImage / blockHeight); + const sliceSize = bytesPerRow * (mipSize[1] / blockHeight - 1) + bytesPerBlock * (mipSize[0] / blockWidth); + const byteLength = bytesPerSlice * (mipSize[2] - 1) + sliceSize; + return { + bytesPerBlock, + byteLength: align(byteLength, kBufferCopyAlignment), + minBytesPerRow, + bytesPerRow, + rowsPerImage, + mipSize + }; +} +export function fillTextureDataWithTexelValue(texelValue, format, dimension, outputBuffer, size, options = kDefaultLayoutOptions) { + const { + blockWidth, + blockHeight, + bytesPerBlock + } = kTextureFormatInfo[format]; + assert(!!bytesPerBlock && !!blockWidth && !!blockHeight); + assert(bytesPerBlock === texelValue.byteLength); + const { + byteLength, + rowsPerImage, + bytesPerRow + } = getTextureCopyLayout(format, dimension, size, options); + assert(byteLength <= outputBuffer.byteLength); + const mipSize = getMipSizePassthroughLayers(dimension, size, options.mipLevel); + const texelValueBytes = new Uint8Array(texelValue); + const outputTexelValueBytes = new Uint8Array(outputBuffer); + + for (let slice = 0; slice < mipSize[2]; ++slice) { + for (let row = 0; row < mipSize[1]; row += blockHeight) { + for (let col = 0; col < mipSize[0]; col += blockWidth) { + const byteOffset = slice * rowsPerImage * bytesPerRow + row * bytesPerRow + col * texelValue.byteLength; + outputTexelValueBytes.set(texelValueBytes, byteOffset); + } + } + } +} +export function createTextureUploadBuffer(texelValue, device, format, dimension, size, options = kDefaultLayoutOptions) { + const { + byteLength, + bytesPerRow, + rowsPerImage, + bytesPerBlock + } = getTextureCopyLayout(format, dimension, size, options); + const [buffer, mapping] = device.createBufferMapped({ + size: byteLength, + usage: C.BufferUsage.CopySrc + }); + assert(texelValue.byteLength === bytesPerBlock); + fillTextureDataWithTexelValue(texelValue, format, dimension, mapping, size, options); + buffer.unmap(); + return { + buffer, + bytesPerRow, + rowsPerImage + }; +} +//# sourceMappingURL=layout.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/subresource.js b/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/subresource.js new file mode 100644 index 00000000000..04a8e7221a8 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/subresource.js @@ -0,0 +1,54 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function endOfRange(r) { + return 'count' in r ? r.begin + r.count : r.end; +} + +function* rangeAsIterator(r) { + for (let i = r.begin; i < endOfRange(r); ++i) { + yield i; + } +} + +export class SubresourceRange { + constructor(subresources) { + _defineProperty(this, "mipRange", void 0); + + _defineProperty(this, "sliceRange", void 0); + + this.mipRange = { + begin: subresources.mipRange.begin, + end: endOfRange(subresources.mipRange) + }; + this.sliceRange = { + begin: subresources.sliceRange.begin, + end: endOfRange(subresources.sliceRange) + }; + } + + *each() { + for (let level = this.mipRange.begin; level < this.mipRange.end; ++level) { + for (let slice = this.sliceRange.begin; slice < this.sliceRange.end; ++slice) { + yield { + level, + slice + }; + } + } + } + + *mipLevels() { + for (let level = this.mipRange.begin; level < this.mipRange.end; ++level) { + yield { + level, + slices: rangeAsIterator(this.sliceRange) + }; + } + } + +} +//# sourceMappingURL=subresource.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/texelData.js b/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/texelData.js new file mode 100644 index 00000000000..2ea7275e710 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/util/texture/texelData.js @@ -0,0 +1,455 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +import { assert, unreachable } from '../../../common/framework/util/util.js'; +import { kTextureFormatInfo } from '../../capability_info.js'; +import { assertInIntegerRange, float32ToFloatBits, floatAsNormalizedInteger, gammaCompress } from '../conversion.js'; +export let TexelComponent; + +(function (TexelComponent) { + TexelComponent["R"] = "R"; + TexelComponent["G"] = "G"; + TexelComponent["B"] = "B"; + TexelComponent["A"] = "A"; + TexelComponent["Depth"] = "Depth"; + TexelComponent["Stencil"] = "Stencil"; +})(TexelComponent || (TexelComponent = {})); + +var TexelWriteType; // Function to convert a value into a texel value. It returns the converted value +// and the type of the converted value. For example, conversion may convert: +// - floats to unsigned normalized integers +// - floats to half floats, interpreted as uint16 bits + +(function (TexelWriteType) { + TexelWriteType[TexelWriteType["Sint"] = 0] = "Sint"; + TexelWriteType[TexelWriteType["Uint"] = 1] = "Uint"; + TexelWriteType[TexelWriteType["Float"] = 2] = "Float"; +})(TexelWriteType || (TexelWriteType = {})); + +const kR = [TexelComponent.R]; +const kRG = [TexelComponent.R, TexelComponent.G]; +const kRGB = [TexelComponent.R, TexelComponent.G, TexelComponent.B]; +const kRGBA = [TexelComponent.R, TexelComponent.G, TexelComponent.B, TexelComponent.A]; +const kBGRA = [TexelComponent.B, TexelComponent.G, TexelComponent.R, TexelComponent.A]; + +const unorm = bitLength => n => ({ + value: floatAsNormalizedInteger(n, bitLength, false), + type: TexelWriteType.Uint +}); + +const snorm = bitLength => n => ({ + value: floatAsNormalizedInteger(n, bitLength, true), + type: TexelWriteType.Sint +}); + +const uint = bitLength => n => ({ + value: (assertInIntegerRange(n, bitLength, false), n), + type: TexelWriteType.Uint +}); + +const sint = bitLength => n => ({ + value: (assertInIntegerRange(n, bitLength, true), n), + type: TexelWriteType.Sint +}); + +const unorm2 = { + write: unorm(2), + bitLength: 2 +}; +const unorm8 = { + write: unorm(8), + bitLength: 8 +}; +const unorm10 = { + write: unorm(10), + bitLength: 10 +}; +const snorm8 = { + write: snorm(8), + bitLength: 8 +}; +const uint8 = { + write: uint(8), + bitLength: 8 +}; +const uint16 = { + write: uint(16), + bitLength: 16 +}; +const uint32 = { + write: uint(32), + bitLength: 32 +}; +const sint8 = { + write: sint(8), + bitLength: 8 +}; +const sint16 = { + write: sint(16), + bitLength: 16 +}; +const sint32 = { + write: sint(32), + bitLength: 32 +}; +const float10 = { + write: n => ({ + value: float32ToFloatBits(n, 0, 5, 5, 15), + type: TexelWriteType.Uint + }), + bitLength: 10 +}; +const float11 = { + write: n => ({ + value: float32ToFloatBits(n, 0, 5, 6, 15), + type: TexelWriteType.Uint + }), + bitLength: 11 +}; +const float16 = { + write: n => ({ + value: float32ToFloatBits(n, 1, 5, 10, 15), + type: TexelWriteType.Uint + }), + bitLength: 16 +}; +const float32 = { + write: n => ({ + value: Math.fround(n), + type: TexelWriteType.Float + }), + bitLength: 32 +}; + +const repeatComponents = (componentOrder, perComponentInfo) => { + const componentInfo = componentOrder.reduce((acc, curr) => { + return Object.assign(acc, { + [curr]: perComponentInfo + }); + }, {}); + return { + componentOrder, + componentInfo + }; +}; + +const kRepresentationInfo = +/* prettier-ignore */ +{ + 'r8unorm': { ...repeatComponents(kR, unorm8), + sRGB: false + }, + 'r8snorm': { ...repeatComponents(kR, snorm8), + sRGB: false + }, + 'r8uint': { ...repeatComponents(kR, uint8), + sRGB: false + }, + 'r8sint': { ...repeatComponents(kR, sint8), + sRGB: false + }, + 'r16uint': { ...repeatComponents(kR, uint16), + sRGB: false + }, + 'r16sint': { ...repeatComponents(kR, sint16), + sRGB: false + }, + 'r16float': { ...repeatComponents(kR, float16), + sRGB: false + }, + 'rg8unorm': { ...repeatComponents(kRG, unorm8), + sRGB: false + }, + 'rg8snorm': { ...repeatComponents(kRG, snorm8), + sRGB: false + }, + 'rg8uint': { ...repeatComponents(kRG, uint8), + sRGB: false + }, + 'rg8sint': { ...repeatComponents(kRG, sint8), + sRGB: false + }, + 'r32uint': { ...repeatComponents(kR, uint32), + sRGB: false + }, + 'r32sint': { ...repeatComponents(kR, sint32), + sRGB: false + }, + 'r32float': { ...repeatComponents(kR, float32), + sRGB: false + }, + 'rg16uint': { ...repeatComponents(kRG, uint16), + sRGB: false + }, + 'rg16sint': { ...repeatComponents(kRG, sint16), + sRGB: false + }, + 'rg16float': { ...repeatComponents(kRG, float16), + sRGB: false + }, + 'rgba8unorm': { ...repeatComponents(kRGBA, unorm8), + sRGB: false + }, + 'rgba8unorm-srgb': { ...repeatComponents(kRGBA, unorm8), + sRGB: true + }, + 'rgba8snorm': { ...repeatComponents(kRGBA, snorm8), + sRGB: false + }, + 'rgba8uint': { ...repeatComponents(kRGBA, uint8), + sRGB: false + }, + 'rgba8sint': { ...repeatComponents(kRGBA, sint8), + sRGB: false + }, + 'bgra8unorm': { ...repeatComponents(kBGRA, unorm8), + sRGB: false + }, + 'bgra8unorm-srgb': { ...repeatComponents(kBGRA, unorm8), + sRGB: true + }, + 'rg32uint': { ...repeatComponents(kRG, uint32), + sRGB: false + }, + 'rg32sint': { ...repeatComponents(kRG, sint32), + sRGB: false + }, + 'rg32float': { ...repeatComponents(kRG, float32), + sRGB: false + }, + 'rgba16uint': { ...repeatComponents(kRGBA, uint16), + sRGB: false + }, + 'rgba16sint': { ...repeatComponents(kRGBA, sint16), + sRGB: false + }, + 'rgba16float': { ...repeatComponents(kRGBA, float16), + sRGB: false + }, + 'rgba32uint': { ...repeatComponents(kRGBA, uint32), + sRGB: false + }, + 'rgba32sint': { ...repeatComponents(kRGBA, sint32), + sRGB: false + }, + 'rgba32float': { ...repeatComponents(kRGBA, float32), + sRGB: false + }, + 'rgb10a2unorm': { + componentOrder: kRGBA, + componentInfo: { + R: unorm10, + G: unorm10, + B: unorm10, + A: unorm2 + }, + sRGB: false + }, + 'rg11b10float': { + componentOrder: kRGB, + componentInfo: { + R: float11, + G: float11, + B: float10 + }, + sRGB: false + }, + 'depth32float': { + componentOrder: [TexelComponent.Depth], + componentInfo: { + Depth: float32 + }, + sRGB: false + }, + 'depth24plus': { + componentOrder: [TexelComponent.Depth], + componentInfo: { + Depth: null + }, + sRGB: false + }, + 'depth24plus-stencil8': { + componentOrder: [TexelComponent.Depth, TexelComponent.Stencil], + componentInfo: { + Depth: null, + Stencil: null + }, + sRGB: false + } +}; + +class TexelDataRepresentationImpl { + // TODO: Determine endianness of the GPU data? + constructor(format, componentOrder, componentInfo, sRGB) { + this.format = format; + this.componentOrder = componentOrder; + this.componentInfo = componentInfo; + this.sRGB = sRGB; + + _defineProperty(this, "isGPULittleEndian", true); + } + + totalBitLength() { + return this.componentOrder.reduce((acc, curr) => { + return acc + this.componentInfo[curr].bitLength; + }, 0); + } + + setComponent(data, component, n) { + const componentIndex = this.componentOrder.indexOf(component); + assert(componentIndex !== -1); + const bitOffset = this.componentOrder.slice(0, componentIndex).reduce((acc, curr) => { + const componentInfo = this.componentInfo[curr]; + assert(!!componentInfo); + return acc + componentInfo.bitLength; + }, 0); + const componentInfo = this.componentInfo[component]; + assert(!!componentInfo); + const { + write, + bitLength + } = componentInfo; + const { + value, + type + } = write(n); + + switch (type) { + case TexelWriteType.Float: + { + const byteOffset = Math.floor(bitOffset / 8); + const byteLength = Math.ceil(bitLength / 8); + assert(byteOffset === bitOffset / 8 && byteLength === bitLength / 8); + + switch (byteLength) { + case 4: + new DataView(data, byteOffset, byteLength).setFloat32(0, value, this.isGPULittleEndian); + break; + + default: + unreachable(); + } + + break; + } + + case TexelWriteType.Sint: + { + const byteOffset = Math.floor(bitOffset / 8); + const byteLength = Math.ceil(bitLength / 8); + assert(byteOffset === bitOffset / 8 && byteLength === bitLength / 8); + + switch (byteLength) { + case 1: + new DataView(data, byteOffset, byteLength).setInt8(0, value); + break; + + case 2: + new DataView(data, byteOffset, byteLength).setInt16(0, value, this.isGPULittleEndian); + break; + + case 4: + new DataView(data, byteOffset, byteLength).setInt32(0, value, this.isGPULittleEndian); + break; + + default: + unreachable(); + } + + break; + } + + case TexelWriteType.Uint: + { + const byteOffset = Math.floor(bitOffset / 8); + const byteLength = Math.ceil(bitLength / 8); + + if (byteOffset === bitOffset / 8 && byteLength === bitLength / 8) { + switch (byteLength) { + case 1: + new DataView(data, byteOffset, byteLength).setUint8(0, value); + break; + + case 2: + new DataView(data, byteOffset, byteLength).setUint16(0, value, this.isGPULittleEndian); + break; + + case 4: + new DataView(data, byteOffset, byteLength).setUint32(0, value, this.isGPULittleEndian); + break; + + default: + unreachable(); + } + } else { + // Packed representations are all 32-bit and use Uint as the data type. + // ex.) rg10b11float, rgb10a2unorm + switch (this.totalBitLength()) { + case 32: + { + const view = new DataView(data); + const currentValue = view.getUint32(0, this.isGPULittleEndian); + let mask = 0xffffffff; + const bitsToClearRight = bitOffset; + const bitsToClearLeft = 32 - (bitLength + bitOffset); + mask = mask >>> bitsToClearRight << bitsToClearRight; + mask = mask << bitsToClearLeft >>> bitsToClearLeft; + const newValue = currentValue & ~mask | value << bitOffset; + view.setUint32(0, newValue, this.isGPULittleEndian); + break; + } + + default: + unreachable(); + } + } + + break; + } + + default: + unreachable(); + } + } + + getBytes(components) { + if (this.sRGB) { + components = Object.assign({}, components); + assert(components.R !== undefined); + assert(components.G !== undefined); + assert(components.B !== undefined); + [components.R, components.G, components.B] = [gammaCompress(components.R), gammaCompress(components.G), gammaCompress(components.B)]; + } + + const bytesPerBlock = kTextureFormatInfo[this.format].bytesPerBlock; + assert(!!bytesPerBlock); + const data = new ArrayBuffer(bytesPerBlock); + + for (const c of this.componentOrder) { + const componentValue = components[c]; + assert(componentValue !== undefined); + this.setComponent(data, c, componentValue); + } + + return data; + } + +} + +const kRepresentationCache = new Map(); +export function getTexelDataRepresentation(format) { + if (!kRepresentationCache.has(format)) { + const { + componentOrder, + componentInfo, + sRGB + } = kRepresentationInfo[format]; + kRepresentationCache.set(format, new TexelDataRepresentationImpl(format, componentOrder, componentInfo, sRGB)); + } + + return kRepresentationCache.get(format); +} +//# sourceMappingURL=texelData.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/canvas/context_creation.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/canvas/context_creation.spec.js index fd8593b642e..427b15fced4 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/canvas/context_creation.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/canvas/context_creation.spec.js @@ -2,11 +2,11 @@ * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ -export const description = ``; +export const description = ''; import { Fixture } from '../../../common/framework/fixture.js'; -import { TestGroup } from '../../../common/framework/test_group.js'; -export const g = new TestGroup(Fixture); -g.test('canvas element getContext returns GPUCanvasContext', async t => { +import { makeTestGroup } from '../../../common/framework/test_group.js'; +export const g = makeTestGroup(Fixture); +g.test('canvas_element_getContext_returns_GPUCanvasContext').fn(async t => { if (typeof document === 'undefined') { // Skip if there is no document (Workers, Node) t.skip('DOM is not available to create canvas element'); diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js index 5e84113b95a..de978550acc 100644 --- a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js @@ -5,8 +5,8 @@ export const description = ` copy imageBitmap To texture tests. `; -import { pcombine, poptions } from '../../common/framework/params.js'; -import { TestGroup } from '../../common/framework/test_group.js'; +import { poptions, params } from '../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../common/framework/test_group.js'; import { GPUTest } from '../gpu_test.js'; function calculateRowPitch(width, bytesPerPixel) { @@ -26,7 +26,7 @@ class F extends GPUTest { if (check !== undefined) { niceStack.message = check; - this.rec.fail(niceStack); + this.rec.expectationFailed(niceStack); } dst.destroy(); @@ -34,10 +34,11 @@ class F extends GPUTest { } checkBufferWithRowPitch(actual, exp, width, height, rowPitch, bytesPerPixel) { - const lines = []; - let failedPixels = 0; + const failedByteIndices = []; + const failedByteExpectedValues = []; + const failedByteActualValues = []; - for (let i = 0; i < height; ++i) { + iLoop: for (let i = 0; i < height; ++i) { const bytesPerRow = width * bytesPerPixel; for (let j = 0; j < bytesPerRow; ++j) { @@ -45,22 +46,27 @@ class F extends GPUTest { const indexActual = j + rowPitch * i; if (actual[indexActual] !== exp[indexExp]) { - if (failedPixels > 4) { - break; + if (failedByteIndices.length >= 4) { + failedByteIndices.push('...'); + failedByteExpectedValues.push('...'); + failedByteActualValues.push('...'); + break iLoop; } - failedPixels++; - lines.push(`at [${indexExp}], expected ${exp[indexExp]}, got ${actual[indexActual]}`); + failedByteIndices.push(`(${i},${j})`); + failedByteExpectedValues.push(exp[indexExp].toString()); + failedByteActualValues.push(actual[indexActual].toString()); } } + } - if (failedPixels > 4) { - lines.push('... and more'); - break; - } + if (failedByteIndices.length > 0) { + return `at [${failedByteIndices.join(', ')}], \ +expected [${failedByteExpectedValues.join(', ')}], \ +got [${failedByteActualValues.join(', ')}]`; } - return failedPixels > 0 ? lines.join('\n') : undefined; + return undefined; } doTestAndCheckResult(imageBitmapCopyView, dstTextureCopyView, copySize, bytesPerPixel, expectedData) { @@ -95,22 +101,36 @@ class F extends GPUTest { } -export const g = new TestGroup(F); -g.test('from ImageData', async t => { +export const g = makeTestGroup(F); +g.test('from_ImageData').params(params().combine(poptions('width', [1, 2, 4, 15, 255, 256])).combine(poptions('height', [1, 2, 4, 15, 255, 256])).combine(poptions('alpha', ['none', 'premultiply'])).combine(poptions('orientation', ['none', 'flipY']))).fn(async t => { const { width, - height + height, + alpha, + orientation } = t.params; // The texture format is rgba8unorm, so the bytes per pixel is 4. const bytesPerPixel = 4; const imagePixels = new Uint8ClampedArray(bytesPerPixel * width * height); - for (let i = 0; i < width * height * bytesPerPixel; ++i) { - imagePixels[i] = i % 4 === 3 ? 255 : i % 256; + if (alpha === 'premultiply') { + // Make expected value simple to construct: + // Input is (255, 255, 255, a), which will be stored into the ImageBitmap + // as (a, a, a, a). + for (let i = 0; i < width * height * bytesPerPixel; ++i) { + imagePixels[i] = i % 4 !== 3 ? 255 : i % 256; + } + } else { + for (let i = 0; i < width * height * bytesPerPixel; ++i) { + imagePixels[i] = i % 4 === 3 ? 255 : i % 256; + } } const imageData = new ImageData(imagePixels, width, height); - const imageBitmap = await createImageBitmap(imageData); + const imageBitmap = await createImageBitmap(imageData, { + premultiplyAlpha: alpha, + imageOrientation: orientation + }); const dst = t.device.createTexture({ size: { width: imageBitmap.width, @@ -119,7 +139,35 @@ g.test('from ImageData', async t => { }, format: 'rgba8unorm', usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC - }); + }); // Construct expected value + + const expectedPixels = new Uint8ClampedArray(bytesPerPixel * width * height); + + for (let i = 0; i < width * height * bytesPerPixel; ++i) { + expectedPixels[i] = imagePixels[i]; + } + + if (orientation === 'flipY') { + for (let i = 0; i < height; ++i) { + for (let j = 0; j < width * bytesPerPixel; ++j) { + const pos_image_pixel = (height - i - 1) * width * bytesPerPixel + j; + const pos_expected_value = i * width * bytesPerPixel + j; + expectedPixels[pos_expected_value] = imagePixels[pos_image_pixel]; + } + } + } + + if (alpha === 'premultiply') { + for (let i = 0; i < width * height * bytesPerPixel; ++i) { + const alpha_value_position = 3 - i % 4 + i; + + if (i % 4 !== 3) { + // Expected value is (a, a, a, a) + expectedPixels[i] = expectedPixels[alpha_value_position]; + } + } + } + t.doTestAndCheckResult({ imageBitmap, origin: { @@ -132,10 +180,9 @@ g.test('from ImageData', async t => { width: imageBitmap.width, height: imageBitmap.height, depth: 1 - }, bytesPerPixel, imagePixels); -}).params(pcombine(poptions('width', [1, 2, 4, 15, 255, 256]), // -poptions('height', [1, 2, 4, 15, 255, 256]))); -g.test('from canvas', async t => { + }, bytesPerPixel, expectedPixels); +}); +g.test('from_canvas').params(params().combine(poptions('width', [1, 2, 4, 15, 255, 256])).combine(poptions('height', [1, 2, 4, 15, 255, 256]))).fn(async t => { const { width, height @@ -171,7 +218,7 @@ g.test('from canvas', async t => { const imagePixels = new Uint8ClampedArray(bytesPerPixel * width * height); for (let i = 0; i < width * height * bytesPerPixel; ++i) { - imagePixels[i] = i % 256; + imagePixels[i] = i % 4 === 3 ? 255 : i % 256; } const imageData = new ImageData(imagePixels, width, height); @@ -185,7 +232,8 @@ g.test('from canvas', async t => { }, format: 'rgba8unorm', usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC - }); + }); // This will get origin data and even it has premultiplied-alpha + const expectedData = imageCanvasContext.getImageData(0, 0, imageBitmap.width, imageBitmap.height).data; t.doTestAndCheckResult({ imageBitmap, @@ -200,6 +248,5 @@ g.test('from canvas', async t => { height: imageBitmap.height, depth: 1 }, bytesPerPixel, expectedData); -}).params(pcombine(poptions('width', [1, 2, 4, 15, 255, 256]), // -poptions('height', [1, 2, 4, 15, 255, 256]))); +}); //# sourceMappingURL=copyImageBitmapToTexture.spec.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_clear.html b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_clear.html new file mode 100644 index 00000000000..86a3da939db --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_clear.html @@ -0,0 +1,10 @@ +<html class="reftest-wait"> + <title>WebGPU canvas_clear</title> + <meta charset="utf-8" /> + <link rel="help" href="https://gpuweb.github.io/gpuweb/" /> + <meta name="assert" content="WebGPU cleared canvas should be presented correctly" /> + <link rel="match" href="./ref/canvas_clear-ref.html" /> + <canvas id="gpucanvas" width="10" height="10"></canvas> + <script src="/common/reftest-wait.js"></script> + <script type="module" src="canvas_clear.js"></script> +</html> diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_clear.js b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_clear.js new file mode 100644 index 00000000000..52ffaedad84 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_clear.js @@ -0,0 +1,31 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { runRefTest } from './gpu_ref_test.js'; +runRefTest(async t => { + const canvas = document.getElementById('gpucanvas'); + const ctx = canvas.getContext('gpupresent'); + const swapChain = ctx.configureSwapChain({ + device: t.device, + format: 'bgra8unorm' + }); + const colorAttachment = swapChain.getCurrentTexture(); + const colorAttachmentView = colorAttachment.createView(); + const encoder = t.device.createCommandEncoder(); + const pass = encoder.beginRenderPass({ + colorAttachments: [{ + attachment: colorAttachmentView, + loadValue: { + r: 0.0, + g: 1.0, + b: 0.0, + a: 1.0 + }, + storeOp: 'store' + }] + }); + pass.endPass(); + t.device.defaultQueue.submit([encoder.finish()]); +}); +//# sourceMappingURL=canvas_clear.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_complex.js b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_complex.js new file mode 100644 index 00000000000..1e63a0ab202 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_complex.js @@ -0,0 +1,90 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { unreachable } from '../../../common/framework/util/util.js'; +import { runRefTest } from './gpu_ref_test.js'; // <canvas> element from html page + +export function run(format) { + runRefTest(async t => { + const ctx = cvs.getContext('gpupresent'); + + switch (format) { + case 'bgra8unorm': + case 'rgba16float': + break; + + default: + unreachable(); + } + + const swapChain = ctx.configureSwapChain({ + device: t.device, + format, + usage: GPUTextureUsage.COPY_DST + }); + const rows = 2; + const bytesPerRow = 256; + const [buffer, mapping] = t.device.createBufferMapped({ + size: rows * bytesPerRow, + usage: GPUBufferUsage.COPY_SRC + }); + + switch (format) { + case 'bgra8unorm': + { + const data = new Uint8Array(mapping); + data.set(new Uint8Array([0x00, 0x00, 0x7f, 0xff]), 0); // red + + data.set(new Uint8Array([0x00, 0x7f, 0x00, 0xff]), 4); // green + + data.set(new Uint8Array([0x7f, 0x00, 0x00, 0xff]), 256 + 0); // blue + + data.set(new Uint8Array([0x00, 0x7f, 0x7f, 0xff]), 256 + 4); // yellow + } + break; + + case 'rgba16float': + { + // Untested! + const zero = 0x0000; + const half = 0x3800; + const one = 0x3c00; + const data = new DataView(mapping); + data.setUint16(0x000, half, false); // red + + data.setUint16(0x002, zero, false); + data.setUint16(0x004, zero, false); + data.setUint16(0x008, one, false); + data.setUint16(0x010, zero, false); // green + + data.setUint16(0x020, half, false); + data.setUint16(0x040, zero, false); + data.setUint16(0x080, one, false); + data.setUint16(0x100, zero, false); // blue + + data.setUint16(0x102, zero, false); + data.setUint16(0x104, half, false); + data.setUint16(0x108, one, false); + data.setUint16(0x110, half, false); // yellow + + data.setUint16(0x120, half, false); + data.setUint16(0x140, zero, false); + data.setUint16(0x180, one, false); + } + break; + } + + buffer.unmap(); + const texture = swapChain.getCurrentTexture(); + const encoder = t.device.createCommandEncoder(); + encoder.copyBufferToTexture({ + buffer, + bytesPerRow + }, { + texture + }, [2, 2, 1]); + t.device.defaultQueue.submit([encoder.finish()]); + }); +} +//# sourceMappingURL=canvas_complex.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_complex_bgra8unorm.html b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_complex_bgra8unorm.html new file mode 100644 index 00000000000..1310543648e --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/canvas_complex_bgra8unorm.html @@ -0,0 +1,18 @@ +<html class="reftest-wait"> + <title>WebGPU canvas_complex_bgra8unorm</title> + <meta charset="utf-8" /> + <link rel="help" href="https://gpuweb.github.io/gpuweb/" /> + <meta + name="assert" + content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space" + /> + <link rel="match" href="./ref/canvas_complex-ref.html" /> + + <canvas id="cvs" width="2" height="2" style="width: 20px; height: 20px;"></canvas> + <script src="/common/reftest-wait.js"></script> + <script type="module"> + import { run } from './canvas_complex.js'; + run('bgra8unorm'); + // TODO: make a copy of this test for rgba16float + </script> +</html> diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/gpu_ref_test.js b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/gpu_ref_test.js new file mode 100644 index 00000000000..f45f232557c --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/gpu_ref_test.js @@ -0,0 +1,17 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +import { assert } from '../../../common/framework/util/util.js'; +export async function runRefTest(fn) { + assert(typeof navigator !== 'undefined' && navigator.gpu !== undefined, 'No WebGPU implementation found'); + const adapter = await navigator.gpu.requestAdapter(); + const device = await adapter.requestDevice(); + const queue = device.defaultQueue; + await fn({ + device, + queue + }); + takeScreenshotDelayed(50); +} +//# sourceMappingURL=gpu_ref_test.js.map
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/ref/canvas_clear-ref.html b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/ref/canvas_clear-ref.html new file mode 100644 index 00000000000..2e078118627 --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/ref/canvas_clear-ref.html @@ -0,0 +1,12 @@ +<html> + <title>WebGPU canvas_clear (ref)</title> + <meta charset="utf-8" /> + <link rel="help" href="https://gpuweb.github.io/gpuweb/" /> + <canvas id="myCanvas" width="10" height="10"></canvas> + <script> + var c = document.getElementById('myCanvas'); + var ctx = c.getContext('2d'); + ctx.fillStyle = '#00FF00'; + ctx.fillRect(0, 0, c.width, c.height); + </script> +</html> diff --git a/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/ref/canvas_complex-ref.html b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/ref/canvas_complex-ref.html new file mode 100644 index 00000000000..3d5b3b3376d --- /dev/null +++ b/tests/wpt/web-platform-tests/webgpu/webgpu/web-platform/reftests/ref/canvas_complex-ref.html @@ -0,0 +1,17 @@ +<html> + <title>WebGPU canvas_complex (ref)</title> + <meta charset="utf-8" /> + <link rel="help" href="https://gpuweb.github.io/gpuweb/" /> + <canvas id="cvs" width="2" height="2" style="width: 20px; height: 20px;"></canvas> + <script> + const ctx = cvs.getContext('2d'); + ctx.fillStyle = '#7F0000'; + ctx.fillRect(0, 0, 1, 1); + ctx.fillStyle = '#007F00'; + ctx.fillRect(1, 0, 1, 1); + ctx.fillStyle = '#00007F'; + ctx.fillRect(0, 1, 1, 1); + ctx.fillStyle = '#7F7F00'; + ctx.fillRect(1, 1, 1, 1); + </script> +</html> diff --git a/tests/wpt/web-platform-tests/webtransport/quic/handlers/client-indication.quic.py b/tests/wpt/web-platform-tests/webtransport/quic/handlers/client-indication.quic.py index da0701cc04b..56238c7514c 100644 --- a/tests/wpt/web-platform-tests/webtransport/quic/handlers/client-indication.quic.py +++ b/tests/wpt/web-platform-tests/webtransport/quic/handlers/client-indication.quic.py @@ -12,6 +12,9 @@ async def notify_pass(connection: QuicConnectionProtocol): writer.write_eof() +# Verifies that the client indication sent by the client is correct. Creates +# a unidirectional stream containing "PASS" when the check finishes +# sucessfully. def handle_client_indication(connection: QuicConnectionProtocol, origin: str, query: Dict[str, str]): logging.log(logging.INFO, 'origin = %s, query = %s' % (origin, query)) diff --git a/tests/wpt/webgl/meta/conformance2/rendering/draw-buffers.html.ini b/tests/wpt/webgl/meta/conformance2/rendering/draw-buffers.html.ini index d0af30448df..d4b3a4f7564 100644 --- a/tests/wpt/webgl/meta/conformance2/rendering/draw-buffers.html.ini +++ b/tests/wpt/webgl/meta/conformance2/rendering/draw-buffers.html.ini @@ -140,3 +140,6 @@ [WebGL test #52: attachment 7 should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 0,0,0,255] expected: FAIL + [WebGL test #42: attachment 5 should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 0,0,255,0] + expected: FAIL + |