weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
use super::*;

// ------------------------------------------------------------------
// 8. Free success & error mapping
// ------------------------------------------------------------------

#[test]
fn ifds_vyre_resident_free_resident_success() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    a.free_resident(r).unwrap();
    assert_eq!(b.free_count(), 1);
    assert!(b.alive_resources().is_empty());
}

#[test]
fn ifds_vyre_resident_free_resident_err_propagates() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    b.inject_next_free(InjectedFailure::PoisonedLock {
        lock_error: "free lock".into(),
    });
    let err = a.free_resident(r).unwrap_err();
    assert!(err.contains("free lock"));
}

#[test]
#[should_panic(expected = "double-free")]
fn ifds_vyre_resident_free_double_free_panics() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    a.free_resident(r.clone()).unwrap();
    let _ = a.free_resident(r);
}

#[test]
#[should_panic(expected = "use-after-free")]
fn ifds_vyre_resident_upload_after_free_panics() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    a.free_resident(r.clone()).unwrap();
    let _ = a.upload_resident(&r, &[1u8]);
}

#[test]
#[should_panic(expected = "use-after-free")]
fn ifds_vyre_resident_download_after_free_panics() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    a.free_resident(r.clone()).unwrap();
    let _ = a.download_resident(&r);
}

#[test]
#[should_panic(expected = "use-after-free")]
fn ifds_vyre_resident_dispatch_after_free_panics() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    a.free_resident(r.clone()).unwrap();
    let p = program();
    let _ = a.dispatch_resident(&p, &[r], None);
}

// ------------------------------------------------------------------
// 9. Dispatch success
// ------------------------------------------------------------------

#[test]
fn ifds_vyre_resident_dispatch_zero_resources() {
    let b = backend();
    let a = adapter(&b);
    let p = program();
    a.dispatch_resident(&p, &[], None).unwrap();
    assert_eq!(b.dispatch_count(), 1);
    let d = b.take_dispatches();
    assert_eq!(d[0].resource_handles.len(), 0);
    assert_eq!(d[0].grid_override, None);
}

#[test]
fn ifds_vyre_resident_dispatch_one_resource() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    let p = program();
    a.dispatch_resident(&p, &[r], None).unwrap();
    assert_eq!(b.dispatch_count(), 1);
    let d = b.take_dispatches();
    assert_eq!(d[0].resource_handles.len(), 1);
}

#[test]
fn ifds_vyre_resident_dispatch_three_resources() {
    let b = backend();
    let a = adapter(&b);
    let r1 = a.allocate_resident(64).unwrap();
    let r2 = a.allocate_resident(64).unwrap();
    let r3 = a.allocate_resident(64).unwrap();
    let p = program();
    a.dispatch_resident(&p, &[r1, r2, r3], None).unwrap();
    let d = b.take_dispatches();
    assert_eq!(d[0].resource_handles.len(), 3);
}

#[test]
fn ifds_vyre_resident_dispatch_grid_override_none() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    let p = program();
    a.dispatch_resident(&p, &[r], None).unwrap();
    assert_eq!(b.take_dispatches()[0].grid_override, None);
}

#[test]
fn ifds_vyre_resident_dispatch_grid_override_some() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    let p = program();
    a.dispatch_resident(&p, &[r], Some([64, 1, 1])).unwrap();
    assert_eq!(b.take_dispatches()[0].grid_override, Some([64, 1, 1]));
}

#[test]
fn ifds_vyre_resident_dispatch_grid_override_3d() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    let p = program();
    a.dispatch_resident(&p, &[r], Some([8, 8, 1])).unwrap();
    assert_eq!(b.take_dispatches()[0].grid_override, Some([8, 8, 1]));
}

#[test]
fn ifds_vyre_resident_dispatch_records_program_op_id() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    let mut p = program();
    p.entry_op_id = Some("test_op".into());
    a.dispatch_resident(&p, &[r], None).unwrap();
    assert_eq!(b.take_dispatches()[0].program_op_id, Some("test_op".into()));
}

#[test]
fn ifds_vyre_resident_dispatch_err_propagates() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    let p = program();
    b.inject_next_dispatch(InjectedFailure::DispatchFailed {
        code: Some(99),
        message: "dispatch boom".into(),
    });
    let err = a.dispatch_resident(&p, &[r], None).unwrap_err();
    assert!(err.contains("dispatch boom"));
    assert!(err.contains("99"));
}

#[test]
fn ifds_vyre_resident_dispatch_err_unsupported_feature() {
    let b = backend();
    let a = adapter(&b);
    let r = a.allocate_resident(64).unwrap();
    let p = program();
    b.inject_next_dispatch(InjectedFailure::UnsupportedFeature {
        name: "wave_ops".into(),
    });
    let err = a.dispatch_resident(&p, &[r], None).unwrap_err();
    assert!(err.contains("wave_ops"));
}