//! ISV bus round-trip tests. Requires a CUDA device on this host.

use ml_alpha::isv::{IsvBus, SLOTS};
use ml_core::device::MlDevice;

fn test_device() -> MlDevice {
    MlDevice::cuda(0).expect("CUDA 0 required for ml-alpha tests")
}

#[test]
fn isv_bus_round_trip_one_slot() {
    let dev = test_device();
    let mut bus = IsvBus::new(&dev).expect("alloc");
    bus.write_slot(7, 3.14).expect("write");
    let snap = bus.snapshot().expect("read");
    approx::assert_relative_eq!(snap[7], 3.14_f32, epsilon = 1e-6);
    for (i, v) in snap.iter().enumerate() {
        if i == 7 {
            continue;
        }
        assert_eq!(*v, 0.0_f32, "slot {i} should be zero on init");
    }
}

#[test]
fn isv_bus_has_32_slots() {
    let dev = test_device();
    let bus = IsvBus::new(&dev).expect("alloc");
    assert_eq!(bus.len(), SLOTS);
    assert_eq!(SLOTS, 32);
}

#[test]
fn isv_bus_multi_slot_writes_independent() {
    let dev = test_device();
    let mut bus = IsvBus::new(&dev).expect("alloc");
    bus.write_slot(0, 1.0).unwrap();
    bus.write_slot(15, 2.0).unwrap();
    bus.write_slot(31, 3.0).unwrap();
    let snap = bus.snapshot().unwrap();
    approx::assert_relative_eq!(snap[0], 1.0);
    approx::assert_relative_eq!(snap[15], 2.0);
    approx::assert_relative_eq!(snap[31], 3.0);
    for i in [1, 7, 14, 16, 30] {
        assert_eq!(snap[i], 0.0, "slot {i} unexpectedly nonzero");
    }
}
