diff options
| -rw-r--r-- | apps/fparkan-vulkan-smoke/src/main.rs | 20 | ||||
| -rw-r--r-- | fixtures/acceptance/coverage.tsv | 2 | ||||
| -rw-r--r-- | xtask/src/main.rs | 114 |
3 files changed, 124 insertions, 12 deletions
diff --git a/apps/fparkan-vulkan-smoke/src/main.rs b/apps/fparkan-vulkan-smoke/src/main.rs index 13451a3..86052d5 100644 --- a/apps/fparkan-vulkan-smoke/src/main.rs +++ b/apps/fparkan-vulkan-smoke/src/main.rs @@ -576,6 +576,26 @@ mod tests { } #[test] + fn rejects_deprecated_self_assertion_flags() { + for flag in [ + "--status", + "--platform", + "--validation-error-count", + "--resize-count", + "--swapchain-recreate-count", + ] { + let parsed = SmokeOptions::parse(&[ + "--out".to_string(), + "target/report.json".to_string(), + flag.to_string(), + "value".to_string(), + ]); + + assert_eq!(parsed, Err(format!("unknown native smoke option: {flag}"))); + } + } + + #[test] fn renders_string_array_json() { assert_eq!( render_string_array(&["VUID-A".to_string(), "VUID-B".to_string()]), diff --git a/fixtures/acceptance/coverage.tsv b/fixtures/acceptance/coverage.tsv index a66e9dd..22e0a5b 100644 --- a/fixtures/acceptance/coverage.tsv +++ b/fixtures/acceptance/coverage.tsv @@ -15,7 +15,7 @@ S0-ARCH-007 covered cargo xtask ci runs fmt, policy, workspace test, clippy, rus S0-ARCH-008 covered cargo xtask policy rejects moving Rust toolchains and workspace rust-version drift S0-ARCH-009 covered .github/workflows/ci.yml runs a pinned MSRV backend-neutral crate job S0-ARCH-010 covered cargo xtask acceptance audit emits measured commit_sha, git_dirty, runner_identity, rust_toolchain, and msrv metadata into the JSON artifact -S0-ARCH-011 covered .github/workflows/ci.yml runs cargo run -p fparkan-vulkan-smoke --locked -- --out target/fparkan/native-smoke/macos.json and cargo xtask native-smoke audit enforces a passed macOS 300-frame report with measured resize/recreate, validation=0, and provenance fields for git_dirty and runner_identity +S0-ARCH-011 covered .github/workflows/ci.yml runs cargo run -p fparkan-vulkan-smoke --locked -- --out target/fparkan/native-smoke/macos.json and cargo xtask native-smoke audit enforces a passed macOS 300-frame report with measured resize/recreate, validation=0, clean git provenance, exact commit SHA shape, and a platform-consistent target triple S0-DIAG-001 covered cargo test -p fparkan-diagnostics --offline diagnostic_chain_preserves_context S0-DIAG-002 covered cargo test -p fparkan-diagnostics --offline json_is_stable S0-CORPUS-001 covered cargo test -p fparkan-corpus --offline deterministic_traversal_is_creation_order_independent diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 7b02a52..609cbfa 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1583,6 +1583,16 @@ fn validate_native_smoke_report( report: &serde_json::Value, failures: &mut Vec<String>, ) { + validate_native_smoke_status_fields(platform, report, failures); + validate_native_smoke_provenance_fields(platform, report, failures); + validate_native_smoke_runtime_fields(platform, report, failures); +} + +fn validate_native_smoke_status_fields( + platform: &str, + report: &serde_json::Value, + failures: &mut Vec<String>, +) { expect_string_field( platform, report, @@ -1634,13 +1644,16 @@ fn validate_native_smoke_report( "created", failures, ); - expect_u64_at_least(platform, report, "frames", 300, failures); - expect_u64_at_least(platform, report, "resize_count", 1, failures); - expect_u64_at_least(platform, report, "swapchain_recreate_count", 1, failures); - expect_u64_field(platform, report, "validation_warning_count", 0, failures); - expect_u64_field(platform, report, "validation_error_count", 0, failures); - expect_nonempty_string(platform, report, "commit_sha", failures); +} + +fn validate_native_smoke_provenance_fields( + platform: &str, + report: &serde_json::Value, + failures: &mut Vec<String>, +) { + expect_commit_sha(platform, report, failures); expect_bool_field(platform, report, "git_dirty", failures); + expect_bool_field_value(platform, report, "git_dirty", false, failures); expect_nonempty_string(platform, report, "runner_identity", failures); expect_string_field( platform, @@ -1651,6 +1664,19 @@ fn validate_native_smoke_report( ); expect_string_field(platform, report, "platform", platform, failures); expect_nonempty_string(platform, report, "target_triple", failures); + expect_target_triple_matches_platform(platform, report, failures); +} + +fn validate_native_smoke_runtime_fields( + platform: &str, + report: &serde_json::Value, + failures: &mut Vec<String>, +) { + expect_u64_at_least(platform, report, "frames", 300, failures); + expect_u64_at_least(platform, report, "resize_count", 1, failures); + expect_u64_at_least(platform, report, "swapchain_recreate_count", 1, failures); + expect_u64_field(platform, report, "validation_warning_count", 0, failures); + expect_u64_field(platform, report, "validation_error_count", 0, failures); expect_nonempty_string(platform, report, "shader_manifest_hash", failures); expect_nonempty_string(platform, report, "vulkan_device_name", failures); expect_u64_at_least( @@ -1727,6 +1753,58 @@ fn expect_bool_field( } } +fn expect_bool_field_value( + platform: &str, + report: &serde_json::Value, + field: &str, + expected: bool, + failures: &mut Vec<String>, +) { + match report.get(field) { + Some(serde_json::Value::Bool(actual)) if *actual == expected => {} + Some(serde_json::Value::Bool(actual)) => { + failures.push(format!( + "{platform}: {field} expected {expected}, found {actual}" + )); + } + Some(_) => failures.push(format!("{platform}: {field} must be a boolean")), + None => failures.push(format!("{platform}: missing {field}")), + } +} + +fn expect_commit_sha(platform: &str, report: &serde_json::Value, failures: &mut Vec<String>) { + match report.get("commit_sha") { + Some(serde_json::Value::String(commit_sha)) + if commit_sha.len() == 40 && commit_sha.chars().all(|ch| ch.is_ascii_hexdigit()) => {} + Some(serde_json::Value::String(_)) => failures.push(format!( + "{platform}: commit_sha must be a 40-character lowercase or uppercase hex string" + )), + Some(_) => failures.push(format!("{platform}: commit_sha must be a string")), + None => failures.push(format!("{platform}: missing commit_sha")), + } +} + +fn expect_target_triple_matches_platform( + platform: &str, + report: &serde_json::Value, + failures: &mut Vec<String>, +) { + let Ok(target_triple) = json_string_field(report, "target_triple") else { + return; + }; + let matches_platform = match platform { + "macos" => target_triple.contains("apple-darwin"), + "linux" => target_triple.contains("linux"), + "windows" => target_triple.contains("windows"), + _ => true, + }; + if !matches_platform { + failures.push(format!( + "{platform}: target_triple {target_triple:?} does not match platform" + )); + } +} + fn expect_u64_at_least( platform: &str, report: &serde_json::Value, @@ -2518,6 +2596,12 @@ mod tests { let reports = ["macos"] .into_iter() .map(|platform| { + let target_triple = match platform { + "macos" => "aarch64-apple-darwin", + "linux" => "x86_64-unknown-linux-gnu", + "windows" => "x86_64-pc-windows-msvc", + _ => "unknown-target", + }; ( platform.to_string(), serde_json::json!({ @@ -2526,7 +2610,7 @@ mod tests { "git_dirty": false, "runner_identity": "github-actions/12345/stage0-macos", "rust_toolchain": measured_rust_toolchain_version(), - "target_triple": format!("{platform}-test-target"), + "target_triple": target_triple, "platform": platform, "status": "passed", "frames": 300, @@ -2563,11 +2647,11 @@ mod tests { "macos".to_string(), serde_json::json!({ "schema_version": "fparkan-native-smoke-v1", - "commit_sha": "0123456789abcdef0123456789abcdef01234567", - "git_dirty": "dirty", + "commit_sha": "unknown", + "git_dirty": true, "runner_identity": "", "rust_toolchain": measured_rust_toolchain_version(), - "target_triple": "aarch64-apple-darwin", + "target_triple": "x86_64-unknown-linux-gnu", "platform": "macos", "status": "blocked", "frames": 0, @@ -2592,8 +2676,16 @@ mod tests { assert!( failures.contains(&"macos: status expected \"passed\", found \"blocked\"".to_string()) ); - assert!(failures.contains(&"macos: git_dirty must be a boolean".to_string())); + assert!(failures.contains( + &"macos: commit_sha must be a 40-character lowercase or uppercase hex string" + .to_string() + )); + assert!(failures.contains(&"macos: git_dirty expected false, found true".to_string())); assert!(failures.contains(&"macos: runner_identity must be non-empty".to_string())); + assert!(failures.contains( + &"macos: target_triple \"x86_64-unknown-linux-gnu\" does not match platform" + .to_string() + )); assert!(failures.contains(&"macos: frames expected >= 300, found 0".to_string())); assert!(failures .contains(&"macos: validation_error_count must be an unsigned integer".to_string())); |
