mod harness;
use std::future::Future;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use alksocks::consumer::{AssociateSession, BindSession, Socks5ChannelSession};
use alksocks::egress::{Egress, EgressError, EgressFactory};
use alksocks::error::SocksSessionError;
use alksocks::params::Socks5Params;
use alksocks::rfc1928::consts;
use alksocks::rfc1928::util::target_addr::{TargetAddr, ToTargetAddr};
use alksocks::rfc1928::Socks5Command;
use harness::{
bind_identity, both_scopes_identity, consumer_identity, echo_accept, echo_dial, echo_egress,
wire_consumer_side_with, wire_with, ConsumerSideTopology, RawRfcClient, RegisterMode, Topology,
ECHO_BIND_PORT,
};
const TIMEOUT_SECS: u64 = 10;
type RawPump = tokio::task::JoinHandle<(u64, u64)>;
type RawClient = RawRfcClient<tokio::io::DuplexStream>;
type RoundTrip<'a> = std::pin::Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'a>>;
async fn within<T>(fut: impl Future<Output = T>) -> T {
tokio::time::timeout(std::time::Duration::from_secs(TIMEOUT_SECS), fut)
.await
.expect("operation timed out")
}
async fn full_raw_topology() -> Topology {
wire_with(
RegisterMode::Producer {
dial: echo_dial(),
egress: Some(echo_egress()),
accept: Some(echo_accept()),
},
Some(both_scopes_identity()),
None,
Arc::new(alkcall::core::auth::NoopIdentityProvider),
)
.await
}
async fn open_adopt_pump(topo: &Topology) -> (RawClient, RawPump) {
let response = topo
.consumer_call
.call(alksocks::OP_SOCKS5_OPEN, Socks5Params::as_json())
.await;
let out = response.result.expect("the socks5 channel opens");
let channel_id = out
.get("channel_id")
.and_then(|v| v.as_u64())
.expect("the reply carries channel_id") as u32;
let (send, recv) = topo
.consumer_manager
.adopt_channel(channel_id, alksocks::SOCKS5_ALPN, None)
.await
.expect("adopt the producer-allocated id");
let (stream_peer, stream_self) = tokio::io::duplex(64 * 1024);
let pump = tokio::spawn(alkcall::channels::pump::pump_bidi(
stream_self,
Box::new(recv) as Box<dyn AsyncRead + Send + Unpin>,
Box::new(send) as Box<dyn AsyncWrite + Send + Unpin>,
));
(RawRfcClient::new(stream_peer), pump)
}
async fn raw_associate(topo: &Topology) -> (RawClient, RawPump) {
let (mut raw, pump) = open_adopt_pump(topo).await;
raw.greet().await.expect("greet");
raw.request(
Socks5Command::UDPAssociate,
&TargetAddr::Domain("relay.test".into(), 1080),
)
.await
.expect("request written");
let (code, addr) = raw.read_reply().await.expect("reply read");
assert_eq!(code, consts::SOCKS5_REPLY_SUCCEEDED, "the associate reply");
assert_eq!(
(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]),
(127, 0, 0, 1, 0, 0),
"the reply carries the sentinel BND.ADDR"
);
(raw, pump)
}
async fn raw_bind(topo: &Topology, host: &str) -> (RawClient, RawPump) {
let (mut raw, pump) = open_adopt_pump(topo).await;
raw.greet().await.expect("greet");
raw.request(
Socks5Command::TCPBind,
&TargetAddr::Domain(host.into(), ECHO_BIND_PORT),
)
.await
.expect("request written");
let (code1, addr1) = raw.read_reply().await.expect("reply#1");
assert_eq!(code1, consts::SOCKS5_REPLY_SUCCEEDED, "reply#1 success");
assert_eq!(
u16::from_be_bytes([addr1[addr1.len() - 2], addr1[addr1.len() - 1]]),
ECHO_BIND_PORT,
"reply#1 carries the factory's advertised port"
);
let (code2, addr2) = raw.read_reply().await.expect("reply#2");
assert_eq!(code2, consts::SOCKS5_REPLY_SUCCEEDED, "reply#2 success");
let peer_port = u16::from_be_bytes([addr2[addr2.len() - 2], addr2[addr2.len() - 1]]);
assert_eq!(peer_port, 44444, "reply#2 carries the accepted peer");
(raw, pump)
}
async fn connect_round_trip(topo: &Topology, host: String, tag: String) -> Result<(), String> {
let (mut raw, _pump) = open_adopt_pump(topo).await;
let code = raw
.connect(&TargetAddr::Domain(host, 443))
.await
.map_err(|e| e.to_string())?;
if code != consts::SOCKS5_REPLY_SUCCEEDED {
return Err(format!("reply code {code}"));
}
raw.stream
.write_all(tag.as_bytes())
.await
.map_err(|e| e.to_string())?;
let mut buf = vec![0u8; tag.len()];
raw.stream
.read_exact(&mut buf)
.await
.map_err(|e| e.to_string())?;
if buf != tag.as_bytes() {
return Err("echo mismatch".into());
}
Ok(())
}
async fn associate_round_trip(
topo: &Topology,
octet: u8,
tag: &'static [u8],
) -> Result<(), String> {
let (mut raw, _pump) = raw_associate(topo).await;
let target = TargetAddr::Ip(SocketAddr::from(([10, 0, 0, octet], 53)));
raw.stream
.write_all(&udp_frame(&target, tag))
.await
.map_err(|e| e.to_string())?;
let mut buf = vec![0u8; 2 + 7 + tag.len()];
raw.stream
.read_exact(&mut buf)
.await
.map_err(|e| e.to_string())?;
let (src, payload) = udp_unframe(&buf);
if src != target {
return Err("echo source mismatch".into());
}
if &payload[..] != tag {
return Err("echo payload mismatch".into());
}
Ok(())
}
async fn bind_round_trip(
topo: &Topology,
host: impl ToString,
tag: &'static [u8],
) -> Result<(), String> {
let (mut raw, _pump) = raw_bind(topo, &host.to_string()).await;
raw.stream.write_all(tag).await.map_err(|e| e.to_string())?;
let mut buf = vec![0u8; tag.len()];
raw.stream
.read_exact(&mut buf)
.await
.map_err(|e| e.to_string())?;
if buf != tag {
return Err("echo mismatch".into());
}
Ok(())
}
fn tcp_fut<'a>(topo: &'a Topology, host: String, tag: String) -> RoundTrip<'a> {
Box::pin(connect_round_trip(topo, host, tag))
}
fn udp_fut<'a>(topo: &'a Topology, octet: u8, tag: &'static [u8]) -> RoundTrip<'a> {
Box::pin(associate_round_trip(topo, octet, tag))
}
fn bind_fut<'a>(topo: &'a Topology, host: String, tag: &'static [u8]) -> RoundTrip<'a> {
Box::pin(bind_round_trip(topo, host, tag))
}
use harness::{parked_accept_factory as parked_accept, udp_frame, udp_unframe};
struct HotNoneEgress {
echo: tokio::sync::mpsc::UnboundedSender<bytes::Bytes>,
replies: tokio::sync::Mutex<tokio::sync::mpsc::UnboundedReceiver<bytes::Bytes>>,
}
impl Egress for HotNoneEgress {
fn send(
&mut self,
addr: TargetAddr,
payload: bytes::Bytes,
) -> futures::future::BoxFuture<'_, Result<(), EgressError>> {
Box::pin(async move {
let mut inner = addr
.to_be_bytes()
.map_err(|e| EgressError::General(format!("addr encode: {e}")))?;
inner.extend_from_slice(&payload);
self.echo
.send(bytes::Bytes::from(inner))
.map_err(|_| EgressError::General("egress closed".into()))
})
}
fn next_reply(
&mut self,
) -> futures::future::BoxFuture<'_, Result<Option<bytes::Bytes>, EgressError>> {
Box::pin(async move {
match self.replies.lock().await.try_recv() {
Ok(inner) => Ok(Some(inner)),
Err(_) => Ok(None),
}
})
}
}
fn hot_none_egress() -> EgressFactory {
Arc::new(|| {
Box::pin(async {
let (echo, replies) = tokio::sync::mpsc::unbounded_channel();
Ok(Box::new(HotNoneEgress {
echo,
replies: tokio::sync::Mutex::new(replies),
}) as Box<dyn Egress + Send>)
})
})
}
async fn no_leaked_channels(topo: &ConsumerSideTopology) {
let deadline = std::time::Duration::from_secs(5);
let consumer_ids = topo.consumer.manager().channel_ids();
assert!(
consumer_ids.iter().all(|&id| id == 0),
"consumer leaked channel entries: {consumer_ids:?}"
);
tokio::time::timeout(deadline, async {
loop {
let producer_ids = topo.producer_manager.channel_ids();
if producer_ids.iter().all(|&id| id == 0) {
return;
}
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
}
})
.await
.expect("the producer's handler-exit teardown reaps the entry");
}
fn expect_forbidden(err: &SocksSessionError) -> bool {
match err {
SocksSessionError::Open(open) => match open.open_ref() {
alkcall::channels::client::ChannelOpenError::CallFailed { error } => {
error.code == "FORBIDDEN"
}
_ => false,
},
_ => false,
}
}
async fn consumer_connect_round_trip(
topo: &ConsumerSideTopology,
host: String,
tag: String,
) -> Result<(), String> {
let mut session = Socks5ChannelSession::connect(
topo.consumer.as_ref(),
(host.as_str(), 443u16).to_target_addr().unwrap(),
)
.await
.map_err(|e| format!("connect: {e}"))?;
session
.split()
.expect("pipe")
.1
.write_all(tag.as_bytes())
.await
.map_err(|e| e.to_string())?;
let (mut read, _) = session.split().expect("pipe");
let mut buf = vec![0u8; tag.len()];
read.read_exact(&mut buf).await.map_err(|e| e.to_string())?;
if buf != tag.as_bytes() {
return Err("echo mismatch".into());
}
session.close().await;
Ok(())
}
async fn consumer_associate_round_trip(
topo: &ConsumerSideTopology,
octet: u8,
tag: &'static [u8],
) -> Result<(), String> {
let mut assoc = AssociateSession::associate(topo.consumer.as_ref())
.await
.map_err(|e| format!("associate: {e}"))?;
let target = TargetAddr::Ip(SocketAddr::from(([10, 0, 1, octet], 53)));
assoc
.send_datagram(&target, tag)
.await
.map_err(|e| format!("send: {e}"))?;
let (src, payload) = within(assoc.recv_datagram())
.await
.map_err(|e| format!("recv: {e}"))?
.expect("a datagram (not eof)");
if src != target {
return Err("echo source mismatch".into());
}
if &payload[..] != tag {
return Err("echo payload mismatch".into());
}
assoc.close().await;
Ok(())
}
fn consumer_tcp_fut<'a>(
topo: &'a ConsumerSideTopology,
host: String,
tag: String,
) -> RoundTrip<'a> {
Box::pin(consumer_connect_round_trip(topo, host, tag))
}
fn consumer_udp_fut<'a>(
topo: &'a ConsumerSideTopology,
octet: u8,
tag: &'static [u8],
) -> RoundTrip<'a> {
Box::pin(consumer_associate_round_trip(topo, octet, tag))
}
fn consumer_bind_fut<'a>(
topo: &'a ConsumerSideTopology,
host: String,
tag: &'static [u8],
) -> RoundTrip<'a> {
Box::pin(consumer_bind_round_trip(topo, host, tag))
}
async fn consumer_bind_round_trip(
topo: &ConsumerSideTopology,
host: String,
tag: &'static [u8],
) -> Result<(), String> {
let mut session = BindSession::bind(
topo.consumer.as_ref(),
(host.as_str(), ECHO_BIND_PORT).to_target_addr().unwrap(),
)
.await
.map_err(|e| format!("bind: {e}"))?;
let mut plane = session
.await_inbound()
.await
.map_err(|e| format!("reply#2: {e}"))?
.expect("the data plane");
plane.write_all(tag).await.map_err(|e| e.to_string())?;
plane.flush().await.map_err(|e| e.to_string())?;
let mut buf = vec![0u8; tag.len()];
within(plane.read_exact(&mut buf))
.await
.map_err(|e| e.to_string())?;
if buf != tag {
return Err("echo mismatch".into());
}
drop(plane);
session.close().await;
Ok(())
}
#[tokio::test]
async fn one_registration_all_three_commands_interleaved() {
let topo = full_raw_topology().await;
let (mut connect_raw, connect_pump) = open_adopt_pump(&topo).await;
let (mut assoc_raw, assoc_pump) = raw_associate(&topo).await;
let (mut bind_raw, bind_pump) = raw_bind(&topo, "bind.test").await;
connect_raw.greet().await.expect("greet");
connect_raw
.request(
Socks5Command::TCPConnect,
&TargetAddr::Domain("interleaved.test".into(), 443),
)
.await
.expect("request written");
let (code, _addr) = connect_raw.read_reply().await.expect("reply read");
assert_eq!(code, consts::SOCKS5_REPLY_SUCCEEDED);
connect_raw.stream.write_all(b"tcp1").await.expect("write");
let mut buf = [0u8; 4];
connect_raw.stream.read_exact(&mut buf).await.expect("echo");
assert_eq!(&buf, b"tcp1");
let udp_target = TargetAddr::Ip(SocketAddr::from(([10, 0, 0, 1], 53)));
assoc_raw
.stream
.write_all(&udp_frame(&udp_target, b"udp1"))
.await
.expect("datagram");
let mut frame_buf = vec![0u8; 2 + 7 + 4];
assoc_raw
.stream
.read_exact(&mut frame_buf)
.await
.expect("frame");
let (_, payload) = udp_unframe(&frame_buf);
assert_eq!(&payload[..], b"udp1");
bind_raw.stream.write_all(b"bin1").await.expect("write");
bind_raw.stream.read_exact(&mut buf).await.expect("echo");
assert_eq!(&buf, b"bin1");
drop(connect_raw);
within(connect_pump).await.expect("the CONNECT pump ends");
assoc_raw
.stream
.write_all(&udp_frame(&udp_target, b"still"))
.await
.expect("datagram");
let mut frame_buf = vec![0u8; 2 + 7 + 5];
assoc_raw
.stream
.read_exact(&mut frame_buf)
.await
.expect("frame");
let (_, payload) = udp_unframe(&frame_buf);
assert_eq!(&payload[..], b"still");
bind_raw.stream.write_all(b"alive").await.expect("write");
let mut buf = [0u8; 5];
bind_raw.stream.read_exact(&mut buf).await.expect("echo");
assert_eq!(&buf, b"alive");
drop(assoc_raw);
drop(bind_raw);
within(assoc_pump).await.expect("associate pump");
within(bind_pump).await.expect("bind pump");
}
#[tokio::test]
async fn concurrent_mixed_sessions_over_one_connection() {
let topo = full_raw_topology().await;
const UDP_TAGS: [&[u8]; 3] = [b"udp-zero0", b"udp-one!1", b"udp-two!2"];
const BIND_TAGS: [&[u8]; 3] = [b"bind-z0", b"bind-o1", b"bind-t2"];
let mut futs: Vec<RoundTrip> = Vec::new();
for i in 0..3usize {
futs.push(tcp_fut(&topo, format!("c{i}.test"), format!("tcp{i}")));
futs.push(udp_fut(&topo, 10 + i as u8, UDP_TAGS[i]));
futs.push(bind_fut(&topo, format!("b{i}.test"), BIND_TAGS[i]));
}
let results = futures::future::join_all(futs).await;
for (i, result) in results.into_iter().enumerate() {
result.unwrap_or_else(|e| panic!("concurrent session {i} failed: {e}"));
}
connect_round_trip(&topo, "after.test".into(), "again".into())
.await
.expect("fresh connect after the load");
associate_round_trip(&topo, 20, b"again")
.await
.expect("fresh associate after the load");
bind_round_trip(&topo, "after.test", b"again")
.await
.expect("fresh bind after the load");
}
#[tokio::test]
async fn concurrent_consumer_sessions_over_one_connection() {
let topo = wire_consumer_side_with(
echo_dial(),
Some(echo_egress()),
Some(echo_accept()),
Some(both_scopes_identity()),
)
.await;
const UDP_TAGS: [&[u8]; 2] = [b"cu-zero00", b"cu-one!!1"];
const BIND_TAGS: [&[u8]; 2] = [b"cb-zero", b"cb-one!"];
let mut futs: Vec<RoundTrip> = Vec::new();
for i in 0..2usize {
futs.push(consumer_tcp_fut(
&topo,
format!("cc{i}.test"),
format!("t{i}"),
));
futs.push(consumer_udp_fut(&topo, 30 + i as u8, UDP_TAGS[i]));
futs.push(consumer_bind_fut(
&topo,
format!("cb{i}.test"),
BIND_TAGS[i],
));
}
let results = futures::future::join_all(futs).await;
for (i, result) in results.into_iter().enumerate() {
result.unwrap_or_else(|e| panic!("consumer session {i} failed: {e}"));
}
no_leaked_channels(&topo).await;
}
#[tokio::test]
async fn teardown_connect_half_close_then_every_command_serves_fresh() {
let topo = full_raw_topology().await;
let (mut raw, pump) = open_adopt_pump(&topo).await;
let code = raw
.connect(&TargetAddr::Domain("drop.test".into(), 443))
.await
.expect("connect");
assert_eq!(code, consts::SOCKS5_REPLY_SUCCEEDED);
raw.stream.write_all(b"pre").await.expect("write");
let mut buf = [0u8; 3];
raw.stream.read_exact(&mut buf).await.expect("echo");
assert_eq!(&buf, b"pre");
drop(raw);
within(pump)
.await
.expect("the pump ends on the client half-close");
let (mut raw, _pump) = open_adopt_pump(&topo).await;
let code = raw
.connect(&TargetAddr::Domain("fresh.test".into(), 443))
.await
.expect("fresh connect");
assert_eq!(code, consts::SOCKS5_REPLY_SUCCEEDED);
raw.stream.write_all(b"again").await.expect("write");
let mut buf = [0u8; 5];
raw.stream.read_exact(&mut buf).await.expect("echo");
assert_eq!(&buf, b"again");
let (mut assoc, _pump) = raw_associate(&topo).await;
let target = TargetAddr::Ip(SocketAddr::from(([10, 0, 0, 2], 53)));
assoc
.stream
.write_all(&udp_frame(&target, b"fresh"))
.await
.expect("datagram");
let mut frame_buf = vec![0u8; 2 + 7 + 5];
assoc
.stream
.read_exact(&mut frame_buf)
.await
.expect("frame");
let (_, payload) = udp_unframe(&frame_buf);
assert_eq!(&payload[..], b"fresh");
bind_round_trip(&topo, "fresh.test", b"fresh")
.await
.expect("fresh bind");
}
#[tokio::test]
async fn teardown_associate_eof_then_every_command_serves_fresh() {
let topo = full_raw_topology().await;
let (mut assoc, pump) = raw_associate(&topo).await;
let target = TargetAddr::Ip(SocketAddr::from(([10, 0, 0, 3], 53)));
assoc
.stream
.write_all(&udp_frame(&target, b"pre"))
.await
.expect("datagram");
let mut frame_buf = vec![0u8; 2 + 7 + 3];
assoc
.stream
.read_exact(&mut frame_buf)
.await
.expect("frame");
let (_, payload) = udp_unframe(&frame_buf);
assert_eq!(&payload[..], b"pre");
drop(assoc);
within(pump).await.expect("the stage ends on channel EOF");
let (mut assoc, _pump) = raw_associate(&topo).await;
assoc
.stream
.write_all(&udp_frame(&target, b"fresh"))
.await
.expect("datagram");
let mut frame_buf = vec![0u8; 2 + 7 + 5];
assoc
.stream
.read_exact(&mut frame_buf)
.await
.expect("frame");
let (_, payload) = udp_unframe(&frame_buf);
assert_eq!(&payload[..], b"fresh");
connect_round_trip(&topo, "fresh.test".into(), "again".into())
.await
.expect("fresh connect");
bind_round_trip(&topo, "fresh.test", b"fresh")
.await
.expect("fresh bind");
}
#[tokio::test]
async fn teardown_bind_client_gone_releases_the_accept_then_serves_fresh() {
let topo = wire_with(
RegisterMode::Producer {
dial: echo_dial(),
egress: Some(echo_egress()),
accept: Some(parked_accept()),
},
Some(both_scopes_identity()),
None,
Arc::new(alkcall::core::auth::NoopIdentityProvider),
)
.await;
let (mut raw, pump) = open_adopt_pump(&topo).await;
raw.greet().await.expect("greet");
raw.request(
Socks5Command::TCPBind,
&TargetAddr::Domain("gone.test".into(), ECHO_BIND_PORT),
)
.await
.expect("request written");
let (code1, _addr) = raw.read_reply().await.expect("reply#1");
assert_eq!(code1, consts::SOCKS5_REPLY_SUCCEEDED);
drop(raw);
within(pump)
.await
.expect("the session ends on the client-gone teardown");
let (mut raw, pump) = open_adopt_pump(&topo).await;
raw.greet().await.expect("greet");
raw.request(
Socks5Command::TCPBind,
&TargetAddr::Domain("fresh.test".into(), ECHO_BIND_PORT),
)
.await
.expect("request written");
let (code1, _addr) = raw.read_reply().await.expect("reply#1");
assert_eq!(code1, consts::SOCKS5_REPLY_SUCCEEDED);
drop(raw);
within(pump)
.await
.expect("the fresh BIND session ends cleanly");
connect_round_trip(&topo, "fresh.test".into(), "again".into())
.await
.expect("fresh connect after the bind teardown");
}
#[tokio::test]
async fn identity_matrix_open_only_connect_associate_serve_bind_refused_0x02() {
let topo = wire_with(
RegisterMode::Producer {
dial: echo_dial(),
egress: Some(echo_egress()),
accept: Some(echo_accept()),
},
Some(consumer_identity()),
None,
Arc::new(alkcall::core::auth::NoopIdentityProvider),
)
.await;
connect_round_trip(&topo, "open.test".into(), "tcp".into())
.await
.expect("CONNECT serves the open-only identity");
associate_round_trip(&topo, 40, b"udp")
.await
.expect("ASSOCIATE serves the open-only identity");
let (mut raw, pump) = open_adopt_pump(&topo).await;
raw.greet().await.expect("greet");
raw.request(
Socks5Command::TCPBind,
&TargetAddr::Domain("gate.test".into(), ECHO_BIND_PORT),
)
.await
.expect("request written");
let (code, _addr) = raw.read_reply().await.expect("reply read");
assert_eq!(
code,
consts::SOCKS5_REPLY_CONNECTION_NOT_ALLOWED,
"the command gate's 0x02"
);
drop(raw);
within(pump).await.expect("the gated session ends");
connect_round_trip(&topo, "still.test".into(), "again".into())
.await
.expect("CONNECT still serves after the BIND refusal");
assert_eq!(
topo.identity_witness.lock().await.as_deref(),
Some("consumer")
);
}
#[tokio::test]
async fn identity_matrix_bind_only_fails_closed_at_the_open_gate() {
let topo = wire_with(
RegisterMode::Producer {
dial: echo_dial(),
egress: Some(echo_egress()),
accept: Some(echo_accept()),
},
Some(bind_identity()),
None,
Arc::new(alkcall::core::auth::NoopIdentityProvider),
)
.await;
let response = topo
.consumer_call
.call(alksocks::OP_SOCKS5_OPEN, Socks5Params::as_json())
.await;
let err = response
.result
.expect_err("a bind-only identity fails closed");
assert_eq!(err.code, "FORBIDDEN");
assert!(topo
.consumer_manager
.channel_ids()
.into_iter()
.all(|id| id == 0));
assert!(topo
.producer
.manager()
.channel_ids()
.into_iter()
.all(|id| id == 0));
assert!(
topo.identity_witness.lock().await.is_none(),
"the establisher never ran; fail-closed"
);
let ctopo = wire_consumer_side_with(
echo_dial(),
None,
Some(echo_accept()),
Some(bind_identity()),
)
.await;
let err = BindSession::bind(
ctopo.consumer.as_ref(),
("bind.test", ECHO_BIND_PORT).to_target_addr().unwrap(),
)
.await
.expect_err("a bind-only identity fails closed");
assert!(
expect_forbidden(&err),
"FORBIDDEN is the open error: {err:?}"
);
no_leaked_channels(&ctopo).await;
}
#[tokio::test]
async fn identity_matrix_both_scopes_serve_every_command() {
let topo = full_raw_topology().await;
connect_round_trip(&topo, "both.test".into(), "tcp".into())
.await
.expect("CONNECT serves the both-scopes identity");
associate_round_trip(&topo, 50, b"udp")
.await
.expect("ASSOCIATE serves the both-scopes identity");
bind_round_trip(&topo, "both.test", b"bind")
.await
.expect("BIND serves the both-scopes identity");
assert_eq!(
topo.identity_witness.lock().await.as_deref(),
Some("consumer-both")
);
}
#[tokio::test]
async fn readiness_contract_holds_under_concurrent_load() {
let topo = wire_with(
RegisterMode::Producer {
dial: echo_dial(),
egress: Some(hot_none_egress()),
accept: None,
},
Some(both_scopes_identity()),
None,
Arc::new(alkcall::core::auth::NoopIdentityProvider),
)
.await;
const UDP_TAGS: [&[u8]; 2] = [b"hot-zero0", b"hot-one!!"];
let mut futs: Vec<RoundTrip> = UDP_TAGS
.into_iter()
.enumerate()
.map(|(i, tag)| udp_fut(&topo, 40 + i as u8, tag))
.collect();
futs.push(tcp_fut(&topo, "hot.test".into(), "tcp".into()));
let results = futures::future::join_all(futs).await;
for (i, result) in results.into_iter().enumerate() {
result.unwrap_or_else(|e| panic!("the stage starved under load (session {i}): {e}"));
}
associate_round_trip(&topo, 50, b"again")
.await
.expect("fresh associate after the hot-egress load");
}
#[tokio::test]
async fn producer_builder_registers_and_serves_all_three_commands() {
let topo = wire_with(
RegisterMode::ProducerBuilder {
dial: echo_dial(),
egress: Some(echo_egress()),
accept: Some(echo_accept()),
bind_policy: None,
},
Some(both_scopes_identity()),
None,
Arc::new(alkcall::core::auth::NoopIdentityProvider),
)
.await;
connect_round_trip(&topo, "builder.test".into(), "tcp".into())
.await
.expect("CONNECT serves through the builder registration");
associate_round_trip(&topo, 60, b"udp")
.await
.expect("ASSOCIATE serves through the builder registration");
bind_round_trip(&topo, "builder.test", b"bind")
.await
.expect("BIND serves through the builder registration");
assert_eq!(
topo.identity_witness.lock().await.as_deref(),
Some("consumer-both")
);
}