use assert_cmd::cargo::cargo_bin;
use std::{
    process::{self, Command},
    time::Duration,
};
use tempfile::tempdir;

pub mod common;

#[tokio::test]
#[cfg(unix)]
async fn running_the_node_works_and_can_be_interrupted() {
    use nix::{
        sys::signal::{
            kill,
            Signal::{self, SIGINT, SIGTERM,},
        },
        unistd::Pid,
    };

    async fn run_command_and_kill(signal: Signal) {
        let tmpdir = tempdir().expect("could not create temp dir");

        let mut cmd = Command::new(cargo_bin("ghost"))
            .stdout(process::Stdio::piped())
            .stderr(process::Stdio::piped())
            .args(["--dev", "-d"])
            .arg(tmpdir.path())
            .arg("--no-hardware-benchmark")
            .spawn()
            .unwrap();

        let (ws_url, _) = common::find_ws_url_from_output(cmd.stderr.take().unwrap());

        // Let produce three blocks.
        common::wait_n_finalized_blocks(3, from_secs(60)), &ws_url)
            .await
            .unwrap();

        assert!(cmd.try_wait().unwrap().is_none(), "the process should still be running");
        kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap();
        assert_eq!(
            common::wait_for(&mut cmd, 30).map(|x| x.success()),
            Some(true),
            "the process must exit gracefully after signal {}",
            signal,
        );
    }

    run_command_and_kill(SIGINT).await;
    run_command_and_kill(SIGTERM).await;
}