vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
use std::collections::BTreeSet;
use std::fs;

use tempfile::TempDir;
use vyre_conform::enforce::{enforce_gpu_mandatory, ForbiddenKind, CRITICAL};

#[test]
fn gpu_mandatory_gate_flags_every_optional_gpu_pattern() {
    let tmp = TempDir::new().expect("tempdir");
    write_workspace(tmp.path());
    write_rust_fixture(tmp.path());
    write_manifest_fixture(tmp.path());

    let findings = enforce_gpu_mandatory(tmp.path()).expect_err("fixture must fail the gate");
    let kinds = findings
        .iter()
        .map(|finding| finding.kind)
        .collect::<BTreeSet<_>>();

    for kind in [
        ForbiddenKind::GpuCfg,
        ForbiddenKind::GpuCfgAlias,
        ForbiddenKind::GpuCfgAttr,
        ForbiddenKind::CargoGpuFeature,
        ForbiddenKind::SilentGpuUnavailableFallback,
        ForbiddenKind::SwallowedGpuProbeError,
    ] {
        assert!(
            kinds.contains(&kind),
            "missing finding kind {kind:?}: {findings:#?}"
        );
    }

    assert!(
        findings.len() >= 11,
        "each banned pattern in the fixture must produce a finding: {findings:#?}"
    );
    for finding in &findings {
        assert_eq!(finding.severity, CRITICAL);
        assert!(finding.line > 0, "finding must include a line: {finding:?}");
        assert!(
            finding.column > 0,
            "finding must include a column: {finding:?}"
        );
        assert!(
            finding.fix.starts_with("Fix:"),
            "finding must tell the user how to fix it: {finding:?}"
        );
    }
}

fn write_workspace(root: &std::path::Path) {
    fs::write(
        root.join("Cargo.toml"),
        r#"
[workspace]
members = ["core"]

[features]
skip-gpu = []
"#,
    )
    .expect("write root manifest");
}

fn write_manifest_fixture(root: &std::path::Path) {
    fs::create_dir_all(root.join("core")).expect("core dir");
    fs::write(
        root.join("core/Cargo.toml"),
        r#"
[package]
name = "fixture-core"
version = "0.0.0"
edition = "2021"

[features]
gpu = []
cpu-only = []
no-gpu = []
"#,
    )
    .expect("write core manifest");
}

fn write_rust_fixture(root: &std::path::Path) {
    fs::create_dir_all(root.join("core/src")).expect("core/src dir");
    fs::write(
        root.join("core/src/lib.rs"),
        r#"
#![cfg(feature = "gpu")]

#[cfg(feature = "gpu")]
fn positive_gpu_cfg() {}

#[cfg(not(feature = "gpu"))]
fn negative_gpu_cfg() {}

#[cfg(any(test, feature = "gpu"))]
fn any_gpu_cfg() {}

#[cfg(all(test, feature = "gpu"))]
fn all_gpu_cfg() {}

#[cfg_attr(not(feature = "gpu"), ignore)]
fn cfg_attr_ignore() {}

#[cfg_attr(not(feature = "gpu"), should_panic)]
fn cfg_attr_should_panic() {}

#[cfg(test_gpu_feature)]
fn renamed_alias() {}

fn print_then_return() -> Result<(), String> {
    eprintln!("GPU unavailable, skipping");
    return Ok(());
}

fn print_no_gpu_then_none() -> Option<()> {
    println!("no GPU available");
    return None;
}

fn err_probe_swallowed() -> Result<(), String> {
    if let Err(_) = gpu_probe() {
        return Ok(());
    }
    Ok(())
}

fn ok_probe_swallowed() {
    let _ = cached_device().ok();
    let _ = Backend::try_new().ok();
}
"#,
    )
    .expect("write rust fixture");
}