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 //! Integration tests for vmm-swap feature
6
7 #[cfg(unix)]
8 mod common;
9
10 #[cfg(unix)]
11 mod test {
12 use base::pagesize;
13 use base::sys::wait_for_pid;
14 use base::AsRawDescriptor;
15 use base::FromRawDescriptor;
16 use base::IntoRawDescriptor;
17 use base::SafeDescriptor;
18 use base::Tube;
19 use swap::userfaultfd::register_regions;
20 use swap::userfaultfd::unregister_regions;
21 use swap::userfaultfd::Userfaultfd;
22
23 use super::common::*;
24
register_region_skip_obsolete_process()25 pub fn register_region_skip_obsolete_process() {
26 let shm = create_shared_memory("test", 3 * pagesize());
27 let uffd = create_uffd_for_test();
28 let base_addr = shm.base_addr();
29 let regions = [base_addr..(base_addr + 3 * pagesize())];
30 let (tube_main, tube_child) = Tube::pair().unwrap();
31 let pid = unsafe { libc::fork() };
32 if pid == 0 {
33 // child process
34 let uffd = create_uffd_for_test();
35 tube_child
36 .send(&unsafe { SafeDescriptor::from_raw_descriptor(uffd.as_raw_descriptor()) })
37 .unwrap();
38 std::process::exit(0);
39 }
40 let uffd_descriptor = tube_main
41 .recv::<SafeDescriptor>()
42 .unwrap()
43 .into_raw_descriptor();
44 wait_for_pid(pid, 0).unwrap();
45 let uffd_child = unsafe { Userfaultfd::from_raw_descriptor(uffd_descriptor) };
46
47 let result = unsafe { register_regions(®ions, &[uffd, uffd_child]) };
48
49 // no error from ENOMEM
50 assert_eq!(result.is_ok(), true);
51 }
52
unregister_region_skip_obsolete_process()53 pub fn unregister_region_skip_obsolete_process() {
54 let shm = create_shared_memory("test", 3 * pagesize());
55 let uffd = create_uffd_for_test();
56 let base_addr = shm.base_addr();
57 let regions = [base_addr..(base_addr + 3 * pagesize())];
58 let (tube_main, tube_child) = Tube::pair().unwrap();
59 let pid = unsafe { libc::fork() };
60 if pid == 0 {
61 // child process
62 let uffd = create_uffd_for_test();
63 tube_child
64 .send(&unsafe { SafeDescriptor::from_raw_descriptor(uffd.as_raw_descriptor()) })
65 .unwrap();
66 tube_child.recv::<u8>().unwrap();
67 std::process::exit(0);
68 }
69 let uffd_descriptor = tube_main
70 .recv::<SafeDescriptor>()
71 .unwrap()
72 .into_raw_descriptor();
73 let uffd_child = unsafe { Userfaultfd::from_raw_descriptor(uffd_descriptor) };
74 let uffds = [uffd, uffd_child];
75
76 unsafe { register_regions(®ions, &uffds) }.unwrap();
77 tube_main.send(&0_u8).unwrap();
78 // wait until the child process die and the uffd_child become obsolete.
79 wait_for_pid(pid, 0).unwrap();
80 let result = unregister_regions(®ions, &uffds);
81
82 // no error from ENOMEM
83 assert_eq!(result.is_ok(), true);
84 }
85 }
86
main()87 fn main() {
88 let args = libtest_mimic::Arguments {
89 // Force single-threaded execution to allow safe use of libc::fork in these tests.
90 test_threads: Some(1),
91 ..libtest_mimic::Arguments::from_args()
92 };
93
94 let tests = vec![
95 #[cfg(unix)]
96 libtest_mimic::Trial::test("register_region_skip_obsolete_process", move || {
97 test::register_region_skip_obsolete_process();
98 Ok(())
99 }),
100 #[cfg(unix)]
101 libtest_mimic::Trial::test("unregister_region_skip_obsolete_process", move || {
102 test::unregister_region_skip_obsolete_process();
103 Ok(())
104 }),
105 ];
106 libtest_mimic::run(&args, tests).exit();
107 }
108