Bug 1720941, part 1: build(ci): integrate WebGPU CTS into CI r=webgpu-reviewers,taskgraph-reviewers,jmaher,jimb

Vendor in WebGPU CTS so that we can run it against our implementation of WebGPU. This patch includes:

1. Some linting configuration tweaks, to silence issues that weren't straightforward to fix in CTS upstream.
2. Some WPT runner configuration to enable preferences, and skip MacOS testing altogether (since it's not targeted by our current work).
3. A new Rust binary crate that, when run from a development environment:
    1. Creates a vendored copy of WebGPU CTS in `<gecko>/dom/webgpu/tests/cts/checkout/`.
    2. Generates private Web Platform Tests (see also `<gecko>/testing/web-platform/docs/index.rst`). To do this, we:
        1. Use upstream test generation via `npm` scripts, which creates a single `cts.https.html` file with thousands of variants.
        2. Chunk the `cts.https.html` file into parts that Taskcluster can distribute without timing out individual jobs. IMO, this is the most likely part of these changes to need further iteration, because:
            1. We currently naively divide tests by number of variant, and have made no effort to empirically prove that we're dividing execution time of chunks.
            2. There is currently no stability in the distribution of tests per chunk. Test variants are essentially a flattened list of the tree structure used to organize tests. Adding a few tests that end up being placed in the middle of the list can cause the chunk with new tests _and all subsequent chunks_ to have their contents changed, which will probably cause a disproportionate number of line changes to review.:
        3. Fix `script` tag(s) so they actually work with the WPT test runner for private tests (viz., in the `testing/web-platform/mozilla` directory).

The output of the new vendoring binary is designed make the above steps transparent. N.B. that no actual vendoring in of files has happened yet; the next patch will add the results of running this script.

Differential Revision: https://phabricator.services.mozilla.com/D169951
This commit is contained in:
Erich Gubler 2023-03-15 20:13:45 +00:00
Родитель 9d92df5215
Коммит af02a85436
13 изменённых файлов: 1819 добавлений и 7 удалений

Просмотреть файл

@ -171,6 +171,7 @@ _OPT\.OBJ/
^servo/ports/geckolib/target/
^dom/base/rust/target/
^servo/components/style/target/
^dom/webgpu/tests/cts/vendor/target/
# Ignore mozharness execution files
^testing/mozharness/.tox/

Просмотреть файл

@ -0,0 +1,17 @@
# WebGPU CTS vendor checkout
This directory contains the following:
```sh
.
├── README.md # You are here!
├── arguments.txt # Used by `vendor/`
├── checkout/ # Our vendored copy of WebGPU CTS
├── myexpectations.txt # Used by `vendor/`
└── vendor/ # Rust binary crate for updating `checkout/` and generating WPT tests
```
## Re-vendoring
You can re-vendor by running the Rust binary crate from its Cargo project root. Change your working
directory to `vendor/` and invoke `cargo run -- --help` for more details.

Просмотреть файл

@ -0,0 +1 @@
?q=

Просмотреть файл

889
dom/webgpu/tests/cts/vendor/Cargo.lock сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,889 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
dependencies = [
"bitflags",
"clap_derive",
"clap_lex",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "crossbeam"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
dependencies = [
"cfg-if",
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
[[package]]
name = "dircpy"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10b6622b9d0dc20c70e74ff24c56493278d7d9299ac8729deb923703616e5a7e"
dependencies = [
"jwalk",
"log",
"walkdir",
]
[[package]]
name = "dunce"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "env_logger"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "format"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "901e1b63ac63f86d9fb836b1ae8b43e5a9f2338975e9de24f36a1af4acf23ac8"
dependencies = [
"format-core",
"format-macro",
]
[[package]]
name = "format-core"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e66b70d6700c47044b73e43dd0649e0d6bfef18f87919c23785cdbd1aaa9d3f5"
[[package]]
name = "format-macro"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f9faac4e57f217563dd1fd58628a0c526aa37a681ffac76ca80d64907370a4c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "getrandom"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "io-lifetimes"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "is_ci"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
[[package]]
name = "jwalk"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dbcda57db8b6dc067e589628b7348639014e793d9e8137d8cf215e8b133a0bd"
dependencies = [
"crossbeam",
"rayon",
]
[[package]]
name = "lets_find_up"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91a14fb0b4300e025486cc8bc096c7173c2c615ce8f9c6da7829a4af3f5afbd"
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
[[package]]
name = "miette"
version = "5.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4afd9b301defa984bbdbe112b4763e093ed191750a0d914a78c1106b2d0fe703"
dependencies = [
"atty",
"backtrace",
"miette-derive",
"once_cell",
"owo-colors",
"supports-color",
"supports-hyperlinks",
"supports-unicode",
"terminal_size",
"textwrap",
"thiserror",
"unicode-width",
]
[[package]]
name = "miette-derive"
version = "5.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97c2401ab7ac5282ca5c8b518a87635b1a93762b0b90b9990c509888eeccba29"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "object"
version = "0.30.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "owo-colors"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "regex"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustix"
version = "0.36.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "shell-words"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]]
name = "smawk"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "supports-color"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f"
dependencies = [
"atty",
"is_ci",
]
[[package]]
name = "supports-hyperlinks"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "590b34f7c5f01ecc9d78dba4b3f445f31df750a67621cf31626f3b7441ce6406"
dependencies = [
"atty",
]
[[package]]
name = "supports-unicode"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8b945e45b417b125a8ec51f1b7df2f8df7920367700d1f98aedd21e5735f8b2"
dependencies = [
"atty",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "terminal_size"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "textwrap"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
dependencies = [
"smawk",
"unicode-linebreak",
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-linebreak"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137"
dependencies = [
"hashbrown",
"regex",
]
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "vendor-webgpu-cts"
version = "0.1.0"
dependencies = [
"clap",
"dircpy",
"dunce",
"env_logger",
"format",
"lets_find_up",
"log",
"miette",
"regex",
"shell-words",
"thiserror",
"which",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "which"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
dependencies = [
"either",
"libc",
"once_cell",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"

20
dom/webgpu/tests/cts/vendor/Cargo.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
[package]
name = "vendor-webgpu-cts"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.1.6", features = ["derive"] }
dircpy = "0.3.14"
dunce = "1.0.3"
env_logger = "0.10.0"
format = "0.2.4"
lets_find_up = "0.0.3"
log = "0.4.17"
miette = { version = "5.5.0", features = ["fancy"] }
regex = "1.7.1"
shell-words = "1.1.0"
thiserror = "1.0.38"
which = "4.4.0"
[workspace]

310
dom/webgpu/tests/cts/vendor/src/fs.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,310 @@
use std::{
ffi::OsStr,
fmt::{self, Display},
fs,
ops::Deref,
path::{Path, PathBuf, StripPrefixError},
};
use miette::{ensure, Context, IntoDiagnostic};
#[derive(Debug)]
pub(crate) struct FileRoot {
nickname: &'static str,
path: PathBuf,
}
impl FileRoot {
pub(crate) fn new<P>(nickname: &'static str, path: P) -> miette::Result<Self>
where
P: AsRef<Path>,
{
let path = path.as_ref();
Ok(Self {
nickname,
path: dunce::canonicalize(path)
.map_err(miette::Report::msg)
.wrap_err_with(|| format!("failed to canonicalize {path:?}"))?,
})
}
pub(crate) fn nickname(&self) -> &str {
self.nickname
}
pub(crate) fn try_child<P>(&self, path: P) -> Result<Child<'_>, StripPrefixError>
where
P: AsRef<Path>,
{
let path = path.as_ref();
if path.is_absolute() {
path.strip_prefix(&self.path)?;
}
Ok(Child {
root: self,
path: self.path.join(path),
})
}
#[track_caller]
pub(crate) fn child<P>(&self, path: P) -> Child<'_>
where
P: AsRef<Path>,
{
self.try_child(path)
.into_diagnostic()
.wrap_err("invariant violation: `path` is absolute and not a child of this file root")
.unwrap()
}
fn removed_dir<P>(&self, path: P) -> miette::Result<Child<'_>>
where
P: AsRef<Path>,
{
let path = path.as_ref();
let child = self.child(path);
if child.exists() {
log::info!("removing old contents of {child}…",);
log::trace!("removing directory {:?}", &*child);
fs::remove_dir_all(&*child)
.map_err(miette::Report::msg)
.wrap_err_with(|| format!("failed to remove old contents of {child}"))?;
}
Ok(child)
}
fn removed_file<P>(&self, path: P) -> miette::Result<Child<'_>>
where
P: AsRef<Path>,
{
let path = path.as_ref();
let child = self.child(path);
if child.exists() {
log::info!("removing old copy of {child}…",);
fs::remove_file(&*child)
.map_err(miette::Report::msg)
.wrap_err_with(|| format!("failed to remove old copy of {child}"))?;
}
Ok(child)
}
pub(crate) fn regen_dir<P>(
&self,
path: P,
gen: impl FnOnce(&Child<'_>) -> miette::Result<()>,
) -> miette::Result<Child<'_>>
where
P: AsRef<Path>,
{
let child = self.removed_dir(path)?;
gen(&child)?;
ensure!(
child.is_dir(),
"{} was not regenerated for an unknown reason",
child,
);
Ok(child)
}
pub(crate) fn regen_file<P>(
&self,
path: P,
gen: impl FnOnce(&Child<'_>) -> miette::Result<()>,
) -> miette::Result<Child<'_>>
where
P: AsRef<Path>,
{
let child = self.removed_file(path)?;
gen(&child)?;
ensure!(
child.is_file(),
"{} was not regenerated for an unknown reason",
child,
);
Ok(child)
}
}
impl Deref for FileRoot {
type Target = Path;
fn deref(&self) -> &Self::Target {
&self.path
}
}
impl AsRef<Path> for FileRoot {
fn as_ref(&self) -> &Path {
&self.path
}
}
impl AsRef<OsStr> for FileRoot {
fn as_ref(&self) -> &OsStr {
self.path.as_os_str()
}
}
impl Display for FileRoot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { nickname, path } = self;
write!(f, "`{}` (AKA `<{nickname}>`)", path.display())
}
}
pub(crate) struct Child<'a> {
root: &'a FileRoot,
/// NOTE: This is always an absolute path that is a child of the `root`.
path: PathBuf,
}
impl Child<'_> {
pub(crate) fn relative_path(&self) -> &Path {
let Self { root, path } = self;
path.strip_prefix(root).unwrap()
}
pub(crate) fn try_child<P>(&self, path: P) -> Result<Self, StripPrefixError>
where
P: AsRef<Path>,
{
let child_path = path.as_ref();
let Self { root, path } = self;
if child_path.is_absolute() {
child_path.strip_prefix(path)?;
}
Ok(Child {
root,
path: path.join(child_path),
})
}
#[track_caller]
pub(crate) fn child<P>(&self, path: P) -> Child<'_>
where
P: AsRef<Path>,
{
self.try_child(path)
.into_diagnostic()
.wrap_err("invariant violation: `path` is absolute and not a child of this child")
.unwrap()
}
}
impl Deref for Child<'_> {
type Target = Path;
fn deref(&self) -> &Self::Target {
&self.path
}
}
impl AsRef<Path> for Child<'_> {
fn as_ref(&self) -> &Path {
&self.path
}
}
impl AsRef<OsStr> for Child<'_> {
fn as_ref(&self) -> &OsStr {
self.path.as_os_str()
}
}
impl Display for Child<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"`<{}>{}{}`",
self.root.nickname(),
std::path::MAIN_SEPARATOR,
self.relative_path().display()
)
}
}
pub(crate) fn existing_file<P>(path: P) -> P
where
P: AsRef<Path>,
{
let p = path.as_ref();
assert!(p.is_file(), "{p:?} does not exist as a file");
path
}
pub(crate) fn copy_dir<P, Q>(source: P, dest: Q) -> miette::Result<()>
where
P: Display + AsRef<Path>,
Q: Display + AsRef<Path>,
{
log::debug!(
"copy-merging directories from {} into {}",
source.as_ref().display(),
dest.as_ref().display(),
);
::dircpy::copy_dir(&source, &dest)
.into_diagnostic()
.wrap_err_with(|| format!("failed to copy files from {source} to {dest}"))
}
pub(crate) fn read_to_string<P>(path: P) -> miette::Result<String>
where
P: AsRef<Path>,
{
fs::read_to_string(&path)
.into_diagnostic()
.wrap_err_with(|| {
format!(
"failed to read UTF-8 string from path {}",
path.as_ref().display()
)
})
}
pub(crate) fn copy<P1, P2>(from: P1, to: P2) -> miette::Result<u64>
where
P1: AsRef<Path>,
P2: AsRef<Path>,
{
fs::copy(&from, &to).into_diagnostic().wrap_err_with(|| {
format!(
"failed to copy {} to {}",
from.as_ref().display(),
to.as_ref().display()
)
})
}
pub(crate) fn create_dir_all<P>(path: P) -> miette::Result<()>
where
P: AsRef<Path>,
{
fs::create_dir_all(&path)
.into_diagnostic()
.wrap_err_with(|| {
format!(
"failed to create directories leading up to {}",
path.as_ref().display()
)
})
}
pub(crate) fn remove_file<P>(path: P) -> miette::Result<()>
where
P: AsRef<Path>,
{
fs::remove_file(&path)
.into_diagnostic()
.wrap_err_with(|| format!("failed to remove file at path {}", path.as_ref().display()))
}
pub(crate) fn write<P, C>(path: P, contents: C) -> miette::Result<()>
where
P: AsRef<Path>,
C: AsRef<[u8]>,
{
fs::write(&path, &contents)
.into_diagnostic()
.wrap_err_with(|| format!("failed to write to path {}", path.as_ref().display()))
}

