diff options
Diffstat (limited to 'vendor/rustix/tests/mm')
-rw-r--r-- | vendor/rustix/tests/mm/main.rs | 13 | ||||
-rw-r--r-- | vendor/rustix/tests/mm/mlock.rs | 79 | ||||
-rw-r--r-- | vendor/rustix/tests/mm/mmap.rs | 163 | ||||
-rw-r--r-- | vendor/rustix/tests/mm/prot.rs | 4 |
4 files changed, 259 insertions, 0 deletions
diff --git a/vendor/rustix/tests/mm/main.rs b/vendor/rustix/tests/mm/main.rs new file mode 100644 index 000000000..ee746d900 --- /dev/null +++ b/vendor/rustix/tests/mm/main.rs @@ -0,0 +1,13 @@ +//! Tests for [`rustix::mm`]. + +#![cfg(feature = "mm")] +#![cfg_attr(target_os = "wasi", feature(wasi_ext))] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] + +#[cfg(not(windows))] +#[cfg(not(target_os = "wasi"))] +mod mlock; +#[cfg(not(windows))] +mod mmap; +#[cfg(not(windows))] +mod prot; diff --git a/vendor/rustix/tests/mm/mlock.rs b/vendor/rustix/tests/mm/mlock.rs new file mode 100644 index 000000000..c4a1a83b5 --- /dev/null +++ b/vendor/rustix/tests/mm/mlock.rs @@ -0,0 +1,79 @@ +//! Tests for `mlock`. +//! +//! We can't easily test that it actually locks memory, but we can test that we +//! can call it and either get success or a reasonable error message. + +use std::ffi::c_void; + +#[test] +fn test_mlock() { + let mut buf = vec![0_u8; 4096]; + + unsafe { + match rustix::mm::mlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()) { + Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(), + // Tests won't always have enough memory or permissions, and that's ok. + Err(rustix::io::Errno::PERM) | Err(rustix::io::Errno::NOMEM) => {} + // But they shouldn't fail otherwise. + Err(other) => Err(other).unwrap(), + } + } +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_mlock_with() { + let mut buf = vec![0_u8; 4096]; + + unsafe { + match rustix::mm::mlock_with( + buf.as_mut_ptr().cast::<c_void>(), + buf.len(), + rustix::mm::MlockFlags::empty(), + ) { + Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(), + // Tests won't always have enough memory or permissions, and that's ok. + Err(rustix::io::Errno::PERM) + | Err(rustix::io::Errno::NOMEM) + | Err(rustix::io::Errno::NOSYS) => {} + // But they shouldn't fail otherwise. + Err(other) => Err(other).unwrap(), + } + } +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_mlock_with_onfault() { + // With glibc, `mlock2` with `MLOCK_ONFAULT` returns `EINVAL` if the + // `mlock2` system call returns `ENOSYS`. That's not what we want + // here though, because `ENOSYS` just means the OS doesn't have + // `mlock2`, while `EINVAL` may indicate a bug in rustix. + // + // To work around this, we use `libc::syscall` to make a `mlock2` + // syscall directly to test for `ENOSYS`, before running the main + // test below. + unsafe { + if libc::syscall(libc::SYS_mlock2, 0, 0) == -1 && libc_errno::errno().0 == libc::ENOSYS { + return; + } + } + + let mut buf = vec![0_u8; 4096]; + + unsafe { + match rustix::mm::mlock_with( + buf.as_mut_ptr().cast::<c_void>(), + buf.len(), + rustix::mm::MlockFlags::ONFAULT, + ) { + Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(), + // Tests won't always have enough memory or permissions, and that's ok. + Err(rustix::io::Errno::PERM) + | Err(rustix::io::Errno::NOMEM) + | Err(rustix::io::Errno::NOSYS) => {} + // But they shouldn't fail otherwise. + Err(other) => Err(other).unwrap(), + } + } +} diff --git a/vendor/rustix/tests/mm/mmap.rs b/vendor/rustix/tests/mm/mmap.rs new file mode 100644 index 000000000..6b27287d7 --- /dev/null +++ b/vendor/rustix/tests/mm/mmap.rs @@ -0,0 +1,163 @@ +#![cfg(not(target_os = "wasi"))] + +#[cfg(feature = "fs")] +#[cfg(not(target_os = "redox"))] +#[test] +fn test_mmap() { + use rustix::fs::{cwd, openat, Mode, OFlags}; + use rustix::io::write; + use rustix::mm::{mmap, munmap, MapFlags, ProtFlags}; + use std::ptr::null_mut; + use std::slice; + + let tmp = tempfile::tempdir().unwrap(); + let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); + + let file = openat( + &dir, + "foo", + OFlags::CREATE | OFlags::WRONLY | OFlags::TRUNC, + Mode::RUSR, + ) + .unwrap(); + write(&file, &[b'a'; 8192]).unwrap(); + drop(file); + + let file = openat(&dir, "foo", OFlags::RDONLY, Mode::empty()).unwrap(); + unsafe { + let addr = mmap( + null_mut(), + 8192, + ProtFlags::READ, + MapFlags::PRIVATE, + &file, + 0, + ) + .unwrap(); + let slice = slice::from_raw_parts(addr.cast::<u8>(), 8192); + assert_eq!(slice, &[b'a'; 8192]); + + munmap(addr, 8192).unwrap(); + } + + let file = openat(&dir, "foo", OFlags::RDONLY, Mode::empty()).unwrap(); + unsafe { + assert_eq!( + mmap( + null_mut(), + 8192, + ProtFlags::READ, + MapFlags::PRIVATE, + &file, + u64::MAX, + ) + .unwrap_err() + .raw_os_error(), + libc::EINVAL + ); + } +} + +#[test] +fn test_mmap_anonymous() { + use rustix::mm::{mmap_anonymous, munmap, MapFlags, ProtFlags}; + use std::ptr::null_mut; + use std::slice; + + unsafe { + let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap(); + let slice = slice::from_raw_parts(addr.cast::<u8>(), 8192); + assert_eq!(slice, &[b'\0'; 8192]); + + munmap(addr, 8192).unwrap(); + } +} + +#[test] +fn test_mprotect() { + use rustix::mm::{mmap_anonymous, mprotect, munmap, MapFlags, MprotectFlags, ProtFlags}; + use std::ptr::null_mut; + use std::slice; + + unsafe { + let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap(); + + mprotect(addr, 8192, MprotectFlags::empty()).unwrap(); + mprotect(addr, 8192, MprotectFlags::READ).unwrap(); + + let slice = slice::from_raw_parts(addr.cast::<u8>(), 8192); + assert_eq!(slice, &[b'\0'; 8192]); + + munmap(addr, 8192).unwrap(); + } +} + +#[test] +fn test_mlock() { + use rustix::mm::{mlock, mmap_anonymous, munlock, munmap, MapFlags, ProtFlags}; + #[cfg(any(target_os = "android", target_os = "linux"))] + use rustix::mm::{mlock_with, MlockFlags}; + use std::ptr::null_mut; + + unsafe { + let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap(); + + mlock(addr, 8192).unwrap(); + munlock(addr, 8192).unwrap(); + + #[cfg(any(target_os = "android", target_os = "linux"))] + { + match mlock_with(addr, 8192, MlockFlags::empty()) { + Err(rustix::io::Errno::NOSYS) => (), + Err(err) => Err(err).unwrap(), + Ok(()) => munlock(addr, 8192).unwrap(), + } + + #[cfg(linux_raw)] // libc doesn't expose `MLOCK_UNFAULT` yet. + { + match mlock_with(addr, 8192, MlockFlags::ONFAULT) { + Err(rustix::io::Errno::NOSYS) => (), + Err(err) => Err(err).unwrap(), + Ok(()) => munlock(addr, 8192).unwrap(), + } + munlock(addr, 8192).unwrap(); + } + } + + munmap(addr, 8192).unwrap(); + } +} + +#[cfg(not(target_os = "redox"))] +#[test] +fn test_madvise() { + use rustix::mm::{madvise, mmap_anonymous, munmap, Advice, MapFlags, ProtFlags}; + use std::ptr::null_mut; + + unsafe { + let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap(); + + madvise(addr, 8192, Advice::Normal).unwrap(); + madvise(addr, 8192, Advice::DontNeed).unwrap(); + + #[cfg(any(target_os = "android", target_os = "linux"))] + madvise(addr, 8192, Advice::LinuxDontNeed).unwrap(); + + munmap(addr, 8192).unwrap(); + } +} + +#[test] +fn test_msync() { + use rustix::mm::{mmap_anonymous, msync, munmap, MapFlags, MsyncFlags, ProtFlags}; + use std::ptr::null_mut; + + unsafe { + let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap(); + + msync(addr, 8192, MsyncFlags::SYNC).unwrap(); + msync(addr, 8192, MsyncFlags::ASYNC).unwrap(); + + munmap(addr, 8192).unwrap(); + } +} diff --git a/vendor/rustix/tests/mm/prot.rs b/vendor/rustix/tests/mm/prot.rs new file mode 100644 index 000000000..6c86a8f2a --- /dev/null +++ b/vendor/rustix/tests/mm/prot.rs @@ -0,0 +1,4 @@ +#[test] +fn test_prot_flags() { + assert_eq!(libc::PROT_NONE, 0); +} |