use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use futures::future::BoxFuture;
use tango::backend::{default_backend, Backend, BackendDev, BackendServer, BackendServerConfig};
use tango::server::{ClassDef, ServerBuilder};
use tango::error::Result;
use tango::dev::DevProxy;
use tango::testing::TestContext;
#[derive(Debug)]
struct Counting {
inner: Arc<dyn Backend>,
connects: AtomicUsize,
}
impl Backend for Counting {
fn connect(&self, itr: &str) -> BoxFuture<'_, Result<Arc<dyn BackendDev>>> {
self.connects.fetch_add(1, Ordering::Relaxed);
self.inner.connect(itr)
}
fn connect_at(&self, host: &str, port: u16, name: &str) -> BoxFuture<'_, Result<Arc<dyn BackendDev>>> {
self.connects.fetch_add(1, Ordering::Relaxed);
self.inner.connect_at(host, port, name)
}
fn serve<'a>(&'a self, config: &'a BackendServerConfig) -> BoxFuture<'a, Result<Arc<dyn BackendServer>>> {
self.inner.serve(config)
}
}
#[test]
fn served_by_this_process() {
let counting = Arc::new(Counting { inner: default_backend(), connects: AtomicUsize::new(0) });
let serve = |inst: &str| {
let ctx = TestContext::new().unwrap();
ctx.database().add_server(&format!("Motor/{inst}"), &[("test/motor/1", "Motor")]).unwrap();
let server = ServerBuilder::new("Motor", inst)
.backend(Arc::clone(&counting) as Arc<dyn Backend>)
.database(ctx.database().clone())
.host("127.0.0.1")
.class(ClassDef::<()>::new_default("Motor"))
.serve().unwrap();
let database = tango::database::DatabaseProxy::new_with_backend(Arc::clone(&counting) as Arc<dyn Backend>, ctx.host(), ctx.port());
let dev = DevProxy::new_from_database_with_backend(Arc::clone(&counting) as Arc<dyn Backend>, &database, "test/motor/1");
(ctx, server, dev)
};
let (_ctx_a, server_a, dev_a) = serve("a");
let (_ctx_b, server_b, dev_b) = serve("b");
assert_eq!(dev_a.admin_dev_name().unwrap().to_lowercase(), "dserver/motor/a");
assert_eq!(dev_b.admin_dev_name().unwrap().to_lowercase(), "dserver/motor/b");
dev_a.admin_dev().unwrap().ping().unwrap();
for server in [&server_a, &server_b] {
let backend = server.server().backend().unwrap();
let port = backend.port();
assert_eq!(&*backend.host(), "127.0.0.1");
let dev = DevProxy::new_with_backend(Arc::clone(&counting) as Arc<dyn Backend>, &*format!("tango://127.0.0.1:{port}/test/motor/1#dbase=no"));
assert_eq!(&*dev.admin_dev_name().unwrap(), server.server().admin_dev_name());
}
assert_eq!(counting.connects.load(Ordering::Relaxed), 0);
drop(server_a);
assert!(dev_a.ping().is_err());
dev_b.ping().unwrap();
}