460
dom/webgpu/tests/cts/vendor/src/main.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,460 @@
use std::{
collections::BTreeSet,
env::{current_dir, set_current_dir},
num::NonZeroUsize,
path::{Path, PathBuf},
process::ExitCode,
};
use clap::Parser;
use lets_find_up::{find_up_with, FindUpKind, FindUpOptions};
use miette::{ensure, miette, Context, Diagnostic, IntoDiagnostic, Report, SourceSpan};
use regex::Regex;
use crate::{
fs::{copy_dir, create_dir_all, existing_file, remove_file, FileRoot},
path::join_path,
process::{which, EasyCommand},
};
mod fs;
mod path;
mod process;
/// Vendor WebGPU CTS tests from a local Git checkout of [our `gpuweb/cts` fork].
///
/// WPT tests are generated into `testing/web-platform/mozilla/tests/webgpu/`. If the set of tests
/// changes upstream, make sure that the generated output still matches up with test expectation
/// metadata in `testing/web-platform/mozilla/meta/webgpu/`.
///
/// [our `gpuweb/cts` fork]: https://github.com/mozilla/gpuweb-cts
#[derive(Debug, Parser)]
struct CliArgs {
/// A path to the top-level directory of your WebGPU CTS checkout.
cts_checkout_path: PathBuf,
/// The maximum capacity for test variant chunks.
///
/// This tools divides the large number of CTS tests generated by upstream and chunks them into
/// multiple files. It's important to use a number that does not cause tests to time out in
/// Taskcluster. The current default value has been empirically tested for only this criteria.
/// Note that the way tests are divided may change in the future.
///
/// If you intend to change the value long-term, change the default here.
#[clap(long, default_value = "25")]
chunk_size: NonZeroUsize,
}
fn main() -> ExitCode {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.parse_default_env()
.init();
let args = CliArgs::parse();
match run(args) {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
log::error!("{e:?}");
ExitCode::FAILURE
}
}
}
fn run(args: CliArgs) -> miette::Result<()> {
let CliArgs {
chunk_size,
cts_checkout_path,
} = args;
let orig_working_dir = current_dir().unwrap();
let cts_dir = join_path(["dom", "webgpu", "tests", "cts"]);
let cts_vendor_dir = join_path([&*cts_dir, "vendor".as_ref()]);
let gecko_ckt = {
let failed_find_hg_err = || {
miette!(
"failed to find a Mercurial repository (`.hgrc`) in any of current working \
directory and its parent directories"
)
};
let hg_root = {
let mut dir = find_up_with(
".hg",
FindUpOptions {
cwd: Path::new("."),
kind: FindUpKind::Dir,
},
)
.map_err(Report::msg)
.wrap_err_with(failed_find_hg_err)?
.ok_or_else(failed_find_hg_err)?;
dir.pop();
dir
};
let root = FileRoot::new("gecko", &hg_root)?;
log::info!("detected Gecko repository root at {root}");
ensure!(
root.try_child(&orig_working_dir)
.map_or(false, |c| c.relative_path() == cts_vendor_dir),
"It is expected to run this tool from the root of its Cargo project, but this does \
not appear to have been done. Bailing."
);
root
};
let cts_vendor_dir = gecko_ckt.child(orig_working_dir.parent().unwrap());
let wpt_tests_dir = {
let child = gecko_ckt.child(join_path(["testing", "web-platform", "mozilla", "tests"]));
ensure!(
child.is_dir(),
"WPT tests dir ({}) does not appear to exist",
child,
);
child
};
let (cts_ckt_git_dir, cts_ckt) = {
let failed_find_git_err = || {
miette!(
"failed to find a Git repository (`.git` directory) in the provided path and all \
of its parent directories"
)
};
let git_dir = find_up_with(
".git",
FindUpOptions {
cwd: &cts_checkout_path,
kind: FindUpKind::Dir,
},
)
.map_err(Report::msg)
.wrap_err_with(failed_find_git_err)?
.ok_or_else(failed_find_git_err)?;
let ckt = FileRoot::new("cts", git_dir.parent().unwrap())?;
log::debug!("detected CTS checkout root at {ckt}");
(git_dir, ckt)
};
let git_bin = which("git", "Git binary")?;
let npm_bin = which("npm", "NPM binary")?;
// XXX: It'd be nice to expose separate operations for copying in source and generating WPT
// cases from the vendored copy. Checks like these really only matter when updating source.
let ensure_no_child = |p1: &FileRoot, p2| {
ensure!(
p1.try_child(p2).is_err(),
"{p1} is a child path of {p2}, which is not supported"
);
Ok(())
};
ensure_no_child(&cts_ckt, &gecko_ckt)?;
ensure_no_child(&gecko_ckt, &cts_ckt)?;
log::info!("making a vendored copy of checked-in files from {cts_ckt}…",);
gecko_ckt.regen_file(
join_path([&*cts_dir, "checkout_commit.txt".as_ref()]),
|checkout_commit_file| {
let mut git_status_porcelain_cmd = EasyCommand::new(&git_bin, |cmd| {
cmd.args(["status", "--porcelain"])
.envs([
("GIT_DIR", &*cts_ckt_git_dir),
("GIT_WORK_TREE", &*cts_ckt),
])
});
log::info!(
" …ensuring the working tree and index are clean with \
{git_status_porcelain_cmd}"
);
let git_status_porcelain_output = git_status_porcelain_cmd.just_stdout_utf8()?;
ensure!(
git_status_porcelain_output.is_empty(),
"expected a clean CTS working tree and index, but {}'s output was not empty; \
for reference, it was:\n\n{}",
git_status_porcelain_cmd,
git_status_porcelain_output,
);
gecko_ckt.regen_dir(&cts_vendor_dir.join("checkout"), |vendored_ckt_dir| {
log::info!(" …copying files tracked by Git to {vendored_ckt_dir}…");
let files_to_vendor = {
let mut git_ls_files_cmd = EasyCommand::new(&git_bin, |cmd| {
cmd.arg("ls-files").env("GIT_DIR", &cts_ckt_git_dir)
});
log::debug!(" …getting files to vendor from {git_ls_files_cmd}…");
let output = git_ls_files_cmd.just_stdout_utf8()?;
let mut files = output
.split_terminator('\n')
.map(PathBuf::from)
.collect::<BTreeSet<_>>();
log::trace!(" …files from {git_ls_files_cmd}: {files:#?}");
log::trace!(" …validating that files from Git repo still exist…");
let files_not_found = files
.iter()
.filter(|p| !cts_ckt.child(p).exists())
.collect::<Vec<_>>();
ensure!(
files_not_found.is_empty(),
"the following files were returned by `git ls-files`, but do not exist on disk: \
{:#?}",
files_not_found,
);
log::trace!(" …stripping files we actually don't want to vendor…");
let files_to_actually_not_vendor = [
// There's no reason to bring this over, and lots of reasons to not bring in
// security-sensitive content unless we have to.
"deploy_key.enc",
]
.map(Path::new);
log::trace!(" …files we don't want: {files_to_actually_not_vendor:?}");
for path in files_to_actually_not_vendor {
ensure!(
files.remove(path),
"failed to remove {} from list of files to vendor; does it still exist?",
cts_ckt.child(path)
);
}
files
};
log::debug!(" …now doing the copying…");
for path in files_to_vendor {
let vendor_from_path = cts_ckt.child(&path);
let vendor_to_path = vendored_ckt_dir.child(&path);
if let Some(parent) = vendor_to_path.parent() {
create_dir_all(vendored_ckt_dir.child(parent))?;
}
log::trace!(" …copying {vendor_from_path} to {vendor_to_path}…");
fs::copy(&vendor_from_path, &vendor_to_path)?;
}
Ok(())
})?;
log::info!(" …writing commit ref pointed to by `HEAD` to {checkout_commit_file}…");
let mut git_rev_parse_head_cmd = EasyCommand::new(&git_bin, |cmd| {
cmd.args(["rev-parse", "HEAD"])
.env("GIT_DIR", &cts_ckt_git_dir)
});
log::trace!(" …getting output of {git_rev_parse_head_cmd}…");
fs::write(
checkout_commit_file,
git_rev_parse_head_cmd.just_stdout_utf8()?,
)
.wrap_err_with(|| format!("failed to write HEAD ref to {checkout_commit_file}"))
},
)?;
set_current_dir(&*cts_ckt)
.into_diagnostic()
.wrap_err("failed to change working directory to CTS checkout")?;
log::debug!("changed CWD to {cts_ckt}");
let mut npm_ci_cmd = EasyCommand::new(&npm_bin, |cmd| cmd.arg("ci"));
log::info!(
"ensuring a clean {} directory with {npm_ci_cmd}…",
cts_ckt.child("node_modules"),
);
npm_ci_cmd.spawn()?;
let out_dir = cts_ckt.regen_dir("out", |out_dir| {
let mut npm_run_standalone_cmd =
EasyCommand::new(&npm_bin, |cmd| cmd.args(["run", "standalone"]));
log::info!(
"generating standalone runner files into {out_dir} with {npm_run_standalone_cmd}…"
);
npm_run_standalone_cmd.spawn()
})?;
let out_wpt_dir = cts_ckt.regen_dir("out-wpt", |out_wpt_dir| {
let mut npm_run_wpt_cmd = EasyCommand::new(&npm_bin, |cmd| cmd.args(["run", "wpt"]));
log::info!("generating WPT test cases into {out_wpt_dir} with {npm_run_wpt_cmd}…");
npm_run_wpt_cmd.spawn()
})?;
let cts_https_html_path = out_wpt_dir.child("cts.https.html");
log::info!("refining the output of {cts_https_html_path} with `npm run gen_wpt_cts_html …`…");
EasyCommand::new(&npm_bin, |cmd| {
cmd.args(["run", "gen_wpt_cts_html"])
.arg(existing_file(&cts_https_html_path))
.args([
existing_file(cts_ckt.child(join_path([
"src",
"common",
"templates",
"cts.https.html",
]))),
existing_file(cts_vendor_dir.child("arguments.txt")),
existing_file(cts_vendor_dir.child("myexpectations.txt")),
])
.arg("")
})
.spawn()?;
log::info!("stealing standalone runtime files from {out_dir} for {out_wpt_dir}…");
for subdir in [
&["external"] as &[_],
&["common", "internal"],
&["common", "util"],
]
.map(join_path)
{
let out_subdir = out_dir.child(&subdir);
let out_wpt_subdir = out_wpt_dir.child(subdir);
log::info!(" …copying from {out_subdir} to {out_wpt_subdir}…");
copy_dir(out_subdir, out_wpt_subdir)?
}
log::info!(" …done stealing!");
log::info!("analyzing {cts_https_html_path}…");
let cts_https_html_content = fs::read_to_string(&*cts_https_html_path)?;
let cts_boilerplate;
let cts_cases;
{
{
let (boilerplate, cases_start) = {
let cases_start_idx = cts_https_html_content
.find("<meta name=variant")
.ok_or_else(|| miette!("no test cases found; this is unexpected!"))?;
cts_https_html_content.split_at(cases_start_idx)
};
cts_boilerplate = {
if !boilerplate.is_empty() {
#[derive(Debug, Diagnostic, thiserror::Error)]
#[error("last character before test cases was not a newline; bug, or weird?")]
#[diagnostic(severity("warning"))]
struct Oops {
#[label(
"this character ({:?}) was expected to be a newline, so that the test \
spec. following it is on its own line",
source_code.chars().last().unwrap()
)]
span: SourceSpan,
#[source_code]
source_code: String,
}
ensure!(
boilerplate.ends_with('\n'),
Oops {
span: SourceSpan::from(0..boilerplate.len()),
source_code: cts_https_html_content,
}
);
}
// NOTE: Adding `_mozilla` is necessary because [that's how it's mounted][source].
//
// [source]: https://searchfox.org/mozilla-central/rev/cd2121e7d83af1b421c95e8c923db70e692dab5f/testing/web-platform/mozilla/README#1-4]
log::info!(
" …fixing `script` paths in WPT boilerplate so they work as Mozilla-private \
WPT tests"
);
let expected_wpt_script_tag =
"<script type=module src=/webgpu/common/runtime/wpt.js></script>";
ensure!(
boilerplate.contains(expected_wpt_script_tag),
"failed to find expected `script` tag for `wpt.js` \
({:?}); did something change upstream?",
expected_wpt_script_tag
);
boilerplate.replacen(
expected_wpt_script_tag,
"<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>",
1,
)
};
log::info!(" …parsing test variants in {cts_https_html_path}…");
cts_cases = cases_start.split_terminator('\n').collect::<Vec<_>>();
let mut parsing_failed = false;
let meta_variant_regex =
Regex::new("^<meta name=variant content='([^']*?)'>$").unwrap();
cts_cases.iter().for_each(|line| {
if !meta_variant_regex.is_match(line) {
parsing_failed = true;
log::error!("line is not a test case: {line:?}");
}
});
ensure!(
!parsing_failed,
"one or more test case lines failed to parse, fix it and try again"
);
};
log::trace!("\"original\" HTML boilerplate:\n\n{}", cts_boilerplate);
ensure!(
!cts_cases.is_empty(),
"no test cases found; this is unexpected!"
);
log::info!(" …found {} test cases", cts_cases.len());
}
cts_ckt.regen_dir(out_wpt_dir.join("chunked"), |chunked_tests_dir| {
// NOTE: We use an extremely simple chunking algorithm here. This was done in the name of
// speed of initial implementation. However, this might cause a significant amount of churn
// when tests get updated.
let chunks = cts_cases.chunks(chunk_size.get()).zip(1u32..);
log::info!(
"re-distributing tests into {} chunks of {chunk_size}…",
chunks.clone().count()
);
let mut failed_writing = false;
for (chunk, chunk_idx) in chunks {
// NOTE: Using `0`-padding here was considered, but it's probably not worth it. That
// would be in conflict with stable file paths as the set of tests grows.
let chunk_dir = chunked_tests_dir.child(chunk_idx.to_string());
match create_dir_all(&chunk_dir) {
Ok(()) => log::trace!("made directory {}", chunk_dir.display()),
Err(e) => {
failed_writing = true;
log::error!("{e:#}");
continue;
}
}
let chunk_file_path = chunk_dir.child("cts.https.html");
let chunk_file_content = {
let mut content = cts_boilerplate.as_bytes().to_vec();
for line in chunk {
content.extend(line.as_bytes());
content.extend(b"\n");
}
content
};
match fs::write(&chunk_file_path, &chunk_file_content).wrap_err_with(|| {
miette!("failed to write chunked output to path {chunk_file_path}")
}) {
Ok(()) => log::debug!(" …wrote {chunk_file_path}"),
Err(e) => {
failed_writing = true;
log::error!("{e:#}");
}
}
}
ensure!(
!failed_writing,
"failed to write one or more chunked WPT test files; see above output for more details"
);
log::debug!(" …finished writing new chunked WPT test files!");
log::info!(" …removing {cts_https_html_path}, now that it's been divided into chunks…");
remove_file(&cts_https_html_path)?;
Ok(())
})?;
gecko_ckt.regen_dir(wpt_tests_dir.join("webgpu"), |wpt_webgpu_tests_dir| {
log::info!("copying contents of {out_wpt_dir} to {wpt_webgpu_tests_dir}…");
copy_dir(&out_wpt_dir, wpt_webgpu_tests_dir)
})?;
log::info!("All done! Now get your CTS _ON_! :)");
Ok(())
}

