Skip to content

Commit 1da2177

Browse files
Add skip conditions to CTS runner (gfx-rs#7949)
1 parent dd50e56 commit 1da2177

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

.github/workflows/cts.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@ jobs:
2323
- name: Windows x86_64
2424
os: windows-2022
2525
target: x86_64-pc-windows-msvc
26+
backend: dx12
2627

2728
# Mac
2829
- name: Mac aarch64
2930
os: macos-14
3031
target: x86_64-apple-darwin
32+
backend: metal
3133

3234
# Linux
3335
- name: Linux x86_64
3436
os: ubuntu-24.04
3537
target: x86_64-unknown-linux-gnu
38+
backend: vulkan
3639

3740
name: CTS ${{ matrix.name }}
3841
runs-on: ${{ matrix.os }}
@@ -84,7 +87,7 @@ jobs:
8487

8588
- name: run CTS
8689
shell: bash
87-
run: cargo xtask cts --llvm-cov
90+
run: cargo xtask cts --llvm-cov --backend ${{ matrix.backend }}
8891

8992
- name: Generate coverage report
9093
id: coverage

xtask/src/cts.rs

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
1+
//! Interface for running the WebGPU CTS (Conformance Test Suite) against wgpu.
2+
//!
3+
//! To run the default set of tests from `cts_runner/test.lst`:
4+
//!
5+
//! ```sh
6+
//! cargo xtask cts
7+
//! ```
8+
//!
9+
//! To run a specific test selector:
10+
//!
11+
//! ```sh
12+
//! cargo xtask cts 'webgpu:api,operation,command_buffer,basic:*'
13+
//! ```
14+
//!
15+
//! You can also supply your own test list in a file:
16+
//!
17+
//! ```sh
18+
//! cargo xtask cts -f your_tests.lst
19+
//! ```
20+
//!
21+
//! Each line in a test list file is a test selector that will be passed to the
22+
//! CTS's own command line runner. Note that wildcards may only be used to specify
23+
//! running all tests in a file, or all subtests in a test.
24+
//!
25+
//! A test line may optionally contain a `fails-if(backend)` clause. This
26+
//! indicates that the test should be skipped on that backend, however, the
27+
//! runner will only do so if the `--backend` flag is passed to tell it where
28+
//! it is running.
29+
//!
30+
//! Lines starting with `//` or `#` in the test list are treated as comments and
31+
//! ignored.
32+
133
use anyhow::{bail, Context};
234
use pico_args::Arguments;
3-
use std::ffi::OsString;
35+
use regex_lite::{Regex, RegexBuilder};
36+
use std::{ffi::OsString, sync::LazyLock};
437
use xshell::Shell;
538

639
/// Path within the repository where the CTS will be checked out.
@@ -15,16 +48,42 @@ const CTS_GIT_URL: &str = "https://github.com/gpuweb/cts.git";
1548
/// Path to default CTS test list.
1649
const CTS_DEFAULT_TEST_LIST: &str = "cts_runner/test.lst";
1750

51+
static TEST_LINE_REGEX: LazyLock<Regex> = LazyLock::new(|| {
52+
RegexBuilder::new(r#"(?:fails-if\s*\(\s*(?<fails_if>\w+)\s*\)\s+)?(?<selector>.*)"#)
53+
.build()
54+
.unwrap()
55+
});
56+
57+
#[derive(Default)]
58+
struct TestLine {
59+
pub selector: OsString,
60+
pub fails_if: Option<String>,
61+
}
62+
1863
pub fn run_cts(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
1964
let skip_checkout = args.contains("--skip-checkout");
2065
let llvm_cov = args.contains("--llvm-cov");
66+
let running_on_backend = args.opt_value_from_str::<_, String>("--backend")?;
67+
68+
if running_on_backend.is_none() {
69+
log::warn!(
70+
"fails-if conditions are only evaluated if a backend is specified with --backend"
71+
);
72+
}
2173

2274
let mut list_files = Vec::<OsString>::new();
2375
while let Some(file) = args.opt_value_from_str("-f")? {
2476
list_files.push(file);
2577
}
2678

27-
let mut tests = args.finish();
79+
let mut tests = args
80+
.finish()
81+
.into_iter()
82+
.map(|selector| TestLine {
83+
selector,
84+
..Default::default()
85+
})
86+
.collect::<Vec<_>>();
2887

2988
if tests.is_empty() && list_files.is_empty() {
3089
log::info!("Reading default test list from {CTS_DEFAULT_TEST_LIST}");
@@ -35,7 +94,13 @@ pub fn run_cts(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
3594
tests.extend(shell.read_file(file)?.lines().filter_map(|line| {
3695
let trimmed = line.trim();
3796
let is_comment = trimmed.starts_with("//") || trimmed.starts_with("#");
38-
(!trimmed.is_empty() && !is_comment).then(|| OsString::from(trimmed))
97+
let captures = TEST_LINE_REGEX
98+
.captures(trimmed)
99+
.expect("Invalid test line: {trimmed}");
100+
(!trimmed.is_empty() && !is_comment).then(|| TestLine {
101+
selector: OsString::from(&captures["selector"]),
102+
fails_if: captures.name("fails_if").map(|m| m.as_str().to_string()),
103+
})
39104
}))
40105
}
41106

@@ -142,15 +207,27 @@ pub fn run_cts(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
142207

143208
log::info!("Running CTS");
144209
for test in &tests {
145-
log::info!("Running {}", test.to_string_lossy());
210+
match (&test.fails_if, &running_on_backend) {
211+
(Some(backend), Some(running_on_backend)) if backend == running_on_backend => {
212+
log::info!(
213+
"Skipping {} on {} backend",
214+
test.selector.to_string_lossy(),
215+
running_on_backend,
216+
);
217+
continue;
218+
}
219+
_ => {}
220+
}
221+
222+
log::info!("Running {}", test.selector.to_string_lossy());
146223
shell
147224
.cmd("cargo")
148225
.args(run_flags)
149226
.args(["--manifest-path".as_ref(), wgpu_cargo_toml.as_os_str()])
150227
.args(["-p", "cts_runner"])
151228
.args(["--bin", "cts_runner"])
152229
.args(["--", "./tools/run_deno", "--verbose"])
153-
.args([test])
230+
.args([&test.selector])
154231
.run()
155232
.context("CTS failed")?;
156233
}

0 commit comments

Comments
 (0)