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(any(target_os = "android", target_os = "linux"))]
6 mod test {
7 use std::thread;
8 use std::time::Duration;
9
10 use base::getpid;
11 use base::AsRawDescriptor;
12 use base::Tube;
13 use jail::fork::fork_process;
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 // SAFETY: child pid is expected to be valid and we wait on the child
56 unsafe { libc::kill(child.pid, libc::SIGKILL) };
57 child.wait().unwrap();
58 }
59
thread_name_trimmed()60 pub fn thread_name_trimmed() {
61 let (tube, fork_tube) = Tube::pair().expect("failed to create tube");
62 let jail = Minijail::new().unwrap();
63 let keep_rds = vec![fork_tube.as_raw_descriptor()];
64 let thread_name = String::from("12345678901234567890");
65
66 let child = fork_process(jail, keep_rds, Some(thread_name), || {
67 fork_tube.send::<u32>(&1).unwrap();
68 thread::sleep(Duration::from_secs(10));
69 })
70 .expect("failed to fork");
71
72 // wait the forked process running.
73 tube.recv::<u32>().unwrap();
74 let thread_comm =
75 std::fs::read_to_string(format!("/proc/{0}/task/{0}/comm", child.pid)).unwrap();
76
77 assert_eq!(thread_comm, "123456789012345\n");
78
79 // SAFETY: child pid is expected to be valid and we wait on the child
80 unsafe { libc::kill(child.pid, libc::SIGKILL) };
81 child.wait().unwrap();
82 }
83
wait_for_success()84 pub fn wait_for_success() {
85 let jail = Minijail::new().unwrap();
86 let child = fork_process(jail, vec![], None, || {
87 // exit successfully
88 })
89 .expect("failed to fork");
90
91 assert_eq!(child.wait().unwrap(), 0);
92 }
93
wait_for_panic()94 pub fn wait_for_panic() {
95 let jail = Minijail::new().unwrap();
96 let child = fork_process(jail, vec![], None, || {
97 panic!("fails");
98 })
99 .expect("failed to fork");
100
101 assert_eq!(child.wait().unwrap(), 101);
102 }
103 }
104
main()105 fn main() {
106 let args = libtest_mimic::Arguments {
107 // Force single-threaded execution to allow safe use of libc::fork in these tests.
108 test_threads: Some(1),
109 ..libtest_mimic::Arguments::from_args()
110 };
111
112 let tests = vec![
113 #[cfg(any(target_os = "android", target_os = "linux"))]
114 libtest_mimic::Trial::test("pid_diff", move || {
115 test::pid_diff();
116 Ok(())
117 }),
118 #[cfg(any(target_os = "android", target_os = "linux"))]
119 libtest_mimic::Trial::test("thread_name", move || {
120 test::thread_name();
121 Ok(())
122 }),
123 #[cfg(any(target_os = "android", target_os = "linux"))]
124 libtest_mimic::Trial::test("thread_name_trimmed", move || {
125 test::thread_name_trimmed();
126 Ok(())
127 }),
128 #[cfg(any(target_os = "android", target_os = "linux"))]
129 libtest_mimic::Trial::test("wait_for_success", move || {
130 test::wait_for_success();
131 Ok(())
132 }),
133 #[cfg(any(target_os = "android", target_os = "linux"))]
134 libtest_mimic::Trial::test("wait_for_panic", move || {
135 test::wait_for_panic();
136 Ok(())
137 }),
138 ];
139 libtest_mimic::run(&args, tests).exit();
140 }
141