1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #[cfg(unix)]
6 mod test {
7 use std::thread;
8 use std::time::Duration;
9
10 use base::getpid;
11 use base::unix::process::fork_process;
12 use base::AsRawDescriptor;
13 use base::Tube;
14 use minijail::Minijail;
15
pid_diff()16 pub fn pid_diff() {
17 let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
18 let jail = Minijail::new().unwrap();
19 let keep_rds = vec![fork_tube.as_raw_descriptor()];
20
21 let pid = getpid();
22 let child = fork_process(jail, keep_rds, None, || {
23 // checks that this is a genuine fork with a new PID
24 if pid != getpid() {
25 fork_tube.send(&1).unwrap()
26 } else {
27 fork_tube.send(&2).unwrap()
28 }
29 })
30 .expect("failed to fork");
31
32 assert_eq!(tube.recv::<u32>().unwrap(), 1);
33 child.wait().unwrap();
34 }
35
thread_name()36 pub fn thread_name() {
37 let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
38 let jail = Minijail::new().unwrap();
39 let keep_rds = vec![fork_tube.as_raw_descriptor()];
40 let thread_name = String::from("thread_name");
41
42 let child = fork_process(jail, keep_rds, Some(thread_name.clone()), || {
43 fork_tube.send::<u32>(&1).unwrap();
44 thread::sleep(Duration::from_secs(10));
45 })
46 .expect("failed to fork");
47
48 // wait the forked process running.
49 tube.recv::<u32>().unwrap();
50 let thread_comm =
51 std::fs::read_to_string(format!("/proc/{0}/task/{0}/comm", child.pid)).unwrap();
52
53 assert_eq!(thread_comm, thread_name + "\n");
54
55 unsafe { libc::kill(child.pid, libc::SIGKILL) };
56 child.wait().unwrap();
57 }
58
thread_name_trimmed()59 pub fn thread_name_trimmed() {
60 let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
61 let jail = Minijail::new().unwrap();
62 let keep_rds = vec![fork_tube.as_raw_descriptor()];
63 let thread_name = String::from("12345678901234567890");
64
65 let child = fork_process(jail, keep_rds, Some(thread_name), || {
66 fork_tube.send::<u32>(&1).unwrap();
67 thread::sleep(Duration::from_secs(10));
68 })
69 .expect("failed to fork");
70
71 // wait the forked process running.
72 tube.recv::<u32>().unwrap();
73 let thread_comm =
74 std::fs::read_to_string(format!("/proc/{0}/task/{0}/comm", child.pid)).unwrap();
75
76 assert_eq!(thread_comm, "123456789012345\n");
77
78 unsafe { libc::kill(child.pid, libc::SIGKILL) };
79 child.wait().unwrap();
80 }
81
wait_for_success()82 pub fn wait_for_success() {
83 let jail = Minijail::new().unwrap();
84 let child = fork_process(jail, vec![], None, || {
85 // exit successfully
86 })
87 .expect("failed to fork");
88
89 assert_eq!(child.wait().unwrap(), 0);
90 }
91
wait_for_panic()92 pub fn wait_for_panic() {
93 let jail = Minijail::new().unwrap();
94 let child = fork_process(jail, vec![], None, || {
95 panic!("fails");
96 })
97 .expect("failed to fork");
98
99 assert_eq!(child.wait().unwrap(), 101);
100 }
101 }
102
main()103 fn main() {
104 let args = libtest_mimic::Arguments {
105 // Force single-threaded execution to allow safe use of libc::fork in these tests.
106 test_threads: Some(1),
107 ..libtest_mimic::Arguments::from_args()
108 };
109
110 let tests = vec![
111 #[cfg(unix)]
112 libtest_mimic::Trial::test("pid_diff", move || {
113 test::pid_diff();
114 Ok(())
115 }),
116 #[cfg(unix)]
117 libtest_mimic::Trial::test("thread_name", move || {
118 test::thread_name();
119 Ok(())
120 }),
121 #[cfg(unix)]
122 libtest_mimic::Trial::test("thread_name_trimmed", move || {
123 test::thread_name_trimmed();
124 Ok(())
125 }),
126 #[cfg(unix)]
127 libtest_mimic::Trial::test("wait_for_success", move || {
128 test::wait_for_success();
129 Ok(())
130 }),
131 #[cfg(unix)]
132 libtest_mimic::Trial::test("wait_for_panic", move || {
133 test::wait_for_panic();
134 Ok(())
135 }),
136 ];
137 libtest_mimic::run(&args, tests).exit();
138 }
139