aetheric-gpu 0.1.0-alpha

Aetheric Silicon: turn this host's RAM into a Digital GPU endpoint
//! End-to-end integration test: boot a Digital GPU from this host's RAM,
//! allocate virtual capacity, and verify the slow-hill curve behaves.

use digital_gpu::*;
use std::time::Instant;

#[test]
fn boot_digital_gpu_with_default_spec() {
    let gpu = GpuHandle::boot(GpuSpec::new().effective_gb(32))
        .expect("should boot a default 32 GB digital GPU");

    assert!(gpu.effective_capacity_gb() >= 32);
}

#[test]
fn boot_with_compression_expansion() {
    // 1 GB physical, 32x expansion -> 32 GB effective
    let gpu = GpuHandle::boot(GpuSpec::new()
        .effective_gb(32)
        .physical_gb(2));
    assert!(gpu.is_ok(), "should boot with 2 GB physical / 32 GB effective");
}

#[test]
fn boot_with_int4_compression() {
    // 8 GB physical, 8x expansion -> 64 GB effective
    let gpu = GpuHandle::boot(GpuSpec::new()
        .effective_gb(64)
        .compression(CompressionMode::Int4)
        .physical_gb(8));
    assert!(gpu.is_ok());
}

#[test]
fn large_physical_gb_oversubscribes() {
    // Oversubscription is now allowed — the slow-hill curve handles it.
    // 64 TB physical will fail at arena allocation, not spec validation.
    let gpu = GpuHandle::boot(GpuSpec::new()
        .effective_gb(128)
        .physical_gb(64 * 1024));
    // May succeed or fail at arena allocation — both are acceptable.
    // The key is that spec validation itself no longer rejects oversubscription.
    let _ = gpu;
}

#[test]
fn curve_sample_is_monotonic() {
    let gpu = GpuHandle::boot(GpuSpec::new().effective_gb(64))
        .expect("boot ok");
    let samples = gpu.curve_sample(64 * 1024 * 1024 * 1024, 10);
    assert!(samples.len() <= 11 && samples.len() >= 1);

    // Should be non-increasing in bandwidth as we go up in capacity
    let mut last_bw = f64::MAX;
    for s in &samples {
        assert!(s.bandwidth_gib_s <= last_bw + 1e-9,
                "bandwidth should never increase: {} -> {}",
                last_bw, s.bandwidth_gib_s);
        last_bw = s.bandwidth_gib_s;
    }
}

#[test]
fn bandwidth_query_first_gib_in_fast_pool() {
    let gpu = GpuHandle::boot(GpuSpec::new().effective_gb(64))
        .expect("boot ok");
    // Effective virtual capacity at 1 GB should map to ~1 GB / 32 = 32 MB physical
    // (well within any host's RAM, so should be at fast pool peak)
    let bw = gpu.bandwidth_at_effective(1024 * 1024 * 1024);
    assert!(bw > 10.0,
        "1 GB virtual should give > 10 GiB/s, got {}", bw);
}

#[test]
fn compressed_arena_allocate_8x_over_physical() {
    // Allocate 6 GB virtual from a 6 GB arena via 32x binary GEMM expansion
    let gpu = GpuHandle::boot(GpuSpec::new()
        .physical_gb(6)
        .effective_gb(192))  // 192 GB effective via 32x compression
        .expect("boot ok");

    if let Some(arena) = gpu.compressed_arena() {
        let alloc = arena.allocate_effective(4 * 1024 * 1024 * 1024);
        // Should succeed: requesting 4 GB virtual = 128 MB physical (fits in 6 GB arena)
        assert!(alloc.is_ok(), "4 GB virtual allocation failed");
    }
}

#[test]
fn boot_speed_smoke_test() {
    let start = Instant::now();
    let _ = GpuHandle::boot(GpuSpec::new().effective_gb(8));
    let elapsed = start.elapsed();
    assert!(elapsed.as_secs() < 60,
        "boot took {}s, should be < 60s", elapsed.as_secs());
}

#[test]
fn explicit_no_compression_works() {
    let gpu = GpuHandle::boot(GpuSpec::new()
        .effective_gb(8)
        .compression(CompressionMode::None)
        .physical_gb(8));
    assert!(gpu.is_ok());
    // With None compression, no compressed_arena is built,
    // so compressed_arena() returns None
    assert!(gpu.unwrap().compressed_arena().is_none());
}

#[test]
fn cluster_enabled_boots_with_discovery() {
    // Should boot and start a discovery thread
    let gpu = GpuHandle::boot(GpuSpec::new()
        .effective_gb(8)
        .enable_cluster());
    assert!(gpu.is_ok(), "cluster-enabled boot should succeed");
}