summaryrefslogtreecommitdiffstats
path: root/library/std/src/process/tests.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /library/std/src/process/tests.rs
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/process/tests.rs')
-rw-r--r--library/std/src/process/tests.rs132
1 files changed, 131 insertions, 1 deletions
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 366b59146..07d4de5c1 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -434,6 +434,91 @@ fn test_creation_flags() {
assert!(events > 0);
}
+/// Tests proc thread attributes by spawning a process with a custom parent process,
+/// then comparing the parent process ID with the expected parent process ID.
+#[test]
+#[cfg(windows)]
+fn test_proc_thread_attributes() {
+ use crate::mem;
+ use crate::os::windows::io::AsRawHandle;
+ use crate::os::windows::process::CommandExt;
+ use crate::sys::c::{CloseHandle, BOOL, HANDLE};
+ use crate::sys::cvt;
+
+ #[repr(C)]
+ #[allow(non_snake_case)]
+ struct PROCESSENTRY32W {
+ dwSize: u32,
+ cntUsage: u32,
+ th32ProcessID: u32,
+ th32DefaultHeapID: usize,
+ th32ModuleID: u32,
+ cntThreads: u32,
+ th32ParentProcessID: u32,
+ pcPriClassBase: i32,
+ dwFlags: u32,
+ szExeFile: [u16; 260],
+ }
+
+ extern "system" {
+ fn CreateToolhelp32Snapshot(dwflags: u32, th32processid: u32) -> HANDLE;
+ fn Process32First(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
+ fn Process32Next(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
+ }
+
+ const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
+ const TH32CS_SNAPPROCESS: u32 = 0x00000002;
+
+ struct ProcessDropGuard(crate::process::Child);
+
+ impl Drop for ProcessDropGuard {
+ fn drop(&mut self) {
+ let _ = self.0.kill();
+ }
+ }
+
+ let parent = ProcessDropGuard(Command::new("cmd").spawn().unwrap());
+
+ let mut child_cmd = Command::new("cmd");
+
+ unsafe {
+ child_cmd
+ .raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.0.as_raw_handle() as isize);
+ }
+
+ let child = ProcessDropGuard(child_cmd.spawn().unwrap());
+
+ let h_snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
+
+ let mut process_entry = PROCESSENTRY32W {
+ dwSize: mem::size_of::<PROCESSENTRY32W>() as u32,
+ cntUsage: 0,
+ th32ProcessID: 0,
+ th32DefaultHeapID: 0,
+ th32ModuleID: 0,
+ cntThreads: 0,
+ th32ParentProcessID: 0,
+ pcPriClassBase: 0,
+ dwFlags: 0,
+ szExeFile: [0; 260],
+ };
+
+ unsafe { cvt(Process32First(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
+
+ loop {
+ if child.0.id() == process_entry.th32ProcessID {
+ break;
+ }
+ unsafe { cvt(Process32Next(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
+ }
+
+ unsafe { cvt(CloseHandle(h_snapshot)) }.unwrap();
+
+ assert_eq!(parent.0.id(), process_entry.th32ParentProcessID);
+
+ drop(child)
+}
+
#[test]
fn test_command_implements_send_sync() {
fn take_send_sync_type<T: Send + Sync>(_: T) {}
@@ -452,7 +537,7 @@ fn env_empty() {
#[test]
#[cfg(not(windows))]
#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
-fn main() {
+fn debug_print() {
const PIDFD: &'static str =
if cfg!(target_os = "linux") { " create_pidfd: false,\n" } else { "" };
@@ -541,6 +626,51 @@ fn main() {
{PIDFD}}}"#
)
);
+
+ let mut command_with_removed_env = Command::new("boring-name");
+ command_with_removed_env.env_remove("FOO").env_remove("BAR");
+ assert_eq!(format!("{command_with_removed_env:?}"), r#"env -u BAR -u FOO "boring-name""#);
+ assert_eq!(
+ format!("{command_with_removed_env:#?}"),
+ format!(
+ r#"Command {{
+ program: "boring-name",
+ args: [
+ "boring-name",
+ ],
+ env: CommandEnv {{
+ clear: false,
+ vars: {{
+ "BAR": None,
+ "FOO": None,
+ }},
+ }},
+{PIDFD}}}"#
+ )
+ );
+
+ let mut command_with_cleared_env = Command::new("boring-name");
+ command_with_cleared_env.env_clear().env("BAR", "val").env_remove("FOO");
+ assert_eq!(format!("{command_with_cleared_env:?}"), r#"env -i BAR="val" "boring-name""#);
+ assert_eq!(
+ format!("{command_with_cleared_env:#?}"),
+ format!(
+ r#"Command {{
+ program: "boring-name",
+ args: [
+ "boring-name",
+ ],
+ env: CommandEnv {{
+ clear: true,
+ vars: {{
+ "BAR": Some(
+ "val",
+ ),
+ }},
+ }},
+{PIDFD}}}"#
+ )
+ );
}
// See issue #91991