mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Update web-platform-tests to revision 6c36430fc9e5ae99b06eba617f557e0271dd78b7
This commit is contained in:
parent
216c13cdc4
commit
594dfab11c
142 changed files with 987 additions and 9381 deletions
|
@ -1,4 +0,0 @@
|
|||
[hit-test-floats-003.html]
|
||||
[Miss float below something else]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[hit-test-floats-005.html]
|
||||
[Miss clipped float]
|
||||
expected: FAIL
|
||||
|
|
@ -17,6 +17,3 @@
|
|||
[test the top of layer]
|
||||
expected: FAIL
|
||||
|
||||
[test some point of the element: top left corner]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[matchMedia-display-none-iframe.html]
|
||||
expected: ERROR
|
|
@ -0,0 +1,10 @@
|
|||
[Event-dispatch-click.html]
|
||||
[event state during post-click handling]
|
||||
expected: FAIL
|
||||
|
||||
[disabled radio should be checked from dispatchEvent(new MouseEvent("click"))]
|
||||
expected: FAIL
|
||||
|
||||
[disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))]
|
||||
expected: FAIL
|
||||
|
|
@ -315,15 +315,18 @@
|
|||
[<iframe>: separate response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
||||
[<iframe>: separate response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/plain ]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -56,6 +56,9 @@
|
|||
[separate text/javascript x/x]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript error]
|
||||
[separate text/javascript;charset=windows-1252 error text/javascript]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript ]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -11,6 +11,3 @@
|
|||
[X-Content-Type-Options%3A%20nosniff%2C%2C%40%23%24%23%25%25%26%5E%26%5E*()()11!]
|
||||
expected: FAIL
|
||||
|
||||
[X-Content-Type-Options%3A%20%2Cnosniff]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_3.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[creating_browsing_context_test_01.html]
|
||||
[first argument: absolute url]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
[iframe_sandbox_popups_escaping-1.html]
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[iframe_sandbox_popups_escaping-2.html]
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[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
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[iframe_sandbox_popups_nonescaping-2.html]
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[iframe_sandbox_popups_nonescaping-3.html]
|
||||
expected: TIMEOUT
|
||||
expected: CRASH
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
[htmlanchorelement_noopener.html]
|
||||
expected: TIMEOUT
|
||||
[Check that targeting of rel=noopener with a given name reuses an existing window with that name]
|
||||
expected: FAIL
|
||||
|
||||
[Check that rel=noopener with target=_top does a normal load]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Check that rel=noopener with target=_self does a normal load]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Check that rel=noopener with target=_parent does a normal load]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[077.html]
|
||||
[ adding several types of scripts through the DOM and removing some of them confuses scheduler ]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[018.html]
|
||||
expected: TIMEOUT
|
||||
[origin of the script that invoked the method, javascript:]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
[xrSession_requestSessionDuringEnd.https.html]
|
||||
[Create new session in OnSessionEnded event]
|
||||
expected: FAIL
|
||||
|
||||
[Create mew session in end promise]
|
||||
expected: FAIL
|
||||
|
|
@ -15751,6 +15751,13 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"historical-manual.html": [
|
||||
"0e2147222d9435793374e37bdf1cb49796749711",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"relatedTarget-attribute-manual.html": [
|
||||
"c5a897d68e4cd79265d99bb0f637feaf144f6cd4",
|
||||
[
|
||||
|
@ -16081,7 +16088,7 @@
|
|||
},
|
||||
"the-dragevent-interface": {
|
||||
"dragevent-manual.html": [
|
||||
"aafe83205fdf3fda301caba3a5313a9a177771b6",
|
||||
"e4d754e459077bbe5dcb59d0ca9ab2d92fa3bdfd",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
|
@ -245365,40 +245372,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
|
@ -248892,7 +248865,7 @@
|
|||
]
|
||||
},
|
||||
"support-promises.js": [
|
||||
"8195be341e18860865c072bc78a1efa1f25f2d56",
|
||||
"9128bfe151ab9cda59ff6e3d4487024b0b7cd0cb",
|
||||
[]
|
||||
],
|
||||
"support.js": [
|
||||
|
@ -330366,7 +330339,7 @@
|
|||
[]
|
||||
],
|
||||
"build.sh": [
|
||||
"ae1563ad85de7f5cc502d75b079121236de9b249",
|
||||
"f69fa4ff17d9ffe18559c34546139872c6a8e2e2",
|
||||
[]
|
||||
],
|
||||
"current-work-canvas.xhtml": [
|
||||
|
@ -341389,7 +341362,7 @@
|
|||
]
|
||||
},
|
||||
"lint.ignore": [
|
||||
"6b79e8a757ddbc16278511d0ace1a69720f5bdb9",
|
||||
"a17a09402e01ca07a56b8270d1ec45f745377544",
|
||||
[]
|
||||
],
|
||||
"loading": {
|
||||
|
@ -351367,11 +351340,11 @@
|
|||
[]
|
||||
],
|
||||
"lint.py": [
|
||||
"8a1149c7f054c897163c9310f335ec2183259afc",
|
||||
"7bec438b773da96e30986aa974b66043248bc079",
|
||||
[]
|
||||
],
|
||||
"rules.py": [
|
||||
"1bf78b7bb405f132536d162ba920dd2de9e08f09",
|
||||
"f6e23aef58ad3a97a0ba8bf5514cb802f2e0f31b",
|
||||
[]
|
||||
],
|
||||
"tests": {
|
||||
|
@ -351576,7 +351549,7 @@
|
|||
[]
|
||||
],
|
||||
"test_path_lints.py": [
|
||||
"7368216cd3dd6ba54843cfe7390b876a357d3490",
|
||||
"9fefb7a1d7e0615044ae00acb0b8e64481e41b97",
|
||||
[]
|
||||
]
|
||||
}
|
||||
|
@ -358091,7 +358064,7 @@
|
|||
[]
|
||||
],
|
||||
"executormarionette.py": [
|
||||
"05223d374feb7bfeea1321d2ec8fbd99fa9fddb7",
|
||||
"1ba9f06aabc8cf10e91cf3aa92643562f05a1c1a",
|
||||
[]
|
||||
],
|
||||
"executoropera.py": [
|
||||
|
@ -360637,7 +360610,7 @@
|
|||
[]
|
||||
],
|
||||
"test_actions_wdspec.html": [
|
||||
"39a8876e54ad183b900acbb552a5930b5b4b83fd",
|
||||
"0253add960792f79bef8a8747dac26661c4a2f86",
|
||||
[]
|
||||
]
|
||||
}
|
||||
|
@ -360804,357 +360777,13 @@
|
|||
[]
|
||||
],
|
||||
"META.yml": [
|
||||
"befe8a68dd5d060da9480f9a967fd11060281967",
|
||||
"163130faea362a087959cee4cfbaba729893e225",
|
||||
[]
|
||||
],
|
||||
"README.md": [
|
||||
"ef0dbfee60ce3e787131ca40e5be64952e578e03",
|
||||
"24a68b3ad3e89ea6617f02d90c890c1d04cf717e",
|
||||
[]
|
||||
],
|
||||
"common": {
|
||||
"framework": {
|
||||
"file_loader.js": [
|
||||
"0f25ca465d3df9231ad1faecd4373305ee423847",
|
||||
[]
|
||||
],
|
||||
"fixture.js": [
|
||||
"ef23f06596bd7cc244484102008db8ca9485c2c8",
|
||||
[]
|
||||
],
|
||||
"gpu": {
|
||||
"device_pool.js": [
|
||||
"848e5802817b43e26c8e25ecfec48c0ea9fe8816",
|
||||
[]
|
||||
],
|
||||
"implementation.js": [
|
||||
"670872b5d6e32ebf3815935fdd9fec605056a30c",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"logging": {
|
||||
"log_message.js": [
|
||||
"11f352f892e76eb0140f0fe36249f41e103e1e05",
|
||||
[]
|
||||
],
|
||||
"logger.js": [
|
||||
"8d66c554c5ad8b48df127d914883fc8f4578bc38",
|
||||
[]
|
||||
],
|
||||
"result.js": [
|
||||
"813e781ba28ce0471d17d439c0fc20ed400f68ac",
|
||||
[]
|
||||
],
|
||||
"test_case_recorder.js": [
|
||||
"d16af0f2b861421cb77050648440ae4e4fbd3d39",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"params_builder.js": [
|
||||
"10dd239df93c6ce1a9ae8559586c6c304b3243e2",
|
||||
[]
|
||||
],
|
||||
"params_utils.js": [
|
||||
"161feb5d4306ea30ae56c7ba6f76ac81f90a25ba",
|
||||
[]
|
||||
],
|
||||
"query": {
|
||||
"compare.js": [
|
||||
"52396f352e64e13e30d9823f04e55525be38624e",
|
||||
[]
|
||||
],
|
||||
"encode_selectively.js": [
|
||||
"e153cf8ccd89b8e6bfb0346581e0139eed865565",
|
||||
[]
|
||||
],
|
||||
"parseQuery.js": [
|
||||
"758227cc520f486f4a0662d0935eaa86a1aa937b",
|
||||
[]
|
||||
],
|
||||
"query.js": [
|
||||
"8b352241f8b95b1caa60ac331e7f4c47b5236c64",
|
||||
[]
|
||||
],
|
||||
"separators.js": [
|
||||
"e378a9d1d290de77dfc46f00e8afa644ce13cb18",
|
||||
[]
|
||||
],
|
||||
"stringify_params.js": [
|
||||
"b5503ffb54ead8677dfb5189aecd9e46fcf30cad",
|
||||
[]
|
||||
],
|
||||
"validQueryPart.js": [
|
||||
"3c051afc94b46f2500b13eafceac6a8dc0171c3e",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"test_group.js": [
|
||||
"5ced9cd3d372ad9b5d6e1ad3f240554e2bab490b",
|
||||
[]
|
||||
],
|
||||
"test_suite_listing.js": [
|
||||
"99c900217c1463e09faefd01e0db96498db7ca92",
|
||||
[]
|
||||
],
|
||||
"tree.js": [
|
||||
"69dfac21a635c278dae9daab4c8adb81aec550d9",
|
||||
[]
|
||||
],
|
||||
"util": {
|
||||
"async_mutex.js": [
|
||||
"cb900605bcfe77bae785c207419787e317bf1d73",
|
||||
[]
|
||||
],
|
||||
"collect_garbage.js": [
|
||||
"d4b5bb19b233f4306241973e5d7935af715f7141",
|
||||
[]
|
||||
],
|
||||
"stack.js": [
|
||||
"99653f888066181e5fbac7a7a4331f6cb4fe3ecb",
|
||||
[]
|
||||
],
|
||||
"timeout.js": [
|
||||
"e565a518efc045cfc90e7dd7b23dc65604c6b805",
|
||||
[]
|
||||
],
|
||||
"util.js": [
|
||||
"b64379982a60f7b4551b7611feb7fdcf288d560e",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"version.js": [
|
||||
"4b233137825b86fb1d70896601d6e63a4f42865d",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"runtime": {
|
||||
"helper": {
|
||||
"options.js": [
|
||||
"1a90beadf1ee459911b2b549fc9359b44fe37bbd",
|
||||
[]
|
||||
],
|
||||
"test_worker-worker.js": [
|
||||
"a02c98c2bbfbc27ae109fed082702f5367b2afad",
|
||||
[]
|
||||
],
|
||||
"test_worker.js": [
|
||||
"7e8b9a47c077261e8dcacb21487989edbd146e2c",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"wpt.js": [
|
||||
"dc38b77b1d5ad3517f0463285f35881cf28aee08",
|
||||
[]
|
||||
]
|
||||
}
|
||||
},
|
||||
"webgpu": {
|
||||
"api": {
|
||||
"operation": {
|
||||
"buffers": {
|
||||
"create_mapped.spec.js": [
|
||||
"1c3b1254d503727d9efd189ec6b9eba5bac3a79b",
|
||||
[]
|
||||
],
|
||||
"map.spec.js": [
|
||||
"e8c86ec1b8a4539742d10309967b1d0578b38cee",
|
||||
[]
|
||||
],
|
||||
"map_detach.spec.js": [
|
||||
"8ae0be0b197ac1ae1a6bac48dacd00ecc8ec2a9e",
|
||||
[]
|
||||
],
|
||||
"map_oom.spec.js": [
|
||||
"8494dc7ddc769f166a6422531d34565cd4810a16",
|
||||
[]
|
||||
],
|
||||
"mapping_test.js": [
|
||||
"b7349059035d46dffc1156314c7dfe7ec7526d54",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"command_buffer": {
|
||||
"basic.spec.js": [
|
||||
"547a08683f7318d5aceb2e26096166c1c994c579",
|
||||
[]
|
||||
],
|
||||
"copies.spec.js": [
|
||||
"cc2ea6deae161d2025119beda183dfb767b63795",
|
||||
[]
|
||||
],
|
||||
"render": {
|
||||
"basic.spec.js": [
|
||||
"815eb5b70b0092c096fe385ad94729f62ef44761",
|
||||
[]
|
||||
]
|
||||
}
|
||||
},
|
||||
"fences.spec.js": [
|
||||
"f9f079b6241fa99a6895250329b18fb88d895ac3",
|
||||
[]
|
||||
],
|
||||
"resource_init": {
|
||||
"copied_texture_clear.spec.js": [
|
||||
"f5b8b697d74e75ecd2e5fb149f29d69e8c6c3610",
|
||||
[]
|
||||
],
|
||||
"texture_zero_init_test.js": [
|
||||
"8dda949f85954069826ee50aa5b58933b5fc8e3f",
|
||||
[]
|
||||
]
|
||||
}
|
||||
},
|
||||
"validation": {
|
||||
"createBindGroup.spec.js": [
|
||||
"5deed893d5e4ef039d25479b63c2a35892e81d17",
|
||||
[]
|
||||
],
|
||||
"createBindGroupLayout.spec.js": [
|
||||
"2fec032c178f8be0b92ef45278d39886ad9cfc8d",
|
||||
[]
|
||||
],
|
||||
"createPipelineLayout.spec.js": [
|
||||
"4e293fa725dfe18f789f4fb7afaf0fad4a0cd14c",
|
||||
[]
|
||||
],
|
||||
"createTexture.spec.js": [
|
||||
"2ef8d19523311d64519af8ecff18d27ac9695749",
|
||||
[]
|
||||
],
|
||||
"createView.spec.js": [
|
||||
"3ad1ca97d7d069b6fd6fd0fb216051a0c6dbf742",
|
||||
[]
|
||||
],
|
||||
"error_scope.spec.js": [
|
||||
"3edbec2dc417fc4cb95ab67baefc1d0f1a798154",
|
||||
[]
|
||||
],
|
||||
"fences.spec.js": [
|
||||
"2ab0691e3ce6cadb532a94a43d568b8a111a8430",
|
||||
[]
|
||||
],
|
||||
"queue_submit.spec.js": [
|
||||
"24e386b9d22c2bbea0fca8e8b5c94c770e8ed7d5",
|
||||
[]
|
||||
],
|
||||
"render_pass_descriptor.spec.js": [
|
||||
"3c1b111fea4a79aab8cd8defbc61152e7e5302ea",
|
||||
[]
|
||||
],
|
||||
"setBindGroup.spec.js": [
|
||||
"95786a8f78d3a6fe230d6a08c3cfb83c93a97666",
|
||||
[]
|
||||
],
|
||||
"setBlendColor.spec.js": [
|
||||
"469641df04341795efdad946ea65eb517a51265c",
|
||||
[]
|
||||
],
|
||||
"setScissorRect.spec.js": [
|
||||
"8381865a6938c4a32d81744fb1bbaaf41ae309fb",
|
||||
[]
|
||||
],
|
||||
"setStencilReference.spec.js": [
|
||||
"f205239d86142ea08880f226f9d9ae052a385aa1",
|
||||
[]
|
||||
],
|
||||
"setViewport.spec.js": [
|
||||
"f1168c11086fd4fa7114c36b9895bab49b66a410",
|
||||
[]
|
||||
],
|
||||
"validation_test.js": [
|
||||
"17eb97bcc63daafbda34a661bafd0da688d7bb8b",
|
||||
[]
|
||||
]
|
||||
}
|
||||
},
|
||||
"capability_info.js": [
|
||||
"47d508ac3e3c5abfe9d2c4da3ab1ee412dec8030",
|
||||
[]
|
||||
],
|
||||
"examples.spec.js": [
|
||||
"28b9ae47f2c25183ba68b1bcb7303a033541213b",
|
||||
[]
|
||||
],
|
||||
"gpu_test.js": [
|
||||
"e740af1113b88f548768c33a0d378490d3d8320b",
|
||||
[]
|
||||
],
|
||||
"idl": {
|
||||
"constants": {
|
||||
"flags.spec.js": [
|
||||
"5a6d7868aa531677f8660768ce87a73564727314",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"idl_test.js": [
|
||||
"0665ad208cd8453352a1c4a030614b40b3783de7",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"listing.js": [
|
||||
"a8b67e72547db017720f5e7fb4e88f024eab2bf4",
|
||||
[]
|
||||
],
|
||||
"util": {
|
||||
"conversion.js": [
|
||||
"73c04fe56badcff5aee3bf665465b24c81d4f3bf",
|
||||
[]
|
||||
],
|
||||
"math.js": [
|
||||
"19720d631c55590bfbfc223e9c6409eded4d6232",
|
||||
[]
|
||||
],
|
||||
"texture": {
|
||||
"layout.js": [
|
||||
"425aa2020d75eace60d793d9148cc9cd531af475",
|
||||
[]
|
||||
],
|
||||
"subresource.js": [
|
||||
"04a8e7221a8ad8a9f76369d4e3f2ffa4fe21a056",
|
||||
[]
|
||||
],
|
||||
"texelData.js": [
|
||||
"2ea7275e710a5e47a59480ca2a56c1026172e6bf",
|
||||
[]
|
||||
]
|
||||
}
|
||||
},
|
||||
"web-platform": {
|
||||
"canvas": {
|
||||
"context_creation.spec.js": [
|
||||
"427b15fced447160db36ca3d6f829211f5080206",
|
||||
[]
|
||||
]
|
||||
},
|
||||
"copyImageBitmapToTexture.spec.js": [
|
||||
"efdc21ded93736439f8112c35e9a39600b07739c",
|
||||
[]
|
||||
],
|
||||
"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",
|
||||
[]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"webmessaging": {
|
||||
"META.yml": [
|
||||
|
@ -368531,7 +368160,7 @@
|
|||
]
|
||||
],
|
||||
"idbobjectstore_putall.tentative.any.js": [
|
||||
"a312d71d03d59c5c9369afa1492aacd0e91e9a5d",
|
||||
"26bcc87a4c3234c2de5699c5443d75b4419eab02",
|
||||
[
|
||||
"IndexedDB/idbobjectstore_putall.tentative.any.html",
|
||||
{
|
||||
|
@ -416222,7 +415851,7 @@
|
|||
]
|
||||
],
|
||||
"Event-dispatch-click.html": [
|
||||
"7690f753d9cd0b47f2c2c25352576caed970cd19",
|
||||
"4b07103027139b4d7679da4e50eb3d82ab8b12d2",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
|
@ -432154,7 +431783,7 @@
|
|||
]
|
||||
],
|
||||
"event-counts-zero.html": [
|
||||
"3ec90dd69138f35197774239dfc12f554c9284b2",
|
||||
"e00eb40255b853b67ea959bf7ebeb12d066374ec",
|
||||
[
|
||||
null,
|
||||
{
|
||||
|
@ -459609,6 +459238,13 @@
|
|||
]
|
||||
]
|
||||
},
|
||||
"historical.html": [
|
||||
"5cba688ff83e6dae90100b315a9fa86f69974502",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"synthetic": {
|
||||
"001.html": [
|
||||
"f90c345740df3f9c4366d01a3d47e323b30069fc",
|
||||
|
@ -486616,6 +486252,20 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"first-contentful-canvas-none.html": [
|
||||
"33a4352126c0d59668e5fdd30d96a4c54ad34468",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"first-contentful-canvas-webgl2.html": [
|
||||
"f7c5f50ecba0bd5a5d45fb41a02d0457e49e6713",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"first-contentful-canvas.html": [
|
||||
"e6a4365b760c7126be458c505a49ef1ea7234d53",
|
||||
[
|
||||
|
@ -501642,7 +501292,7 @@
|
|||
]
|
||||
],
|
||||
"scroll-animation-effect-phases.tentative.html": [
|
||||
"df7ab69404cb00a9e09ec03593f531a50999630a",
|
||||
"b8e678e9218395f43f2690a67fb1d887ce73dacc",
|
||||
[
|
||||
null,
|
||||
{
|
||||
|
@ -504615,6 +504265,13 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"element-internals-shadowroot.tentative.html": [
|
||||
"0f01cc41acf153512ff00b1147ccc224087167eb",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"getinnerhtml.tentative.html": [
|
||||
"2f8ecad418b818f35220550479f9c02e1889744e",
|
||||
[
|
||||
|
@ -524535,6 +524192,15 @@
|
|||
]
|
||||
]
|
||||
},
|
||||
"webcodecs": {
|
||||
"video-track-reader.html": [
|
||||
"087e0bb935b6033876c9b7eed10274bab02d8910",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
]
|
||||
},
|
||||
"webdriver": {
|
||||
"tests": {
|
||||
"idlharness.html": [
|
||||
|
@ -524633,119 +524299,6 @@
|
|||
]
|
||||
]
|
||||
},
|
||||
"webgpu": {
|
||||
"cts.html": [
|
||||
"e78afee421ad7d11a16adbd89fb4a833d0b1aece",
|
||||
[
|
||||
"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_detach:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"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,copies:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"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,resource_init,copied_texture_clear:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,createBindGroup:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,createPipelineLayout:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,createTexture:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,createView:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,error_scope:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,fences:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"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,setBindGroup:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,setBlendColor:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,setScissorRect:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,setStencilReference:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,setViewport:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:examples:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:idl,constants,flags:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:web-platform,canvas,context_creation:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:web-platform,copyImageBitmapToTexture:*",
|
||||
{}
|
||||
]
|
||||
]
|
||||
},
|
||||
"webhid": {
|
||||
"idlharness.https.window.js": [
|
||||
"fa763e0d80ac7e196cd276a9aed5a7a33f9d8331",
|
||||
|
@ -533117,6 +532670,13 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"xrSession_requestSessionDuringEnd.https.html": [
|
||||
"2ab6cb7fbb5ede0523a143e042a459e6f3c5cde5",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
]
|
||||
],
|
||||
"xrSession_sameObject.https.html": [
|
||||
"66aeef81c50c36ff2fc50dcc7c45749f25605893",
|
||||
[
|
||||
|
@ -563277,7 +562837,7 @@
|
|||
]
|
||||
],
|
||||
"pointer.py": [
|
||||
"a752203587bed5ebcfa50599f0548feb69ca4c98",
|
||||
"d021eee7c9404cf09194a41632b6093c72ce961d",
|
||||
[
|
||||
null,
|
||||
{
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[hit-test-floats-003.html]
|
||||
[Miss float below something else]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[hit-test-floats-005.html]
|
||||
[Miss clipped float]
|
||||
expected: FAIL
|
||||
|
|
@ -21,6 +21,3 @@
|
|||
[test the top of layer]
|
||||
expected: FAIL
|
||||
|
||||
[test some point of the element: top left corner]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[matchMedia-display-none-iframe.html]
|
||||
expected: ERROR
|
|
@ -2,3 +2,10 @@
|
|||
type: testharness
|
||||
[event state during post-click handling]
|
||||
expected: FAIL
|
||||
|
||||
[disabled radio should be checked from dispatchEvent(new MouseEvent("click"))]
|
||||
expected: FAIL
|
||||
|
||||
[disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -315,15 +315,18 @@
|
|||
[<iframe>: separate response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
||||
[<iframe>: separate response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/plain ]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -56,6 +56,9 @@
|
|||
[separate text/javascript x/x]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript error]
|
||||
[separate text/javascript;charset=windows-1252 error text/javascript]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript ]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -11,6 +11,3 @@
|
|||
[X-Content-Type-Options%3A%20nosniff%2C%2C%40%23%24%23%25%25%26%5E%26%5E*()()11!]
|
||||
expected: FAIL
|
||||
|
||||
[X-Content-Type-Options%3A%20%2Cnosniff]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_3.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[creating_browsing_context_test_01.html]
|
||||
[first argument: absolute url]
|
||||
expected: FAIL
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[iframe_sandbox_popups_escaping-1.html]
|
||||
type: testharness
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[iframe_sandbox_popups_escaping-2.html]
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[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
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[iframe_sandbox_popups_nonescaping-2.html]
|
||||
type: testharness
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[iframe_sandbox_popups_nonescaping-3.html]
|
||||
type: testharness
|
||||
expected: TIMEOUT
|
||||
expected: CRASH
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[htmlanchorelement_noopener.html]
|
||||
type: testharness
|
||||
expected: TIMEOUT
|
||||
[Check that targeting of rel=noopener with a given name ignores an existing window with that name]
|
||||
expected: NOTRUN
|
||||
|
||||
|
@ -7,11 +8,11 @@
|
|||
expected: FAIL
|
||||
|
||||
[Check that rel=noopener with target=_top does a normal load]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Check that rel=noopener with target=_self does a normal load]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
[Check that rel=noopener with target=_parent does a normal load]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[077.html]
|
||||
[ adding several types of scripts through the DOM and removing some of them confuses scheduler ]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[018.html]
|
||||
expected: TIMEOUT
|
||||
[origin of the script that invoked the method, javascript:]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
[xrSession_requestSessionDuringEnd.https.html]
|
||||
[Create new session in OnSessionEnded event]
|
||||
expected: FAIL
|
||||
|
||||
[Create mew session in end promise]
|
||||
expected: FAIL
|
||||
|
|
@ -6,12 +6,13 @@ promise_test(async testCase => {
|
|||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
let values = [
|
||||
const values = [
|
||||
{isbn: 'one', title: 'title1'},
|
||||
{isbn: 'two', title: 'title2'},
|
||||
{isbn: 'three', title: 'title3'}
|
||||
];
|
||||
let putAllRequest = objectStore.putAll(values);
|
||||
const putAllRequest = objectStore.putAllValues(values);
|
||||
// TODO(nums): Check that correct keys are returned.
|
||||
await promiseForRequest(testCase, putAllRequest);
|
||||
await promiseForTransaction(testCase, txn);
|
||||
|
||||
|
@ -28,4 +29,152 @@ promise_test(async testCase => {
|
|||
['title1', 'title2', 'title3'],
|
||||
'All three retrieved titles should match those that were put.');
|
||||
db.close();
|
||||
}, 'Data can be successfully inputted into an object store using putAll.');
|
||||
}, 'Data can be successfully inserted into an object store using putAll.');
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, db => {
|
||||
const store = createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const values = [
|
||||
{isbn: ['one', 'two', 'three'], title: 'title1'},
|
||||
{isbn: ['four', 'five', 'six'], title: 'title2'},
|
||||
{isbn: ['seven', 'eight', 'nine'], title: 'title3'}
|
||||
];
|
||||
const putAllRequest = objectStore.putAllValues(values);
|
||||
// TODO(nums): Check that correct keys are returned.
|
||||
await promiseForRequest(testCase, putAllRequest);
|
||||
await promiseForTransaction(testCase, txn);
|
||||
|
||||
const txn2 = db.transaction(['books'], 'readonly');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequest1 = objectStore2.get(['one', 'two', 'three']);
|
||||
const getRequest2 = objectStore2.get(['four', 'five', 'six']);
|
||||
const getRequest3 = objectStore2.get(['seven', 'eight', 'nine']);
|
||||
await promiseForTransaction(testCase, txn2);
|
||||
assert_array_equals(
|
||||
[getRequest1.result.title,
|
||||
getRequest2.result.title,
|
||||
getRequest3.result.title],
|
||||
['title1', 'title2', 'title3'],
|
||||
'All three retrieved titles should match those that were put.');
|
||||
db.close();
|
||||
}, 'Values with array keys can be successfully inserted into an object'
|
||||
+ ' store using putAll.');
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, db => {
|
||||
const store = createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const putAllRequest = objectStore.putAllValues([]);
|
||||
await promiseForRequest(testCase, putAllRequest);
|
||||
await promiseForTransaction(testCase, txn);
|
||||
// TODO(nums): Check that an empty key array is returned.
|
||||
db.close();
|
||||
}, 'Inserting an empty list using putAll.');
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, db => {
|
||||
const store = createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const putAllRequest = objectStore.putAllValues([{}, {}, {}]);
|
||||
// TODO(nums): Check that correct keys are returned.
|
||||
await promiseForRequest(testCase, putAllRequest);
|
||||
await promiseForTransaction(testCase, txn);
|
||||
|
||||
const txn2 = db.transaction(['books'], 'readonly');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequest1 = objectStore2.get(1);
|
||||
const getRequest2 = objectStore2.get(2);
|
||||
const getRequest3 = objectStore2.get(3);
|
||||
await Promise.all([
|
||||
promiseForRequest(testCase, getRequest1),
|
||||
promiseForRequest(testCase, getRequest2),
|
||||
promiseForRequest(testCase, getRequest3),
|
||||
]);
|
||||
db.close();
|
||||
}, 'Empty values can be inserted into an objectstore'
|
||||
+ ' with a key generator using putAll.');
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, db => {
|
||||
const store = createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readonly');
|
||||
const objectStore = txn.objectStore('books');
|
||||
assert_throws_dom('ReadOnlyError',
|
||||
() => { objectStore.putAllValues([{}]); },
|
||||
'The transaction is readonly');
|
||||
db.close();
|
||||
}, 'Attempting to insert with a read only transaction using putAll throws a '
|
||||
+ 'ReadOnlyError.');
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, db => {
|
||||
const store = createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const putRequest = await objectStore.put({isbn: 1, title: "duplicate"});
|
||||
await promiseForRequest(testCase, putRequest);
|
||||
const putAllRequest = objectStore.putAllValues([
|
||||
{isbn: 2, title: "duplicate"},
|
||||
{isbn: 3, title: "duplicate"}
|
||||
]);
|
||||
const errorEvent = await requestWatcher(testCase,
|
||||
putAllRequest).wait_for('error');
|
||||
assert_equals(errorEvent.target.error.name, "ConstraintError");
|
||||
errorEvent.preventDefault();
|
||||
// The transaction still receives the error event even though it
|
||||
// isn't aborted.
|
||||
await transactionWatcher(testCase, txn).wait_for(['error', 'complete']);
|
||||
|
||||
const txn2 = db.transaction(['books'], 'readonly');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequest1 = objectStore2.get(1);
|
||||
const getRequest2 = objectStore2.get(2);
|
||||
const getRequest3 = objectStore2.get(3);
|
||||
await promiseForTransaction(testCase, txn2);
|
||||
assert_array_equals(
|
||||
[getRequest1.result.title, getRequest2.result, getRequest3.result],
|
||||
["duplicate", undefined, undefined],
|
||||
'None of the values should have been inserted.');
|
||||
db.close();
|
||||
}, 'Inserting duplicate unique keys into a store that already has the key'
|
||||
+ 'using putAll throws a ConstraintError.');
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, db => {
|
||||
const store = createBooksStoreWithoutAutoIncrement(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const values = [
|
||||
{title: "title1", isbn: 1},
|
||||
{title: "title2"}
|
||||
];
|
||||
assert_throws_dom('DataError',
|
||||
() => { const putAllRequest = objectStore.putAllValues(values); },
|
||||
"Evaluating the object store's key path did not yield a value");
|
||||
|
||||
const txn2 = db.transaction(['books'], 'readonly');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequest1 = objectStore2.get(1);
|
||||
const getRequest2 = objectStore2.get(2);
|
||||
await promiseForTransaction(testCase, txn2);
|
||||
assert_array_equals(
|
||||
[getRequest1.result, getRequest2.result],
|
||||
[undefined, undefined],
|
||||
'No data should have been inserted');
|
||||
db.close();
|
||||
}, 'Inserting values without the key into an object store that'
|
||||
+ ' does not have generated keys throws an exception.');
|
||||
|
||||
// TODO(nums): Add test for insertion into multi entry indexes
|
||||
// TODO(nums): Add test for inserting unique keys into a store
|
||||
// that doesn't already have the key https://crbug.com/1115649
|
||||
|
|
|
@ -196,7 +196,19 @@ const createBooksStore = (testCase, database) => {
|
|||
{ keyPath: 'isbn', autoIncrement: true });
|
||||
store.createIndex('by_author', 'author');
|
||||
store.createIndex('by_title', 'title', { unique: true });
|
||||
for (let record of BOOKS_RECORD_DATA)
|
||||
for (const record of BOOKS_RECORD_DATA)
|
||||
store.put(record);
|
||||
return store;
|
||||
}
|
||||
|
||||
// Creates a 'books' object store whose contents closely resembles the first
|
||||
// example in the IndexedDB specification, just without autoincrementing.
|
||||
const createBooksStoreWithoutAutoIncrement = (testCase, database) => {
|
||||
const store = database.createObjectStore('books',
|
||||
{ keyPath: 'isbn' });
|
||||
store.createIndex('by_author', 'author');
|
||||
store.createIndex('by_title', 'title', { unique: true });
|
||||
for (const record of BOOKS_RECORD_DATA)
|
||||
store.put(record);
|
||||
return store;
|
||||
}
|
||||
|
|
|
@ -209,6 +209,38 @@ async_test(t => {
|
|||
input.dispatchEvent(new MouseEvent('click'));
|
||||
}, `disconnected radio should be checked from dispatchEvent(new MouseEvent('click'))`);
|
||||
|
||||
test(() => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
input.disabled = true;
|
||||
input.dispatchEvent(new MouseEvent("click"));
|
||||
assert_true(input.checked);
|
||||
}, `disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))`);
|
||||
|
||||
test(() => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "radio";
|
||||
input.disabled = true;
|
||||
input.dispatchEvent(new MouseEvent("click"));
|
||||
assert_true(input.checked);
|
||||
}, `disabled radio should be checked from dispatchEvent(new MouseEvent("click"))`);
|
||||
|
||||
async_test(t => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
input.disabled = true;
|
||||
input.onclick = t.step_func_done();
|
||||
input.dispatchEvent(new MouseEvent("click"));
|
||||
}, `disabled checkbox should fire onclick`);
|
||||
|
||||
async_test(t => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "radio";
|
||||
input.disabled = true;
|
||||
input.onclick = t.step_func_done();
|
||||
input.dispatchEvent(new MouseEvent("click"));
|
||||
}, `disabled radio should fire onclick`);
|
||||
|
||||
async_test(function(t) {
|
||||
var form = document.createElement("form")
|
||||
var didSubmit = false
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
'dragstart',
|
||||
'dragend',
|
||||
'dragenter',
|
||||
// 'dragexit'? Unclear if it will be removed from HTML spec or not.
|
||||
'dragleave',
|
||||
'dragover',
|
||||
'drop'
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
set -ex
|
||||
|
||||
cd "${0%/*}"
|
||||
virtualenv -p python2 .virtualenv
|
||||
virtualenv -p python .virtualenv
|
||||
.virtualenv/bin/pip install pyyaml cairocffi
|
||||
.virtualenv/bin/python gentest.py
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Historical drag-and-drop features</title>
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<style>
|
||||
.test-square {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#draggable {
|
||||
background: orange;
|
||||
}
|
||||
|
||||
#dropzone {
|
||||
background: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Drag the orange square onto the blue square and release it.</p>
|
||||
|
||||
<div draggable="true" id="draggable" class="test-square" ondragstart="event.dataTransfer.setData('text/plain', null)"></div>
|
||||
<div id="dropzone" class="test-square"></div>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
async_test(t => {
|
||||
let dragexitCount = 0;
|
||||
document.addEventListener("dragexit", () => {
|
||||
++dragexitCount;
|
||||
});
|
||||
|
||||
// Prevent the event to allow drop
|
||||
document.addEventListener("dragover", e => {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
document.addEventListener("drop", t.step_func_done(() => {
|
||||
assert_equals(dragexitCount, 0);
|
||||
}));
|
||||
}, `dragexit must not fire during drag-and-drop`);
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Historical drag-and-drop features</title>
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
const potentialBadLocations = [
|
||||
window,
|
||||
document,
|
||||
HTMLElement.prototype,
|
||||
SVGElement.prototype,
|
||||
Document.prototype,
|
||||
HTMLDocument.prototype,
|
||||
Element.prototype
|
||||
];
|
||||
for (const location of potentialBadLocations) {
|
||||
assert_false("ondragexit" in location,
|
||||
`${location.constructor.name} must not have a property "ondragexit"`);
|
||||
}
|
||||
}, `ondragexit must not be present on the GlobalEventHandlers locations`);
|
||||
</script>
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<script>
|
||||
var drag, element;
|
||||
var Events = ['ondragstart', 'ondrag', 'ondragover', 'ondragenter', 'ondragexit', 'ondragleave', 'ondrop', 'ondragend'];
|
||||
var Events = ['ondragstart', 'ondrag', 'ondragover', 'ondragenter', 'ondragleave', 'ondrop', 'ondragend'];
|
||||
|
||||
setup(function() {
|
||||
drag = document.querySelector('#drag');
|
||||
|
@ -54,10 +54,6 @@
|
|||
assert_inherits(element, 'ondragenter', 'Check if have ondragenter attribute');
|
||||
}, 'Check if have ondragenter attribute');
|
||||
|
||||
test(function() {
|
||||
assert_inherits(element, 'ondragexit', 'Check if have ondragexit attribute');
|
||||
}, 'Check if have ondragexit attribute');
|
||||
|
||||
test(function() {
|
||||
assert_inherits(element, 'ondragleave', 'Check if have dragleave attribute');
|
||||
}, 'Check if have dragleave attribute');
|
||||
|
@ -96,4 +92,4 @@
|
|||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -726,6 +726,12 @@ MISSING DEPENDENCY: web-nfc/resources/nfc-helpers.js
|
|||
MISSING DEPENDENCY: webusb/resources/usb-helpers.js
|
||||
MISSING DEPENDENCY: webxr/resources/webxr_util.js
|
||||
|
||||
# TODO(Hexcles): delete these files once we include them in mojojs.zip.
|
||||
MOJOM-JS: resources/chromium/image_capture.mojom.js
|
||||
MOJOM-JS: resources/chromium/sensor_provider.mojom.js
|
||||
MOJOM-JS: resources/chromium/mojo_web_test_helper_test.mojom.js
|
||||
MOJOM-JS: resources/chromium/sensor.mojom.js
|
||||
|
||||
# Tests that are false positives for using Ahem as a system font
|
||||
AHEM SYSTEM FONT: acid/acid3/test.html
|
||||
AHEM SYSTEM FONT: resource-timing/resources/all_resource_types.htm
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Performance Paint Timing Test: FCP due to canvas</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/utils.js"></script>
|
||||
<canvas id="canvas" width="200" height="200"></canvas>
|
||||
|
||||
<script>
|
||||
setup({"hide_test_state": true});
|
||||
promise_test(async t => {
|
||||
assert_implements(window.PerformancePaintTiming, "Paint Timing isn't supported.");
|
||||
await new Promise(r => window.addEventListener('load', r));
|
||||
await assertNoFirstContentfulPaint(t);
|
||||
}, 'First contentful paint should not fire for canvas type none');
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Performance Paint Timing Test: FCP due to canvas</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<canvas id="canvas" width="200" height="200"></canvas>
|
||||
|
||||
<script>
|
||||
setup({ "hide_test_state": true });
|
||||
async_test(function (t) {
|
||||
assert_implements(window.PerformancePaintTiming, "Paint Timing isn't supported.");
|
||||
const canvas = document.getElementById("canvas");
|
||||
const context = canvas.getContext("webgl2");
|
||||
if (!context) {
|
||||
assert_implements_optional(context, "WebGL 2 Canvas isn't supported.")
|
||||
}
|
||||
context.clearColor(0.3, 0.3, 0.3, 1);
|
||||
context.clear(context.COLOR_BUFFER_BIT);
|
||||
function testPaintEntries() {
|
||||
const bufferedEntries = performance.getEntriesByType('paint');
|
||||
if (bufferedEntries.length < 2) {
|
||||
t.step_timeout(function () {
|
||||
testPaintEntries();
|
||||
}, 20);
|
||||
return;
|
||||
}
|
||||
t.step(function () {
|
||||
assert_equals(bufferedEntries.length, 2, "There should be two paint timing instances.");
|
||||
assert_equals(bufferedEntries[0].entryType, "paint");
|
||||
assert_equals(bufferedEntries[0].name, "first-paint");
|
||||
assert_equals(bufferedEntries[1].entryType, "paint");
|
||||
assert_equals(bufferedEntries[1].name, "first-contentful-paint");
|
||||
t.done();
|
||||
});
|
||||
};
|
||||
t.step(function () {
|
||||
testPaintEntries();
|
||||
});
|
||||
}, "First contentful paint fires due to webgl2 canvas render.");
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -151,4 +151,167 @@
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
function createKeyframeEffectOpacity(test){
|
||||
return new KeyframeEffect(
|
||||
createDiv(test),
|
||||
{
|
||||
opacity: [0.3, 0.7]
|
||||
},
|
||||
{
|
||||
duration: 1000
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function verifyTimelineBeforePhase(animation){
|
||||
assert_equals(animation.timeline.phase, "before");
|
||||
assert_equals(animation.timeline.currentTime, 0);
|
||||
assert_equals(animation.currentTime, 0);
|
||||
assert_equals(
|
||||
animation.effect.getComputedTiming().localTime,
|
||||
0,
|
||||
"effect local time in timeline before phase");
|
||||
}
|
||||
|
||||
function verifyEffectBeforePhase(animation){
|
||||
// progress == null AND opacity == 1 implies we are in the effect before
|
||||
// phase
|
||||
assert_equals(
|
||||
animation.effect.getComputedTiming().progress,
|
||||
null
|
||||
);
|
||||
assert_equals(
|
||||
window.getComputedStyle(animation.effect.target).getPropertyValue("opacity"),
|
||||
"1"
|
||||
);
|
||||
}
|
||||
|
||||
promise_test(async t => {
|
||||
const animation = new Animation(
|
||||
createKeyframeEffectOpacity(t),
|
||||
createScrollTimelineWithOffsets(t, "20%", "80%")
|
||||
);
|
||||
|
||||
const scroller = animation.timeline.scrollSource;
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
|
||||
animation.play();
|
||||
await animation.ready;
|
||||
|
||||
verifyTimelineBeforePhase(animation);
|
||||
verifyEffectBeforePhase(animation);
|
||||
|
||||
animation.pause();
|
||||
await waitForNextFrame();
|
||||
|
||||
verifyTimelineBeforePhase(animation);
|
||||
verifyEffectBeforePhase(animation);
|
||||
|
||||
animation.play();
|
||||
await waitForNextFrame();
|
||||
|
||||
verifyTimelineBeforePhase(animation);
|
||||
verifyEffectBeforePhase(animation);
|
||||
}, 'Verify that (play -> pause -> play) doesn\'t change phase/progress.');
|
||||
|
||||
promise_test(async t => {
|
||||
const animation = new Animation(
|
||||
createKeyframeEffectOpacity(t),
|
||||
createScrollTimelineWithOffsets(t, "20%", "80%")
|
||||
);
|
||||
|
||||
const scroller = animation.timeline.scrollSource;
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
|
||||
animation.play();
|
||||
await animation.ready;
|
||||
|
||||
verifyTimelineBeforePhase(animation);
|
||||
verifyEffectBeforePhase(animation);
|
||||
|
||||
animation.pause();
|
||||
await waitForNextFrame();
|
||||
|
||||
verifyTimelineBeforePhase(animation);
|
||||
verifyEffectBeforePhase(animation);
|
||||
|
||||
// Scrolling should not cause the animation effect to change.
|
||||
scroller.scrollTop = 0.5 * maxScroll;
|
||||
await waitForNextFrame();
|
||||
|
||||
// Check timeline phase
|
||||
assert_equals(animation.timeline.phase, "active");
|
||||
assert_equals(animation.timeline.currentTime, 500);
|
||||
assert_equals(animation.currentTime, 0);
|
||||
assert_equals(
|
||||
animation.effect.getComputedTiming().localTime,
|
||||
0,
|
||||
"effect local time"
|
||||
);
|
||||
|
||||
// Make sure the effect is still in the before phase even though the
|
||||
// timeline is not.
|
||||
verifyEffectBeforePhase(animation);
|
||||
}, 'Pause in before phase, scroll timeline into active phase, animation ' +
|
||||
'should remain in the before phase');
|
||||
|
||||
promise_test(async t => {
|
||||
const animation = new Animation(
|
||||
createKeyframeEffectOpacity(t),
|
||||
createScrollTimelineWithOffsets(t, "20%", "80%")
|
||||
);
|
||||
const scroller = animation.timeline.scrollSource;
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
|
||||
animation.play();
|
||||
await animation.ready;
|
||||
|
||||
// Causes the timeline to be inactive
|
||||
scroller.style.overflow = "visible";
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
|
||||
// Check timeline phase
|
||||
assert_equals(animation.timeline.phase, "inactive");
|
||||
assert_equals(animation.timeline.currentTime, null);
|
||||
assert_equals(animation.currentTime, null);
|
||||
assert_equals(
|
||||
animation.effect.getComputedTiming().localTime,
|
||||
null,
|
||||
"effect local time with inactive timeline"
|
||||
);
|
||||
|
||||
verifyEffectBeforePhase(animation);
|
||||
|
||||
// Setting the current time while timeline is inactive should cause hold phase
|
||||
// and hold time to be populated
|
||||
animation.currentTime = 500;
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
|
||||
// Check timeline phase
|
||||
assert_equals(animation.timeline.phase, "inactive");
|
||||
assert_equals(animation.timeline.currentTime, null);
|
||||
assert_equals(animation.currentTime, 500);
|
||||
assert_equals(
|
||||
animation.effect.getComputedTiming().localTime,
|
||||
500,
|
||||
"effect local time after setting animation current time"
|
||||
);
|
||||
|
||||
// Check effect phase
|
||||
// progress == 0.5 AND opacity == 0.5 shows we are in the effect active phase
|
||||
assert_equals(
|
||||
animation.effect.getComputedTiming().progress,
|
||||
0.5,
|
||||
"effect progress"
|
||||
);
|
||||
assert_equals(
|
||||
window.getComputedStyle(animation.effect.target).getPropertyValue("opacity"),
|
||||
"0.5",
|
||||
"effect opacity after setting animation current time"
|
||||
);
|
||||
}, 'Make scroller inactive, then set current time to an in range time');
|
||||
|
||||
</script>
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>ElementInternals.shadowRoot</title>
|
||||
<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
|
||||
<link rel="help" href="https://github.com/w3c/webcomponents/issues/871">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
test(() => {
|
||||
let constructed = false;
|
||||
customElements.define('custom-open', class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
const elementInternals = this.attachInternals();
|
||||
assert_equals(elementInternals.shadowRoot, null);
|
||||
const shadow = this.attachShadow({mode: 'open'});
|
||||
assert_equals(elementInternals.shadowRoot, shadow);
|
||||
constructed = true;
|
||||
}
|
||||
});
|
||||
const element = document.createElement('custom-open');
|
||||
assert_true(constructed);
|
||||
}, 'ElementInternals.shadowRoot allows access to open shadow root');
|
||||
|
||||
test(() => {
|
||||
let constructed = false;
|
||||
customElements.define('custom-closed', class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
const elementInternals = this.attachInternals();
|
||||
assert_equals(elementInternals.shadowRoot, null);
|
||||
const shadow = this.attachShadow({mode: 'closed'});
|
||||
assert_equals(elementInternals.shadowRoot, shadow);
|
||||
assert_equals(this.shadowRoot, null);
|
||||
constructed = true;
|
||||
}
|
||||
});
|
||||
const element = document.createElement('custom-closed');
|
||||
assert_true(constructed);
|
||||
}, 'ElementInternals.shadowRoot allows access to closed shadow root');
|
||||
|
||||
</script>
|
|
@ -198,6 +198,13 @@ def check_gitignore_file(repo_root, path):
|
|||
return [rules.GitIgnoreFile.error(path)]
|
||||
|
||||
|
||||
def check_mojom_js(repo_root, path):
|
||||
# type: (Text, Text) -> List[rules.Error]
|
||||
if path.endswith(".mojom.js"):
|
||||
return [rules.MojomJSFile.error(path)]
|
||||
return []
|
||||
|
||||
|
||||
def check_ahem_copy(repo_root, path):
|
||||
# type: (Text, Text) -> List[rules.Error]
|
||||
lpath = path.lower()
|
||||
|
@ -997,8 +1004,9 @@ def lint(repo_root, paths, output_format, ignore_glob=None):
|
|||
logger.info(line)
|
||||
return sum(itervalues(error_count))
|
||||
|
||||
|
||||
path_lints = [check_file_type, check_path_length, check_worker_collision, check_ahem_copy,
|
||||
check_tentative_directories, check_gitignore_file]
|
||||
check_mojom_js, check_tentative_directories, check_gitignore_file]
|
||||
all_paths_lints = [check_css_globally_unique, check_unique_testharness_basenames]
|
||||
file_lints = [check_regexp_line, check_parsed, check_python_ast, check_script_metadata,
|
||||
check_ahem_system_font]
|
||||
|
|
|
@ -81,6 +81,18 @@ class GitIgnoreFile(Rule):
|
|||
description = ".gitignore found outside the root"
|
||||
|
||||
|
||||
class MojomJSFile(Rule):
|
||||
name = "MOJOM-JS"
|
||||
description = "Don't check *.mojom.js files into WPT"
|
||||
to_fix = """
|
||||
Check if the file is already included in mojojs.zip:
|
||||
https://source.chromium.org/chromium/chromium/src/+/master:chrome/tools/build/linux/FILES.cfg
|
||||
If yes, use `loadMojoResources` from `resources/test-only-api.js` to load
|
||||
it; if not, contact ecosystem-infra@chromium.org for adding new files
|
||||
to mojojs.zip.
|
||||
"""
|
||||
|
||||
|
||||
class AhemCopy(Rule):
|
||||
name = "AHEM COPY"
|
||||
description = "Don't add extra copies of Ahem, use /fonts/Ahem.ttf"
|
||||
|
|
|
@ -7,6 +7,7 @@ from ..lint import check_path
|
|||
from .base import check_errors
|
||||
import pytest
|
||||
|
||||
|
||||
def test_allowed_path_length():
|
||||
basename = 29 * "test/"
|
||||
|
||||
|
@ -29,6 +30,7 @@ def test_forbidden_path_length():
|
|||
check_errors(errors)
|
||||
assert errors == [("PATH LENGTH", message, filename, None)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path_ending,generated", [(".worker.html", ".worker.js"),
|
||||
(".any.worker.html", ".any.js"),
|
||||
(".any.html", ".any.js")])
|
||||
|
@ -70,6 +72,7 @@ def test_ahem_copy(path):
|
|||
|
||||
assert errors == [expected_error]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", ["ahem.woff",
|
||||
"ahem.ttff",
|
||||
"support/ahem.woff",
|
||||
|
@ -79,6 +82,16 @@ def test_ahem_copy_negative(path):
|
|||
|
||||
assert errors == []
|
||||
|
||||
|
||||
def test_mojom_js_file():
|
||||
path = "resources/fake_device.mojom.js"
|
||||
errors = check_path("/foo/", path)
|
||||
assert errors == [("MOJOM-JS",
|
||||
"Don't check *.mojom.js files into WPT",
|
||||
path,
|
||||
None)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", ["css/foo.tentative/bar.html",
|
||||
"css/.tentative/bar.html",
|
||||
"css/tentative.bar/baz.html",
|
||||
|
@ -94,6 +107,7 @@ def test_tentative_directories(path):
|
|||
|
||||
assert errors == [expected_error]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", ["css/bar.html",
|
||||
"css/tentative/baz.html"])
|
||||
def test_tentative_directories_negative(path):
|
||||
|
@ -102,6 +116,7 @@ def test_tentative_directories_negative(path):
|
|||
|
||||
assert errors == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", ["elsewhere/.gitignore",
|
||||
"else/where/.gitignore"
|
||||
"elsewhere/tools/.gitignore",
|
||||
|
@ -120,6 +135,7 @@ def test_gitignore_file(path):
|
|||
|
||||
assert errors == [expected_error]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", [".gitignore",
|
||||
"elsewhere/.gitignores",
|
||||
"elsewhere/name.gitignore",
|
||||
|
|
|
@ -56,6 +56,24 @@ def do_delayed_imports():
|
|||
from marionette_driver import marionette, errors
|
||||
|
||||
|
||||
def _switch_to_window(marionette, handle):
|
||||
"""Switch to the specified window; subsequent commands will be
|
||||
directed at the new window.
|
||||
|
||||
This is a workaround for issue 24924[0]; marionettedriver 3.1.0 dropped the
|
||||
'name' parameter from its switch_to_window command, but it is still needed
|
||||
for at least Firefox 79.
|
||||
|
||||
[0]: https://github.com/web-platform-tests/wpt/issues/24924
|
||||
|
||||
:param marionette: The Marionette instance
|
||||
:param handle: The id of the window to switch to.
|
||||
"""
|
||||
marionette._send_message("WebDriver:SwitchToWindow",
|
||||
{"handle": handle, "name": handle, "focus": True})
|
||||
marionette.window = handle
|
||||
|
||||
|
||||
class MarionetteBaseProtocolPart(BaseProtocolPart):
|
||||
def __init__(self, parent):
|
||||
super(MarionetteBaseProtocolPart, self).__init__(parent)
|
||||
|
@ -83,7 +101,7 @@ class MarionetteBaseProtocolPart(BaseProtocolPart):
|
|||
return self.marionette.current_window_handle
|
||||
|
||||
def set_window(self, handle):
|
||||
self.marionette.switch_to_window(handle)
|
||||
_switch_to_window(self.marionette, handle)
|
||||
|
||||
def load(self, url):
|
||||
self.marionette.navigate(url)
|
||||
|
@ -171,13 +189,13 @@ class MarionetteTestharnessProtocolPart(TestharnessProtocolPart):
|
|||
for handle in handles:
|
||||
try:
|
||||
self.logger.info("Closing window %s" % handle)
|
||||
self.marionette.switch_to_window(handle)
|
||||
_switch_to_window(self.marionette, handle)
|
||||
self.dismiss_alert(lambda: self.marionette.close())
|
||||
except errors.NoSuchWindowException:
|
||||
# We might have raced with the previous test to close this
|
||||
# window, skip it.
|
||||
pass
|
||||
self.marionette.switch_to_window(runner_handle)
|
||||
_switch_to_window(self.marionette, runner_handle)
|
||||
return runner_handle
|
||||
|
||||
def close_old_windows(self, url_protocol):
|
||||
|
@ -489,7 +507,7 @@ class MarionetteCoverageProtocolPart(CoverageProtocolPart):
|
|||
def dump(self):
|
||||
if len(self.marionette.window_handles):
|
||||
handle = self.marionette.window_handles[0]
|
||||
self.marionette.switch_to_window(handle)
|
||||
_switch_to_window(self.marionette, handle)
|
||||
|
||||
script = """
|
||||
var callback = arguments[arguments.length - 1];
|
||||
|
@ -585,7 +603,7 @@ class MarionettePrintProtocolPart(PrintProtocolPart):
|
|||
|
||||
def pdf_to_png(self, pdf_base64, page_ranges):
|
||||
handle = self.marionette.current_window_handle
|
||||
self.marionette.switch_to_window(self.runner_handle)
|
||||
_switch_to_window(self.marionette, self.runner_handle)
|
||||
try:
|
||||
rv = self.marionette.execute_async_script("""
|
||||
let callback = arguments[arguments.length - 1];
|
||||
|
@ -594,7 +612,7 @@ render('%s').then(result => callback(result))""" % pdf_base64, new_sandbox=False
|
|||
rv = [item for i, item in enumerate(rv) if i + 1 in page_numbers]
|
||||
return rv
|
||||
finally:
|
||||
self.marionette.switch_to_window(handle)
|
||||
_switch_to_window(self.marionette, handle)
|
||||
|
||||
class MarionetteProtocol(Protocol):
|
||||
implements = [MarionetteBaseProtocolPart,
|
||||
|
@ -883,7 +901,7 @@ class MarionetteRefTestExecutor(RefTestExecutor):
|
|||
if self.protocol.marionette and self.protocol.marionette.session_id:
|
||||
handles = self.protocol.marionette.window_handles
|
||||
if handles:
|
||||
self.protocol.marionette.switch_to_window(handles[0])
|
||||
_switch_to_window(self.protocol.marionette, handles[0])
|
||||
super(MarionetteRefTestExecutor, self).teardown()
|
||||
except Exception:
|
||||
# Ignore errors during teardown
|
||||
|
@ -903,8 +921,8 @@ class MarionetteRefTestExecutor(RefTestExecutor):
|
|||
if not isinstance(self.implementation, InternalRefTestImplementation):
|
||||
if self.close_after_done and self.has_window:
|
||||
self.protocol.marionette.close()
|
||||
self.protocol.marionette.switch_to_window(
|
||||
self.protocol.marionette.window_handles[-1])
|
||||
_switch_to_window(self.protocol.marionette,
|
||||
self.protocol.marionette.window_handles[-1])
|
||||
self.has_window = False
|
||||
|
||||
if not self.has_window:
|
||||
|
@ -1012,7 +1030,7 @@ class InternalRefTestImplementation(RefTestImplementation):
|
|||
# focus
|
||||
handles = self.executor.protocol.marionette.window_handles
|
||||
if handles:
|
||||
self.executor.protocol.marionette.switch_to_window(handles[0])
|
||||
_switch_to_window(self.executor.protocol.marionette, handles[0])
|
||||
except Exception:
|
||||
# Ignore errors during teardown
|
||||
self.logger.warning(traceback.format_exc())
|
||||
|
|
132
tests/wpt/web-platform-tests/webcodecs/video-track-reader.html
Normal file
132
tests/wpt/web-platform-tests/webcodecs/video-track-reader.html
Normal file
|
@ -0,0 +1,132 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>Test the VideoTrackReader API.</title>
|
||||
<body></body>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/media.js"></script>
|
||||
<script>
|
||||
|
||||
var testVideo = {
|
||||
url: getVideoURI('/media/movie_5'),
|
||||
height: 240,
|
||||
width: 320,
|
||||
}
|
||||
|
||||
async function getMediaStream() {
|
||||
let video = document.createElement('video');
|
||||
document.body.appendChild(video);
|
||||
video.src = testVideo.url;
|
||||
await video.play();
|
||||
|
||||
return video.captureStream();
|
||||
}
|
||||
|
||||
async_test(async function(t) {
|
||||
let stream = await getMediaStream();
|
||||
let vtr = new VideoTrackReader(stream.getVideoTracks()[0]);
|
||||
|
||||
t.done();
|
||||
}, 'Test we can construct a VideoTrackReader.');
|
||||
|
||||
async_test(async function(t) {
|
||||
let stream = await getMediaStream();
|
||||
let vtr = new VideoTrackReader(stream.getVideoTracks()[0]);
|
||||
|
||||
let numberFrames = 0;
|
||||
|
||||
vtr.start(t.step_func((frame) => {
|
||||
assert_equals(frame.codedWidth, testVideo.width);
|
||||
assert_equals(frame.codedHeight, testVideo.height);
|
||||
assert_not_equals(frame.timestamp, null);
|
||||
frame.destroy();
|
||||
|
||||
if (++numberFrames == 5){
|
||||
vtr.stop();
|
||||
t.done();
|
||||
}
|
||||
}));
|
||||
|
||||
}, 'Test we can start and stop a VideoTrackReader.');
|
||||
|
||||
async_test(async function(t) {
|
||||
let stream = await getMediaStream();
|
||||
let vtr = new VideoTrackReader(stream.getVideoTracks()[0]);
|
||||
|
||||
let stoppedOnce = false;
|
||||
|
||||
vtr.start(t.step_func(() => {
|
||||
if(!stoppedOnce) {
|
||||
vtr.stop();
|
||||
vtr.start(t.step_func_done());
|
||||
stoppedOnce = true;
|
||||
} else {
|
||||
assert_unreached("A stopped callback should never be called again");
|
||||
}
|
||||
}));
|
||||
|
||||
}, 'Test we can restart a stopped VideoTrackReader.');
|
||||
|
||||
async_test(async function(t) {
|
||||
let stream = await getMediaStream();
|
||||
let track = stream.getVideoTracks()[0];
|
||||
|
||||
let vtr_a = new VideoTrackReader(track);
|
||||
let vtr_b = new VideoTrackReader(track);
|
||||
|
||||
let receivedFrame_a = false;
|
||||
let receivedFrame_b = false;
|
||||
|
||||
vtr_a.start(t.step_func(() => {
|
||||
receivedFrame_a = true;
|
||||
|
||||
if (receivedFrame_a && receivedFrame_b)
|
||||
t.done();
|
||||
}));
|
||||
|
||||
vtr_b.start(t.step_func(() => {
|
||||
receivedFrame_b = true;
|
||||
|
||||
if (receivedFrame_a && receivedFrame_b)
|
||||
t.done();
|
||||
}));
|
||||
|
||||
}, 'Test we can create multiple VideoTrackReaders from the same track.');
|
||||
|
||||
async_test(async function(t) {
|
||||
let stream = await getMediaStream();
|
||||
let audioTrack = stream.getAudioTracks()[0];
|
||||
|
||||
assert_throws_js(TypeError, () => {
|
||||
let vtr = new VideoTrackReader(audioTrack);
|
||||
})
|
||||
|
||||
t.done();
|
||||
}, 'Test creating a VideoTrackReaders from an audio track throws.');
|
||||
|
||||
async_test(async function(t) {
|
||||
let stream = await getMediaStream();
|
||||
let vtr = new VideoTrackReader(stream.getVideoTracks()[0]);
|
||||
|
||||
assert_throws_dom("InvalidStateError", () => {
|
||||
vtr.stop();
|
||||
})
|
||||
|
||||
t.done();
|
||||
}, 'Test stopping a stopped VideoTrackReader throws.');
|
||||
|
||||
async_test(async function(t) {
|
||||
let stream = await getMediaStream();
|
||||
let vtr = new VideoTrackReader(stream.getVideoTracks()[0]);
|
||||
|
||||
vtr.start(() => {});
|
||||
|
||||
assert_throws_dom("InvalidStateError", () => {
|
||||
vtr.start(() => {});
|
||||
})
|
||||
|
||||
t.done();
|
||||
}, 'Test starting a started VideoTrackReader throws.');
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -169,6 +169,5 @@ def test_drag_and_drop_with_draggable_element(session,
|
|||
drag_events_captured = [ev["type"] for ev in e if ev["type"].startswith("drag") or ev["type"].startswith("drop")]
|
||||
assert "dragend" in drag_events_captured
|
||||
assert "dragenter" in drag_events_captured
|
||||
assert "dragexit" in drag_events_captured
|
||||
assert "dragleave" in drag_events_captured
|
||||
assert "drop" in drag_events_captured
|
||||
assert "drop" in drag_events_captured
|
||||
|
|
|
@ -178,7 +178,6 @@
|
|||
draggable.addEventListener("dragend", recordPointerEvent);
|
||||
draggable.addEventListener("dragleave", recordPointerEvent);
|
||||
draggable.addEventListener("dragover", recordPointerEvent);
|
||||
draggable.addEventListener("dragexit", recordPointerEvent);
|
||||
|
||||
var droppable = document.getElementById("droppable");
|
||||
droppable.addEventListener("drop", recordPointerEvent);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
spec: https://gpuweb.github.io/gpuweb/
|
||||
suggested_reviewers:
|
||||
- kainino0x
|
||||
- JusSn
|
||||
- kvark
|
||||
|
|
|
@ -5,6 +5,13 @@ support and hardware support, so this API cannot run on most automated testing
|
|||
infrastructure. Tests inside this directory should always be skipped if
|
||||
appropriate GPU hardware is not available.
|
||||
|
||||
The contents of this directory are automatically generated from TypeScript
|
||||
~~The contents of this directory are automatically generated from TypeScript
|
||||
sources which live upstream in the [WebGPU CTS](https://github.com/gpuweb/cts).
|
||||
They are periodically built and pushed to WPT.
|
||||
They are periodically built and pushed to WPT.~~
|
||||
|
||||
**NOTE:** This directory is currently empty while WebGPU is in flux, as it's
|
||||
not practical for browser developers to sync their WebGPU implementations with
|
||||
WPT auto-import and auto-export of these tests. Instead, browsers should pin
|
||||
("vendor") a specific version of the gpuweb/cts repository, and check the built
|
||||
files into the browser repository as non-exported wpt tests (like Chromium's
|
||||
`wpt_internal`).
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* 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, query, subqueriesToExpand.map(q => parseQuery(q)));
|
||||
}
|
||||
|
||||
async loadCases(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
|
|
@ -1,120 +0,0 @@
|
|||
/**
|
||||
* 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';
|
||||
export class SkipTestCase extends Error {} // A Fixture is a class used to instantiate each test case at run time.
|
||||
// A new instance of the Fixture is created for every single test case
|
||||
// (i.e. every time the test function is run).
|
||||
|
||||
export class Fixture {
|
||||
constructor(rec, params) {
|
||||
_defineProperty(this, "params", void 0);
|
||||
|
||||
_defineProperty(this, "rec", void 0);
|
||||
|
||||
_defineProperty(this, "eventualExpectations", []);
|
||||
|
||||
_defineProperty(this, "numOutstandingAsyncExpectations", 0);
|
||||
|
||||
this.rec = rec;
|
||||
this.params = params;
|
||||
} // This has to be a member function instead of an async `createFixture` function, because
|
||||
// we need to be able to ergonomically override it in subclasses.
|
||||
|
||||
|
||||
async init() {}
|
||||
|
||||
debug(msg) {
|
||||
this.rec.debug(new Error(msg));
|
||||
}
|
||||
|
||||
skip(msg) {
|
||||
throw new SkipTestCase(msg);
|
||||
}
|
||||
|
||||
async finalize() {
|
||||
assert(this.numOutstandingAsyncExpectations === 0, 'there were outstanding asynchronous expectations (e.g. shouldReject) at the end of the test');
|
||||
await Promise.all(this.eventualExpectations);
|
||||
}
|
||||
|
||||
warn(msg) {
|
||||
this.rec.warn(new Error(msg));
|
||||
}
|
||||
|
||||
fail(msg) {
|
||||
this.rec.expectationFailed(new Error(msg));
|
||||
}
|
||||
|
||||
async immediateAsyncExpectation(fn) {
|
||||
this.numOutstandingAsyncExpectations++;
|
||||
const ret = await fn();
|
||||
this.numOutstandingAsyncExpectations--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
eventualAsyncExpectation(fn) {
|
||||
const promise = fn(new Error());
|
||||
this.eventualExpectations.push(promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
expectErrorValue(expectedName, ex, niceStack) {
|
||||
if (!(ex instanceof Error)) {
|
||||
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}: ${ex}`;
|
||||
this.rec.expectationFailed(niceStack);
|
||||
} else {
|
||||
niceStack.message = `OK: threw ${actualName}${ex.message}`;
|
||||
this.rec.debug(niceStack);
|
||||
}
|
||||
}
|
||||
|
||||
shouldReject(expectedName, p, msg) {
|
||||
this.eventualAsyncExpectation(async niceStack => {
|
||||
const m = msg ? ': ' + msg : '';
|
||||
|
||||
try {
|
||||
await p;
|
||||
niceStack.message = 'DID NOT REJECT' + m;
|
||||
this.rec.expectationFailed(niceStack);
|
||||
} catch (ex) {
|
||||
niceStack.message = m;
|
||||
this.expectErrorValue(expectedName, ex, niceStack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
shouldThrow(expectedName, fn, msg) {
|
||||
const m = msg ? ': ' + msg : '';
|
||||
|
||||
try {
|
||||
fn();
|
||||
this.rec.expectationFailed(new Error('DID NOT THROW' + m));
|
||||
} catch (ex) {
|
||||
this.expectErrorValue(expectedName, ex, new Error(m));
|
||||
}
|
||||
}
|
||||
|
||||
expect(cond, msg) {
|
||||
if (cond) {
|
||||
const m = msg ? ': ' + msg : '';
|
||||
this.rec.debug(new Error('expect OK' + m));
|
||||
} else {
|
||||
this.rec.expectationFailed(new Error(msg));
|
||||
}
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=fixture.js.map
|
|
@ -1,132 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
/// <reference types="@webgpu/types" />
|
||||
import { assert } from '../util/util.js';
|
||||
let impl = undefined;
|
||||
export function getGPU() {
|
||||
if (impl) {
|
||||
return impl;
|
||||
}
|
||||
|
||||
assert(typeof navigator !== 'undefined' && navigator.gpu !== undefined, 'No WebGPU implementation found');
|
||||
impl = navigator.gpu;
|
||||
return impl;
|
||||
}
|
||||
//# sourceMappingURL=implementation.js.map
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
//# sourceMappingURL=result.js.map
|
|
@ -1,137 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,111 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
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 (paramKeyIsPublic(k)) {
|
||||
publicParams[k] = params[k];
|
||||
}
|
||||
}
|
||||
|
||||
return publicParams;
|
||||
}
|
||||
export const badParamValueChars = new RegExp('[' + kParamKVSeparator + kParamSeparator + kWildcard + ']');
|
||||
export function publicParamsEquals(x, y) {
|
||||
return comparePublicParamsPaths(x, y) === Ordering.Equal;
|
||||
}
|
||||
//# sourceMappingURL=params_utils.js.map
|
|
@ -1,104 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,122 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,125 +0,0 @@
|
|||
/**
|
||||
* 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';
|
||||
/**
|
||||
* Represents a test query of some level.
|
||||
*
|
||||
* TestQuery types are immutable.
|
||||
*/
|
||||
|
||||
// SingleCase
|
||||
|
||||
/**
|
||||
* A multi-file test query, like `s:*` or `s:a,b,*`.
|
||||
*
|
||||
* Immutable (makes copies of constructor args).
|
||||
*/
|
||||
export class TestQueryMultiFile {
|
||||
constructor(suite, file) {
|
||||
_defineProperty(this, "level", 1);
|
||||
|
||||
_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));
|
||||
}
|
||||
|
||||
toStringHelper() {
|
||||
return [this.suite, [...this.filePathParts, kWildcard].join(kPathSeparator)];
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* A multi-test test query, like `s:f:*` or `s:f:a,b,*`.
|
||||
*
|
||||
* Immutable (makes copies of constructor args).
|
||||
*/
|
||||
|
||||
export class TestQueryMultiTest extends TestQueryMultiFile {
|
||||
constructor(suite, file, test) {
|
||||
super(suite, file);
|
||||
|
||||
_defineProperty(this, "level", 2);
|
||||
|
||||
_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)];
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* A multi-case test query, like `s:f:t:*` or `s:f:t:a,b,*`.
|
||||
*
|
||||
* Immutable (makes copies of constructor args), except for param values
|
||||
* (which aren't normally supposed to change; they're marked readonly in CaseParams).
|
||||
*/
|
||||
|
||||
export class TestQueryMultiCase extends TestQueryMultiTest {
|
||||
constructor(suite, file, test, params) {
|
||||
super(suite, file, test);
|
||||
|
||||
_defineProperty(this, "level", 3);
|
||||
|
||||
_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)];
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* A multi-case test query, like `s:f:t:` or `s:f:t:a=1,b=1`.
|
||||
*
|
||||
* Immutable (makes copies of constructor args).
|
||||
*/
|
||||
|
||||
export class TestQuerySingleCase extends TestQueryMultiCase {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
_defineProperty(this, "level", 4);
|
||||
|
||||
_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
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
/** Separator between big parts: suite:file:test:case */
|
||||
export const kBigSeparator = ':';
|
||||
/** Separator between path,to,file or path,to,test */
|
||||
|
||||
export const kPathSeparator = ',';
|
||||
/** Separator between k=v;k=v */
|
||||
|
||||
export const kParamSeparator = ';';
|
||||
/** Separator between key and value in k=v */
|
||||
|
||||
export const kParamKVSeparator = '=';
|
||||
/** Final wildcard, if query is not single-case */
|
||||
|
||||
export const kWildcard = '*';
|
||||
//# sourceMappingURL=separators.js.map
|
|
@ -1,20 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,7 +0,0 @@
|
|||
/**
|
||||
* 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
|
|
@ -1,161 +0,0 @@
|
|||
/**
|
||||
* 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 { 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';
|
||||
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);
|
||||
|
||||
_defineProperty(this, "seen", new Set());
|
||||
|
||||
_defineProperty(this, "tests", []);
|
||||
|
||||
this.fixture = fixture;
|
||||
}
|
||||
|
||||
*iterate() {
|
||||
for (const test of this.tests) {
|
||||
yield* test.iterate();
|
||||
}
|
||||
}
|
||||
|
||||
checkName(name) {
|
||||
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)}`);
|
||||
assert(!this.seen.has(name), `Duplicate test name: ${name}`);
|
||||
this.seen.add(name);
|
||||
} // TODO: This could take a fixture, too, to override the one for the group.
|
||||
|
||||
|
||||
test(name) {
|
||||
this.checkName(name);
|
||||
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;
|
||||
}
|
||||
|
||||
checkCaseNamesAndDuplicates() {
|
||||
for (const test of this.tests) {
|
||||
test.checkCaseNamesAndDuplicates();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestBuilder {
|
||||
constructor(testPath, fixture) {
|
||||
_defineProperty(this, "testPath", void 0);
|
||||
|
||||
_defineProperty(this, "fixture", void 0);
|
||||
|
||||
_defineProperty(this, "testFn", void 0);
|
||||
|
||||
_defineProperty(this, "cases", undefined);
|
||||
|
||||
this.testPath = testPath;
|
||||
this.fixture = fixture;
|
||||
}
|
||||
|
||||
fn(fn) {
|
||||
this.testFn = fn;
|
||||
}
|
||||
|
||||
checkCaseNamesAndDuplicates() {
|
||||
if (this.cases === undefined) {
|
||||
return;
|
||||
} // This is n^2.
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
params(casesIterable) {
|
||||
assert(this.cases === undefined, 'test case is already parameterized');
|
||||
this.cases = Array.from(casesIterable);
|
||||
return this;
|
||||
}
|
||||
|
||||
*iterate() {
|
||||
assert(this.testFn !== undefined, 'No test function (.fn()) for test');
|
||||
|
||||
for (const params of this.cases || [{}]) {
|
||||
yield new RunCaseSpecific(this.testPath, params, this.fixture, this.testFn);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RunCaseSpecific {
|
||||
constructor(testPath, params, fixture, fn) {
|
||||
_defineProperty(this, "id", void 0);
|
||||
|
||||
_defineProperty(this, "params", void 0);
|
||||
|
||||
_defineProperty(this, "fixture", void 0);
|
||||
|
||||
_defineProperty(this, "fn", void 0);
|
||||
|
||||
this.id = {
|
||||
test: testPath,
|
||||
params: extractPublicParams(params)
|
||||
};
|
||||
this.params = params;
|
||||
this.fixture = fixture;
|
||||
this.fn = fn;
|
||||
}
|
||||
|
||||
async run(rec) {
|
||||
rec.start();
|
||||
|
||||
try {
|
||||
const inst = new this.fixture(rec, this.params || {});
|
||||
|
||||
try {
|
||||
await inst.init();
|
||||
await this.fn(inst);
|
||||
} finally {
|
||||
// Runs as long as constructor succeeded, even if initialization or the test failed.
|
||||
await inst.finalize();
|
||||
}
|
||||
} 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
|
||||
// or unexpected validation/OOM error from the GPUDevice.
|
||||
rec.threw(ex);
|
||||
}
|
||||
|
||||
rec.finish();
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=test_group.js.map
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
//# sourceMappingURL=test_suite_listing.js.map
|
|
@ -1,361 +0,0 @@
|
|||
/**
|
||||
* 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 { compareQueries, Ordering } from './query/compare.js';
|
||||
import { TestQueryMultiCase, TestQuerySingleCase, TestQueryMultiFile, TestQueryMultiTest } from './query/query.js';
|
||||
import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './query/separators.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.
|
||||
|
||||
export class TestTree {
|
||||
constructor(root) {
|
||||
_defineProperty(this, "root", void 0);
|
||||
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
iterateCollapsedQueries() {
|
||||
return TestTree.iterateSubtreeCollapsedQueries(this.root);
|
||||
}
|
||||
|
||||
iterateLeaves() {
|
||||
return TestTree.iterateSubtreeLeaves(this.root);
|
||||
}
|
||||
/**
|
||||
* If a parent and its child are at different levels, then
|
||||
* generally the parent has only one child, i.e.:
|
||||
* a,* { a,b,* { a,b:* { ... } } }
|
||||
* Collapse that down into:
|
||||
* a,* { a,b:* { ... } }
|
||||
* which is less needlessly verbose when displaying the tree in the standalone runner.
|
||||
*/
|
||||
|
||||
|
||||
dissolveLevelBoundaries() {
|
||||
const newRoot = dissolveLevelBoundaries(this.root);
|
||||
assert(newRoot === 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static *iterateSubtreeLeaves(subtree) {
|
||||
for (const [, child] of subtree.children) {
|
||||
if ('children' in child) {
|
||||
yield* TestTree.iterateSubtreeLeaves(child);
|
||||
} else {
|
||||
yield child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static subtreeToString(name, tree, indent) {
|
||||
const collapsible = 'run' in tree ? '>' : tree.collapsible ? '+' : '-';
|
||||
let s = indent + `${collapsible} ${JSON.stringify(name)} => ${tree.query}`;
|
||||
|
||||
if ('children' in tree) {
|
||||
if (tree.description !== undefined) {
|
||||
s += `\n${indent} | ${JSON.stringify(tree.description)}`;
|
||||
}
|
||||
|
||||
for (const [name, child] of tree.children) {
|
||||
s += '\n' + TestTree.subtreeToString(name, child, indent + ' ');
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
} // TODO: Consider having subqueriesToExpand actually impact the depth-order of params in the tree.
|
||||
|
||||
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:
|
||||
|
||||
|
||||
let foundCase = false; // L0 is suite:*
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
{
|
||||
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 ('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 spec = await loader.importSpecFile(queryToLoad.suite, entry.file);
|
||||
const description = spec.description.trim(); // subtreeL1 is suite:a,b:*
|
||||
|
||||
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).
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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');
|
||||
return new TestTree(subtreeL0);
|
||||
}
|
||||
|
||||
function makeTreeForSuite(suite) {
|
||||
return {
|
||||
readableRelativeName: suite + kBigSeparator,
|
||||
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 {
|
||||
readableRelativeName: part + kPathSeparator + kWildcard,
|
||||
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, []);
|
||||
assert(file.length > 0, 'file path is empty');
|
||||
return {
|
||||
readableRelativeName: file[file.length - 1] + kBigSeparator + kWildcard,
|
||||
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 {
|
||||
readableRelativeName: part + kPathSeparator + kWildcard,
|
||||
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, {});
|
||||
assert(subqueryTest.length > 0, 'subqueryTest is empty');
|
||||
return {
|
||||
readableRelativeName: subqueryTest[subqueryTest.length - 1] + kBigSeparator + kWildcard,
|
||||
kWildcard,
|
||||
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 {
|
||||
readableRelativeName: name + kParamSeparator + kWildcard,
|
||||
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 = {
|
||||
readableRelativeName: readableNameForCase(query),
|
||||
query,
|
||||
run: rec => t.run(rec)
|
||||
};
|
||||
assert(!parent.children.has(key));
|
||||
parent.children.set(key, leaf);
|
||||
}
|
||||
|
||||
function dissolveLevelBoundaries(tree) {
|
||||
if ('children' in tree) {
|
||||
if (tree.children.size === 1 && tree.description === undefined) {
|
||||
// Loops exactly once
|
||||
for (const [, child] of tree.children) {
|
||||
if (child.query.level > tree.query.level) {
|
||||
const newtree = dissolveLevelBoundaries(child);
|
||||
return newtree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const [k, child] of tree.children) {
|
||||
const newChild = dissolveLevelBoundaries(child);
|
||||
|
||||
if (newChild !== child) {
|
||||
tree.children.set(k, newChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
/** Generate a readable relative name for a case (used in standalone). */
|
||||
|
||||
|
||||
function readableNameForCase(query) {
|
||||
const paramsKeys = Object.keys(query.params);
|
||||
|
||||
if (paramsKeys.length === 0) {
|
||||
return query.testPathParts[query.testPathParts.length - 1] + kBigSeparator;
|
||||
} else {
|
||||
const lastKey = paramsKeys[paramsKeys.length - 1];
|
||||
return stringifySingleParam(lastKey, query.params[lastKey]);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=tree.js.map
|
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
* 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; }
|
||||
|
||||
export class AsyncMutex {
|
||||
constructor() {
|
||||
_defineProperty(this, "newestQueueItem", void 0);
|
||||
}
|
||||
|
||||
// Run an async function with a lock on this mutex.
|
||||
// Waits until the mutex is available, locks it, runs the function, then releases it.
|
||||
async with(fn) {
|
||||
const p = (async () => {
|
||||
// If the mutex is locked, wait for the last thing in the queue before running.
|
||||
// (Everything in the queue runs in order, so this is after everything currently enqueued.)
|
||||
if (this.newestQueueItem) {
|
||||
await this.newestQueueItem;
|
||||
}
|
||||
|
||||
return fn();
|
||||
})(); // Push the newly-created Promise onto the queue by replacing the old "newest" item.
|
||||
|
||||
|
||||
this.newestQueueItem = p; // And return so the caller can wait on the result.
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=async_mutex.js.map
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* 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';
|
||||
temp; // dummy use of unused variable
|
||||
|
||||
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
|
|
@ -1,83 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
// 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 lines = e.stack.split('\n');
|
||||
|
||||
for (let i = lines.length - 1; i >= 0; --i) {
|
||||
const line = lines[i];
|
||||
|
||||
if (line.indexOf('.spec.') !== -1) {
|
||||
return lines.slice(0, i + 1).join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
return e.stack;
|
||||
} // *** Examples ***
|
||||
//
|
||||
// Node fail()
|
||||
// > Error:
|
||||
// > at CaseRecorder.fail (/Users/kainino/src/cts/src/common/framework/logger.ts:99:30)
|
||||
// > at RunCaseSpecific.exports.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/logger.spec.ts:80:7)
|
||||
// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)
|
||||
// x at processTicksAndRejections (internal/process/task_queues.js:86:5)
|
||||
//
|
||||
// Node throw
|
||||
// > Error: hello
|
||||
// > at RunCaseSpecific.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/test_group.spec.ts:51:11)
|
||||
// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)
|
||||
// x at processTicksAndRejections (internal/process/task_queues.js:86:5)
|
||||
//
|
||||
// Firefox fail()
|
||||
// > fail@http://localhost:8080/out/framework/logger.js:104:30
|
||||
// > expect@http://localhost:8080/out/framework/default_fixture.js:59:16
|
||||
// > @http://localhost:8080/out/unittests/util.spec.js:35:5
|
||||
// x run@http://localhost:8080/out/framework/test_group.js:119:18
|
||||
//
|
||||
// Firefox throw
|
||||
// > @http://localhost:8080/out/unittests/test_group.spec.js:48:11
|
||||
// x run@http://localhost:8080/out/framework/test_group.js:119:18
|
||||
//
|
||||
// Safari fail()
|
||||
// > fail@http://localhost:8080/out/framework/logger.js:104:39
|
||||
// > expect@http://localhost:8080/out/framework/default_fixture.js:59:20
|
||||
// > http://localhost:8080/out/unittests/util.spec.js:35:11
|
||||
// x http://localhost:8080/out/framework/test_group.js:119:20
|
||||
// x asyncFunctionResume@[native code]
|
||||
// x [native code]
|
||||
// x promiseReactionJob@[native code]
|
||||
//
|
||||
// Safari throw
|
||||
// > http://localhost:8080/out/unittests/test_group.spec.js:48:20
|
||||
// x http://localhost:8080/out/framework/test_group.js:119:20
|
||||
// x asyncFunctionResume@[native code]
|
||||
// x [native code]
|
||||
// x promiseReactionJob@[native code]
|
||||
//
|
||||
// Chrome fail()
|
||||
// x Error
|
||||
// x at CaseRecorder.fail (http://localhost:8080/out/framework/logger.js:104:30)
|
||||
// x at DefaultFixture.expect (http://localhost:8080/out/framework/default_fixture.js:59:16)
|
||||
// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/util.spec.js:35:5)
|
||||
// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)
|
||||
// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)
|
||||
// x at async http://localhost:8080/out/runtime/standalone.js:102:7
|
||||
//
|
||||
// Chrome throw
|
||||
// x Error: hello
|
||||
// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)
|
||||
// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)"
|
||||
// x at async Promise.all (index 0)
|
||||
// x at async TestGroupTest.run (http://localhost:8080/out/unittests/test_group_test.js:6:5)
|
||||
// x at async RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:53:15)
|
||||
// x at async RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:7)
|
||||
// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)
|
||||
// x at async http://localhost:8080/out/runtime/standalone.js:102:7
|
||||
//# sourceMappingURL=stack.js.map
|
|
@ -1,6 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
export const timeout = typeof step_timeout !== 'undefined' ? step_timeout : setTimeout;
|
||||
//# sourceMappingURL=timeout.js.map
|
|
@ -1,63 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
import { timeout } from './timeout.js';
|
||||
export function assert(condition, msg) {
|
||||
if (!condition) {
|
||||
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) {
|
||||
throw new Error(msg);
|
||||
} // performance.now() is available in all browsers, but not in scope by default in Node.
|
||||
|
||||
const perf = typeof performance !== 'undefined' ? performance : require('perf_hooks').performance;
|
||||
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) => {
|
||||
timeout(() => {
|
||||
reject(new PromiseTimeoutError(msg));
|
||||
}, ms);
|
||||
});
|
||||
}
|
||||
export function raceWithRejectOnTimeout(p, ms, msg) {
|
||||
return Promise.race([p, rejectOnTimeout(ms, msg)]);
|
||||
}
|
||||
export function objectEquals(x, y) {
|
||||
if (typeof x !== 'object' || typeof y !== 'object') return x === y;
|
||||
if (x === null || y === null) return x === y;
|
||||
if (x.constructor !== y.constructor) return false;
|
||||
if (x instanceof Function) return x === y;
|
||||
if (x instanceof RegExp) return x === y;
|
||||
if (x === y || x.valueOf() === y.valueOf()) return true;
|
||||
if (Array.isArray(x) && Array.isArray(y) && x.length !== y.length) return false;
|
||||
if (x instanceof Date) return false;
|
||||
if (!(x instanceof Object)) return false;
|
||||
if (!(y instanceof Object)) return false;
|
||||
const x1 = x;
|
||||
const y1 = y;
|
||||
const p = Object.keys(x);
|
||||
return Object.keys(y).every(i => p.indexOf(i) !== -1) && p.every(i => objectEquals(x1[i], y1[i]));
|
||||
}
|
||||
export function range(n, fn) {
|
||||
return [...new Array(n)].map((_, i) => fn(i));
|
||||
}
|
||||
//# sourceMappingURL=util.js.map
|
|
@ -1,3 +0,0 @@
|
|||
// AUTO-GENERATED - DO NOT EDIT. See tools/gen_version.
|
||||
|
||||
export const version = '21f8f997c1db17e2daa6d0c9e8794a5c3216f373';
|
|
@ -1,10 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
const url = new URL(window.location.toString());
|
||||
export function optionEnabled(opt) {
|
||||
const val = url.searchParams.get(opt);
|
||||
return val !== null && val !== '0';
|
||||
}
|
||||
//# sourceMappingURL=options.js.map
|
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
import { DefaultTestFileLoader } from '../../framework/file_loader.js';
|
||||
import { Logger } from '../../framework/logging/logger.js';
|
||||
import { parseQuery } from '../../framework/query/parseQuery.js';
|
||||
import { assert } from '../../framework/util/util.js';
|
||||
// should be DedicatedWorkerGlobalScope
|
||||
const loader = new DefaultTestFileLoader();
|
||||
|
||||
self.onmessage = async ev => {
|
||||
const query = ev.data.query;
|
||||
const debug = ev.data.debug;
|
||||
const log = new Logger(debug);
|
||||
const testcases = Array.from(await loader.loadCases(parseQuery(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
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=test_worker-worker.js.map
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
* 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 { LogMessageWithStack } from '../../framework/logging/log_message.js';
|
||||
export class TestWorker {
|
||||
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';
|
||||
this.worker = new Worker(workerPath, {
|
||||
type: 'module'
|
||||
});
|
||||
|
||||
this.worker.onmessage = ev => {
|
||||
const query = ev.data.query;
|
||||
const result = ev.data.result;
|
||||
|
||||
if (result.logs) {
|
||||
for (const l of result.logs) {
|
||||
Object.setPrototypeOf(l, LogMessageWithStack.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
this.resolvers.get(query)(result); // TODO(kainino0x): update the Logger with this result (or don't have a logger and update the
|
||||
// entire results JSON somehow at some point).
|
||||
};
|
||||
}
|
||||
|
||||
async run(rec, query) {
|
||||
this.worker.postMessage({
|
||||
query,
|
||||
debug: this.debug
|
||||
});
|
||||
const workerResult = await new Promise(resolve => {
|
||||
this.resolvers.set(query, resolve);
|
||||
});
|
||||
rec.injectResult(workerResult);
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=test_worker.js.map
|
|
@ -1,58 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
import { DefaultTestFileLoader } from '../framework/file_loader.js';
|
||||
import { Logger } from '../framework/logging/logger.js';
|
||||
import { parseQuery } from '../framework/query/parseQuery.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 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.loadCases(parseQuery(qs[0]));
|
||||
await addWPTTests(testcases);
|
||||
})(); // Note: `async_test`s 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 testcase of testcases) {
|
||||
const name = testcase.query.toString();
|
||||
|
||||
const wpt_fn = function () {
|
||||
const p = mutex.with(async () => {
|
||||
const [rec, res] = log.record(name);
|
||||
|
||||
if (worker) {
|
||||
await worker.run(rec, name);
|
||||
} else {
|
||||
await testcase.run(rec);
|
||||
}
|
||||
|
||||
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.done();
|
||||
});
|
||||
running.push(p);
|
||||
return p;
|
||||
};
|
||||
|
||||
async_test(wpt_fn, name);
|
||||
}
|
||||
|
||||
return Promise.all(running).then(() => log);
|
||||
}
|
||||
//# sourceMappingURL=wpt.js.map
|
|
@ -1,56 +0,0 @@
|
|||
<!-- AUTO-GENERATED - DO NOT EDIT. See WebGPU CTS: tools/gen_wpt_cts_html. -->
|
||||
<!--
|
||||
This test suite is built from the TypeScript sources at:
|
||||
https://github.com/gpuweb/cts
|
||||
|
||||
If you are debugging WebGPU conformance tests, it's highly recommended that
|
||||
you use the standalone interactive runner in that repository, which
|
||||
provides tools for easier debugging and editing (source maps, debug
|
||||
logging, warn/skip functionality, etc.)
|
||||
|
||||
NOTE:
|
||||
The WPT version of this file is generated with *one variant per test spec
|
||||
file*. If your harness needs more fine-grained suppressions, you'll need to
|
||||
generate your own variants list from your suppression list.
|
||||
See `tools/gen_wpt_cts_html` to do this.
|
||||
|
||||
When run under browser CI, the original cts.html should be skipped, and
|
||||
this alternate version should be run instead, under a non-exported WPT test
|
||||
directory (e.g. Chromium's wpt_internal).
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<title>WebGPU CTS</title>
|
||||
<meta charset=utf-8>
|
||||
<link rel=help href='https://gpuweb.github.io/gpuweb/'>
|
||||
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<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,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:idl,constants,flags:*'>
|
||||
<meta name=variant content='?q=webgpu:web-platform,canvas,context_creation:*'>
|
||||
<meta name=variant content='?q=webgpu:web-platform,copyImageBitmapToTexture:*'>
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
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 = 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 | (mappable ? GPUBufferUsage.MAP_WRITE : 0)
|
||||
});
|
||||
t.checkMapWrite(buffer, arrayBuffer, size);
|
||||
});
|
||||
//# sourceMappingURL=create_mapped.spec.js.map
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
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 = 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);
|
||||
});
|
||||
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
|
||||
});
|
||||
const expected = new Uint32Array(new ArrayBuffer(size));
|
||||
const data = new Uint32Array(init);
|
||||
|
||||
for (let i = 0; i < data.length; ++i) {
|
||||
data[i] = expected[i] = i + 1;
|
||||
}
|
||||
|
||||
buffer.unmap();
|
||||
const actual = new Uint8Array(await buffer.mapReadAsync());
|
||||
t.expectBuffer(actual, new Uint8Array(expected.buffer));
|
||||
});
|
||||
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 | (mappable ? GPUBufferUsage.MAP_WRITE : 0)
|
||||
});
|
||||
t.checkMapWrite(buffer, arrayBuffer, size);
|
||||
});
|
||||
//# sourceMappingURL=map.spec.js.map
|
|
@ -1,82 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
export const description = '';
|
||||
import { makeTestGroup } from '../../../../common/framework/test_group.js';
|
||||
import { GPUTest } from '../../../gpu_test.js';
|
||||
|
||||
class F extends GPUTest {
|
||||
checkDetach(buffer, arrayBuffer, unmap, destroy) {
|
||||
const view = new Uint8Array(arrayBuffer);
|
||||
this.expect(arrayBuffer.byteLength === 4);
|
||||
this.expect(view.length === 4);
|
||||
if (unmap) buffer.unmap();
|
||||
if (destroy) buffer.destroy();
|
||||
this.expect(arrayBuffer.byteLength === 0, 'ArrayBuffer should be detached');
|
||||
this.expect(view.byteLength === 0, 'ArrayBufferView should be detached');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
g.test('mapReadAsync').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_READ
|
||||
});
|
||||
const arrayBuffer = await buffer.mapReadAsync();
|
||||
t.checkDetach(buffer, arrayBuffer, t.params.unmap, t.params.destroy);
|
||||
});
|
||||
g.test('create_mapped').params([{
|
||||
unmap: true,
|
||||
destroy: false
|
||||
}, {
|
||||
unmap: false,
|
||||
destroy: true
|
||||
}, {
|
||||
unmap: true,
|
||||
destroy: true
|
||||
}]).fn(async t => {
|
||||
const desc = {
|
||||
size: 4,
|
||||
usage: GPUBufferUsage.MAP_WRITE
|
||||
};
|
||||
const [buffer, arrayBuffer] = t.device.createBufferMapped(desc);
|
||||
const view = new Uint8Array(arrayBuffer);
|
||||
t.expect(arrayBuffer.byteLength === 4);
|
||||
t.expect(view.length === 4);
|
||||
if (t.params.unmap) buffer.unmap();
|
||||
if (t.params.destroy) buffer.destroy();
|
||||
t.expect(arrayBuffer.byteLength === 0, 'ArrayBuffer should be detached');
|
||||
t.expect(view.byteLength === 0, 'ArrayBufferView should be detached');
|
||||
});
|
||||
//# sourceMappingURL=map_detach.spec.js.map
|
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
export const description = '';
|
||||
import { makeTestGroup } from '../../../../common/framework/test_group.js';
|
||||
import { GPUTest } from '../../../gpu_test.js';
|
||||
|
||||
function getBufferDesc(usage) {
|
||||
return {
|
||||
size: Number.MAX_SAFE_INTEGER,
|
||||
usage
|
||||
};
|
||||
}
|
||||
|
||||
export const g = makeTestGroup(GPUTest);
|
||||
g.test('mapWriteAsync').fn(async t => {
|
||||
const buffer = t.expectGPUError('out-of-memory', () => {
|
||||
return t.device.createBuffer(getBufferDesc(GPUBufferUsage.MAP_WRITE));
|
||||
});
|
||||
t.shouldReject('OperationError', buffer.mapWriteAsync());
|
||||
});
|
||||
g.test('mapReadAsync').fn(async t => {
|
||||
const buffer = t.expectGPUError('out-of-memory', () => {
|
||||
return t.device.createBuffer(getBufferDesc(GPUBufferUsage.MAP_READ));
|
||||
});
|
||||
t.shouldReject('OperationError', buffer.mapReadAsync());
|
||||
});
|
||||
g.test('createBufferMapped').fn(async t => {
|
||||
t.shouldThrow('RangeError', () => {
|
||||
t.device.createBufferMapped(getBufferDesc(GPUBufferUsage.COPY_SRC));
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=map_oom.spec.js.map
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
import { GPUTest } from '../../../gpu_test.js';
|
||||
export class MappingTest extends GPUTest {
|
||||
checkMapWrite(buffer, mappedContents, size) {
|
||||
this.checkMapWriteZeroed(mappedContents, size);
|
||||
const mappedView = new Uint32Array(mappedContents);
|
||||
const expected = new Uint32Array(new ArrayBuffer(size));
|
||||
this.expect(mappedView.byteLength === size);
|
||||
|
||||
for (let i = 0; i < mappedView.length; ++i) {
|
||||
mappedView[i] = expected[i] = i + 1;
|
||||
}
|
||||
|
||||
buffer.unmap();
|
||||
this.expectContents(buffer, expected);
|
||||
}
|
||||
|
||||
checkMapWriteZeroed(arrayBuffer, expectedSize) {
|
||||
this.expect(arrayBuffer.byteLength === expectedSize);
|
||||
const view = new Uint8Array(arrayBuffer);
|
||||
this.expectZero(view);
|
||||
}
|
||||
|
||||
expectZero(actual) {
|
||||
const size = actual.byteLength;
|
||||
|
||||
for (let i = 0; i < size; ++i) {
|
||||
if (actual[i] !== 0) {
|
||||
this.fail(`at [${i}], expected zero, got ${actual[i]}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//# sourceMappingURL=mapping_test.js.map
|
|
@ -1,16 +0,0 @@
|
|||
/**
|
||||
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
|
||||
**/
|
||||
|
||||
export const description = `
|
||||
Basic tests.
|
||||
`;
|
||||
import { makeTestGroup } from '../../../../common/framework/test_group.js';
|
||||
import { GPUTest } from '../../../gpu_test.js';
|
||||
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]);
|
||||
});
|
||||
//# sourceMappingURL=basic.spec.js.map
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue