[WIP] Daemon & CLI
This commit is contained in:
parent
56aad3a023
commit
8b158108bb
100 changed files with 6519 additions and 1596 deletions
52
iota-daemon-lib/tests/command_router.rs
Normal file
52
iota-daemon-lib/tests/command_router.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use async_trait::async_trait;
|
||||
use iota_daemon_lib::{CommandRouter, DaemonRuntime, DaemonServices};
|
||||
use iota_ipc::{LocalRequest, ResponseResult};
|
||||
use mtp::codec::CommunicationValue;
|
||||
use omikron_connector::{OmikronClient, OmikronError};
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
struct FakeOmikron {
|
||||
reconnects: AtomicUsize,
|
||||
}
|
||||
#[async_trait]
|
||||
impl OmikronClient for FakeOmikron {
|
||||
async fn send_message(&self, _: &CommunicationValue) -> Result<(), OmikronError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn await_response(
|
||||
&self,
|
||||
_: &CommunicationValue,
|
||||
_: Duration,
|
||||
) -> Result<CommunicationValue, OmikronError> {
|
||||
Err(OmikronError::Disconnected("fake".into()))
|
||||
}
|
||||
async fn reconnect(&self) -> Result<(), OmikronError> {
|
||||
self.reconnects.fetch_add(1, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
async fn is_connected(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn reconnect_uses_the_injected_client() {
|
||||
let fake = Arc::new(FakeOmikron {
|
||||
reconnects: AtomicUsize::new(0),
|
||||
});
|
||||
let services = Arc::new(DaemonServices {
|
||||
omikron: fake.clone(),
|
||||
users: Default::default(),
|
||||
config: Default::default(),
|
||||
});
|
||||
let router = CommandRouter::new(Arc::new(DaemonRuntime::new()), services);
|
||||
assert!(matches!(
|
||||
router.route(1, LocalRequest::ReconnectOmikron).await.result,
|
||||
ResponseResult::Ok(_)
|
||||
));
|
||||
assert_eq!(fake.reconnects.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
29
iota-daemon-lib/tests/daemon_health.rs
Normal file
29
iota-daemon-lib/tests/daemon_health.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use iota_daemon_lib::{DaemonRuntime, StartupPhase};
|
||||
use iota_ipc::{ComponentId, HealthStatus, LifecyclePhase};
|
||||
|
||||
#[test]
|
||||
fn component_failures_are_independent_and_recovery_is_scoped() {
|
||||
let runtime = DaemonRuntime::new();
|
||||
runtime.set_component_degraded(ComponentId::Omikron, "offline".into());
|
||||
runtime.set_component_failed(ComponentId::Web, "bind failed".into());
|
||||
runtime.set_startup_phase(StartupPhase::Ready);
|
||||
let snapshot = runtime.snapshot();
|
||||
assert_eq!(snapshot.lifecycle, LifecyclePhase::Ready);
|
||||
assert_eq!(snapshot.overall_health, HealthStatus::Degraded);
|
||||
assert_eq!(
|
||||
snapshot.components[&ComponentId::Omikron].status,
|
||||
HealthStatus::Degraded
|
||||
);
|
||||
runtime.set_component_healthy(ComponentId::Web, None);
|
||||
assert_eq!(
|
||||
runtime.snapshot().components[&ComponentId::Omikron].status,
|
||||
HealthStatus::Degraded
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn critical_failure_is_failed_but_optional_degradation_is_not() {
|
||||
let runtime = DaemonRuntime::new();
|
||||
runtime.set_component_failed(ComponentId::Storage, "database unavailable".into());
|
||||
assert_eq!(runtime.snapshot().overall_health, HealthStatus::Failed);
|
||||
}
|
||||
40
iota-daemon-lib/tests/shutdown.rs
Normal file
40
iota-daemon-lib/tests/shutdown.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use iota_daemon_lib::{DaemonRuntime, ShutdownReason};
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::test]
|
||||
async fn shutdown_reason_is_first_write_wins_and_tasks_join() {
|
||||
let runtime = DaemonRuntime::new();
|
||||
runtime.shutdown(ShutdownReason::Fatal("first".into()));
|
||||
runtime.shutdown(ShutdownReason::Restart);
|
||||
assert_eq!(
|
||||
runtime.shutdown_reason(),
|
||||
Some(ShutdownReason::Fatal("first".into()))
|
||||
);
|
||||
runtime.tasks.spawn_tracked("quick", async { Ok(()) }).await;
|
||||
assert!(
|
||||
runtime
|
||||
.tasks
|
||||
.join_with_timeout(Duration::from_millis(100))
|
||||
.await
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn long_task_is_aborted_at_join_timeout() {
|
||||
let runtime = DaemonRuntime::new();
|
||||
runtime
|
||||
.tasks
|
||||
.spawn_tracked("slow", async {
|
||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
assert!(
|
||||
runtime
|
||||
.tasks
|
||||
.join_with_timeout(Duration::from_millis(10))
|
||||
.await
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue