diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/rustix/tests/process | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rustix/tests/process')
-rw-r--r-- | vendor/rustix/tests/process/cpu_set.rs | 14 | ||||
-rw-r--r-- | vendor/rustix/tests/process/id.rs | 65 | ||||
-rw-r--r-- | vendor/rustix/tests/process/main.rs | 28 | ||||
-rw-r--r-- | vendor/rustix/tests/process/membarrier.rs | 40 | ||||
-rw-r--r-- | vendor/rustix/tests/process/priority.rs | 83 | ||||
-rw-r--r-- | vendor/rustix/tests/process/proc.rs | 5 | ||||
-rw-r--r-- | vendor/rustix/tests/process/rlimit.rs | 51 | ||||
-rw-r--r-- | vendor/rustix/tests/process/sched_yield.rs | 7 | ||||
-rw-r--r-- | vendor/rustix/tests/process/uname.rs | 13 | ||||
-rw-r--r-- | vendor/rustix/tests/process/wait.rs | 25 | ||||
-rw-r--r-- | vendor/rustix/tests/process/weak.rs | 201 | ||||
-rw-r--r-- | vendor/rustix/tests/process/working_directory.rs | 43 |
12 files changed, 575 insertions, 0 deletions
diff --git a/vendor/rustix/tests/process/cpu_set.rs b/vendor/rustix/tests/process/cpu_set.rs new file mode 100644 index 000000000..c4d9edf08 --- /dev/null +++ b/vendor/rustix/tests/process/cpu_set.rs @@ -0,0 +1,14 @@ +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_cpu_set() { + let set = rustix::process::sched_getaffinity(None).unwrap(); + + let mut count = 0; + for i in 0..rustix::process::CpuSet::MAX_CPU { + if set.is_set(i) { + count += 1; + } + } + + assert_eq!(count, set.count()); +} diff --git a/vendor/rustix/tests/process/id.rs b/vendor/rustix/tests/process/id.rs new file mode 100644 index 000000000..10095fa60 --- /dev/null +++ b/vendor/rustix/tests/process/id.rs @@ -0,0 +1,65 @@ +use rustix::process; + +#[test] +fn test_getuid() { + assert_eq!(process::getuid(), process::getuid()); + unsafe { + assert_eq!(process::getuid().as_raw(), libc::getuid()); + assert_eq!(process::getuid().is_root(), libc::getuid() == 0); + } +} + +#[test] +fn test_getgid() { + assert_eq!(process::getgid(), process::getgid()); + unsafe { + assert_eq!(process::getgid().as_raw(), libc::getgid()); + assert_eq!(process::getgid().is_root(), libc::getgid() == 0); + } +} + +#[test] +fn test_geteuid() { + assert_eq!(process::geteuid(), process::geteuid()); + unsafe { + assert_eq!(process::geteuid().as_raw(), libc::geteuid()); + assert_eq!(process::geteuid().is_root(), libc::geteuid() == 0); + } +} + +#[test] +fn test_getegid() { + assert_eq!(process::getegid(), process::getegid()); + unsafe { + assert_eq!(process::getegid().as_raw(), libc::getegid()); + assert_eq!(process::getegid().is_root(), libc::getegid() == 0); + } +} + +#[test] +fn test_getpid() { + assert_eq!(process::getpid(), process::getpid()); + unsafe { + assert_eq!( + process::getpid().as_raw_nonzero().get() as libc::pid_t, + libc::getpid() + ); + assert_eq!(process::getpid().is_init(), libc::getpid() == 1); + } +} + +#[test] +fn test_getppid() { + assert_eq!(process::getppid(), process::getppid()); + unsafe { + assert_eq!( + process::Pid::as_raw(process::getppid()) as libc::pid_t, + libc::getppid() + ); + if let Some(ppid) = process::getppid() { + assert_eq!(ppid.is_init(), libc::getppid() == 1); + } else { + assert_eq!(libc::getppid(), 0); + } + } +} diff --git a/vendor/rustix/tests/process/main.rs b/vendor/rustix/tests/process/main.rs new file mode 100644 index 000000000..90aa34c59 --- /dev/null +++ b/vendor/rustix/tests/process/main.rs @@ -0,0 +1,28 @@ +//! Tests for [`rustix::process`]. + +#![cfg(feature = "process")] +#![cfg(not(windows))] +#![cfg_attr(target_os = "wasi", feature(wasi_ext))] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] +#![cfg_attr(core_c_str, feature(core_c_str))] + +#[cfg(not(target_os = "wasi"))] +#[macro_use] +mod weak; + +mod cpu_set; +#[cfg(not(target_os = "wasi"))] // WASI doesn't have get[gpu]id. +mod id; +#[cfg(any(target_os = "android", target_os = "linux"))] +mod membarrier; +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] // WASI doesn't have [gs]etpriority. +mod priority; +#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +mod rlimit; +mod sched_yield; +#[cfg(not(target_os = "wasi"))] // WASI doesn't have uname. +mod uname; +#[cfg(not(target_os = "wasi"))] // WASI doesn't have waitpid. +mod wait; +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] +mod working_directory; diff --git a/vendor/rustix/tests/process/membarrier.rs b/vendor/rustix/tests/process/membarrier.rs new file mode 100644 index 000000000..ed9b00c1a --- /dev/null +++ b/vendor/rustix/tests/process/membarrier.rs @@ -0,0 +1,40 @@ +#[test] +fn test_membarrier() { + use rustix::process::{membarrier, membarrier_query, MembarrierCommand, MembarrierQuery}; + + let query: MembarrierQuery = membarrier_query(); + + // Supported registration commands should succeed. + for cmd in [ + MembarrierCommand::RegisterGlobalExpedited, + MembarrierCommand::RegisterPrivateExpedited, + MembarrierCommand::RegisterPrivateExpeditedSyncCore, + MembarrierCommand::RegisterPrivateExpeditedRseq, + ] + .iter() + .copied() + { + if query.contains_command(cmd) { + membarrier(cmd).unwrap(); + } + } + + // All supported commands should now succeed, and all unsupported + // commands should fail. + for cmd in [ + MembarrierCommand::Global, + MembarrierCommand::GlobalExpedited, + MembarrierCommand::PrivateExpedited, + MembarrierCommand::PrivateExpeditedSyncCore, + MembarrierCommand::PrivateExpeditedRseq, + ] + .iter() + .copied() + { + if query.contains_command(cmd) { + membarrier(cmd).unwrap(); + } else { + membarrier(cmd).unwrap_err(); + } + } +} diff --git a/vendor/rustix/tests/process/priority.rs b/vendor/rustix/tests/process/priority.rs new file mode 100644 index 000000000..7feb1467a --- /dev/null +++ b/vendor/rustix/tests/process/priority.rs @@ -0,0 +1,83 @@ +use rustix::process::nice; +#[cfg(not(target_os = "redox"))] +use rustix::process::{getpriority_process, setpriority_process}; + +#[cfg(not(target_os = "freebsd"))] // FreeBSD's nice(3) doesn't return the old value. +#[test] +fn test_priorities() { + let old = nice(0).unwrap(); + + #[cfg(not(target_os = "redox"))] + { + let get_prio = getpriority_process(None).unwrap(); + assert_eq!(get_prio, old); + } + + // Lower the priority by one. + let new = nice(1).unwrap(); + + // If the test wasn't running with the lowest priority initially, test that + // we were able to lower the priority. + if old < 19 { + assert_eq!(old + 1, new); + } + + let get = nice(0).unwrap(); + assert_eq!(new, get); + + #[cfg(not(target_os = "redox"))] + { + let get_prio = getpriority_process(None).unwrap(); + assert_eq!(get_prio, new); + + setpriority_process(None, get + 1).unwrap(); + let now = getpriority_process(None).unwrap(); + + // If the test wasn't running with the lowest priority initially, test + // that we were able to lower the priority. + if get < 19 { + assert_eq!(get + 1, now); + } + setpriority_process(None, get + 10000).unwrap(); + let now = getpriority_process(None).unwrap(); + // Linux's max is 19; Darwin's max is 20. + assert!(now >= 19 && now <= 20); + // Darwin appears to return `EPERM` on an out of range `nice`. + if let Ok(again) = nice(1) { + assert_eq!(now, again); + } + } +} + +/// FreeBSD's `nice` doesn't return the new nice value, so use a specialized +/// test. +#[cfg(target_os = "freebsd")] +#[test] +fn test_priorities() { + let start = getpriority_process(None).unwrap(); + + let _ = nice(0).unwrap(); + + let now = getpriority_process(None).unwrap(); + assert_eq!(start, now); + + let _ = nice(1).unwrap(); + + let now = getpriority_process(None).unwrap(); + assert_eq!(start + 1, now); + + setpriority_process(None, start + 2).unwrap(); + + let now = getpriority_process(None).unwrap(); + assert_eq!(start + 2, now); + + setpriority_process(None, 10000).unwrap(); + + let now = getpriority_process(None).unwrap(); + assert_eq!(now, 20); + + let _ = nice(1).unwrap(); + + let now = getpriority_process(None).unwrap(); + assert_eq!(now, 20); +} diff --git a/vendor/rustix/tests/process/proc.rs b/vendor/rustix/tests/process/proc.rs new file mode 100644 index 000000000..e85d85883 --- /dev/null +++ b/vendor/rustix/tests/process/proc.rs @@ -0,0 +1,5 @@ +#[test] +fn test_proc_funcs() { + let _maps = rustix::io::proc_self_maps().unwrap(); + let _pagemap = rustix::io::proc_self_pagemap().unwrap(); +} diff --git a/vendor/rustix/tests/process/rlimit.rs b/vendor/rustix/tests/process/rlimit.rs new file mode 100644 index 000000000..b01f9204c --- /dev/null +++ b/vendor/rustix/tests/process/rlimit.rs @@ -0,0 +1,51 @@ +use rustix::process::{Resource, Rlimit}; + +#[test] +fn test_getrlimit() { + let lim = rustix::process::getrlimit(Resource::Stack); + assert_ne!(lim.current, Some(0)); + assert_ne!(lim.maximum, Some(0)); +} + +#[test] +fn test_setrlimit() { + let old = rustix::process::getrlimit(Resource::Core); + let new = Rlimit { + current: Some(0), + maximum: Some(4096), + }; + assert_ne!(old, new); + rustix::process::setrlimit(Resource::Core, new.clone()).unwrap(); + + let lim = rustix::process::getrlimit(Resource::Core); + assert_eq!(lim, new); + + #[cfg(any(target_os = "android", target_os = "linux"))] + { + let new = Rlimit { + current: Some(0), + maximum: Some(0), + }; + + let first = rustix::process::getrlimit(Resource::Core); + + let old = match rustix::process::prlimit(None, Resource::Core, new.clone()) { + Ok(rlimit) => rlimit, + Err(rustix::io::Errno::NOSYS) => return, + Err(e) => Err(e).unwrap(), + }; + + assert_eq!(first, old); + + let other = Rlimit { + current: Some(0), + maximum: Some(0), + }; + + let again = + rustix::process::prlimit(Some(rustix::process::getpid()), Resource::Core, other) + .unwrap(); + + assert_eq!(again, new); + } +} diff --git a/vendor/rustix/tests/process/sched_yield.rs b/vendor/rustix/tests/process/sched_yield.rs new file mode 100644 index 000000000..eacf17d5e --- /dev/null +++ b/vendor/rustix/tests/process/sched_yield.rs @@ -0,0 +1,7 @@ +use rustix::process::sched_yield; + +#[test] +fn test_sched_yield() { + // Just make sure we can call it. + sched_yield(); +} diff --git a/vendor/rustix/tests/process/uname.rs b/vendor/rustix/tests/process/uname.rs new file mode 100644 index 000000000..bc944c49e --- /dev/null +++ b/vendor/rustix/tests/process/uname.rs @@ -0,0 +1,13 @@ +#[test] +fn test_uname() { + let name: rustix::process::Uname = rustix::process::uname(); + + assert!(!name.sysname().to_bytes().is_empty()); + assert!(!name.nodename().to_bytes().is_empty()); + assert!(!name.release().to_bytes().is_empty()); + assert!(!name.version().to_bytes().is_empty()); + assert!(!name.machine().to_bytes().is_empty()); + + #[cfg(any(target_os = "android", target_os = "linux"))] + assert!(!name.domainname().to_bytes().is_empty()); +} diff --git a/vendor/rustix/tests/process/wait.rs b/vendor/rustix/tests/process/wait.rs new file mode 100644 index 000000000..a1f25a631 --- /dev/null +++ b/vendor/rustix/tests/process/wait.rs @@ -0,0 +1,25 @@ +use libc::{kill, SIGSTOP}; +use rustix::process; +use serial_test::serial; +use std::process::{Command, Stdio}; + +// These tests must execute serially to prevent race condition, where +// `test_wait` waits for the child process spawned in `test_waitpid`, causing +// the tests to get stuck. + +#[test] +#[serial] +fn test_waitpid() { + let child = Command::new("yes") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .expect("failed to execute child"); + unsafe { kill(child.id() as _, SIGSTOP) }; + + let pid = unsafe { process::Pid::from_raw(child.id() as _) }; + let status = process::waitpid(pid, process::WaitOptions::UNTRACED) + .expect("failed to wait") + .unwrap(); + assert!(status.stopped()); +} diff --git a/vendor/rustix/tests/process/weak.rs b/vendor/rustix/tests/process/weak.rs new file mode 100644 index 000000000..d4f00f999 --- /dev/null +++ b/vendor/rustix/tests/process/weak.rs @@ -0,0 +1,201 @@ +// Implementation derived from `weak` in Rust's +// library/std/src/sys/unix/weak.rs at revision +// fd0cb0cdc21dd9c06025277d772108f8d42cb25f. + +//! Support for "weak linkage" to symbols on Unix +//! +//! Some I/O operations we do in libstd require newer versions of OSes but we +//! need to maintain binary compatibility with older releases for now. In order +//! to use the new functionality when available we use this module for +//! detection. +//! +//! One option to use here is weak linkage, but that is unfortunately only +//! really workable on Linux. Hence, use dlsym to get the symbol value at +//! runtime. This is also done for compatibility with older versions of glibc, +//! and to avoid creating dependencies on `GLIBC_PRIVATE` symbols. It assumes +//! that we've been dynamically linked to the library the symbol comes from, +//! but that is currently always the case for things like libpthread/libc. +//! +//! A long time ago this used weak linkage for the `__pthread_get_minstack` +//! symbol, but that caused Debian to detect an unnecessarily strict versioned +//! dependency on libc6 (#23628). + +// There are a variety of `#[cfg]`s controlling which targets are involved in +// each instance of `weak!` and `syscall!`. Rather than trying to unify all of +// that, we'll just allow that some unix targets don't use this module at all. +#![allow(dead_code, unused_macros)] +#![allow(clippy::doc_markdown)] + +use core::ffi::c_void; +use core::ptr::null_mut; +use core::sync::atomic::{self, AtomicPtr, Ordering}; +use core::{marker, mem}; +use rustix::ffi::CStr; + +const NULL: *mut c_void = null_mut(); +const INVALID: *mut c_void = 1 as *mut c_void; + +macro_rules! weak { + (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + #[allow(non_upper_case_globals)] + static $name: $crate::weak::Weak<unsafe extern fn($($t),*) -> $ret> = + $crate::weak::Weak::new(concat!(stringify!($name), '\0')); + ) +} + +pub(crate) struct Weak<F> { + name: &'static str, + addr: AtomicPtr<c_void>, + _marker: marker::PhantomData<F>, +} + +impl<F> Weak<F> { + pub(crate) const fn new(name: &'static str) -> Self { + Self { + name, + addr: AtomicPtr::new(INVALID), + _marker: marker::PhantomData, + } + } + + pub(crate) fn get(&self) -> Option<F> { + assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>()); + unsafe { + // Relaxed is fine here because we fence before reading through the + // pointer (see the comment below). + match self.addr.load(Ordering::Relaxed) { + INVALID => self.initialize(), + NULL => None, + addr => { + let func = mem::transmute_copy::<*mut c_void, F>(&addr); + // The caller is presumably going to read through this value + // (by calling the function we've dlsymed). This means we'd + // need to have loaded it with at least C11's consume + // ordering in order to be guaranteed that the data we read + // from the pointer isn't from before the pointer was + // stored. Rust has no equivalent to memory_order_consume, + // so we use an acquire fence (sorry, ARM). + // + // Now, in practice this likely isn't needed even on CPUs + // where relaxed and consume mean different things. The + // symbols we're loading are probably present (or not) at + // init, and even if they aren't the runtime dynamic loader + // is extremely likely have sufficient barriers internally + // (possibly implicitly, for example the ones provided by + // invoking `mprotect`). + // + // That said, none of that's *guaranteed*, and so we fence. + atomic::fence(Ordering::Acquire); + Some(func) + } + } + } + } + + // Cold because it should only happen during first-time initialization. + #[cold] + unsafe fn initialize(&self) -> Option<F> { + let val = fetch(self.name); + // This synchronizes with the acquire fence in `get`. + self.addr.store(val, Ordering::Release); + + match val { + NULL => None, + addr => Some(mem::transmute_copy::<*mut c_void, F>(&addr)), + } + } +} + +unsafe fn fetch(name: &str) -> *mut c_void { + let name = match CStr::from_bytes_with_nul(name.as_bytes()) { + Ok(c_str) => c_str, + Err(..) => return null_mut(), + }; + libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr().cast()) +} + +#[cfg(not(any(target_os = "android", target_os = "linux")))] +macro_rules! syscall { + (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + unsafe fn $name($($arg_name: $t),*) -> $ret { + weak! { fn $name($($t),*) -> $ret } + + if let Some(fun) = $name.get() { + fun($($arg_name),*) + } else { + errno::set_errno(errno::Errno(libc::ENOSYS)); + -1 + } + } + ) +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +macro_rules! syscall { + (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + unsafe fn $name($($arg_name:$t),*) -> $ret { + // This looks like a hack, but concat_idents only accepts idents + // (not paths). + use libc::*; + + trait AsSyscallArg { + type SyscallArgType; + fn as_syscall_arg(self) -> Self::SyscallArgType; + } + + // Pass pointer types as pointers, to preserve provenance. + impl<T> AsSyscallArg for *mut T { + type SyscallArgType = *mut T; + fn as_syscall_arg(self) -> Self::SyscallArgType { self } + } + impl<T> AsSyscallArg for *const T { + type SyscallArgType = *const T; + fn as_syscall_arg(self) -> Self::SyscallArgType { self } + } + + // Pass `BorrowedFd` values as the integer value. + impl AsSyscallArg for $crate::fd::BorrowedFd<'_> { + type SyscallArgType = c::c_long; + fn as_syscall_arg(self) -> Self::SyscallArgType { + $crate::fd::AsRawFd::as_raw_fd(&self) as _ + } + } + + // Coerce integer values into `c_long`. + impl AsSyscallArg for i32 { + type SyscallArgType = c::c_long; + fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + impl AsSyscallArg for u32 { + type SyscallArgType = c::c_long; + fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + impl AsSyscallArg for usize { + type SyscallArgType = c::c_long; + fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + + syscall( + concat_idents!(SYS_, $name), + $($arg_name.as_syscall_arg()),* + ) as $ret + } + ) +} + +macro_rules! weakcall { + ($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + $vis unsafe fn $name($($arg_name: $t),*) -> $ret { + weak! { fn $name($($t),*) -> $ret } + + // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` + // interposition, but if it's not found just fail. + if let Some(fun) = $name.get() { + fun($($arg_name),*) + } else { + errno::set_errno(errno::Errno(libc::ENOSYS)); + -1 + } + } + ) +} diff --git a/vendor/rustix/tests/process/working_directory.rs b/vendor/rustix/tests/process/working_directory.rs new file mode 100644 index 000000000..1c3262bb9 --- /dev/null +++ b/vendor/rustix/tests/process/working_directory.rs @@ -0,0 +1,43 @@ +#![cfg(feature = "fs")] + +#[cfg(not(target_os = "macos"))] +use rustix::fs::{Mode, OFlags}; +use tempfile::{tempdir, TempDir}; + +#[allow(unused)] +fn tmpdir() -> TempDir { + tempdir().expect("expected to be able to create a temporary directory") +} + +/// Disable this test on macos because GHA has a weird system folder structure +/// that makes this test fail. +#[cfg(not(target_os = "macos"))] +#[test] +fn test_changing_working_directory() { + let tmpdir = tmpdir(); + + let orig_cwd = rustix::process::getcwd(Vec::new()).expect("get the cwd"); + let orig_fd_cwd = rustix::fs::openat(rustix::fs::cwd(), ".", OFlags::RDONLY, Mode::empty()) + .expect("get a fd for the current directory"); + + rustix::process::chdir(tmpdir.path()).expect("changing dir to the tmp"); + let ch1_cwd = rustix::process::getcwd(Vec::new()).expect("get the cwd"); + + assert_ne!(orig_cwd, ch1_cwd, "The cwd hasn't changed!"); + assert_eq!( + ch1_cwd.to_string_lossy(), + tmpdir.path().to_string_lossy(), + "The cwd is not the same as the tmpdir" + ); + + #[cfg(not(target_os = "fuchsia"))] + rustix::process::fchdir(orig_fd_cwd).expect("changing dir to the original"); + #[cfg(target_os = "fushcia")] + rustix::process::chdir(orig_cwd).expect("changing dir to the original"); + let ch2_cwd = rustix::process::getcwd(ch1_cwd).expect("get the cwd"); + + assert_eq!( + orig_cwd, ch2_cwd, + "The cwd wasn't changed back to the its original position" + ); +} |