lxmf-sdk 0.7.0

High-level Rust SDK for LXMF clients and RPC-backed LXMF workflows.
Documentation
use super::*;
use lxmf_core::announce::encode_delivery_display_name_app_data;

#[test]
fn announce_record_from_raw_extracts_lxmf_delivery_display_name() {
    let app_data =
        encode_delivery_display_name_app_data("Alice Router").expect("encoded display name");

    let record = AnnounceRecord::from_raw(
        "dest",
        "identity",
        DESTINATION_KIND_LXMF_DELIVERY,
        app_data.as_slice(),
        2,
        "iface",
        42,
    );

    assert_eq!(record.destination_hex, "dest");
    assert_eq!(record.identity_hex, "identity");
    assert_eq!(record.destination_kind, DESTINATION_KIND_LXMF_DELIVERY);
    assert_eq!(record.app_data, hex::encode(app_data));
    assert_eq!(record.display_name.as_deref(), Some("Alice Router"));
    assert_eq!(record.hops, 2);
    assert_eq!(record.interface_hex, "iface");
    assert_eq!(record.received_at_ms, 42);
}

#[test]
fn announce_record_from_raw_preserves_text_app_data() {
    let record = AnnounceRecord::from_raw(
        "appdest",
        "identity",
        DESTINATION_KIND_APP,
        b"R3AKT;EMergencyMessages;name=Bravo",
        1,
        "iface",
        100,
    );

    assert_eq!(record.app_data, "R3AKT;EMergencyMessages;name=Bravo");
    assert!(record.display_name.is_none());
}

#[test]
fn announce_record_from_raw_hex_encodes_malformed_binary_app_data() {
    let record = AnnounceRecord::from_raw(
        "otherdest",
        "identity",
        DESTINATION_KIND_OTHER,
        &[0xff, 0xfe, 0x00],
        1,
        "iface",
        100,
    );

    assert_eq!(record.app_data, "fffe00");
    assert!(record.display_name.is_none());
}

#[test]
fn non_delivery_announce_does_not_parse_lxmf_display_name() {
    let app_data =
        encode_delivery_display_name_app_data("Relay Name").expect("encoded display name");

    let record = AnnounceRecord::from_raw(
        "propdest",
        "identity",
        DESTINATION_KIND_LXMF_PROPAGATION,
        app_data.as_slice(),
        1,
        "iface",
        100,
    );

    assert_eq!(record.destination_kind, DESTINATION_KIND_LXMF_PROPAGATION);
    assert_eq!(record.app_data, hex::encode(app_data));
    assert!(record.display_name.is_none());
}

#[test]
fn peer_projection_merges_app_and_lxmf_announces() {
    let mut store = MessagingStore::default();
    store.record_announce(AnnounceRecord {
        destination_hex: "appdest".into(),
        identity_hex: "identity".into(),
        destination_kind: "app".into(),
        app_data: "R3AKT".into(),
        display_name: None,
        hops: 1,
        interface_hex: "iface".into(),
        received_at_ms: 10,
    });
    store.record_announce(AnnounceRecord {
        destination_hex: "lxmfdest".into(),
        identity_hex: "identity".into(),
        destination_kind: "lxmf_delivery".into(),
        app_data: "chat".into(),
        display_name: Some("Alice".into()),
        hops: 1,
        interface_hex: "iface".into(),
        received_at_ms: 20,
    });

    let peers = store.list_peers(["lxmfdest"]);
    assert_eq!(peers.len(), 1);
    assert_eq!(peers[0].destination_hex, "appdest");
    assert_eq!(peers[0].lxmf_destination_hex.as_deref(), Some("lxmfdest"));
    assert_eq!(peers[0].display_name.as_deref(), Some("Alice"));
    assert_eq!(peers[0].state, PeerState::Connected);
}

#[test]
fn conversation_projection_uses_lxmf_destination_for_peer_lookup() {
    let mut store = MessagingStore::default();
    store.record_announce(AnnounceRecord {
        destination_hex: "appdest".into(),
        identity_hex: "identity".into(),
        destination_kind: "app".into(),
        app_data: "R3AKT".into(),
        display_name: None,
        hops: 1,
        interface_hex: "iface".into(),
        received_at_ms: 10,
    });
    store.record_announce(AnnounceRecord {
        destination_hex: "lxmfdest".into(),
        identity_hex: "identity".into(),
        destination_kind: "lxmf_delivery".into(),
        app_data: "chat".into(),
        display_name: Some("Alice".into()),
        hops: 1,
        interface_hex: "iface".into(),
        received_at_ms: 20,
    });
    store.upsert_message(MessageRecord {
        message_id_hex: "msg".into(),
        conversation_id: "lxmfdest".into(),
        direction: MessageDirection::Outbound,
        destination_hex: "lxmfdest".into(),
        source_hex: None,
        title: None,
        body_utf8: "hello".into(),
        method: MessageMethod::Direct,
        state: MessageState::Delivered,
        detail: None,
        sent_at_ms: Some(30),
        received_at_ms: None,
        updated_at_ms: 30,
    });

    let conversations = store.list_conversations(std::iter::empty::<&str>());
    assert_eq!(conversations.len(), 1);
    assert_eq!(conversations[0].peer_display_name.as_deref(), Some("Alice"));
}