#[cfg(unix)]
#[path = "stub_node_api.rs"]
mod stub_node_api;
#[cfg(unix)]
mod tests {
use blvm_node::module::ipc::client::ModuleIpcClient;
use blvm_node::module::ipc::protocol::RequestMessage;
use blvm_node::module::ipc::server::ModuleIpcServer;
use blvm_node::module::traits::ModuleError;
use blvm_node::Hash;
use std::sync::Arc;
use tempfile::TempDir;
use tokio::time::{sleep, Duration};
use super::stub_node_api::MockNodeAPI;
fn setup_test_socket() -> (TempDir, std::path::PathBuf) {
let temp_dir = TempDir::new().unwrap();
let socket_path = temp_dir.path().join("test.sock");
(temp_dir, socket_path)
}
#[tokio::test]
async fn test_client_connection_failure() {
let (_temp_dir, socket_path) = setup_test_socket();
let result = ModuleIpcClient::connect(&socket_path).await;
assert!(result.is_err());
if let Err(ModuleError::IpcError(_)) = result {
} else {
panic!("Expected IpcError");
}
}
#[tokio::test]
async fn test_client_handshake() {
let (_temp_dir, socket_path) = setup_test_socket();
let node_api = Arc::new(MockNodeAPI);
let server_path = socket_path.clone();
let server_handle = tokio::spawn(async move {
let mut server = ModuleIpcServer::new(&server_path);
let _ = server.start(node_api).await;
});
sleep(Duration::from_millis(100)).await;
let mut client = match ModuleIpcClient::connect(&socket_path).await {
Ok(c) => c,
Err(_) => {
sleep(Duration::from_millis(200)).await;
ModuleIpcClient::connect(&socket_path).await.unwrap()
}
};
let correlation_id = client.next_correlation_id();
let handshake = RequestMessage {
correlation_id,
request_type: blvm_node::module::ipc::protocol::MessageType::Handshake,
payload: blvm_node::module::ipc::protocol::RequestPayload::Handshake {
module_id: "test-module".to_string(),
module_name: "Test Module".to_string(),
version: "1.0.0".to_string(),
},
};
let response = client.request(handshake).await.unwrap();
assert!(response.success);
assert_eq!(response.correlation_id, correlation_id);
server_handle.abort();
}
#[tokio::test]
async fn test_client_correlation_id_increment() {
let (_temp_dir, socket_path) = setup_test_socket();
let node_api = Arc::new(MockNodeAPI);
let server_path = socket_path.clone();
let server_handle = tokio::spawn(async move {
let mut server = ModuleIpcServer::new(&server_path);
let _ = server.start(node_api).await;
});
sleep(Duration::from_millis(100)).await;
let mut client = ModuleIpcClient::connect(&socket_path).await.unwrap();
let handshake_id = client.next_correlation_id();
let handshake = RequestMessage {
correlation_id: handshake_id,
request_type: blvm_node::module::ipc::protocol::MessageType::Handshake,
payload: blvm_node::module::ipc::protocol::RequestPayload::Handshake {
module_id: "test".to_string(),
module_name: "Test".to_string(),
version: "1.0.0".to_string(),
},
};
let _ = client.request(handshake).await;
let id1 = client.next_correlation_id();
let id2 = client.next_correlation_id();
assert_eq!(id2, id1.wrapping_add(1));
server_handle.abort();
}
#[tokio::test]
async fn test_client_request_response_matching() {
let (_temp_dir, socket_path) = setup_test_socket();
let node_api = Arc::new(MockNodeAPI);
let server_path = socket_path.clone();
let server_handle = tokio::spawn(async move {
let mut server = ModuleIpcServer::new(&server_path);
let _ = server.start(node_api).await;
});
sleep(Duration::from_millis(100)).await;
let mut client = ModuleIpcClient::connect(&socket_path).await.unwrap();
let handshake_id = client.next_correlation_id();
let handshake = RequestMessage {
correlation_id: handshake_id,
request_type: blvm_node::module::ipc::protocol::MessageType::Handshake,
payload: blvm_node::module::ipc::protocol::RequestPayload::Handshake {
module_id: "test".to_string(),
module_name: "Test".to_string(),
version: "1.0.0".to_string(),
},
};
let _ = client.request(handshake).await;
let hash: Hash = [0xab; 32];
let correlation_id = client.next_correlation_id();
let request = RequestMessage::get_block(correlation_id, hash);
let response = client.request(request).await.unwrap();
assert_eq!(response.correlation_id, correlation_id);
assert!(response.success);
server_handle.abort();
}
#[tokio::test]
async fn test_client_receive_event_timeout() {
let (_temp_dir, socket_path) = setup_test_socket();
let node_api = Arc::new(MockNodeAPI);
let server_path = socket_path.clone();
let server_handle = tokio::spawn(async move {
let mut server = ModuleIpcServer::new(&server_path);
let _ = server.start(node_api).await;
});
sleep(Duration::from_millis(100)).await;
let mut client = ModuleIpcClient::connect(&socket_path).await.unwrap();
let handshake_id = client.next_correlation_id();
let handshake = RequestMessage {
correlation_id: handshake_id,
request_type: blvm_node::module::ipc::protocol::MessageType::Handshake,
payload: blvm_node::module::ipc::protocol::RequestPayload::Handshake {
module_id: "test".to_string(),
module_name: "Test".to_string(),
version: "1.0.0".to_string(),
},
};
let _ = client.request(handshake).await;
let event = client.receive_event().await.unwrap();
assert!(event.is_none());
server_handle.abort();
}
#[tokio::test]
async fn test_client_connection_closed_error() {
let (_temp_dir, socket_path) = setup_test_socket();
let node_api = Arc::new(MockNodeAPI);
let server_path = socket_path.clone();
let server_handle = tokio::spawn(async move {
let mut server = ModuleIpcServer::new(&server_path);
let _ = server.start(node_api).await;
});
sleep(Duration::from_millis(100)).await;
let mut client = ModuleIpcClient::connect(&socket_path).await.unwrap();
let handshake_id = client.next_correlation_id();
let handshake = RequestMessage {
correlation_id: handshake_id,
request_type: blvm_node::module::ipc::protocol::MessageType::Handshake,
payload: blvm_node::module::ipc::protocol::RequestPayload::Handshake {
module_id: "test".to_string(),
module_name: "Test".to_string(),
version: "1.0.0".to_string(),
},
};
let _ = client.request(handshake).await;
server_handle.abort();
sleep(Duration::from_millis(100)).await;
let hash: Hash = [0xcd; 32];
let correlation_id = client.next_correlation_id();
let request = RequestMessage::get_block(correlation_id, hash);
let result = client.request(request).await;
assert!(result.is_err());
}
}