netlink-packet-connector 0.1.0

An implementation of the Linux kernel Connector API using netlink-packet-core.
Documentation
use super::*;
use netlink_packet_core::NetlinkHeader;

#[test]
fn test_connector_message_new() {
    let data = vec![1, 2, 3, 4, 5];
    let message = ConnectorMessage::new(100, 200, 300, 400, 0x1234, data.clone());

    assert_eq!(message.idx(), 100);
    assert_eq!(message.value(), 200);
    assert_eq!(message.seq(), 300);
    assert_eq!(message.ack(), 400);
    assert_eq!(message.flags(), 0x1234);
    assert_eq!(message.data(), &data);
}

#[test]
fn test_connector_message_getters() {
    let data = vec![0xFF, 0xAA, 0x55];
    let message = ConnectorMessage::new(0x12345678, 0x87654321, 999, 888, 0xABCD, data.clone());

    assert_eq!(message.idx(), 0x12345678);
    assert_eq!(message.value(), 0x87654321);
    assert_eq!(message.seq(), 999);
    assert_eq!(message.ack(), 888);
    assert_eq!(message.flags(), 0xABCD);
    assert_eq!(message.data(), &data);
}

#[test]
fn test_connector_message_empty_data() {
    let message = ConnectorMessage::new(1, 2, 3, 4, 5, Vec::new());

    assert_eq!(message.data(), &[] as &[u8]);
    assert_eq!(message.data().len(), 0);
}

#[test]
fn test_serialize_basic() {
    let data = vec![0x01, 0x02, 0x03, 0x04];
    let message =
        ConnectorMessage::new(0x11223344, 0x55667788, 0x99AABBCC, 0xDDEEFF00, 0x1122, data);

    let buffer_len = message.buffer_len();
    assert_eq!(buffer_len, 24); // 20 bytes header + 4 bytes data

    let mut buffer = vec![0u8; buffer_len];
    message.serialize(&mut buffer);

    // Verify serialized data
    assert_eq!(NativeEndian::read_u32(&buffer[0..4]), 0x11223344); // idx
    assert_eq!(NativeEndian::read_u32(&buffer[4..8]), 0x55667788); // value
    assert_eq!(NativeEndian::read_u32(&buffer[8..12]), 0x99AABBCC); // seq
    assert_eq!(NativeEndian::read_u32(&buffer[12..16]), 0xDDEEFF00); // ack
    assert_eq!(NativeEndian::read_u16(&buffer[16..18]), 4); // data len
    assert_eq!(NativeEndian::read_u16(&buffer[18..20]), 0x1122); // flags
    assert_eq!(&buffer[20..24], &[0x01, 0x02, 0x03, 0x04]); // data
}

#[test]
fn test_serialize_empty_data() {
    let message = ConnectorMessage::new(1, 2, 3, 4, 5, Vec::new());

    let buffer_len = message.buffer_len();
    assert_eq!(buffer_len, 20); // Only header, no data

    let mut buffer = vec![0u8; buffer_len];
    message.serialize(&mut buffer);

    assert_eq!(NativeEndian::read_u16(&buffer[16..18]), 0); // data len should be 0
}

#[test]
fn test_deserialize_basic() {
    let mut payload = vec![0u8; 24];

    // Prepare payload
    NativeEndian::write_u32(&mut payload[0..4], 0x11223344); // idx
    NativeEndian::write_u32(&mut payload[4..8], 0x55667788); // value
    NativeEndian::write_u32(&mut payload[8..12], 0x99AABBCC); // seq
    NativeEndian::write_u32(&mut payload[12..16], 0xDDEEFF00); // ack
    NativeEndian::write_u16(&mut payload[16..18], 4); // data len
    NativeEndian::write_u16(&mut payload[18..20], 0x1122); // flags
    payload[20..24].copy_from_slice(&[0x01, 0x02, 0x03, 0x04]); // data

    let header = NetlinkHeader::default();
    let message = ConnectorMessage::deserialize(&header, &payload).unwrap();

    assert_eq!(message.idx(), 0x11223344);
    assert_eq!(message.value(), 0x55667788);
    assert_eq!(message.seq(), 0x99AABBCC);
    assert_eq!(message.ack(), 0xDDEEFF00);
    assert_eq!(message.flags(), 0x1122);
    assert_eq!(message.data(), &[0x01, 0x02, 0x03, 0x04]);
}

#[test]
fn test_deserialize_empty_data() {
    let mut payload = vec![0u8; 20];

    NativeEndian::write_u32(&mut payload[0..4], 1); // idx
    NativeEndian::write_u32(&mut payload[4..8], 2); // value
    NativeEndian::write_u32(&mut payload[8..12], 3); // seq
    NativeEndian::write_u32(&mut payload[12..16], 4); // ack
    NativeEndian::write_u16(&mut payload[16..18], 0); // data len = 0
    NativeEndian::write_u16(&mut payload[18..20], 5); // flags

    let header = NetlinkHeader::default();
    let message = ConnectorMessage::deserialize(&header, &payload).unwrap();

    assert_eq!(message.data(), &[] as &[u8]);
}

#[test]
fn test_deserialize_with_padding() {
    // Test with 4-byte padding (data len = 1, but buffer has 4 bytes after header)
    let mut payload = vec![0u8; 24];

    NativeEndian::write_u32(&mut payload[0..4], 1);
    NativeEndian::write_u32(&mut payload[4..8], 2);
    NativeEndian::write_u32(&mut payload[8..12], 3);
    NativeEndian::write_u32(&mut payload[12..16], 4);
    NativeEndian::write_u16(&mut payload[16..18], 1); // data len = 1
    NativeEndian::write_u16(&mut payload[18..20], 5);
    payload[20] = 0xFF; // Only first byte is actual data
                        // bytes 21-23 are padding

    let header = NetlinkHeader::default();
    let message = ConnectorMessage::deserialize(&header, &payload).unwrap();

    assert_eq!(message.data(), &[0xFF]);
}

#[test]
fn test_deserialize_invalid_data_length_negative() {
    let mut payload = vec![0u8; 22]; // Only 2 bytes of data

    NativeEndian::write_u32(&mut payload[0..4], 1);
    NativeEndian::write_u32(&mut payload[4..8], 2);
    NativeEndian::write_u32(&mut payload[8..12], 3);
    NativeEndian::write_u32(&mut payload[12..16], 4);
    NativeEndian::write_u16(&mut payload[16..18], 5); // data len = 5, but only 2 bytes available
    NativeEndian::write_u16(&mut payload[18..20], 6);

    let header = NetlinkHeader::default();
    let result = ConnectorMessage::deserialize(&header, &payload);

    assert!(result.is_err());
    assert_eq!(result.unwrap_err(), DeserializeError("Invalid data length"));
}

#[test]
fn test_deserialize_invalid_data_length_too_much_padding() {
    let mut payload = vec![0u8; 26]; // 6 bytes of data

    NativeEndian::write_u32(&mut payload[0..4], 1);
    NativeEndian::write_u32(&mut payload[4..8], 2);
    NativeEndian::write_u32(&mut payload[8..12], 3);
    NativeEndian::write_u32(&mut payload[12..16], 4);
    NativeEndian::write_u16(&mut payload[16..18], 1); // data len = 1, but 6 bytes available (padding > 4)
    NativeEndian::write_u16(&mut payload[18..20], 5);

    let header = NetlinkHeader::default();
    let result = ConnectorMessage::deserialize(&header, &payload);

    assert!(result.is_err());
    assert_eq!(result.unwrap_err(), DeserializeError("Invalid data length"));
}

#[test]
fn test_serialize_deserialize_roundtrip() {
    let original_data = vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE];
    let original_message = ConnectorMessage::new(
        0x12345678,
        0x87654321,
        0xABCDEF00,
        0x11223344,
        0x5566,
        original_data,
    );

    // Serialize
    let buffer_len = original_message.buffer_len();
    let mut buffer = vec![0u8; buffer_len];
    original_message.serialize(&mut buffer);

    // Deserialize
    let header = NetlinkHeader::default();
    let deserialized_message = ConnectorMessage::deserialize(&header, &buffer).unwrap();

    // Compare
    assert_eq!(original_message, deserialized_message);
}

#[test]
fn test_message_type() {
    let message = ConnectorMessage::new(1, 2, 3, 4, 5, vec![]);
    assert_eq!(message.message_type(), 0);
}

