#![allow(clippy::await_holding_lock)]
#[path = "common/mod.rs"]
mod common;
use std::time::Duration;
use rusty_autossh::{MonitorMode, SshSupervisorBuilder, SupervisorEvent};
use tokio::sync::mpsc;
#[tokio::test(flavor = "current_thread")]
async fn no_concurrent_ssh_children() {
let _lock = common::env_lock().lock().unwrap_or_else(|p| p.into_inner());
let echo = common::echo_child_path();
let (tx, mut rx) = mpsc::channel::<SupervisorEvent>(64);
let mut sup = SshSupervisorBuilder::new()
.ssh_args(vec![])
.ssh_path(echo)
.monitor_mode(MonitorMode::None)
.gate_time(Duration::from_millis(50))
.max_start(Some(3))
.event_sender(tx)
.build()
.expect("builder ok");
let _g = common::env_guard("RUSTY_AUTOSSH_TEST_BEHAVIOR", Some("exit_nonzero"));
let run_handle = tokio::spawn(async move { sup.run().await });
let mut events: Vec<SupervisorEvent> = Vec::new();
while events.len() < 6 {
let Some(ev) = tokio::time::timeout(Duration::from_secs(10), rx.recv())
.await
.ok()
.flatten()
else {
break;
};
let stop = matches!(ev, SupervisorEvent::MaxStartReached { .. });
events.push(ev);
if stop {
break;
}
}
let _ = run_handle.await;
drop(_g);
let mut last_was_spawned = false;
for ev in &events {
match ev {
SupervisorEvent::ChildSpawned { .. } => {
assert!(!last_was_spawned, "two ChildSpawned in a row: {events:?}");
last_was_spawned = true;
}
SupervisorEvent::ChildExited { .. } => {
assert!(last_was_spawned, "ChildExited without prior ChildSpawned");
last_was_spawned = false;
}
_ => {}
}
}
}
#[tokio::test(flavor = "current_thread")]
async fn gate_exceeding_lifetime_resets_retry_counter() {
let _lock = common::env_lock().lock().unwrap_or_else(|p| p.into_inner());
let echo = common::echo_child_path();
let (tx, mut rx) = mpsc::channel::<SupervisorEvent>(64);
let mut sup = SshSupervisorBuilder::new()
.ssh_args(vec![])
.ssh_path(echo)
.monitor_mode(MonitorMode::None)
.gate_time(Duration::from_millis(10))
.max_start(Some(1))
.event_sender(tx)
.build()
.expect("builder ok");
let _g = common::env_guard("RUSTY_AUTOSSH_TEST_BEHAVIOR", Some("exit_zero"));
let res = tokio::time::timeout(Duration::from_secs(15), async {
let r = sup.run().await;
while rx.try_recv().is_ok() {}
r
})
.await
.expect("timeout");
drop(_g);
assert!(res.is_ok());
}