use std::time::Duration;
use postgresql_embedded::Settings;
use serial_test::serial;
use super::*;
use crate::{CleanupMode, test_support::capture_warn_logs};
struct ShutdownRegistrationResetGuard;
impl Drop for ShutdownRegistrationResetGuard {
fn drop(&mut self) { reset_shutdown_registration_for_tests(); }
}
#[test]
fn absent_process_reports_not_running() {
assert!(
!postmaster_process_is_running_for_shutdown(0),
"a non-positive pid must not be reported as running"
);
}
#[test]
fn wait_for_exit_returns_true_for_absent_process() {
assert!(
wait_for_exit(0, Duration::from_millis(20)),
"an already-absent process should be treated as exited"
);
}
#[test]
#[serial(shutdown_hook_state)]
fn shutdown_work_is_none_before_registration() {
reset_shutdown_registration_for_tests();
assert!(
shutdown_work().is_none(),
"no work should be available before registration"
);
}
#[test]
fn stop_postmaster_returns_for_absent_process() {
let work = ShutdownWork {
settings: Settings::default(),
shutdown_timeout: Duration::from_millis(20),
cleanup_mode: CleanupMode::None,
};
let (logs, ()) = capture_warn_logs(|| stop_postmaster(0, &work));
assert!(
!logs
.iter()
.any(|line| line.contains("escalating to forceful termination")),
"an absent process must not trigger forceful escalation, got {logs:?}"
);
}
#[test]
#[serial(shutdown_hook_state)]
fn register_shutdown_hook_is_idempotent() -> color_eyre::Result<()> {
reset_shutdown_registration_for_tests();
let _reset_guard = ShutdownRegistrationResetGuard;
let first_dir = tempfile::tempdir()?;
let second_dir = tempfile::tempdir()?;
let first = Settings {
data_dir: first_dir.path().to_path_buf(),
..Settings::default()
};
let second = Settings {
data_dir: second_dir.path().to_path_buf(),
..Settings::default()
};
register_shutdown_hook(first.clone(), Duration::from_millis(20), CleanupMode::None)?;
register_shutdown_hook(second, Duration::from_millis(999), CleanupMode::Full)?;
let work =
shutdown_work().ok_or_else(|| color_eyre::eyre::eyre!("registration should be present"))?;
color_eyre::eyre::ensure!(
work.settings == first,
"the second registration must not overwrite the first"
);
color_eyre::eyre::ensure!(
work.shutdown_timeout == Duration::from_millis(20),
"the first shutdown timeout must be preserved"
);
color_eyre::eyre::ensure!(
work.cleanup_mode == CleanupMode::None,
"the first cleanup mode must be preserved"
);
Ok(())
}