#[test]
fn test_buffer_len() {
    let message1 = ConnectorMessage::new(1, 2, 3, 4, 5, vec![]);
    assert_eq!(message1.buffer_len(), 20);

    let message2 = ConnectorMessage::new(1, 2, 3, 4, 5, vec![1, 2, 3]);
    assert_eq!(message2.buffer_len(), 23);

    let message3 = ConnectorMessage::new(1, 2, 3, 4, 5, vec![1; 100]);
    assert_eq!(message3.buffer_len(), 120);
}

#[test]
fn test_connector_id_equality() {
    let id1 = ConnectorId {
        idx: 100,
        value: 200,
    };
    let id2 = ConnectorId {
        idx: 100,
        value: 200,
    };
    let id3 = ConnectorId {
        idx: 100,
        value: 201,
    };

    assert_eq!(id1, id2);
    assert_ne!(id1, id3);
}

#[test]
fn test_connector_message_equality() {
    let data = vec![1, 2, 3];
    let msg1 = ConnectorMessage::new(1, 2, 3, 4, 5, data.clone());
    let msg2 = ConnectorMessage::new(1, 2, 3, 4, 5, data.clone());
    let msg3 = ConnectorMessage::new(1, 2, 3, 4, 6, data.clone()); // different flags

    assert_eq!(msg1, msg2);
    assert_ne!(msg1, msg3);
}

#[test]
fn test_deserialize_error_display() {
    let error = DeserializeError("Test error message");
    assert_eq!(format!("{}", error), "Test error message");
}

#[test]
fn test_deserialize_error_description() {
    let error = DeserializeError("Test error");
    assert_eq!(error.to_string(), "Test error");
    assert!(error.source().is_none());
}

#[test]
fn test_deserialize_error_equality() {
    let error1 = DeserializeError("Same message");
    let error2 = DeserializeError("Same message");
    let error3 = DeserializeError("Different message");

    assert_eq!(error1, error2);
    assert_ne!(error1, error3);
}

#[test]
fn test_from_connector_message_to_netlink_payload() {
    let message = ConnectorMessage::new(1, 2, 3, 4, 5, vec![6, 7, 8]);
    let payload: NetlinkPayload<ConnectorMessage> = message.clone().into();

    match payload {
        NetlinkPayload::InnerMessage(inner_msg) => {
            assert_eq!(inner_msg, message);
        }
        _ => panic!("Expected InnerMessage variant"),
    }
}

#[test]
fn test_connector_message_debug_format() {
    let message = ConnectorMessage::new(1, 2, 3, 4, 5, vec![6, 7]);
    let debug_str = format!("{:?}", message);
    assert!(debug_str.contains("ConnectorMessage"));
    assert!(debug_str.contains("ConnectorId"));
}

#[test]
fn test_connector_message_clone() {
    let original = ConnectorMessage::new(1, 2, 3, 4, 5, vec![6, 7, 8]);
    let cloned = original.clone();

    assert_eq!(original, cloned);

    // Verify they are separate instances
    assert_eq!(original.data(), cloned.data());
    assert_ne!(original.data().as_ptr(), cloned.data().as_ptr());
}

#[test]
fn test_large_data_serialization() {
    let large_data = vec![0x42; 1000];
    let message = ConnectorMessage::new(1, 2, 3, 4, 5, large_data.clone());

    let buffer_len = message.buffer_len();
    assert_eq!(buffer_len, 1020); // 20 + 1000

    let mut buffer = vec![0u8; buffer_len];
    message.serialize(&mut buffer);

    // Verify data length field
    assert_eq!(NativeEndian::read_u16(&buffer[16..18]), 1000);

    // Verify data content
    assert_eq!(&buffer[20..], &large_data);
}

#[test]
fn test_edge_case_max_u32_values() {
    let message = ConnectorMessage::new(
        u32::MAX,
        u32::MAX,
        u32::MAX,
        u32::MAX,
        u16::MAX,
        vec![0xFF; 65535],
    );

    assert_eq!(message.idx(), u32::MAX);
    assert_eq!(message.value(), u32::MAX);
    assert_eq!(message.seq(), u32::MAX);
    assert_eq!(message.ack(), u32::MAX);
    assert_eq!(message.flags(), u16::MAX);
    assert_eq!(message.data().len(), 65535);
}