summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/vendor')
-rw-r--r--dom/webgpu/tests/cts/vendor/Cargo.lock889
-rw-r--r--dom/webgpu/tests/cts/vendor/Cargo.toml20
-rw-r--r--dom/webgpu/tests/cts/vendor/src/fs.rs331
-rw-r--r--dom/webgpu/tests/cts/vendor/src/main.rs565
-rw-r--r--dom/webgpu/tests/cts/vendor/src/path.rs23
-rw-r--r--dom/webgpu/tests/cts/vendor/src/process.rs85
6 files changed, 1913 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/vendor/Cargo.lock b/dom/webgpu/tests/cts/vendor/Cargo.lock
new file mode 100644
index 0000000000..ea51837ca5
--- /dev/null
+++ b/dom/webgpu/tests/cts/vendor/Cargo.lock
@@ -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"
diff --git a/dom/webgpu/tests/cts/vendor/Cargo.toml b/dom/webgpu/tests/cts/vendor/Cargo.toml
new file mode 100644
index 0000000000..d7721d1931
--- /dev/null
+++ b/dom/webgpu/tests/cts/vendor/Cargo.toml
@@ -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]
diff --git a/dom/webgpu/tests/cts/vendor/src/fs.rs b/dom/webgpu/tests/cts/vendor/src/fs.rs
new file mode 100644
index 0000000000..31697f9758
--- /dev/null
+++ b/dom/webgpu/tests/cts/vendor/src/fs.rs
@@ -0,0 +1,331 @@
+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 Eq for FileRoot {}
+
+impl PartialEq for FileRoot {
+ fn eq(&self, other: &Self) -> bool {
+ self.path == other.path
+ }
+}
+
+impl Ord for FileRoot {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.path.cmp(&other.path)
+ }
+}
+
+impl PartialOrd for FileRoot {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+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())
+ }
+}
+
+#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
+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) -> Self
+ 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()))
+}
diff --git a/dom/webgpu/tests/cts/vendor/src/main.rs b/dom/webgpu/tests/cts/vendor/src/main.rs
new file mode 100644
index 0000000000..750b65c62e
--- /dev/null
+++ b/dom/webgpu/tests/cts/vendor/src/main.rs
@@ -0,0 +1,565 @@
+use std::{
+ collections::{BTreeMap, BTreeSet},
+ env::{current_dir, set_current_dir},
+ path::{Path, PathBuf},
+ process::ExitCode,
+};
+
+use clap::Parser;
+use lets_find_up::{find_up_with, FindUpKind, FindUpOptions};
+use miette::{bail, 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,
+}
+
+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 { 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 find_up_opts = || FindUpOptions {
+ cwd: Path::new("."),
+ kind: FindUpKind::Dir,
+ };
+ let find_up = |root_dir_name| {
+ let err = || {
+ miette!(
+ concat!(
+ "failed to find a Mercurial repository ({:?}) in any of current ",
+ "working directory and its parent directories",
+ ),
+ root_dir_name
+ )
+ };
+ find_up_with(root_dir_name, find_up_opts())
+ .map_err(Report::msg)
+ .wrap_err_with(err)
+ .and_then(|loc_opt| loc_opt.ok_or_else(err))
+ .map(|mut dir| {
+ dir.pop();
+ dir
+ })
+ };
+ let gecko_source_root = find_up(".hg").or_else(|e| match find_up(".git") {
+ Ok(path) => {
+ log::debug!("{e:?}");
+ Ok(path)
+ }
+ Err(e2) => {
+ log::warn!("{e:?}");
+ log::warn!("{e2:?}");
+ bail!("failed to find a Gecko repository root")
+ }
+ })?;
+
+ let root = FileRoot::new("gecko", &gecko_source_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),
+ concat!(
+ "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 ({child}) does not appear to exist"
+ );
+ child
+ };
+
+ let (cts_ckt_git_dir, cts_ckt) = {
+ let failed_find_git_err = || {
+ miette!(concat!(
+ "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(),
+ concat!(
+ "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(),
+ concat!(
+ "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),
+ concat!(
+ "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_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_ckt.child("tools/gen_wpt_cfg_unchunked.json"),
+ ))
+ })
+ .spawn()?;
+
+ {
+ let extra_cts_https_html_path = out_wpt_dir.child("cts-chunked2sec.https.html");
+ log::info!("removing extraneous {extra_cts_https_html_path}…");
+ remove_file(&*extra_cts_https_html_path)?;
+ }
+
+ log::info!("analyzing {cts_https_html_path}…");
+ let cts_https_html_content = fs::read_to_string(&*cts_https_html_path)?;
+ let cts_boilerplate_short_timeout;
+ let cts_boilerplate_long_timeout;
+ 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)
+ };
+
+ {
+ 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 {}",
+ source_code.chars().last().unwrap(),
+ "the test spec. following it is on its own line"
+ )]
+ 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!(concat!(
+ " …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),
+ concat!(
+ "failed to find expected `script` tag for `wpt.js` ",
+ "({:?}); did something change upstream?",
+ ),
+ expected_wpt_script_tag
+ );
+ let mut boilerplate = boilerplate.replacen(
+ expected_wpt_script_tag,
+ "<script type=module src=/_mozilla/webgpu/common/runtime/wpt.js></script>",
+ 1,
+ );
+
+ cts_boilerplate_short_timeout = boilerplate.clone();
+
+ let timeout_insert_idx = {
+ let meta_charset_utf8 = "\n<meta charset=utf-8>\n";
+ let meta_charset_utf8_idx =
+ boilerplate.find(meta_charset_utf8).ok_or_else(|| {
+ miette!(
+ "could not find {:?} in document; did something change upstream?",
+ meta_charset_utf8
+ )
+ })?;
+ meta_charset_utf8_idx + meta_charset_utf8.len()
+ };
+ boilerplate.insert_str(
+ timeout_insert_idx,
+ concat!(
+ r#"<meta name="timeout" content="long">"#,
+ " <!-- TODO: narrow to only where it's needed, see ",
+ "https://bugzilla.mozilla.org/show_bug.cgi?id=1850537",
+ " -->\n"
+ ),
+ );
+ cts_boilerplate_long_timeout = boilerplate
+ };
+
+ log::info!(" …parsing test variants in {cts_https_html_path}…");
+ let mut parsing_failed = false;
+ let meta_variant_regex = Regex::new(concat!(
+ "^",
+ "<meta name=variant content='\\?q=([^']*?):\\*'>",
+ "$"
+ ))
+ .unwrap();
+ cts_cases = cases_start
+ .split_terminator('\n')
+ .filter_map(|line| {
+ let path_and_meta = meta_variant_regex
+ .captures(line)
+ .map(|caps| (caps[1].to_owned(), line));
+ if path_and_meta.is_none() {
+ parsing_failed = true;
+ log::error!("line is not a test case: {line:?}");
+ }
+ path_and_meta
+ })
+ .collect::<Vec<_>>();
+ 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_short_timeout}");
+
+ 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("cts"), |cts_tests_dir| {
+ log::info!("re-distributing tests into single file per test path…");
+ let mut failed_writing = false;
+ let mut cts_cases_by_spec_file_dir = BTreeMap::<_, BTreeSet<_>>::new();
+ for (path, meta) in cts_cases {
+ let case_dir = {
+ // Context: We want to mirror CTS upstream's `src/webgpu/**/*.spec.ts` paths as
+ // entire WPT tests, with each subtest being a WPT variant. Here's a diagram of
+ // a CTS path to explain why the logic below is correct:
+ //
+ // ```sh
+ // webgpu:this,is,the,spec.ts,file,path:subtest_in_file:…
+ // \____/ \___________________________/^\_____________/
+ // test `*.spec.ts` file path | |
+ // \__________________________________/| |
+ // | | |
+ // We want this… | …but not this. CTS upstream generates
+ // | this too, but we don't want to divide
+ // second ':' character here---/ here (yet).
+ // ```
+ let subtest_and_later_start_idx =
+ match path.match_indices(':').nth(1).map(|(idx, _s)| idx) {
+ Some(some) => some,
+ None => {
+ failed_writing = true;
+ log::error!(
+ concat!(
+ "failed to split suite and test path segments ",
+ "from CTS path `{}`"
+ ),
+ path
+ );
+ continue;
+ }
+ };
+ let slashed =
+ path[..subtest_and_later_start_idx].replace(|c| matches!(c, ':' | ','), "/");
+ cts_tests_dir.child(slashed)
+ };
+ if !cts_cases_by_spec_file_dir
+ .entry(case_dir)
+ .or_default()
+ .insert(meta)
+ {
+ log::warn!("duplicate entry {meta:?} detected")
+ }
+ }
+
+ struct WptEntry<'a> {
+ cases: BTreeSet<&'a str>,
+ timeout_length: TimeoutLength,
+ }
+ enum TimeoutLength {
+ Short,
+ Long,
+ }
+ let split_cases = {
+ let mut split_cases = BTreeMap::new();
+ fn insert_with_default_name<'a>(
+ split_cases: &mut BTreeMap<fs::Child<'a>, WptEntry<'a>>,
+ spec_file_dir: fs::Child<'a>,
+ cases: WptEntry<'a>,
+ ) {
+ let path = spec_file_dir.child("cts.https.html");
+ assert!(split_cases.insert(path, cases).is_none());
+ }
+ {
+ let dld_path =
+ &cts_tests_dir.child("webgpu/api/validation/state/device_lost/destroy");
+ let (spec_file_dir, cases) = cts_cases_by_spec_file_dir
+ .remove_entry(dld_path)
+ .expect("no `device_lost/destroy` tests found; did they move?");
+ insert_with_default_name(
+ &mut split_cases,
+ spec_file_dir,
+ WptEntry {
+ cases,
+ timeout_length: TimeoutLength::Short,
+ },
+ );
+ }
+ for (spec_file_dir, cases) in cts_cases_by_spec_file_dir {
+ insert_with_default_name(
+ &mut split_cases,
+ spec_file_dir,
+ WptEntry {
+ cases,
+ timeout_length: TimeoutLength::Long,
+ },
+ );
+ }
+ split_cases
+ };
+
+ for (path, entry) in split_cases {
+ let dir = path.parent().expect("no parent found for ");
+ match create_dir_all(&dir) {
+ Ok(()) => log::trace!("made directory {}", dir.display()),
+ Err(e) => {
+ failed_writing = true;
+ log::error!("{e:#}");
+ continue;
+ }
+ }
+ let file_contents = {
+ let WptEntry {
+ cases,
+ timeout_length,
+ } = entry;
+ let content = match timeout_length {
+ TimeoutLength::Short => &cts_boilerplate_short_timeout,
+ TimeoutLength::Long => &cts_boilerplate_long_timeout,
+ };
+ let mut content = content.as_bytes().to_vec();
+ for meta in cases {
+ content.extend(meta.as_bytes());
+ content.extend(b"\n");
+ }
+ content
+ };
+ match fs::write(&path, &file_contents)
+ .wrap_err_with(|| miette!("failed to write output to path {path:?}"))
+ {
+ Ok(()) => log::debug!(" …wrote {path}"),
+ Err(e) => {
+ failed_writing = true;
+ log::error!("{e:#}");
+ }
+ }
+ }
+ ensure!(
+ !failed_writing,
+ "failed to write one or more WPT test files; see above output for more details"
+ );
+ log::debug!(" …finished writing new WPT test files!");
+
+ log::info!(" …removing {cts_https_html_path}, now that it's been divided up…");
+ 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(())
+}
diff --git a/dom/webgpu/tests/cts/vendor/src/path.rs b/dom/webgpu/tests/cts/vendor/src/path.rs
new file mode 100644
index 0000000000..aa5bae2e6d
--- /dev/null
+++ b/dom/webgpu/tests/cts/vendor/src/path.rs
@@ -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
+}
diff --git a/dom/webgpu/tests/cts/vendor/src/process.rs b/dom/webgpu/tests/cts/vendor/src/process.rs
new file mode 100644
index 0000000000..b36c3b953d
--- /dev/null
+++ b/dom/webgpu/tests/cts/vendor/src/process.rs
@@ -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}`")
+ }
+}