use motorcortex_rust::blocking::{Request, Subscribe};
use motorcortex_rust::core::ConnectionState;
use motorcortex_rust::{ConnectionOptions, StatusCode};
use crate::{CERT_PATH, URL_REQ, URL_SUB};
fn opts() -> ConnectionOptions {
ConnectionOptions::new(CERT_PATH.to_string(), 5000, 5000)
}
#[test]
fn test_blocking_request_full_lifecycle() {
let req = Request::connect_to(URL_REQ, opts()).expect("connect_to");
assert_eq!(*req.as_async().state().borrow(), ConnectionState::Connected);
assert!(matches!(
req.login("root", "vectioneer").expect("login"),
StatusCode::Ok | StatusCode::ReadOnlyMode,
));
req.request_parameter_tree().expect("tree");
let status = req
.set_parameter("root/Control/dummyDouble", 8.125_f64)
.expect("set");
assert_eq!(status, StatusCode::Ok);
let value: f64 = req
.get_parameter("root/Control/dummyDouble")
.expect("get");
assert_eq!(value, 8.125);
assert_eq!(req.logout().expect("logout"), StatusCode::Ok);
req.disconnect().expect("disconnect");
}
#[test]
fn test_blocking_subscribe_callback_fires() {
use std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
};
let req = Request::connect_to(URL_REQ, opts()).expect("req connect_to");
req.request_parameter_tree().expect("tree");
let sub = Subscribe::connect_to(URL_SUB, opts()).expect("sub connect_to");
let subscription = sub
.subscribe(
&req,
["root/Control/dummyDouble"],
"blocking-cb",
1000,
)
.expect("subscribe");
let fired = Arc::new(AtomicBool::new(false));
let fired_cb = Arc::clone(&fired);
subscription.notify(move |_s| {
fired_cb.store(true, Ordering::Relaxed);
});
req.set_parameter("root/Control/dummyDouble", 12.5_f64)
.expect("set");
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(3);
while !fired.load(Ordering::Relaxed) {
if std::time::Instant::now() > deadline {
panic!("notify callback did not fire within 3 s");
}
std::thread::sleep(std::time::Duration::from_millis(10));
}
sub.unsubscribe(&req, subscription).expect("unsubscribe");
sub.disconnect().expect("sub disconnect");
req.disconnect().expect("req disconnect");
}
#[test]
fn test_blocking_subscription_iter_sees_newly_set_value() {
let req = Request::connect_to(URL_REQ, opts()).expect("req");
req.request_parameter_tree().expect("tree");
let sub = Subscribe::connect_to(URL_SUB, opts()).expect("sub");
let subscription = sub
.subscribe(
&req,
["root/Control/dummyDouble"],
"blocking-iter",
1000,
)
.expect("subscribe");
let mut iter = subscription.iter::<f64>(256);
req.set_parameter("root/Control/dummyDouble", 55.0_f64)
.expect("set");
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(3);
let mut saw = false;
while std::time::Instant::now() < deadline {
match iter.next() {
Some(Ok((_ts, v))) if (v - 55.0).abs() < 1e-9 => {
saw = true;
break;
}
Some(_) => continue,
None => break,
}
}
assert!(saw, "blocking iter must surface the value we wrote");
sub.unsubscribe(&req, subscription).expect("unsubscribe");
sub.disconnect().expect("sub disconnect");
req.disconnect().expect("req disconnect");
}
#[test]
fn test_blocking_request_batch_and_tree_apis() {
let req = Request::connect_to(URL_REQ, opts()).expect("connect_to");
req.login("root", "vectioneer").expect("login");
req.request_parameter_tree().expect("tree");
let tree = req.parameter_tree();
{
let guard = tree.read().unwrap();
assert!(
guard
.get_parameter_info("root/Control/dummyDouble")
.is_some(),
"tree cache must contain the probe parameter",
);
}
let hash = req.get_parameter_tree_hash().expect("hash");
assert_ne!(hash, 0, "populated server should report a non-zero hash");
let status = req
.set_parameters(
&["root/Control/dummyDouble", "root/Control/dummyInt32"],
(7.5_f64, 42_i32),
)
.expect("set_parameters");
assert_eq!(status, StatusCode::Ok);
let (d, i): (f64, i32) = req
.get_parameters(&["root/Control/dummyDouble", "root/Control/dummyInt32"])
.expect("get_parameters");
assert_eq!(d, 7.5);
assert_eq!(i, 42);
let group = req
.create_group(["root/Control/dummyDouble"], "blocking-grp", 1000)
.expect("create_group");
assert_eq!(group.alias, "blocking-grp");
assert_ne!(group.id, 0);
let remove_status = req.remove_group("blocking-grp").expect("remove_group");
assert_eq!(remove_status, StatusCode::Ok);
req.disconnect().expect("disconnect");
}
#[test]
fn test_blocking_subscription_metadata_and_read_api() {
let req = Request::connect_to(URL_REQ, opts()).expect("req");
req.request_parameter_tree().expect("tree");
let sub = Subscribe::connect_to(URL_SUB, opts()).expect("sub");
let subscription = sub
.subscribe(
&req,
["root/Control/dummyDouble"],
"blocking-meta",
1000,
)
.expect("subscribe");
assert_ne!(subscription.id(), 0, "server should assign a non-zero id");
assert_eq!(subscription.name(), "blocking-meta");
let clone = subscription.clone();
assert_eq!(subscription.id(), clone.id());
req.set_parameter("root/Control/dummyDouble", 3.5_f64)
.expect("set");
let (_ts, v): (_, f64) = subscription.latest().expect("latest");
assert!(v.is_finite());
let (_ts, rv): (_, f64) = subscription.read().expect("read");
assert!(rv.is_finite());
let (_ts, flat): (_, Vec<f64>) = subscription.read_all().expect("read_all");
assert_eq!(flat.len(), 1);
assert!(flat[0].is_finite());
sub.unsubscribe(&req, subscription).expect("unsubscribe");
sub.disconnect().expect("sub disconnect");
req.disconnect().expect("req disconnect");
}