23
dom/webgpu/tests/cts/vendor/src/path.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
use std::path::{Path, PathBuf};
/// Construct a [`PathBuf`] from individual [`Path`] components.
///
/// This is a simple and legible way to construct `PathBuf`s that use the system's native path
/// separator character. (It's ugly to see paths mixing `\` and `/`.)
///
/// # Examples
///
/// ```rust
/// # use std::path::Path;
/// # use vendor_webgpu_cts::path::join_path;
/// assert_eq!(&*join_path(["foo", "bar", "baz"]), Path::new("foo/bar/baz"));
/// ```
pub(crate) fn join_path<I, P>(iter: I) -> PathBuf
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
let mut path = PathBuf::new();
path.extend(iter);
path
}

85
dom/webgpu/tests/cts/vendor/src/process.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,85 @@
use std::{
ffi::{OsStr, OsString},
fmt::{self, Display},
iter::once,
process::{Command, Output},
};
use format::lazy_format;
use miette::{ensure, Context, IntoDiagnostic};
pub(crate) fn which(name: &'static str, desc: &str) -> miette::Result<OsString> {
let found = ::which::which(name)
.into_diagnostic()
.wrap_err(lazy_format!("failed to find `{name}` executable"))?;
log::debug!("using {desc} from {}", found.display());
Ok(found.file_name().unwrap().to_owned())
}
pub(crate) struct EasyCommand {
inner: Command,
}
impl EasyCommand {
pub(crate) fn new<C>(cmd: C, f: impl FnOnce(&mut Command) -> &mut Command) -> Self
where
C: AsRef<OsStr>,
{
let mut cmd = Command::new(cmd);
f(&mut cmd);
Self { inner: cmd }
}
pub(crate) fn spawn(&mut self) -> miette::Result<()> {
log::debug!("spawning {self}…");
let status = self
.inner
.spawn()
.into_diagnostic()
.wrap_err_with(|| format!("failed to spawn {self}"))?
.wait()
.into_diagnostic()
.wrap_err_with(|| format!("failed to wait for exit code from {self}"))?;
log::debug!("{self} returned {:?}", status.code());
ensure!(status.success(), "{self} returned {:?}", status.code());
Ok(())
}
fn just_stdout(&mut self) -> miette::Result<Vec<u8>> {
log::debug!("getting `stdout` output of {self}");
let output = self
.inner
.output()
.into_diagnostic()
.wrap_err_with(|| format!("failed to execute `{self}`"))?;
let Output {
status,
stdout: _,
stderr,
} = &output;
log::debug!("{self} returned {:?}", status.code());
ensure!(
status.success(),
"{self} returned {:?}; full output: {output:#?}",
status.code(),
);
assert!(stderr.is_empty());
Ok(output.stdout)
}
pub(crate) fn just_stdout_utf8(&mut self) -> miette::Result<String> {
String::from_utf8(self.just_stdout()?)
.into_diagnostic()
.wrap_err_with(|| format!("output of {self} was not UTF-8 (!?)"))
}
}
impl Display for EasyCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { inner } = self;
let prog = inner.get_program().to_string_lossy();
let args = inner.get_args().map(|a| a.to_string_lossy());
let shell_words = ::shell_words::join(once(prog).chain(args));
write!(f, "`{shell_words}`")
}
}

