| //@ run-pass |
| //@ only-windows |
| //@ needs-subprocess |
| //@ no-prefer-dynamic |
| |
| // Test Windows std::process::Command search path semantics when setting PATH on the child process. |
| // NOTE: The exact semantics here are (possibly) subject to change. |
| |
| use std::process::Command; |
| use std::{env, fs, path}; |
| |
| fn main() { |
| if env::args().skip(1).any(|s| s == "--child") { |
| child(); |
| } else if env::args().skip(1).any(|s| s == "--parent") { |
| parent(); |
| } else { |
| setup(); |
| } |
| } |
| |
| // Set up the directories so that there are three app dirs: |
| // app: Where the parent app is run from |
| // parent: In the parent's PATH env var |
| // child: In the child's PATH env var |
| fn setup() { |
| let exe = env::current_exe().unwrap(); |
| |
| fs::create_dir_all("app").unwrap(); |
| fs::copy(&exe, "app/myapp.exe").unwrap(); |
| fs::create_dir_all("parent").unwrap(); |
| fs::copy(&exe, "parent/myapp.exe").unwrap(); |
| fs::create_dir_all("child").unwrap(); |
| fs::copy(&exe, "child/myapp.exe").unwrap(); |
| |
| let parent_path = path::absolute("parent").unwrap(); |
| let status = |
| Command::new("./app/myapp.exe").env("PATH", parent_path).arg("--parent").status().unwrap(); |
| // print the status in case of abnormal exit |
| dbg!(status); |
| assert!(status.success()); |
| } |
| |
| // The child simply prints the name of its parent directory. |
| fn child() { |
| let exe = env::current_exe().unwrap(); |
| let parent = exe.parent().unwrap().file_name().unwrap(); |
| println!("{}", parent.display()); |
| } |
| |
| fn parent() { |
| let exe = env::current_exe().unwrap(); |
| let name = exe.file_name().unwrap(); |
| |
| // By default, the application dir will be search first for the exe |
| let output = Command::new(&name).arg("--child").output().unwrap(); |
| assert_eq!(output.stdout, b"app\n"); |
| |
| // Setting an environment variable should not change the above. |
| let output = Command::new(&name).arg("--child").env("a", "b").output().unwrap(); |
| assert_eq!(output.stdout, b"app\n"); |
| |
| // Setting a child path means that path will be searched first. |
| let child_path = path::absolute("child").unwrap(); |
| let output = Command::new(&name).arg("--child").env("PATH", child_path).output().unwrap(); |
| assert_eq!(output.stdout, b"child\n"); |
| |
| // Setting a child path that does not contain the exe (currently) means |
| // we fallback to searching the app dir. |
| let output = Command::new(&name).arg("--child").env("PATH", "").output().unwrap(); |
| assert_eq!(output.stdout, b"app\n"); |
| } |