use bytes::Bytes;
use ipfrs_tensorlogic::{
ArrowTensor, ArrowTensorStore, SafetensorsReader, SafetensorsWriter, SharedMemoryPool,
SharedTensorBuffer, SharedTensorInfo, TensorDtype, ZeroCopyConverter,
};
use tempfile::NamedTempFile;
#[test]
fn test_arrow_tensor_zero_copy_access() {
let data: Vec<f32> = (0..1000).map(|i| i as f32 * 0.5).collect();
let tensor = ArrowTensor::from_slice_f32("test_tensor", vec![1000], &data);
assert_eq!(tensor.metadata.name, "test_tensor");
assert_eq!(tensor.metadata.shape, vec![1000]);
assert_eq!(tensor.metadata.dtype, TensorDtype::Float32);
let slice = tensor.as_slice_f32().expect("Failed to get f32 slice");
assert_eq!(slice.len(), 1000);
for (i, &value) in slice.iter().enumerate() {
assert_eq!(value, i as f32 * 0.5);
}
let bytes = tensor.as_bytes();
assert_eq!(bytes.len(), 1000 * 4);
let floats_from_bytes: &[f32] = ZeroCopyConverter::bytes_to_slice(&bytes);
assert_eq!(floats_from_bytes.len(), 1000);
for (i, &value) in floats_from_bytes.iter().enumerate() {
assert_eq!(value, i as f32 * 0.5);
}
}
#[test]
fn test_arrow_tensor_multi_dtype_zero_copy() {
let f32_data: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0];
let f32_tensor = ArrowTensor::from_slice_f32("f32", vec![4], &f32_data);
let f32_slice = f32_tensor.as_slice_f32().unwrap();
assert_eq!(f32_slice, &f32_data[..]);
let f64_data: Vec<f64> = vec![1.0, 2.0, 3.0, 4.0];
let f64_tensor = ArrowTensor::from_slice_f64("f64", vec![4], &f64_data);
let f64_slice = f64_tensor.as_slice_f64().unwrap();
assert_eq!(f64_slice, &f64_data[..]);
let i32_data: Vec<i32> = vec![1, 2, 3, 4];
let i32_tensor = ArrowTensor::from_slice_i32("i32", vec![4], &i32_data);
let i32_slice = i32_tensor.as_slice_i32().unwrap();
assert_eq!(i32_slice, &i32_data[..]);
let i64_data: Vec<i64> = vec![1, 2, 3, 4];
let i64_tensor = ArrowTensor::from_slice_i64("i64", vec![4], &i64_data);
let i64_slice = i64_tensor.as_slice_i64().unwrap();
assert_eq!(i64_slice, &i64_data[..]);
}
#[test]
fn test_arrow_tensor_store_zero_copy() {
let mut store = ArrowTensorStore::new();
let t1 = ArrowTensor::from_slice_f32("weights", vec![10], &[1.0; 10]);
let t2 = ArrowTensor::from_slice_f32("biases", vec![5], &[0.1; 5]);
let t3 = ArrowTensor::from_slice_i32("indices", vec![3], &[0, 1, 2]);
store.insert(t1);
store.insert(t2);
store.insert(t3);
assert_eq!(store.len(), 3);
let weights = store.get("weights").expect("Weights not found");
let weights_slice = weights.as_slice_f32().unwrap();
assert_eq!(weights_slice.len(), 10);
assert!(weights_slice.iter().all(|&x| x == 1.0));
let indices = store.get("indices").expect("Indices not found");
let indices_slice = indices.as_slice_i32().unwrap();
assert_eq!(indices_slice, &[0, 1, 2]);
}
#[test]
fn test_safetensors_zero_copy_loading() {
let mut writer = SafetensorsWriter::new();
writer.add_f32("layer1.weight", vec![128, 64], &vec![0.1; 128 * 64]);
writer.add_f32("layer1.bias", vec![128], &vec![0.01; 128]);
writer.add_f64("high_precision", vec![10], &[std::f64::consts::PI; 10]);
writer.add_i32("vocab_ids", vec![1000], &vec![42; 1000]);
let bytes = writer.serialize().expect("Failed to serialize");
let reader = SafetensorsReader::from_bytes(Bytes::from(bytes)).expect("Failed to load");
let weight = reader
.load_as_arrow("layer1.weight")
.expect("Failed to load weight");
assert_eq!(weight.metadata.shape, vec![128, 64]);
let weight_slice = weight.as_slice_f32().unwrap();
assert_eq!(weight_slice.len(), 128 * 64);
let bias = reader
.load_as_arrow("layer1.bias")
.expect("Failed to load bias");
assert_eq!(bias.metadata.shape, vec![128]);
let bias_slice = bias.as_slice_f32().unwrap();
assert_eq!(bias_slice.len(), 128);
let high_prec = reader
.load_as_arrow("high_precision")
.expect("Failed to load high precision");
let hp_slice = high_prec.as_slice_f64().unwrap();
assert!(hp_slice
.iter()
.all(|&x| (x - std::f64::consts::PI).abs() < 1e-10));
}
#[test]
fn test_shared_memory_zero_copy() {
use tempfile::tempdir;
let dir = tempdir().expect("Failed to create temp dir");
let mut pool = SharedMemoryPool::new(dir.path(), 1024 * 1024 * 100);
let data: Vec<f32> = (0..10000).map(|i| i as f32).collect();
let temp_file = NamedTempFile::new().expect("Failed to create temp file");
let path = temp_file.path();
let tensor_info = SharedTensorInfo {
name: "test_tensor".to_string(),
dtype: TensorDtype::Float32,
shape: vec![10000],
offset: 0,
size: 10000 * 4,
};
let mut buffer =
SharedTensorBuffer::create(path, 10000 * 4, std::slice::from_ref(&tensor_info))
.expect("Failed to create shared buffer");
buffer.write_tensor(&tensor_info, &data);
buffer.flush().expect("Failed to flush");
let readonly = SharedTensorBuffer::open_readonly(path).expect("Failed to create readonly view");
let metadata = readonly.tensor_metadata().expect("Failed to get metadata");
assert_eq!(metadata.len(), 1);
let read_data: Vec<f32> = readonly.read_tensor(&metadata[0]);
assert_eq!(read_data.len(), 10000);
for (i, &value) in read_data.iter().enumerate() {
assert_eq!(value, i as f32);
}
pool.register("test_buffer", readonly)
.expect("Failed to register buffer");
pool.remove("test_buffer");
}
#[test]
fn test_zero_copy_converter() {
let floats: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let bytes = ZeroCopyConverter::slice_to_bytes(&floats);
assert_eq!(bytes.len(), 20);
let floats_back: &[f32] = ZeroCopyConverter::bytes_to_slice(bytes);
assert_eq!(floats_back, &floats[..]);
let doubles: Vec<f64> = vec![1.0, 2.0, 3.0];
let bytes = ZeroCopyConverter::slice_to_bytes(&doubles);
assert_eq!(bytes.len(), 24);
let doubles_back: &[f64] = ZeroCopyConverter::bytes_to_slice(bytes);
assert_eq!(doubles_back, &doubles[..]);
let ints: Vec<i32> = vec![1, 2, 3, 4];
let bytes = ZeroCopyConverter::slice_to_bytes(&ints);
assert_eq!(bytes.len(), 16);
let ints_back: &[i32] = ZeroCopyConverter::bytes_to_slice(bytes);
assert_eq!(ints_back, &ints[..]);
}
#[test]
fn test_arrow_safetensors_roundtrip() {
let mut store = ArrowTensorStore::new();
store.insert(ArrowTensor::from_slice_f32(
"w1",
vec![100],
&vec![0.5; 100],
));
store.insert(ArrowTensor::from_slice_f64("w2", vec![50], &vec![1.5; 50]));
store.insert(ArrowTensor::from_slice_i32("idx", vec![10], &[7; 10]));
let mut writer = SafetensorsWriter::new();
for name in store.names() {
let tensor = store.get(name).unwrap();
match tensor.metadata.dtype {
TensorDtype::Float32 => {
let data = tensor.as_slice_f32().unwrap();
writer.add_f32(&tensor.metadata.name, tensor.metadata.shape.clone(), data);
}
TensorDtype::Float64 => {
let data = tensor.as_slice_f64().unwrap();
writer.add_f64(&tensor.metadata.name, tensor.metadata.shape.clone(), data);
}
TensorDtype::Int32 => {
let data = tensor.as_slice_i32().unwrap();
writer.add_i32(&tensor.metadata.name, tensor.metadata.shape.clone(), data);
}
TensorDtype::Int64 => {
let data = tensor.as_slice_i64().unwrap();
writer.add_i64(&tensor.metadata.name, tensor.metadata.shape.clone(), data);
}
_ => {}
}
}
let bytes = writer.serialize().expect("Failed to serialize");
let reader = SafetensorsReader::from_bytes(Bytes::from(bytes)).expect("Failed to read");
let w1 = reader.load_as_arrow("w1").expect("Failed to load w1");
assert_eq!(w1.as_slice_f32().unwrap().len(), 100);
assert!(w1.as_slice_f32().unwrap().iter().all(|&x| x == 0.5));
let w2 = reader.load_as_arrow("w2").expect("Failed to load w2");
assert_eq!(w2.as_slice_f64().unwrap().len(), 50);
assert!(w2.as_slice_f64().unwrap().iter().all(|&x| x == 1.5));
let idx = reader.load_as_arrow("idx").expect("Failed to load idx");
assert_eq!(idx.as_slice_i32().unwrap().len(), 10);
assert!(idx.as_slice_i32().unwrap().iter().all(|&x| x == 7));
}
#[test]
fn test_large_tensor_zero_copy() {
let size = 10_000_000;
let data: Vec<f32> = (0..size).map(|i| (i % 100) as f32).collect();
let tensor = ArrowTensor::from_slice_f32("large", vec![size], &data);
let slice = tensor.as_slice_f32().expect("Failed to get slice");
assert_eq!(slice.len(), size);
assert_eq!(slice[0], 0.0);
assert_eq!(slice[99], 99.0);
assert_eq!(slice[100], 0.0);
assert_eq!(slice[size - 1], ((size - 1) % 100) as f32);
let bytes = tensor.as_bytes();
assert_eq!(bytes.len(), size * 4);
}
#[test]
fn test_zero_copy_type_mismatch_errors() {
let tensor = ArrowTensor::from_slice_f32("test", vec![10], &[1.0; 10]);
assert!(tensor.as_slice_f64().is_none());
assert!(tensor.as_slice_i32().is_none());
assert!(tensor.as_slice_i64().is_none());
assert!(tensor.as_slice_f32().is_some());
}
#[test]
fn test_zero_copy_memory_management() {
for _ in 0..1000 {
let data: Vec<f32> = (0..1000).map(|i| i as f32).collect();
let tensor = ArrowTensor::from_slice_f32("temp", vec![1000], &data);
let _slice = tensor.as_slice_f32().unwrap();
}
}