139 lines
4.2 KiB
Rust
139 lines
4.2 KiB
Rust
|
|
// Copyright 2022 The ChromiumOS Authors
|
||
|
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
|
// found in the LICENSE file.
|
||
|
|
|
||
|
|
#[cfg(unix)]
|
||
|
|
mod test {
|
||
|
|
use std::thread;
|
||
|
|
use std::time::Duration;
|
||
|
|
|
||
|
|
use base::getpid;
|
||
|
|
use base::unix::process::fork_process;
|
||
|
|
use base::AsRawDescriptor;
|
||
|
|
use base::Tube;
|
||
|
|
use minijail::Minijail;
|
||
|
|
|
||
|
|
pub fn pid_diff() {
|
||
|
|
let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
|
||
|
|
let jail = Minijail::new().unwrap();
|
||
|
|
let keep_rds = vec![fork_tube.as_raw_descriptor()];
|
||
|
|
|
||
|
|
let pid = getpid();
|
||
|
|
let child = fork_process(jail, keep_rds, None, || {
|
||
|
|
// checks that this is a genuine fork with a new PID
|
||
|
|
if pid != getpid() {
|
||
|
|
fork_tube.send(&1).unwrap()
|
||
|
|
} else {
|
||
|
|
fork_tube.send(&2).unwrap()
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.expect("failed to fork");
|
||
|
|
|
||
|
|
assert_eq!(tube.recv::<u32>().unwrap(), 1);
|
||
|
|
child.wait().unwrap();
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn thread_name() {
|
||
|
|
let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
|
||
|
|
let jail = Minijail::new().unwrap();
|
||
|
|
let keep_rds = vec![fork_tube.as_raw_descriptor()];
|
||
|
|
let thread_name = String::from("thread_name");
|
||
|
|
|
||
|
|
let child = fork_process(jail, keep_rds, Some(thread_name.clone()), || {
|
||
|
|
fork_tube.send::<u32>(&1).unwrap();
|
||
|
|
thread::sleep(Duration::from_secs(10));
|
||
|
|
})
|
||
|
|
.expect("failed to fork");
|
||
|
|
|
||
|
|
// wait the forked process running.
|
||
|
|
tube.recv::<u32>().unwrap();
|
||
|
|
let thread_comm =
|
||
|
|
std::fs::read_to_string(format!("/proc/{0}/task/{0}/comm", child.pid)).unwrap();
|
||
|
|
|
||
|
|
assert_eq!(thread_comm, thread_name + "\n");
|
||
|
|
|
||
|
|
unsafe { libc::kill(child.pid, libc::SIGKILL) };
|
||
|
|
child.wait().unwrap();
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn thread_name_trimmed() {
|
||
|
|
let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
|
||
|
|
let jail = Minijail::new().unwrap();
|
||
|
|
let keep_rds = vec![fork_tube.as_raw_descriptor()];
|
||
|
|
let thread_name = String::from("12345678901234567890");
|
||
|
|
|
||
|
|
let child = fork_process(jail, keep_rds, Some(thread_name), || {
|
||
|
|
fork_tube.send::<u32>(&1).unwrap();
|
||
|
|
thread::sleep(Duration::from_secs(10));
|
||
|
|
})
|
||
|
|
.expect("failed to fork");
|
||
|
|
|
||
|
|
// wait the forked process running.
|
||
|
|
tube.recv::<u32>().unwrap();
|
||
|
|
let thread_comm =
|
||
|
|
std::fs::read_to_string(format!("/proc/{0}/task/{0}/comm", child.pid)).unwrap();
|
||
|
|
|
||
|
|
assert_eq!(thread_comm, "123456789012345\n");
|
||
|
|
|
||
|
|
unsafe { libc::kill(child.pid, libc::SIGKILL) };
|
||
|
|
child.wait().unwrap();
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn wait_for_success() {
|
||
|
|
let jail = Minijail::new().unwrap();
|
||
|
|
let child = fork_process(jail, vec![], None, || {
|
||
|
|
// exit successfully
|
||
|
|
})
|
||
|
|
.expect("failed to fork");
|
||
|
|
|
||
|
|
assert_eq!(child.wait().unwrap(), 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn wait_for_panic() {
|
||
|
|
let jail = Minijail::new().unwrap();
|
||
|
|
let child = fork_process(jail, vec![], None, || {
|
||
|
|
panic!("fails");
|
||
|
|
})
|
||
|
|
.expect("failed to fork");
|
||
|
|
|
||
|
|
assert_eq!(child.wait().unwrap(), 101);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn main() {
|
||
|
|
let args = libtest_mimic::Arguments {
|
||
|
|
// Force single-threaded execution to allow safe use of libc::fork in these tests.
|
||
|
|
test_threads: Some(1),
|
||
|
|
..libtest_mimic::Arguments::from_args()
|
||
|
|
};
|
||
|
|
|
||
|
|
let tests = vec![
|
||
|
|
#[cfg(unix)]
|
||
|
|
libtest_mimic::Trial::test("pid_diff", move || {
|
||
|
|
test::pid_diff();
|
||
|
|
Ok(())
|
||
|
|
}),
|
||
|
|
#[cfg(unix)]
|
||
|
|
libtest_mimic::Trial::test("thread_name", move || {
|
||
|
|
test::thread_name();
|
||
|
|
Ok(())
|
||
|
|
}),
|
||
|
|
#[cfg(unix)]
|
||
|
|
libtest_mimic::Trial::test("thread_name_trimmed", move || {
|
||
|
|
test::thread_name_trimmed();
|
||
|
|
Ok(())
|
||
|
|
}),
|
||
|
|
#[cfg(unix)]
|
||
|
|
libtest_mimic::Trial::test("wait_for_success", move || {
|
||
|
|
test::wait_for_success();
|
||
|
|
Ok(())
|
||
|
|
}),
|
||
|
|
#[cfg(unix)]
|
||
|
|
libtest_mimic::Trial::test("wait_for_panic", move || {
|
||
|
|
test::wait_for_panic();
|
||
|
|
Ok(())
|
||
|
|
}),
|
||
|
|
];
|
||
|
|
libtest_mimic::run(&args, tests).exit();
|
||
|
|
}
|