use rust_supervisor::control::command::{CommandResult, ManagedChildState};
use rust_supervisor::id::types::{ChildId, SupervisorPath};
use rust_supervisor::runtime::supervisor::Supervisor;
use rust_supervisor::spec::supervisor::{DynamicSupervisorPolicy, SupervisorSpec};
#[tokio::test]
async fn supervisor_handle_operations_are_idempotent() {
let handle = Supervisor::start(SupervisorSpec::root(Vec::new()))
.await
.unwrap();
let child_id = ChildId::new("worker");
let first = handle
.pause_child(child_id.clone(), "operator", "maintenance")
.await
.unwrap();
let second = handle
.pause_child(child_id.clone(), "operator", "repeat")
.await
.unwrap();
assert_eq!(
first,
CommandResult::ChildState {
child_id: child_id.clone(),
state: ManagedChildState::Paused,
idempotent: false
}
);
assert_eq!(
second,
CommandResult::ChildState {
child_id,
state: ManagedChildState::Paused,
idempotent: true
}
);
}
#[tokio::test]
async fn add_child_and_shutdown_tree_return_results() {
let handle = Supervisor::start(SupervisorSpec::root(Vec::new()))
.await
.unwrap();
let added = handle
.add_child(SupervisorPath::root(), "worker", "operator", "scale")
.await
.unwrap();
let shutdown = handle.shutdown_tree("operator", "done").await.unwrap();
assert_eq!(
added,
CommandResult::ChildAdded {
child_manifest: "worker".to_owned()
}
);
assert!(matches!(shutdown, CommandResult::Shutdown { .. }));
}
#[tokio::test]
async fn add_child_respects_dynamic_supervisor_limit() {
let mut spec = SupervisorSpec::root(Vec::new());
spec.dynamic_supervisor_policy = DynamicSupervisorPolicy::limited(1);
let handle = Supervisor::start(spec).await.unwrap();
let added = handle
.add_child(SupervisorPath::root(), "worker-one", "operator", "scale")
.await
.unwrap();
let rejected = handle
.add_child(SupervisorPath::root(), "worker-two", "operator", "scale")
.await
.unwrap_err();
let state = handle.current_state().await.unwrap();
assert!(matches!(added, CommandResult::ChildAdded { .. }));
assert!(rejected.to_string().contains("child limit"));
assert!(matches!(
state,
CommandResult::CurrentState {
state: rust_supervisor::control::command::CurrentState { child_count: 1, .. }
}
));
}
#[tokio::test]
async fn add_child_rejects_disabled_dynamic_supervisor() {
let mut spec = SupervisorSpec::root(Vec::new());
spec.dynamic_supervisor_policy.enabled = false;
let handle = Supervisor::start(spec).await.unwrap();
let rejected = handle
.add_child(SupervisorPath::root(), "worker", "operator", "scale")
.await
.unwrap_err();
assert!(rejected.to_string().contains("child limit"));
}