summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/tests/process
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/tests/process')
-rw-r--r--vendor/rustix/tests/process/cpu_set.rs14
-rw-r--r--vendor/rustix/tests/process/id.rs65
-rw-r--r--vendor/rustix/tests/process/main.rs28
-rw-r--r--vendor/rustix/tests/process/membarrier.rs40
-rw-r--r--vendor/rustix/tests/process/priority.rs83
-rw-r--r--vendor/rustix/tests/process/proc.rs5
-rw-r--r--vendor/rustix/tests/process/rlimit.rs51
-rw-r--r--vendor/rustix/tests/process/sched_yield.rs7
-rw-r--r--vendor/rustix/tests/process/uname.rs13
-rw-r--r--vendor/rustix/tests/process/wait.rs25
-rw-r--r--vendor/rustix/tests/process/weak.rs201
-rw-r--r--vendor/rustix/tests/process/working_directory.rs43
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"
+ );
+}