use super::*;
const NAMED_SETUP_DEADLINE: Duration = Duration::from_secs(5);
const SLOW_BUT_ANSWERED: Duration = Duration::from_millis(250);
fn spawn_setup_server(reply_delay: Duration) -> Result<ScriptedServer, SdkError> {
ScriptedServer::spawn(move |mut socket| {
let mut buffer = Vec::new();
read_and_discard_one(&mut socket, &mut buffer)?;
std::thread::sleep(reply_delay);
write_frame(
&mut socket,
&Frame::ConnectAck {
flags: 0,
selected_version: CLIENT_MAX_VERSION,
capabilities: 0,
},
)?;
read_and_discard_one(&mut socket, &mut buffer)?;
std::thread::sleep(reply_delay);
write_frame(
&mut socket,
&Frame::SubscribeAck {
flags: 0,
stream_id: SUBSCRIPTION_STREAM_ID,
subscription_id: 42,
selected_schema: SchemaId::new([7; SchemaId::WIRE_LEN]),
},
)?;
wait_for_client_close(&mut socket)
})
}
#[test]
fn the_subscription_reader_carries_no_read_window_in_steady_state() -> Result<(), SdkError> {
let server = spawn_setup_server(Duration::ZERO)?;
server.run(|address| {
let subscription = SubscriptionStream::open(address, "orders", Vec::new())?;
let observed =
subscription
.writer
.read_timeout()
.map_err(|source| SdkError::Connection {
description: format!(
"failed to read the subscription socket read timeout: {source}"
),
})?;
assert_eq!(
observed, None,
"the subscription reader must block with no read window once the control \
exchange is over; a Some(_) here is a cadence, whatever its period"
);
drop(subscription);
Ok(())
})
}
#[test]
fn open_survives_control_replies_slower_than_the_retired_poll_cadence() -> Result<(), SdkError> {
let server = spawn_setup_server(SLOW_BUT_ANSWERED)?;
server.run(|address| {
let subscription = SubscriptionStream::open(address, "orders", Vec::new())?;
assert_eq!(subscription.subscription_id(), 42);
assert!(
NAMED_SETUP_DEADLINE > SLOW_BUT_ANSWERED,
"the fixture's slow reply must sit inside the named deadline"
);
drop(subscription);
Ok(())
})
}
#[test]
fn subscription_source_has_no_retired_reader_poll_family() {
const SOURCES: [&str; 5] = [
include_str!("subscription.rs"),
include_str!("subscription/subscription_reader.rs"),
include_str!("subscription/subscription_setup.rs"),
include_str!("subscription/subscription_signals.rs"),
include_str!("subscription/subscription_wire.rs"),
];
for source in SOURCES {
let production = source.split("#[cfg(test)]").next().unwrap_or(source);
for forbidden in [
"READER_POLL_TIMEOUT",
"AtomicBool",
"stop.load",
"stop.store",
"re-check the stop flag",
"poll the stop flag",
] {
assert!(
!production.contains(forbidden),
"retired subscription-reader poll-family source `{forbidden}` reappeared"
);
}
}
}
const DELIVERED: DeliveredId = DeliveredId {
boot: 1_791_328_512_345,
id: 42,
};
#[test]
fn a_delivered_message_names_its_reply_parent_only_when_it_carries_an_id() {
let with_id = DeliveredMessage {
delivery_seq: 1,
schema_id: SchemaId::new([1; SchemaId::WIRE_LEN]),
payload: Vec::new(),
message: Some(DELIVERED),
};
assert_eq!(with_id.message(), Some(DELIVERED));
assert_eq!(
with_id.reply_parent(),
Some(MessageId::from("1791328512345:42"))
);
let without = DeliveredMessage {
message: None,
..with_id
};
assert_eq!(without.message(), None);
assert_eq!(without.reply_parent(), None);
}
#[test]
fn the_subscription_offers_the_delivered_id_version() {
assert_eq!(CLIENT_MAX_VERSION, DELIVER_MESSAGE_ID_VERSION);
}
#[test]
fn the_reader_keeps_the_delivered_id() -> Result<(), SdkError> {
let server = ScriptedServer::spawn(move |mut socket| {
let mut buffer = Vec::new();
read_and_discard_one(&mut socket, &mut buffer)?;
write_frame(
&mut socket,
&Frame::ConnectAck {
flags: 0,
selected_version: DELIVER_MESSAGE_ID_VERSION,
capabilities: 0,
},
)?;
read_and_discard_one(&mut socket, &mut buffer)?;
let schema = SchemaId::new([7; SchemaId::WIRE_LEN]);
write_frame(
&mut socket,
&Frame::SubscribeAck {
flags: 0,
stream_id: SUBSCRIPTION_STREAM_ID,
subscription_id: 42,
selected_schema: schema,
},
)?;
write_frame(
&mut socket,
&Frame::Deliver {
flags: 0,
stream_id: SUBSCRIPTION_STREAM_ID,
delivery_seq: 1,
envelope: MessageEnvelope::new(schema, CausalContext::independent(), vec![1]),
message: Some(DELIVERED),
},
)?;
wait_for_client_close(&mut socket)
})?;
server.run(|address| {
let subscription = SubscriptionStream::open(address, "orders", Vec::new())?;
let delivered = subscription.recv_timeout(Duration::from_secs(2))?;
assert_eq!(delivered.message(), Some(DELIVERED));
drop(subscription);
Ok(())
})
}