Skip to content

Commit

Permalink
test: multiproc for std
Browse files Browse the repository at this point in the history
  • Loading branch information
passcod committed Apr 16, 2024
1 parent bd268d2 commit 35270b8
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 1 deletion.
14 changes: 13 additions & 1 deletion tests/std_unix/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod prelude {
pub use std::{
io::{Read, Result, Write},
io::{BufRead, BufReader, Read, Result, Write},
os::unix::process::ExitStatusExt,
process::Stdio,
thread::sleep,
Expand All @@ -11,12 +11,24 @@ mod prelude {
pub use process_wrap::std::*;

pub const DIE_TIME: Duration = Duration::from_millis(100);

#[track_caller]
pub fn pid_alive(pid: i32) -> bool {
#[inline]
#[track_caller]
fn inner(pid: i32) -> std::result::Result<bool, remoteprocess::Error> {
Ok(!remoteprocess::Process::new(pid)?.threads()?.is_empty())
}

inner(pid).unwrap_or(false)
}
}

mod id_same_as_inner;
mod inner_read_stdout;
mod into_inner_write_stdin;
mod kill_and_try_wait;
mod multiproc_linux;
mod signals;
mod try_wait_after_die;
mod try_wait_twice_after_sigterm;
Expand Down
173 changes: 173 additions & 0 deletions tests/std_unix/multiproc_linux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#![cfg(target_os = "linux")]

use super::prelude::*;

#[test]
fn process_group_kill_leader() -> Result<()> {
let mut leader = StdCommandWrap::with_new("tests/multiproc_helper.rs", |command| {
command
.arg("1")
.arg("10")
.stdout(Stdio::piped())
.stderr(Stdio::null());
})
.wrap(ProcessGroup::leader())
.spawn()?;
assert!(leader.try_wait()?.is_none(), "leader: pre kill");

sleep(DIE_TIME);

let stdout = leader
.stdout()
.take()
.expect("Option.unwrap(): get leader stdout");
let mut lines = BufReader::new(stdout).lines();
let Some(Ok(line)) = lines.next() else {
panic!("expected line with child pid");
};
let Some((parent, child)) = line.split_once(':') else {
panic!("expected line with parent and child pids");
};

let parent = parent.parse::<i32>().unwrap();
let child = child.parse::<i32>().unwrap();

assert_eq!(parent, leader.id() as _);
assert!(pid_alive(parent), "parent process should be alive");
assert!(pid_alive(child), "child process should be alive");

leader.kill().unwrap();
sleep(DIE_TIME);
assert!(!pid_alive(parent), "parent process should be dead");
assert!(!pid_alive(child), "child process should be dead");

Ok(())
}

#[test]
fn process_group_kill_group() -> Result<()> {
let mut leader = StdCommandWrap::with_new("tests/multiproc_helper.rs", |command| {
command
.arg("1")
.arg("10")
.stdout(Stdio::piped())
.stderr(Stdio::null());
})
.wrap(ProcessGroup::leader())
.spawn()?;
assert!(leader.try_wait()?.is_none(), "leader: pre kill");

sleep(DIE_TIME);

let stdout = leader
.stdout()
.take()
.expect("Option.unwrap(): get leader stdout");
let mut lines = BufReader::new(stdout).lines();
let Some(Ok(line)) = lines.next() else {
panic!("expected line with child pid");
};
let Some((parent, child)) = line.split_once(':') else {
panic!("expected line with parent and child pids");
};

let parent = parent.parse::<i32>().unwrap();
let child = child.parse::<i32>().unwrap();

assert_eq!(parent, leader.id() as _);
assert!(pid_alive(parent), "parent process should be alive");
assert!(pid_alive(child), "child process should be alive");

nix::sys::signal::killpg(nix::unistd::Pid::from_raw(parent), Signal::SIGKILL).unwrap();
sleep(DIE_TIME);
assert!(!pid_alive(child), "child process should be dead");
leader.wait().unwrap();
assert!(!pid_alive(parent), "parent process should be dead");

Ok(())
}

#[test]
fn process_session_kill_leader() -> Result<()> {
let mut leader = StdCommandWrap::with_new("tests/multiproc_helper.rs", |command| {
command
.arg("1")
.arg("10")
.stdout(Stdio::piped())
.stderr(Stdio::null());
})
.wrap(ProcessSession)
.spawn()?;
assert!(leader.try_wait()?.is_none(), "leader: pre kill");

sleep(DIE_TIME);

let stdout = leader
.stdout()
.take()
.expect("Option.unwrap(): get leader stdout");
let mut lines = BufReader::new(stdout).lines();
let Some(Ok(line)) = lines.next() else {
panic!("expected line with child pid");
};
let Some((parent, child)) = line.split_once(':') else {
panic!("expected line with parent and child pids");
};

let parent = parent.parse::<i32>().unwrap();
let child = child.parse::<i32>().unwrap();

assert_eq!(parent, leader.id() as _);
assert!(pid_alive(parent), "parent process should be alive");
assert!(pid_alive(child), "child process should be alive");

leader.kill().unwrap();
sleep(DIE_TIME);
assert!(!pid_alive(parent), "parent process should be dead");
assert!(!pid_alive(child), "child process should be dead");

Ok(())
}

#[test]
fn process_session_kill_group() -> Result<()> {
let mut leader = StdCommandWrap::with_new("tests/multiproc_helper.rs", |command| {
command
.arg("1")
.arg("10")
.stdout(Stdio::piped())
.stderr(Stdio::null());
})
.wrap(ProcessSession)
.spawn()?;
assert!(leader.try_wait()?.is_none(), "leader: pre kill");

sleep(DIE_TIME);

let stdout = leader
.stdout()
.take()
.expect("Option.unwrap(): get leader stdout");
let mut lines = BufReader::new(stdout).lines();
let Some(Ok(line)) = lines.next() else {
panic!("expected line with child pid");
};
let Some((parent, child)) = line.split_once(':') else {
panic!("expected line with parent and child pids");
};

let parent = parent.parse::<i32>().unwrap();
let child = child.parse::<i32>().unwrap();

assert_eq!(parent, leader.id() as _);
assert!(pid_alive(parent), "parent process should be alive");
assert!(pid_alive(child), "child process should be alive");

nix::sys::signal::killpg(nix::unistd::Pid::from_raw(parent), Signal::SIGKILL).unwrap();
sleep(DIE_TIME);
assert!(!pid_alive(child), "child process should be dead");
leader.wait().unwrap();
assert!(!pid_alive(parent), "parent process should be dead");

Ok(())
}

0 comments on commit 35270b8

Please sign in to comment.