• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Tests for `mlock`.
2 //!
3 //! We can't easily test that it actually locks memory, but we can test that we
4 //! can call it and either get success or a reasonable error message.
5 
6 use std::ffi::c_void;
7 
8 #[test]
test_mlock()9 fn test_mlock() {
10     let mut buf = vec![0_u8; 4096];
11 
12     unsafe {
13         match rustix::mm::mlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()) {
14             Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(),
15             // Tests won't always have enough memory or permissions, and that's ok.
16             Err(rustix::io::Errno::PERM) | Err(rustix::io::Errno::NOMEM) => {}
17             // But they shouldn't fail otherwise.
18             Err(other) => Err(other).unwrap(),
19         }
20     }
21 }
22 
23 #[cfg(any(target_os = "android", target_os = "linux"))]
24 #[test]
test_mlock_with()25 fn test_mlock_with() {
26     let mut buf = vec![0_u8; 4096];
27 
28     unsafe {
29         match rustix::mm::mlock_with(
30             buf.as_mut_ptr().cast::<c_void>(),
31             buf.len(),
32             rustix::mm::MlockFlags::empty(),
33         ) {
34             Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(),
35             // Tests won't always have enough memory or permissions, and that's ok.
36             Err(rustix::io::Errno::PERM)
37             | Err(rustix::io::Errno::NOMEM)
38             | Err(rustix::io::Errno::NOSYS) => {}
39             // But they shouldn't fail otherwise.
40             Err(other) => Err(other).unwrap(),
41         }
42     }
43 }
44 
45 #[cfg(any(target_os = "android", target_os = "linux"))]
46 #[test]
test_mlock_with_onfault()47 fn test_mlock_with_onfault() {
48     // With glibc, `mlock2` with `MLOCK_ONFAULT` returns `EINVAL` if the
49     // `mlock2` system call returns `ENOSYS`. That's not what we want
50     // here though, because `ENOSYS` just means the OS doesn't have
51     // `mlock2`, while `EINVAL` may indicate a bug in rustix.
52     //
53     // To work around this, we use `libc::syscall` to make a `mlock2`
54     // syscall directly to test for `ENOSYS`, before running the main
55     // test below.
56     unsafe {
57         if libc::syscall(libc::SYS_mlock2, 0, 0) == -1 && libc_errno::errno().0 == libc::ENOSYS {
58             return;
59         }
60     }
61 
62     let mut buf = vec![0_u8; 4096];
63 
64     unsafe {
65         match rustix::mm::mlock_with(
66             buf.as_mut_ptr().cast::<c_void>(),
67             buf.len(),
68             rustix::mm::MlockFlags::ONFAULT,
69         ) {
70             Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(),
71             // Tests won't always have enough memory or permissions, and that's ok.
72             Err(rustix::io::Errno::PERM)
73             | Err(rustix::io::Errno::NOMEM)
74             | Err(rustix::io::Errno::NOSYS) => {}
75             // But they shouldn't fail otherwise.
76             Err(other) => Err(other).unwrap(),
77         }
78     }
79 }
80