#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
use tempfile::TempDir;
use x0x::identity::{AgentId, MachineId};
use x0x::network::NetworkConfig;
use x0x::{Agent, DirectMessage};
async fn create_test_agent(temp_dir: &TempDir, name: &str) -> Agent {
let machine_key_path = temp_dir.path().join(format!("{name}_machine.key"));
let agent_key_path = temp_dir.path().join(format!("{name}_agent.key"));
let contacts_path = temp_dir.path().join(format!("{name}_contacts.json"));
let cache_dir = temp_dir.path().join(format!("{name}_cache"));
Agent::builder()
.with_machine_key(machine_key_path)
.with_agent_key_path(agent_key_path)
.with_contact_store_path(contacts_path)
.with_peer_cache_dir(cache_dir)
.with_network_config(NetworkConfig::default())
.build()
.await
.expect("Failed to create test agent")
}
#[test]
fn test_direct_message_construction() {
let sender = AgentId([1u8; 32]);
let machine_id = MachineId([2u8; 32]);
let payload = b"test payload".to_vec();
let msg = DirectMessage::new(sender, machine_id, payload.clone());
assert_eq!(msg.sender, sender);
assert_eq!(msg.machine_id, machine_id);
assert_eq!(msg.payload, payload);
assert_eq!(msg.payload_str(), Some("test payload"));
assert!(msg.received_at > 0);
}
#[test]
fn test_direct_message_binary_payload() {
let sender = AgentId([1u8; 32]);
let machine_id = MachineId([2u8; 32]);
let payload = vec![0xff, 0xfe, 0x00];
let msg = DirectMessage::new(sender, machine_id, payload);
assert!(msg.payload_str().is_none());
}
#[tokio::test]
async fn test_agent_has_direct_messaging() {
let temp_dir = TempDir::new().unwrap();
let agent = create_test_agent(&temp_dir, "agent").await;
let dm = agent.direct_messaging();
let connected = dm.connected_agents().await;
assert!(connected.is_empty());
}
#[tokio::test]
async fn test_connected_agents_empty() {
let temp_dir = TempDir::new().unwrap();
let agent = create_test_agent(&temp_dir, "agent").await;
let connected = agent.connected_agents().await;
assert!(connected.is_empty());
}
#[tokio::test]
async fn test_is_agent_connected_unknown() {
let temp_dir = TempDir::new().unwrap();
let agent = create_test_agent(&temp_dir, "agent").await;
let unknown_agent = AgentId([99u8; 32]);
let connected = agent.is_agent_connected(&unknown_agent).await;
assert!(!connected);
}
#[tokio::test]
async fn test_send_direct_agent_not_found() {
let temp_dir = TempDir::new().unwrap();
let agent = create_test_agent(&temp_dir, "agent").await;
let unknown_agent = AgentId([99u8; 32]);
let result = agent.send_direct(&unknown_agent, b"hello".to_vec()).await;
assert!(result.is_err());
let err = result.unwrap_err();
assert!(
matches!(err, x0x::dm::DmError::RecipientKeyUnavailable(_)),
"Expected DmError::RecipientKeyUnavailable, got: {:?}",
err
);
}
#[tokio::test]
async fn test_subscribe_direct() {
let temp_dir = TempDir::new().unwrap();
let agent = create_test_agent(&temp_dir, "agent").await;
let _rx1 = agent.subscribe_direct();
let _rx2 = agent.subscribe_direct();
}
#[tokio::test]
async fn test_direct_messaging_registration() {
let dm = x0x::DirectMessaging::new();
let agent_id = AgentId([1u8; 32]);
let machine_id = MachineId([2u8; 32]);
assert!(dm.lookup_agent(&machine_id).await.is_none());
dm.register_agent(agent_id, machine_id).await;
assert_eq!(dm.lookup_agent(&machine_id).await, Some(agent_id));
}
#[tokio::test]
async fn test_direct_messaging_connection_state() {
let dm = x0x::DirectMessaging::new();
let agent_id = AgentId([1u8; 32]);
let machine_id = MachineId([2u8; 32]);
assert!(!dm.is_connected(&agent_id).await);
assert!(dm.connected_agents().await.is_empty());
dm.mark_connected(agent_id, machine_id).await;
assert!(dm.is_connected(&agent_id).await);
assert_eq!(dm.connected_agents().await, vec![agent_id]);
assert_eq!(dm.get_machine_id(&agent_id).await, Some(machine_id));
dm.mark_disconnected(&agent_id).await;
assert!(!dm.is_connected(&agent_id).await);
assert!(dm.connected_agents().await.is_empty());
}
#[test]
fn test_direct_messaging_encoding() {
let agent_id = AgentId([42u8; 32]);
let payload = b"hello world".to_vec();
let encoded = x0x::DirectMessaging::encode_message(&agent_id, &payload).unwrap();
assert_eq!(encoded[0], 0x10);
assert_eq!(encoded.len(), 1 + 32 + payload.len());
let (decoded_agent, decoded_payload) = x0x::DirectMessaging::decode_message(&encoded).unwrap();
assert_eq!(decoded_agent, agent_id);
assert_eq!(decoded_payload, payload);
}
#[test]
fn test_direct_messaging_max_payload_size() {
let agent_id = AgentId([1u8; 32]);
let max_size = x0x::direct::MAX_DIRECT_PAYLOAD_SIZE;
let at_max = vec![0u8; max_size];
assert!(x0x::DirectMessaging::encode_message(&agent_id, &at_max).is_ok());
let over_max = vec![0u8; max_size + 1];
assert!(x0x::DirectMessaging::encode_message(&agent_id, &over_max).is_err());
}
#[test]
fn test_direct_messaging_decode_wrong_type() {
let mut data = vec![0x00; 50];
data[0] = 0x00;
let result = x0x::DirectMessaging::decode_message(&data);
assert!(result.is_err());
}
#[test]
fn test_direct_messaging_decode_too_short() {
let short = vec![0x10; 20];
let result = x0x::DirectMessaging::decode_message(&short);
assert!(result.is_err());
}