Просмотреть файл

@ -44,15 +44,15 @@ web-platform-tests:
by-test-platform:
android.*/debug: 32
android.*: 24
linux.*64-tsan-qr/opt: 32
linux.*64-asan(-qr)?/opt: 22
linux.*64-ccov.*/opt: 20
linux.*/debug: 16
linux.*64-tsan-qr/opt: 36
linux.*64-asan(-qr)?/opt: 26
linux.*64-ccov.*/opt: 24
linux.*/debug: 24
macosx.*/debug: 18
windows.*32.*/opt: 12
windows.*/debug: 14
windows.*-ccov.*/opt: 14
default: 10
windows.*/debug: 24
windows.*-ccov.*/opt: 24
default: 14
max-run-time:
by-test-platform:
.*-ccov.*/.*: 10800

Просмотреть файл

@ -0,0 +1,4 @@
prefs: [dom.webgpu.enabled:true]
disabled:
if release_or_beta: https://mozilla-hub.atlassian.net/browse/FFXP-223
if os == "mac": https://mozilla-hub.atlassian.net/browse/FFXP-223

Просмотреть файл

@ -52,6 +52,7 @@ dom/tests/mochitest/dom-level2-html/
dom/u2f/tests/pkijs/
dom/webauthn/cbor-cpp/
dom/webauthn/tests/pkijs/
dom/webgpu/tests/cts/checkout/
editor/libeditor/tests/browserscope/lib/richtext/
editor/libeditor/tests/browserscope/lib/richtext2/
extensions/spellcheck/hunspell/src/
@ -161,6 +162,7 @@ testing/talos/talos/tests/kraken/
testing/talos/talos/tests/v8_7/
testing/web-platform/tests/resources/webidl2/
testing/web-platform/tests/tools/third_party/
testing/web-platform/mozilla/tests/webgpu/
testing/xpcshell/dns-packet/
testing/xpcshell/node-ip/
testing/xpcshell/node-http2/