#![allow(dead_code)]
use ek_core::{MAILBOX_CAP, Plugin, PluginContext, ServiceDesc};
use ek_event::Event;
use std::borrow::Cow;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
pub type MailHook = Arc<dyn Fn(&Event) + Send + Sync>;
pub type VoidHook = Arc<dyn Fn() + Send + Sync>;
pub type InitHook = Arc<dyn Fn(&PluginContext) + Send + Sync>;
pub struct TestPlugin {
name_: String,
version_: String,
deps_: Vec<&'static str>,
routes_: Vec<Cow<'static, str>>,
cap_: usize,
services_: Vec<ServiceDesc>,
on_mail_: Option<MailHook>,
on_start_: Option<VoidHook>,
on_stop_: Option<VoidHook>,
on_init_: Option<InitHook>,
}
impl Plugin for TestPlugin {
fn name(&self) -> &str {
&self.name_
}
fn version(&self) -> Cow<'static, str> {
Cow::Owned(self.version_.clone())
}
fn deps(&self) -> &[&str] {
&self.deps_
}
fn routes(&self) -> Vec<Cow<'static, str>> {
self.routes_.clone()
}
fn mailbox_cap(&self) -> usize {
self.cap_
}
fn services(&self) -> Vec<ServiceDesc> {
self.services_.clone()
}
fn on_init(&self, ctx: &PluginContext) {
if let Some(f) = &self.on_init_ {
f(ctx);
}
}
fn on_start(&self) {
if let Some(f) = &self.on_start_ {
f();
}
}
fn on_stop(&self) {
if let Some(f) = &self.on_stop_ {
f();
}
}
fn on_mail(&self, event: &Event) {
if let Some(f) = &self.on_mail_ {
f(event);
}
}
}
pub struct TestPluginBuilder {
inner: TestPlugin,
}
pub fn test_plugin(name: &str) -> TestPluginBuilder {
TestPluginBuilder {
inner: TestPlugin {
name_: name.to_string(),
version_: String::new(),
deps_: Vec::new(),
routes_: Vec::new(),
cap_: MAILBOX_CAP,
services_: Vec::new(),
on_mail_: None,
on_start_: None,
on_stop_: None,
on_init_: None,
},
}
}
impl TestPluginBuilder {
pub fn version(mut self, v: &str) -> Self {
self.inner.version_ = v.to_string();
self
}
pub fn services(mut self, s: Vec<ServiceDesc>) -> Self {
self.inner.services_ = s;
self
}
pub fn deps(mut self, d: &[&'static str]) -> Self {
self.inner.deps_ = d.to_vec();
self
}
pub fn routes(mut self, r: Vec<Cow<'static, str>>) -> Self {
self.inner.routes_ = r;
self
}
pub fn routes_str(mut self, r: &[&'static str]) -> Self {
self.inner.routes_ = r.iter().map(|s| Cow::Borrowed(*s)).collect();
self
}
pub fn routes_owned(mut self, r: Vec<String>) -> Self {
self.inner.routes_ = r.into_iter().map(Cow::Owned).collect();
self
}
pub fn cap(mut self, c: usize) -> Self {
self.inner.cap_ = c;
self
}
pub fn mail<F: Fn(&Event) + Send + Sync + 'static>(mut self, f: F) -> Self {
self.inner.on_mail_ = Some(Arc::new(f));
self
}
pub fn start_hook<F: Fn() + Send + Sync + 'static>(mut self, f: F) -> Self {
self.inner.on_start_ = Some(Arc::new(f));
self
}
pub fn stop_hook<F: Fn() + Send + Sync + 'static>(mut self, f: F) -> Self {
self.inner.on_stop_ = Some(Arc::new(f));
self
}
pub fn init_hook<F: Fn(&PluginContext) + Send + Sync + 'static>(mut self, f: F) -> Self {
self.inner.on_init_ = Some(Arc::new(f));
self
}
pub fn build(self) -> Arc<TestPlugin> {
Arc::new(self.inner)
}
}
pub fn wait_until(timeout: Duration, mut f: impl FnMut() -> bool) -> bool {
let deadline = Instant::now() + timeout;
while Instant::now() < deadline {
if f() {
return true;
}
std::thread::sleep(Duration::from_millis(5));
}
f()
}
pub fn counter() -> Arc<AtomicU64> {
Arc::new(AtomicU64::new(0))
}
pub fn bump(c: &AtomicU64) -> u64 {
c.fetch_add(1, Ordering::AcqRel) + 1
}
pub fn load(c: &AtomicU64) -> u64 {
c.load(Ordering::Acquire)
}
pub fn records<T>() -> Arc<Mutex<Vec<T>>> {
Arc::new(Mutex::new(Vec::new()))
}
pub fn push_record<T>(r: &Arc<Mutex<Vec<T>>>, v: T) {
r.lock().unwrap().push(v);
}
pub fn snapshot<T: Clone>(r: &Arc<Mutex<Vec<T>>>) -> Vec<T> {
r.lock().unwrap().clone()
}