use std::time::Duration;
use zenoh::Wait;
use zenoh::qos::CongestionControl;
use zenoh_ext::{
AdvancedPublisherBuilderExt, AdvancedSubscriberBuilderExt, CacheConfig, HistoryConfig,
MissDetectionConfig,
};
fn config(listen: &[&str], connect: &[&str]) -> zenoh::Config {
let mut c = zenoh::Config::default();
c.insert_json5("scouting/multicast/enabled", "false")
.unwrap();
let as_json = |eps: &[&str]| {
format!(
"[{}]",
eps.iter()
.map(|s| format!("\"{s}\""))
.collect::<Vec<_>>()
.join(",")
)
};
if !listen.is_empty() {
c.insert_json5("listen/endpoints", &as_json(listen))
.unwrap();
c.insert_json5("listen/exit_on_failure", "false").unwrap();
}
if !connect.is_empty() {
c.insert_json5("connect/endpoints", &as_json(connect))
.unwrap();
}
c
}
#[test]
fn advanced_pub_cache_serves_late_joining_subscriber() {
let port = std::net::TcpListener::bind("127.0.0.1:0")
.unwrap()
.local_addr()
.unwrap()
.port();
let endpoint = format!("tcp/127.0.0.1:{port}");
let key = "dora/test/schema-cache/output/@schema";
let schema = b"PRETEND-IPC-SCHEMA-MESSAGE";
let pub_session = zenoh::open(config(&[endpoint.as_str()], &[]))
.wait()
.unwrap();
let publisher = pub_session
.declare_publisher(key)
.congestion_control(CongestionControl::Block)
.sample_miss_detection(MissDetectionConfig::default())
.cache(CacheConfig::default())
.publisher_detection()
.wait()
.unwrap();
publisher.put(schema.as_slice()).wait().unwrap();
std::thread::sleep(Duration::from_millis(300));
let (tx, rx) = std::sync::mpsc::channel();
let sub_session = zenoh::open(config(&[], &[endpoint.as_str()]))
.wait()
.unwrap();
let _subscriber = sub_session
.declare_subscriber(key)
.history(HistoryConfig::default().detect_late_publishers())
.callback(move |sample| {
let _ = tx.send(sample.payload().to_bytes().to_vec());
})
.wait()
.unwrap();
let got = rx
.recv_timeout(Duration::from_secs(10))
.expect("late-joining subscriber must receive the cached schema");
assert_eq!(
got,
schema.as_slice(),
"cached schema bytes must round-trip to the late joiner"
);
}