mod agents;
mod analyze;
mod helpers;
mod memory;
mod mpm;
mod review;
mod search;
pub use agents::AgentsConnector;
pub use analyze::AnalyzeConnector;
pub use memory::MemoryConnector;
pub use mpm::MpmConnector;
pub use review::ReviewConnector;
pub use search::SearchConnector;
use crate::connector::{ServiceConnector, ServiceInfo, ServiceStatus};
#[cfg(test)]
pub(super) static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
pub fn all_connectors() -> Vec<Box<dyn ServiceConnector>> {
vec![
Box::new(SearchConnector::new()),
Box::new(MemoryConnector::new()),
Box::new(AnalyzeConnector::new()),
Box::new(ReviewConnector::new()),
Box::new(MpmConnector::new()),
Box::new(AgentsConnector::new()),
]
}
fn liveness_rank(info: &ServiceInfo) -> u8 {
match info.status {
ServiceStatus::Running => 0,
ServiceStatus::Degraded => 1,
ServiceStatus::Available => 2,
ServiceStatus::Absent => 3,
}
}
pub fn order_for_display(services: &mut [ServiceInfo]) {
services.sort_by_key(liveness_rank);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::connector::ServiceLifecycle;
#[test]
fn test_all_connectors_returns_six() {
let cs = all_connectors();
assert_eq!(cs.len(), 6);
assert_eq!(cs[0].id(), "trusty-search");
assert_eq!(cs[1].id(), "trusty-memory");
assert_eq!(cs[2].id(), "trusty-analyze");
assert_eq!(cs[3].id(), "trusty-review");
assert_eq!(cs[4].id(), "trusty-mpm");
assert_eq!(cs[5].id(), "trusty-agents");
}
#[test]
fn on_demand_members_are_exactly_review_and_analyze() {
let connectors = all_connectors();
let on_demand: Vec<&str> = connectors
.iter()
.filter(|c| c.lifecycle() == ServiceLifecycle::OnDemand)
.map(|c| c.id())
.collect();
assert_eq!(on_demand, vec!["trusty-analyze", "trusty-review"]);
let daemons: Vec<&str> = connectors
.iter()
.filter(|c| c.lifecycle() == ServiceLifecycle::Daemon)
.map(|c| c.id())
.collect();
assert_eq!(
daemons,
vec![
"trusty-search",
"trusty-memory",
"trusty-mpm",
"trusty-agents"
]
);
}
fn info(id: &str, status: ServiceStatus) -> ServiceInfo {
ServiceInfo {
id: id.to_string(),
display_name: id.to_string(),
status,
version: None,
url: None,
hint: None,
lifecycle: ServiceLifecycle::Daemon,
}
}
fn ids(services: &[ServiceInfo]) -> Vec<&str> {
services.iter().map(|s| s.id.as_str()).collect()
}
#[test]
fn order_for_display_puts_running_first() {
let mut services = vec![
info("absent-one", ServiceStatus::Absent),
info("available-one", ServiceStatus::Available),
info("degraded-one", ServiceStatus::Degraded),
info("running-one", ServiceStatus::Running),
];
order_for_display(&mut services);
assert_eq!(
ids(&services),
vec!["running-one", "degraded-one", "available-one", "absent-one"]
);
}
#[test]
fn order_for_display_is_stable_within_a_rank() {
let mut services = vec![
info("trusty-search", ServiceStatus::Running),
info("trusty-memory", ServiceStatus::Running),
info("trusty-analyze", ServiceStatus::Running),
];
order_for_display(&mut services);
assert_eq!(
ids(&services),
vec!["trusty-search", "trusty-memory", "trusty-analyze"]
);
}
#[test]
fn order_for_display_is_idempotent() {
let mut services = vec![
info("b", ServiceStatus::Absent),
info("a", ServiceStatus::Running),
info("c", ServiceStatus::Absent),
];
order_for_display(&mut services);
let once: Vec<String> = services.iter().map(|s| s.id.clone()).collect();
order_for_display(&mut services);
let twice: Vec<String> = services.iter().map(|s| s.id.clone()).collect();
assert_eq!(once, twice);
}
}