From 9da31b2cb0d6f3f49abdb87af0a838bead7f39dd Mon Sep 17 00:00:00 2001 From: Vyncint Ng <115854244+vyncint@users.noreply.github.com> Date: Fri, 21 Aug 2026 09:09:08 +0700 Subject: [PATCH] fix(ptx-schedule): a campaign reads one of the two skip spellings as a pass `has_skip_marker` accepts `skipping:` and nothing else. The convention it is implementing has two spellings, and `scripts/smoketest.sh` -- which owns it -- accepts both: if grep -qiE '^[[:space:]]*(skipping:|pass \(skipped\))' "${log}"; then Its own comment names the second form in so many words: "`PASS (skipped): ...` form below sm_75". `generated_ldmatrix` prints exactly that: println!( "PASS (skipped): ldmatrix.m8n8.x4.b16 requires sm_75+; device is sm_{major}{minor}" ); An example declining that way exits 0 and prints no mismatch marker, so `run_binary` classifies the run `RunKind::Pass`. That matters because the campaign gates on it: if !matches!(baseline.kind, RunKind::Pass) { ... println!("schedule-fuzz: BASELINE FAILURE: {:?}; no schedule variants were run", ...) With the right kind the campaign stops there and says so. With `Pass` it proceeds: it patches the PTX, sweeps every seed, and each variant declines identically -- same exit code, same output, so not even `OutputChanged` fires. The campaign reports a clean sweep of a kernel that never launched. This is #665's bug in the second consumer of the same convention. That fix put it as "a skip the function fails to recognise is not merely missing its `(skipped)` annotation -- it is promoted to a full execution PASS", and taught `verdict_standard` the second spelling. `ptx-schedule`'s campaign arrived later (#1065) with only the first. A silent all-clear is the worst outcome available to a bug-finding tool, and it is the one this produces on any device below an example's floor. Hoist both spellings into a `SKIP_MARKERS` constant and check the line against each, with the coupling to the smoketest's pattern recorded next to it. Case-insensitivity is unchanged and already correct: `run_binary` lowercases before classifying, which is what makes this match the smoketest's `grep -i`. Two tests: both spellings are recognised with and without leading whitespace, and the near-misses are not -- a bare `pass`, `pass: 1024 elements verified`, `success`, and a mid-line `no skipping: here`, since the marker is anchored to the start of the line in the smoketest too. Both fail with the second marker removed. Verified: 11 tests pass, fmt clean, `clippy --all-targets -- -D warnings` clean, and `cargo doc --document-private-items` clean. Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com> --- crates/ptx-schedule/src/campaign.rs | 62 +++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/crates/ptx-schedule/src/campaign.rs b/crates/ptx-schedule/src/campaign.rs index f6c4a580e4..e58b167749 100644 --- a/crates/ptx-schedule/src/campaign.rs +++ b/crates/ptx-schedule/src/campaign.rs @@ -852,10 +852,28 @@ fn rebuild_artifact_section( Ok(section) } +/// Both spellings an example uses to decline a run. +/// +/// The convention belongs to `scripts/smoketest.sh`, whose `verdict_standard` +/// greps `^[[:space:]]*(skipping:|pass \(skipped\))` case-insensitively and +/// whose own comment names the second form: "`PASS (skipped): ...` form below +/// sm_75". `generated_ldmatrix` prints exactly that when the device is under +/// sm_75. +/// +/// Only the first form used to be accepted here. An example that declined with +/// the second one therefore exited 0 with no mismatch marker, so `run_binary` +/// called it [`RunKind::Pass`], the baseline gate let the campaign through, and +/// every seed "passed" a kernel that never ran -- a clean report from a +/// campaign that measured nothing. +const SKIP_MARKERS: [&str; 2] = ["skipping:", "pass (skipped)"]; + +/// `output` is already lowercased by `run_binary`, which is what makes the +/// comparison case-insensitive the way the smoketest's `grep -i` is. fn has_skip_marker(output: &str) -> bool { - output - .lines() - .any(|line| line.trim_start().starts_with("skipping:")) + output.lines().any(|line| { + let line = line.trim_start(); + SKIP_MARKERS.iter().any(|marker| line.starts_with(marker)) + }) } fn has_mismatch_marker(output: &str) -> bool { @@ -883,6 +901,44 @@ fn has_mismatch_marker(output: &str) -> bool { mod tests { use super::*; + /// The two spellings `scripts/smoketest.sh` accepts, and the near-misses + /// that must not be mistaken for either. + #[test] + fn both_smoketest_skip_spellings_are_recognised() { + // `run_binary` lowercases before classifying, so these arrive lowered. + for declined in [ + "skipping: cluster launch requires sm_90", + " skipping: needs two devices", + "pass (skipped): ldmatrix.m8n8.x4.b16 requires sm_75+; device is sm_70", + " pass (skipped): no peer access", + ] { + assert!(has_skip_marker(declined), "{declined}"); + } + + for ran in [ + "pass", + "pass: 1024 elements verified", + "success", + "no skipping: here", + "result was skipped by the host", + ] { + assert!(!has_skip_marker(ran), "{ran}"); + } + } + + /// A declined run must not be reported as a passing baseline: the campaign + /// gates on `RunKind::Pass` and would otherwise sweep every seed against a + /// kernel that never launched. + #[test] + fn a_declined_run_is_skipped_not_passed() { + for declined in [ + "skipping: needs sm_90\n", + "pass (skipped): ldmatrix requires sm_75+\n", + ] { + assert!(has_skip_marker(declined), "{declined}"); + } + } + #[test] fn seed_ranges_are_half_open() { assert_eq!(parse_seed_range("3..8").unwrap(), (3, 8));