use std::mem::{align_of, offset_of, size_of};
use lmflow::ffi::{LMFlowBuffer, LMFlowInputQueueStats, LMFlowNodeStats, LMFlowPacket};
#[test]
fn lmflow_packet_layout() {
assert_eq!(size_of::<LMFlowPacket>(), 40, "LMFlowPacket size");
assert_eq!(align_of::<LMFlowPacket>(), 8, "LMFlowPacket alignment");
assert_eq!(offset_of!(LMFlowPacket, payload), 0);
assert_eq!(offset_of!(LMFlowPacket, type_id), 8);
assert_eq!(offset_of!(LMFlowPacket, timestamp), 16);
assert_eq!(offset_of!(LMFlowPacket, owner), 24);
assert_eq!(offset_of!(LMFlowPacket, drop_fn), 32);
}
#[test]
fn flow_buffer_layout() {
assert_eq!(size_of::<LMFlowBuffer>(), 168, "LMFlowBuffer size");
assert_eq!(align_of::<LMFlowBuffer>(), 8, "LMFlowBuffer alignment");
assert_eq!(offset_of!(LMFlowBuffer, data), 0);
assert_eq!(offset_of!(LMFlowBuffer, shape), 8);
assert_eq!(offset_of!(LMFlowBuffer, strides), 72);
assert_eq!(offset_of!(LMFlowBuffer, ndim), 136);
assert_eq!(offset_of!(LMFlowBuffer, dtype), 140);
assert_eq!(offset_of!(LMFlowBuffer, flags), 144);
assert_eq!(offset_of!(LMFlowBuffer, device), 148);
assert_eq!(offset_of!(LMFlowBuffer, reserved), 152);
}
#[test]
fn flow_node_stats_uses_struct_size_for_forward_compat() {
assert_eq!(offset_of!(LMFlowNodeStats, struct_size), 0);
assert_eq!(size_of::<u32>(), 4);
}
#[test]
fn input_queue_stats_uses_struct_size_for_forward_compat() {
assert_eq!(offset_of!(LMFlowInputQueueStats, struct_size), 0);
assert_eq!(size_of::<u32>(), 4);
}
#[test]
fn abi_version_matches_header() {
assert_eq!(lmflow::ffi::lmflow_abi_version(), 4);
}
#[test]
fn invalid_id_matches_header() {
assert_eq!(lmflow::ffi::INVALID_ID, usize::MAX);
}
#[test]
fn status_codes_match_header() {
use lmflow::status::code;
assert_eq!(code::OK, 0);
assert_eq!(code::INVALID_ARG, 1);
assert_eq!(code::NOT_FOUND, 2);
assert_eq!(code::KERNEL, 3);
assert_eq!(code::PANIC, 4);
assert_eq!(code::WOULD_BLOCK, 5);
assert_eq!(code::TIMEOUT, 6);
assert_eq!(code::CANCELLED, 7);
assert_eq!(code::CLOSED, 8);
assert_eq!(code::ABI, 9);
assert_eq!(code::UNSUPPORTED, 10);
assert_eq!(code::STATE, 11);
}
#[test]
fn poller_overflow_policy_ids_match_header() {
use lmflow::ffi::{
LMFLOW_POLLER_BLOCK, LMFLOW_POLLER_DROP_NEWEST, LMFLOW_POLLER_DROP_OLDEST,
LMFLOW_POLLER_LATEST,
};
assert_eq!(LMFLOW_POLLER_BLOCK, 0);
assert_eq!(LMFLOW_POLLER_DROP_OLDEST, 1);
assert_eq!(LMFLOW_POLLER_DROP_NEWEST, 2);
assert_eq!(LMFLOW_POLLER_LATEST, 3);
}
#[test]
fn dot_view_ids_match_header() {
use lmflow::ffi::{LMFLOW_DOT_COMPACT, LMFLOW_DOT_DIAGNOSTICS, LMFLOW_DOT_TOPOLOGY};
assert_eq!(LMFLOW_DOT_TOPOLOGY, 0);
assert_eq!(LMFLOW_DOT_COMPACT, 1);
assert_eq!(LMFLOW_DOT_DIAGNOSTICS, 2);
}
#[test]
fn builtin_type_ids_match_header() {
use lmflow::packet::type_id;
assert_eq!(type_id::NONE, 0);
assert_eq!(type_id::BYTES, 1);
assert_eq!(type_id::I64, 2);
assert_eq!(type_id::F64, 3);
assert_eq!(type_id::BOOL, 4);
assert_eq!(type_id::STR, 5);
assert_eq!(type_id::BUFFER, 6);
assert_eq!(type_id::HOST_OBJECT, 7);
}
#[test]
fn type_id_hash_matches_cpp_side() {
use lmflow::packet::fnv1a_type_id;
assert_eq!(
fnv1a_type_id("lmflow.test.Stable"),
0xBFB5_31B2_8317_9309,
"Rust 侧 FNV-1a 与 C++ 侧不再一致 —— 跨语言 type_id 会静默失配"
);
assert_eq!(fnv1a_type_id("i"), 0xAF63_E44C_8601_FA24);
assert_eq!(fnv1a_type_id("d"), 0xAF63_D94C_8601_E773);
for i in 0..2000 {
assert!(
fnv1a_type_id(&format!("lmflow.sample.{i}")) >= 16,
"自定义 type_id 不得落入内建区 0..15"
);
}
}
#[test]
fn c_type_id_entry_point_matches_rust_hash() {
use std::ffi::CString;
let name = CString::new("lmflow.test.Stable").unwrap();
let id = unsafe { lmflow::ffi::lmflow_type_id(name.as_ptr()) };
assert_eq!(id, lmflow::packet::fnv1a_type_id("lmflow.test.Stable"));
}
#[test]
fn dtype_ids_and_sizes_match_header() {
use lmflow::packet::{dtype, dtype_size};
assert_eq!(dtype::U8, 0);
assert_eq!(dtype::I8, 1);
assert_eq!(dtype::U16, 2);
assert_eq!(dtype::I16, 3);
assert_eq!(dtype::I32, 4);
assert_eq!(dtype::I64, 5);
assert_eq!(dtype::F16, 6);
assert_eq!(dtype::F32, 7);
assert_eq!(dtype::F64, 8);
assert_eq!(dtype_size(dtype::F32), 4);
}
#[test]
fn timestamp_sentinels_match_header() {
use lmflow::Timestamp;
assert_eq!(Timestamp::unset().0, i64::MIN);
assert_eq!(Timestamp::unstarted().0, i64::MIN + 1);
assert_eq!(Timestamp::pre_stream().0, i64::MIN + 2);
assert_eq!(Timestamp::min().0, i64::MIN + 3);
assert_eq!(Timestamp::max().0, i64::MAX - 3);
assert_eq!(Timestamp::post_stream().0, i64::MAX - 2);
assert_eq!(Timestamp::one_over_post_stream().0, i64::MAX - 1);
assert_eq!(Timestamp::done().0, i64::MAX);
}
#[test]
fn max_dims_matches_header() {
assert_eq!(lmflow::packet::MAX_DIMS, 8);
}