• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&regions, &[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(&regions, &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(&regions, &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