use openigtlink_rust::protocol::message::{IgtlMessage, Message};
use openigtlink_rust::protocol::types::{
GetCapabilityMessage, GetStatusMessage, RtsTDataMessage, StartTDataMessage, StopTDataMessage,
};
#[test]
fn test_get_capability_encoding() {
let msg = GetCapabilityMessage;
let igtl_msg = IgtlMessage::new(msg, "TestDevice").unwrap();
assert_eq!(igtl_msg.header.type_name.as_str().unwrap(), "GET_CAPABIL");
assert_eq!(igtl_msg.header.body_size, 0);
assert_eq!(igtl_msg.header.device_name.as_str().unwrap(), "TestDevice");
}
#[test]
fn test_get_status_encoding() {
let msg = GetStatusMessage;
let igtl_msg = IgtlMessage::new(msg, "QueryClient").unwrap();
assert_eq!(igtl_msg.header.type_name.as_str().unwrap(), "GET_STATUS");
assert_eq!(igtl_msg.header.body_size, 0);
}
#[test]
fn test_stt_tdata_encoding() {
let msg = StartTDataMessage {
resolution: 50, coordinate_name: "RAS".to_string(), };
let igtl_msg = IgtlMessage::new(msg.clone(), "Tracker").unwrap();
assert_eq!(igtl_msg.header.type_name.as_str().unwrap(), "STT_TDATA");
assert_eq!(igtl_msg.header.body_size, 36);
let body = msg.encode_content().unwrap();
assert_eq!(body.len(), 36, "STT_TDATA body must be exactly 36 bytes");
assert_eq!(body[0], 0x00, "Resolution byte 0 should be 0x00");
assert_eq!(body[1], 0x00, "Resolution byte 1 should be 0x00");
assert_eq!(body[2], 0x00, "Resolution byte 2 should be 0x00");
assert_eq!(
body[3], 0x32,
"Resolution byte 3 should be 0x32 (50 decimal)"
);
assert_eq!(body[4], b'R', "Coordinate name byte 0 should be 'R'");
assert_eq!(body[5], b'A', "Coordinate name byte 1 should be 'A'");
assert_eq!(body[6], b'S', "Coordinate name byte 2 should be 'S'");
assert_eq!(body[7], 0x00, "Coordinate name byte 3 should be null");
for (i, byte) in body.iter().enumerate().take(36).skip(8) {
assert_eq!(
*byte, 0x00,
"Coordinate name byte {} should be null-padded",
i
);
}
}
#[test]
fn test_stt_tdata_long_coordinate() {
let long_name = "VeryLongCoordinateSystemNameHere_40ch";
let msg = StartTDataMessage {
resolution: 100,
coordinate_name: long_name.to_string(),
};
let body = msg.encode_content().unwrap();
assert_eq!(body.len(), 36);
let coord_bytes = &body[4..36];
assert_eq!(coord_bytes.len(), 32);
assert_eq!(&coord_bytes[..32], &long_name.as_bytes()[..32]);
}
#[test]
fn test_stp_tdata_encoding() {
let msg = StopTDataMessage;
let igtl_msg = IgtlMessage::new(msg, "Tracker").unwrap();
assert_eq!(igtl_msg.header.type_name.as_str().unwrap(), "STP_TDATA");
assert_eq!(igtl_msg.header.body_size, 0);
}
#[test]
fn test_rts_tdata_encoding() {
let msg_ok = RtsTDataMessage::ok();
let body_ok = msg_ok.encode_content().unwrap();
assert_eq!(body_ok.len(), 2, "RTS_TDATA body must be 2 bytes");
assert_eq!(body_ok[0], 0x00, "Status byte 0 should be 0x00");
assert_eq!(body_ok[1], 0x01, "Status byte 1 should be 0x01 (OK)");
let msg_err = RtsTDataMessage::error();
let body_err = msg_err.encode_content().unwrap();
assert_eq!(body_err.len(), 2, "RTS_TDATA body must be 2 bytes");
assert_eq!(body_err[0], 0x00, "Status byte 0 should be 0x00");
assert_eq!(body_err[1], 0x00, "Status byte 1 should be 0x00 (ERROR)");
let msg_custom = RtsTDataMessage::new(0x1234);
let body_custom = msg_custom.encode_content().unwrap();
assert_eq!(body_custom.len(), 2);
assert_eq!(body_custom[0], 0x12, "Status high byte should be 0x12");
assert_eq!(body_custom[1], 0x34, "Status low byte should be 0x34");
}
#[test]
fn test_stt_tdata_roundtrip() {
let original = StartTDataMessage {
resolution: 33,
coordinate_name: "LPS".to_string(),
};
let encoded = original.encode_content().unwrap();
let decoded = StartTDataMessage::decode_content(&encoded).unwrap();
assert_eq!(decoded.resolution, 33);
assert_eq!(decoded.coordinate_name, "LPS");
}
#[test]
fn test_rts_tdata_roundtrip() {
let statuses = vec![0, 1, 42, 0xFFFF];
for status in statuses {
let original = RtsTDataMessage::new(status);
let encoded = original.encode_content().unwrap();
let decoded = RtsTDataMessage::decode_content(&encoded).unwrap();
assert_eq!(decoded.status, status, "Status {} roundtrip failed", status);
}
}
#[test]
fn test_message_type_length() {
let types = vec![
"GET_CAPABIL", "GET_STATUS", "GET_TRANSFOR", "GET_IMAGE", "GET_TDATA", "GET_POINT", "GET_IMGMETA", "GET_LBMETA", "STT_TDATA", "STP_TDATA", "STP_IMAGE", "STP_TRANSFOR", "RTS_TDATA", ];
for msg_type in types {
assert!(
msg_type.len() <= 12,
"Message type '{}' exceeds 12 characters ({})",
msg_type,
msg_type.len()
);
}
}
#[test]
fn test_header_size() {
use openigtlink_rust::protocol::header::Header;
assert_eq!(
Header::SIZE,
58,
"OpenIGTLink header must be exactly 58 bytes"
);
}
#[test]
fn test_crc_compatibility() {
let msg = GetCapabilityMessage;
let encoded = msg.encode_content().unwrap();
use openigtlink_rust::protocol::crc::calculate_crc;
let crc = calculate_crc(&encoded);
assert_eq!(crc, 0, "Empty message CRC should be 0");
}
#[test]
fn test_full_message_serialization() {
let msg = StartTDataMessage {
resolution: 50,
coordinate_name: "RAS".to_string(),
};
let igtl_msg = IgtlMessage::new(msg, "TestDevice").unwrap();
let serialized = igtl_msg.encode().unwrap();
assert_eq!(
serialized.len(),
58 + 36,
"STT_TDATA message should be 94 bytes (header + body)"
);
assert_eq!(serialized[0], 0x00); assert_eq!(serialized[1], 0x02);
let msg_type = &serialized[2..14];
assert_eq!(&msg_type[..9], b"STT_TDATA");
let body = &serialized[58..];
assert_eq!(body.len(), 36);
assert_eq!(body[0..4], [0x00, 0x00, 0x00, 0x32]); assert_eq!(body[4], b'R'); assert_eq!(body[5], b'A');
assert_eq!(body[6], b'S');
}