mod common;
use std::time::Duration;
use common::Server;
use weida::{Error, GuaranteeSet, OrderingMode, RuntimeConfig, TransferMeta};
const DEADLINE: Duration = Duration::from_secs(15);
async fn within<F: Future>(f: F) -> F::Output {
tokio::time::timeout(DEADLINE, f)
.await
.expect("operation timed out")
}
#[tokio::test]
async fn both_directions_carry_transfers_concurrently() {
let server = Server::start().await;
let bound = server.listener.pair("/link").expect("bound pair");
let client = server.client_runtime();
let dialling = client.pair(server.trust());
within(dialling.connect(&server.url("/link")))
.await
.expect("connect");
assert_eq!(dialling.peer_count(), 1);
within(dialling.send(b"from the dialler"))
.await
.expect("send");
let inbound = within(bound.recv()).await.expect("recv");
assert_eq!(inbound.meta().endpoint.as_deref(), Some("/link"));
assert_eq!(
within(inbound.collect(1024)).await.expect("collect"),
b"from the dialler"
);
within(bound.send(b"from the bound side"))
.await
.expect("send back");
let answer = within(dialling.recv()).await.expect("recv");
assert_eq!(
within(answer.collect(1024)).await.expect("collect"),
b"from the bound side"
);
let up = within(dialling.open(TransferMeta::default()))
.await
.expect("open up");
let down = within(bound.open(TransferMeta::default()))
.await
.expect("open down");
let (mut up, mut down) = (up, down);
within(up.write_all(b"up")).await.expect("write up");
within(down.write_all(b"down")).await.expect("write down");
up.finish().expect("finish up");
down.finish().expect("finish down");
assert_eq!(
within(within(bound.recv()).await.expect("recv up").collect(64))
.await
.expect("collect"),
b"up"
);
assert_eq!(
within(
within(dialling.recv())
.await
.expect("recv down")
.collect(64)
)
.await
.expect("collect"),
b"down"
);
client.shutdown().await;
}
#[tokio::test]
async fn a_second_connection_is_refused_and_the_first_keeps_working() {
let server = Server::start().await;
let bound = server.listener.pair("/link").expect("bound pair");
let first_client = server.client_runtime();
let first = first_client.pair(server.trust());
within(first.connect(&server.url("/link")))
.await
.expect("connect");
within(first.send(b"mine")).await.expect("send");
assert_eq!(
within(within(bound.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"mine"
);
let second_client = server.client_runtime();
let second = second_client.pair(server.trust());
within(second.connect(&server.url("/link")))
.await
.expect("connect: the refusal is per stream, not per connection");
let mut transfer = within(second.open(TransferMeta::default()))
.await
.expect("open");
let past_the_window = vec![0x7au8; 2 * 1024 * 1024];
let refused = match within(transfer.write_all(&past_the_window)).await {
Err(e) => e,
Ok(()) => match transfer.finish() {
Ok(delivery) => within(delivery.delivered())
.await
.expect_err("the newcomer is refused"),
Err(e) => e,
},
};
assert!(
matches!(refused, Error::LimitExceeded),
"expected LIMIT_EXCEEDED, got {refused:?}"
);
within(first.send(b"still mine")).await.expect("send");
assert_eq!(
within(within(bound.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"still mine"
);
within(bound.send(b"and back")).await.expect("send back");
assert_eq!(
within(within(first.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"and back"
);
first_client.shutdown().await;
second_client.shutdown().await;
}
#[tokio::test]
async fn a_peer_that_goes_away_leaves_the_endpoint_claimable() {
let server = Server::start().await;
let bound = server.listener.pair("/link").expect("bound pair");
let first_client = server.client_runtime();
let first = first_client.pair(server.trust());
within(first.connect(&server.url("/link")))
.await
.expect("connect");
within(first.send(b"before")).await.expect("send");
assert_eq!(
within(within(bound.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"before"
);
first_client.shutdown().await;
let second_client = server.client_runtime();
let second = second_client.pair(server.trust());
within(second.connect(&server.url("/link")))
.await
.expect("connect");
let arrived = within(async {
loop {
second.send(b"after").await.expect("send");
if let Ok(transfer) =
tokio::time::timeout(Duration::from_millis(50), bound.recv()).await
{
return transfer.expect("recv");
}
}
})
.await;
assert_eq!(
within(arrived.collect(64)).await.expect("collect"),
b"after"
);
within(bound.send(b"and back")).await.expect("send back");
assert_eq!(
within(within(second.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"and back"
);
second_client.shutdown().await;
}
#[tokio::test]
async fn a_dropped_pair_releases_its_path_on_a_pooled_connection() {
let server = Server::start().await;
let bound = server.listener.pair("/link").expect("bound pair");
let client = server.client_runtime();
let first = client.pair(server.trust());
within(first.connect(&server.url("/link")))
.await
.expect("connect");
drop(first);
let second = client.pair(server.trust());
within(second.connect(&server.url("/link")))
.await
.expect("the path is free again");
within(second.send(b"reused")).await.expect("send");
assert_eq!(
within(within(bound.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"reused"
);
client.shutdown().await;
}
#[tokio::test]
async fn both_halves_of_a_pair_number_their_transfers() {
let ordered = RuntimeConfig {
guarantees: GuaranteeSet {
ordering: OrderingMode::PerProducerDetect,
..GuaranteeSet::CORE
},
..RuntimeConfig::default()
};
let server = Server::start_with_config(ordered.clone()).await;
let bound = server.listener.pair("/link").expect("bound pair");
let client = server.client_runtime_with_config(ordered);
let dialling = client.pair(server.trust());
within(dialling.connect(&server.url("/link")))
.await
.expect("connect");
within(dialling.send(b"up")).await.expect("send up");
let inbound = within(bound.recv()).await.expect("recv");
assert_eq!(
inbound.meta().sequence,
Some(0),
"the dialling half numbers its transfers"
);
within(bound.send(b"down")).await.expect("send down");
let answer = within(dialling.recv()).await.expect("recv");
assert_eq!(
answer.meta().sequence,
Some(0),
"and so does the bound half: one link, one ordering behaviour"
);
client.shutdown().await;
}
#[tokio::test]
async fn a_pair_talks_to_a_bare_peer_and_acceptor_on_the_same_path() {
let server = Server::start().await;
let acceptor = server.listener.acceptor("/link").expect("acceptor");
let client = server.client_runtime();
let dialling = client.pair(server.trust());
within(dialling.connect(&server.url("/link")))
.await
.expect("connect");
within(dialling.send(b"pair to acceptor"))
.await
.expect("send");
match within(acceptor.accept()).await.expect("accept") {
weida::Incoming::Stream(transfer) => {
assert_eq!(transfer.meta().endpoint.as_deref(), Some("/link"));
assert_eq!(
within(transfer.collect(1024)).await.expect("collect"),
b"pair to acceptor"
);
}
other => panic!("a paired send is a one-way transfer, got {other:?}"),
}
let bound_server = Server::start().await;
let bound = bound_server.listener.pair("/link").expect("bound pair");
let bare_client = bound_server.client_runtime();
let peer = bare_client.peer(bound_server.trust());
within(peer.connect(&bound_server.url("/link")))
.await
.expect("connect");
let mut raw = within(peer.open(TransferMeta::default()))
.await
.expect("open");
within(raw.write_all(b"peer to pair")).await.expect("write");
raw.finish().expect("finish");
assert_eq!(
within(within(bound.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"peer to pair"
);
client.shutdown().await;
bare_client.shutdown().await;
}
#[tokio::test]
async fn a_canceled_transfer_is_never_seen_as_complete() {
let server = Server::start().await;
let bound = server.listener.pair("/link").expect("bound pair");
let client = server.client_runtime();
let dialling = client.pair(server.trust());
within(dialling.connect(&server.url("/link")))
.await
.expect("connect");
let mut transfer = within(dialling.open(TransferMeta::default()))
.await
.expect("open");
within(transfer.write_all(b"half a message"))
.await
.expect("write");
let mut inbound = within(bound.recv()).await.expect("recv");
transfer.cancel();
let err = within(inbound.read_capped(1024))
.await
.expect_err("an interrupted transfer is never complete");
assert!(
matches!(err, Error::Canceled),
"expected Canceled, got {err:?}"
);
within(dialling.send(b"the next one")).await.expect("send");
assert_eq!(
within(within(bound.recv()).await.expect("recv").collect(64))
.await
.expect("collect"),
b"the next one"
);
client.shutdown().await;
}