| //@ 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"); | |
| } |