use std::sync::Arc;
use cuda_core::{CudaContext, DeviceBuffer};
#[test]
fn ctx_strong_count_returns_to_baseline_after_buffer_lifecycle() {
let ctx = CudaContext::new(0).expect("failed to create CUDA context");
let stream = ctx.new_stream().expect("failed to create CUDA stream");
let baseline = Arc::strong_count(&ctx);
{
let buf = DeviceBuffer::from_host(&stream, &[1u32, 2, 3, 4])
.expect("from_host failed on happy path");
assert_eq!(
Arc::strong_count(&ctx),
baseline + 1,
"live DeviceBuffer must add exactly one ctx strong count"
);
drop(buf);
}
assert_eq!(
Arc::strong_count(&ctx),
baseline,
"ctx strong count must return to baseline after from_host buffer drop"
);
{
let buf = DeviceBuffer::<f32>::zeroed(&stream, 16).expect("zeroed failed on happy path");
drop(buf);
}
assert_eq!(
Arc::strong_count(&ctx),
baseline,
"ctx strong count must return to baseline after zeroed buffer drop"
);
}
#[test]
fn vram_returns_to_baseline_after_buffer_cycles() {
let ctx = CudaContext::new(0).expect("failed to create CUDA context");
let stream = ctx.new_stream().expect("failed to create CUDA stream");
fn free_mem() -> usize {
let mut free = 0usize;
let mut total = 0usize;
let rc = unsafe { cuda_bindings::cuMemGetInfo_v2(&mut free, &mut total) };
assert_eq!(rc, 0, "cuMemGetInfo failed: {rc}");
free
}
for _ in 0..4 {
let b = DeviceBuffer::<u8>::zeroed(&stream, 1 << 20).expect("warmup alloc failed");
drop(b);
}
ctx.synchronize().expect("sync failed");
let before = free_mem();
for _ in 0..64 {
let b = DeviceBuffer::<u8>::zeroed(&stream, 1 << 20).expect("cycle alloc failed");
drop(b);
}
ctx.synchronize().expect("sync failed");
let after = free_mem();
assert!(
before.abs_diff(after) < (8 << 20),
"device free memory drifted by {} bytes across 64 construct/drop cycles",
before.abs_diff(after)
);
}
#[test]
fn zero_length_construction_succeeds_for_both_constructors() {
let ctx = CudaContext::new(0).expect("failed to create CUDA context");
let stream = ctx.new_stream().expect("failed to create CUDA stream");
let baseline = Arc::strong_count(&ctx);
let zeroed = DeviceBuffer::<u8>::zeroed(&stream, 0).expect("zeroed(len=0) must succeed");
assert_eq!(zeroed.len(), 0);
assert_eq!(zeroed.num_bytes(), 0);
assert!(zeroed.is_empty());
let from_host =
DeviceBuffer::<u32>::from_host(&stream, &[]).expect("from_host(empty) must succeed");
assert_eq!(from_host.len(), 0);
assert_eq!(from_host.num_bytes(), 0);
assert!(from_host.is_empty());
drop(zeroed);
drop(from_host);
assert_eq!(
Arc::strong_count(&ctx),
baseline,
"empty buffers must not leak a ctx strong count"
);
}