diff options
| author | Valentin Popov <valentin@popov.link> | 2026-06-23 22:45:08 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-06-23 22:45:08 +0300 |
| commit | 00ae9067d89a8e8eaa0238e8131ed2aee8121d4d (patch) | |
| tree | 03ec36589390bfab5ab95e40c5872638bff1eb8e | |
| parent | c71e706d6969f516152142bbeebf5f836d38db9b (diff) | |
| download | fparkan-00ae9067d89a8e8eaa0238e8131ed2aee8121d4d.tar.xz fparkan-00ae9067d89a8e8eaa0238e8131ed2aee8121d4d.zip | |
feat: require swapchain recreation evidence in smoke reports
| -rw-r--r-- | apps/fparkan-vulkan-smoke/src/main.rs | 69 | ||||
| -rw-r--r-- | fixtures/acceptance/coverage.tsv | 1 | ||||
| -rw-r--r-- | fixtures/acceptance/stage_0_2_roadmap.md | 1 |
3 files changed, 71 insertions, 0 deletions
diff --git a/apps/fparkan-vulkan-smoke/src/main.rs b/apps/fparkan-vulkan-smoke/src/main.rs index a05a510..5c0e7e3 100644 --- a/apps/fparkan-vulkan-smoke/src/main.rs +++ b/apps/fparkan-vulkan-smoke/src/main.rs @@ -57,6 +57,7 @@ struct SmokeOptions { status: SmokeStatus, frames: u32, resize_count: u32, + swapchain_recreate_count: u32, validation_error_count: Option<u32>, probes: ProbeOptions, reason: Option<String>, @@ -69,6 +70,7 @@ impl SmokeOptions { let mut status = SmokeStatus::Blocked; let mut frames = 0; let mut resize_count = 0; + let mut swapchain_recreate_count = 0; let mut validation_error_count = None; let mut probes = ProbeOptions::default(); let mut reason = None; @@ -105,6 +107,12 @@ impl SmokeOptions { .ok_or_else(|| "--resize-count requires a value".to_string())?; resize_count = parse_u32("--resize-count", value)?; } + "--swapchain-recreate-count" => { + let value = iter + .next() + .ok_or_else(|| "--swapchain-recreate-count requires a value".to_string())?; + swapchain_recreate_count = parse_u32("--swapchain-recreate-count", value)?; + } "--validation-error-count" => { let value = iter .next() @@ -139,6 +147,7 @@ impl SmokeOptions { status, frames, resize_count, + swapchain_recreate_count, validation_error_count, probes, reason, @@ -433,6 +442,12 @@ fn validate_smoke_options( if options.resize_count == 0 { return Err("passed native smoke report requires --resize-count >= 1".to_string()); } + if options.swapchain_recreate_count == 0 { + return Err( + "passed native smoke report requires --swapchain-recreate-count >= 1" + .to_string(), + ); + } if options.validation_error_count != Some(0) { return Err( "passed native smoke report requires --validation-error-count 0".to_string(), @@ -512,6 +527,7 @@ fn render_smoke_report_json( " \"status\": \"{}\",\n", " \"frames\": {},\n", " \"resize_count\": {},\n", + " \"swapchain_recreate_count\": {},\n", " \"validation_error_count\": {},\n", " \"shader_manifest_hash\": \"{}\",\n", " \"vulkan_loader_status\": \"{}\",\n", @@ -536,6 +552,7 @@ fn render_smoke_report_json( options.status.as_str(), options.frames, options.resize_count, + options.swapchain_recreate_count, validation_error_count, json_escape(&shader_manifest.manifest_hash), bootstrap.loader_status.as_str(), @@ -658,6 +675,8 @@ mod tests { "299", "--resize-count", "1", + "--swapchain-recreate-count", + "1", "--validation-error-count", "0", ])) @@ -698,6 +717,8 @@ mod tests { "300", "--resize-count", "1", + "--swapchain-recreate-count", + "1", "--validation-error-count", "0", ])) @@ -726,6 +747,47 @@ mod tests { } #[test] + fn rejects_passed_without_swapchain_recreation() { + let options = SmokeOptions::parse(&strings(&[ + "--platform", + "linux", + "--out", + "target/native.json", + "--status", + "passed", + "--frames", + "300", + "--resize-count", + "1", + "--validation-error-count", + "0", + "--probe-surface", + ])) + .expect("options"); + + assert_eq!( + validate_smoke_options( + &options, + &VulkanBootstrapProbe { + loader_status: VulkanLoaderStatus::Available, + instance_api: Some("1.3.0".to_string()), + loader_error: None, + instance_status: VulkanInstanceStatus::Created, + instance_error: None, + portability_enumeration: false, + window_status: WinitWindowStatus::Planned, + window_width: Some(1280), + window_height: Some(720), + window_error: None, + surface_status: VulkanSurfaceStatus::Planned, + surface_error: None, + }, + ), + Err("passed native smoke report requires --swapchain-recreate-count >= 1".to_string()) + ); + } + + #[test] fn rejects_passed_without_instance_probe() { let options = SmokeOptions::parse(&strings(&[ "--platform", @@ -738,6 +800,8 @@ mod tests { "300", "--resize-count", "1", + "--swapchain-recreate-count", + "1", "--validation-error-count", "0", "--probe-loader", @@ -779,6 +843,8 @@ mod tests { "300", "--resize-count", "1", + "--swapchain-recreate-count", + "1", "--validation-error-count", "0", "--probe-instance", @@ -820,6 +886,8 @@ mod tests { "300", "--resize-count", "1", + "--swapchain-recreate-count", + "1", "--validation-error-count", "0", "--probe-window", @@ -886,6 +954,7 @@ mod tests { assert!(json.contains("\"schema_version\": \"fparkan-native-smoke-v1\"")); assert!(json.contains("\"platform\": \"macos\"")); assert!(json.contains("\"status\": \"blocked\"")); + assert!(json.contains("\"swapchain_recreate_count\": 0")); assert!(json.contains("\"shader_manifest_hash\": \"")); assert!(json.contains("\"vulkan_loader_status\": \"unavailable\"")); assert!(json.contains("\"vulkan_instance_api\": null")); diff --git a/fixtures/acceptance/coverage.tsv b/fixtures/acceptance/coverage.tsv index c886430..9abf379 100644 --- a/fixtures/acceptance/coverage.tsv +++ b/fixtures/acceptance/coverage.tsv @@ -55,6 +55,7 @@ S0-VK-023 covered cargo test -p fparkan-vulkan-smoke --offline rejects_false_pas S0-VK-024 covered cargo test -p fparkan-vulkan-smoke --offline rejects_passed_without_loader_probe formats_vulkan_api_version S0-VK-025 covered cargo test -p fparkan-vulkan-smoke --offline rejects_passed_without_instance_probe parses_instance_probe_as_loader_probe S0-VK-026 covered cargo test -p fparkan-vulkan-smoke --offline rejects_passed_without_window_probe rejects_passed_without_surface_probe parses_surface_probe_as_instance_probe +S0-VK-027 covered cargo test -p fparkan-vulkan-smoke --offline rejects_passed_without_swapchain_recreation blocked_report_includes_shader_manifest_and_bootstrap_status S0-LIMIT-001 covered cargo test -p fparkan-binary --offline rejects_count_stride_overflow S0-LIMIT-002 covered cargo test -p fparkan-binary --offline rejects_oversized_declared_allocation_before_read L1-P1-NRES-001 covered cargo test -p fparkan-nres --offline licensed_corpora_nres_roundtrip_gates diff --git a/fixtures/acceptance/stage_0_2_roadmap.md b/fixtures/acceptance/stage_0_2_roadmap.md index 5fc1f4b..b1d28d8 100644 --- a/fixtures/acceptance/stage_0_2_roadmap.md +++ b/fixtures/acceptance/stage_0_2_roadmap.md @@ -55,6 +55,7 @@ `S0-VK-024` `S0-VK-025` `S0-VK-026` +`S0-VK-027` `S0-LIMIT-001` `S0-LIMIT-002` `L1-P1-NRES-001` |
