mod common;
use rzmq::{Msg, SocketType, ZmqError};
use std::time::Duration;
const SHORT_TIMEOUT: Duration = Duration::from_millis(200);
const LONG_TIMEOUT: Duration = Duration::from_secs(2);
#[tokio::test]
async fn test_req_rep_req_send_without_recv() -> Result<(), ZmqError> {
println!("Starting test_req_rep_req_send_without_recv...");
let ctx = common::test_context();
let req = ctx.socket(SocketType::Req)?;
let rep = ctx.socket(SocketType::Rep)?;
{
let endpoint = "tcp://127.0.0.1:5600"; println!("Binding REP to {}...", endpoint);
rep.bind(endpoint).await?;
tokio::time::sleep(Duration::from_millis(50)).await;
println!("Connecting REQ to {}...", endpoint);
req.connect(endpoint).await?;
tokio::time::sleep(Duration::from_millis(100)).await;
println!("REQ sending Request 1...");
req.send(Msg::from_static(b"Request 1")).await?;
println!("REQ sent Request 1.");
println!("REQ attempting to send Request 2 (should fail)...");
let send2_result = req.send(Msg::from_static(b"Request 2")).await;
assert!(
matches!(send2_result, Err(ZmqError::InvalidState(_))),
"Expected InvalidState error trying to send twice, got {:?}",
send2_result
);
println!("REQ correctly failed to send Request 2.");
println!("REP receiving Request 1...");
let received_req = common::recv_timeout(&rep, LONG_TIMEOUT).await?;
assert_eq!(received_req.data().unwrap(), b"Request 1");
println!("REP received Request 1.");
println!("REP sending Reply 1...");
rep.send(Msg::from_static(b"Reply 1")).await?;
println!("REP sent Reply 1.");
println!("REQ receiving Reply 1...");
let received_rep = common::recv_timeout(&req, LONG_TIMEOUT).await?;
assert_eq!(received_rep.data().unwrap(), b"Reply 1");
println!("REQ received Reply 1.");
println!("REQ sending Request 2 (should succeed)...");
req.send(Msg::from_static(b"Request 2")).await?;
println!("REQ sent Request 2.");
println!("REP receiving Request 2...");
let received_req2 = common::recv_timeout(&rep, LONG_TIMEOUT).await?;
assert_eq!(received_req2.data().unwrap(), b"Request 2");
println!("REP received Request 2.");
rep.send(Msg::from_static(b"Reply 2")).await?;
req.recv().await?; }
println!("Terminating context...");
ctx.term().await?;
println!("Test test_req_rep_req_send_without_recv finished.");
Ok(())
}
#[tokio::test]
async fn test_req_rep_rep_recv_without_request() -> Result<(), ZmqError> {
println!("Starting test_req_rep_rep_recv_without_request...");
let ctx = common::test_context();
let req = ctx.socket(SocketType::Req)?;
let rep = ctx.socket(SocketType::Rep)?;
{
let endpoint = "tcp://127.0.0.1:5601"; println!("Binding REP to {}...", endpoint);
rep.bind(endpoint).await?;
tokio::time::sleep(Duration::from_millis(50)).await;
println!("Connecting REQ to {}...", endpoint);
req.connect(endpoint).await?;
tokio::time::sleep(Duration::from_millis(100)).await;
println!("REP attempting recv (should time out)...");
let recv_result = common::recv_timeout(&rep, SHORT_TIMEOUT).await;
assert!(
matches!(recv_result, Err(ZmqError::Timeout)),
"Expected Timeout error trying to recv early, got {:?}",
recv_result
);
println!("REP correctly timed out waiting for early recv.");
println!("REQ sending Request 1...");
req.send(Msg::from_static(b"Request 1")).await?;
println!("REQ sent Request 1.");
println!("REP receiving Request 1 (should succeed)...");
let received_req = common::recv_timeout(&rep, LONG_TIMEOUT).await?;
assert_eq!(received_req.data().unwrap(), b"Request 1");
println!("REP received Request 1.");
rep.send(Msg::from_static(b"Reply 1")).await?;
req.recv().await?;
}
println!("Terminating context...");
ctx.term().await?;
println!("Test test_req_rep_rep_recv_without_request finished.");
Ok(())
}
#[tokio::test]
async fn test_req_rep_rep_send_without_request() -> Result<(), ZmqError> {
println!("Starting test_req_rep_rep_send_without_request...");
let ctx = common::test_context();
let req = ctx.socket(SocketType::Req)?;
let rep = ctx.socket(SocketType::Rep)?;
{
let endpoint = "tcp://127.0.0.1:5602"; println!("Binding REP to {}...", endpoint);
rep.bind(endpoint).await?;
tokio::time::sleep(Duration::from_millis(50)).await;
println!("Connecting REQ to {}...", endpoint);
req.connect(endpoint).await?;
tokio::time::sleep(Duration::from_millis(100)).await;
println!("REP attempting send (should fail)...");
let send_result = rep.send(Msg::from_static(b"Rep 1")).await;
assert!(
matches!(send_result, Err(ZmqError::InvalidState(_))),
"Expected InvalidState error trying to send early, got {:?}",
send_result
);
println!("REP correctly failed to send early.");
}
println!("Terminating context...");
ctx.term().await?;
println!("Test test_req_rep_rep_send_without_request finished.");
Ok(())
}
#[tokio::test]
async fn test_req_rep_rep_disconnects_while_req_waiting() -> Result<(), ZmqError> {
println!("Starting test_req_rep_rep_disconnects_while_req_waiting...");
let ctx = common::test_context();
let req = ctx.socket(SocketType::Req)?;
let endpoint = "tcp://127.0.0.1:5603"; {
let rep_socket = ctx.socket(SocketType::Rep)?;
println!("Binding REP to {}...", endpoint);
rep_socket.bind(endpoint).await?;
tokio::time::sleep(Duration::from_millis(50)).await;
println!("Connecting REQ to {}...", endpoint);
req.connect(endpoint).await?;
tokio::time::sleep(Duration::from_millis(100)).await;
println!("REQ sending Request...");
req.send(Msg::from_static(b"Request")).await?;
println!("REQ sent Request.");
println!("REP receiving Request...");
let received_req = common::recv_timeout(&rep_socket, LONG_TIMEOUT).await?;
assert_eq!(received_req.data().unwrap(), b"Request");
println!("REP received Request.");
println!("REP socket going out of scope (will trigger close)...");
rep_socket.close().await?;
}
println!("Waiting for REP close propagation...");
tokio::time::sleep(Duration::from_millis(500)).await;
println!("REQ attempting recv (should fail or timeout)...");
let recv_result = common::recv_timeout(&req, LONG_TIMEOUT).await;
println!("REQ recv result: {:?}", recv_result);
assert!(
matches!(recv_result, Err(ZmqError::InvalidState(_))), "Expected InvalidState after REP disconnect, got {:?}",
recv_result
);
println!("REQ correctly failed with InvalidState after REP disconnect.");
println!("REQ attempting send after REP disconnect (should succeed if state reset)...");
let rep2 = ctx.socket(SocketType::Rep)?;
rep2.bind(endpoint).await?; tokio::time::sleep(Duration::from_millis(150)).await;
let send_again_result = req.send(Msg::from_static(b"Request After Reset")).await;
assert!(
send_again_result.is_ok(),
"Expected send to succeed after state reset, got {:?}",
send_again_result
);
println!("REQ successfully sent after state reset.");
let _ = rep2.recv().await;
let _ = rep2.send(Msg::from_static(b"")).await;
let _ = req.recv().await;
println!("Terminating context...");
ctx.term().await?;
println!("Test test_req_rep_rep_disconnects_while_req_waiting finished.");
Ok(())
}
#[tokio::test]
async fn test_req_rep_req_disconnects_before_reply() -> Result<(), ZmqError> {
println!("Starting test_req_rep_req_disconnects_before_reply...");
let ctx = common::test_context();
let rep = ctx.socket(SocketType::Rep)?;
let endpoint = "tcp://127.0.0.1:5604"; println!("Binding REP to {}...", endpoint);
rep.bind(endpoint).await?;
tokio::time::sleep(Duration::from_millis(50)).await;
{
let req = ctx.socket(SocketType::Req)?;
println!("Connecting REQ to {}...", endpoint);
req.connect(endpoint).await?;
tokio::time::sleep(Duration::from_millis(100)).await;
println!("REQ sending Request...");
req.send(Msg::from_static(b"Request")).await?;
println!("REQ sent Request.");
println!("REP receiving Request...");
let received_req = common::recv_timeout(&rep, LONG_TIMEOUT).await?;
assert_eq!(received_req.data().unwrap(), b"Request");
println!("REP received Request.");
println!("REQ socket going out of scope (will trigger close)...");
req.close().await?;
};
println!("Waiting for REQ close propagation...");
tokio::time::sleep(Duration::from_millis(200)).await;
println!("REP attempting send reply (should fail)...");
let send_result = rep.send(Msg::from_static(b"Reply")).await;
println!("REP send result: {:?}", send_result);
assert!(
matches!(send_result, Err(ZmqError::InvalidState(_))),
"Expected InvalidState error, got {:?}",
send_result
);
println!("REP correctly failed to send reply to disconnected REQ.");
println!("Terminating context...");
ctx.term().await?;
println!("Test test_req_rep_req_disconnects_before_reply finished.");
Ok(())
}