]>
git.proxmox.com Git - rustc.git/blob - library/std/src/sys/windows/process/tests.rs
1 use super::make_command_line
;
4 use crate::ffi
::{OsStr, OsString}
;
5 use crate::process
::Command
;
9 let command_line
= &make_command_line(
10 OsStr
::new("quoted exe"),
12 Arg
::Regular(OsString
::from("quote me")),
13 Arg
::Raw(OsString
::from("quote me *not*")),
14 Arg
::Raw(OsString
::from("\t\\")),
15 Arg
::Raw(OsString
::from("internal \\\"backslash-\"quote")),
16 Arg
::Regular(OsString
::from("optional-quotes")),
22 String
::from_utf16(command_line
).unwrap(),
23 "\"quoted exe\" \"quote me\" quote me *not* \t\\ internal \\\"backslash-\"quote optional-quotes"
28 fn test_thread_handle() {
29 use crate::os
::windows
::io
::BorrowedHandle
;
30 use crate::os
::windows
::process
::{ChildExt, CommandExt}
;
31 const CREATE_SUSPENDED
: u32 = 0x00000004;
33 let p
= Command
::new("cmd").args(&["/C", "exit 0"]).creation_flags(CREATE_SUSPENDED
).spawn();
35 let mut p
= p
.unwrap();
38 fn ResumeThread(_
: BorrowedHandle
<'_
>) -> u32;
41 ResumeThread(p
.main_thread_handle());
44 crate::thread
::sleep(crate::time
::Duration
::from_millis(100));
46 let res
= p
.try_wait();
48 assert
!(res
.unwrap().is_some());
49 assert
!(p
.try_wait().unwrap().unwrap().success());
53 fn test_make_command_line() {
54 fn test_wrapper(prog
: &str, args
: &[&str], force_quotes
: bool
) -> String
{
55 let command_line
= &make_command_line(
57 &args
.iter().map(|a
| Arg
::Regular(OsString
::from(a
))).collect
::<Vec
<_
>>(),
61 String
::from_utf16(command_line
).unwrap()
64 assert_eq
!(test_wrapper("prog", &["aaa", "bbb", "ccc"], false), "\"prog\" aaa bbb ccc");
66 assert_eq
!(test_wrapper("prog", &[r
"C:\"], false), r
#""prog" C:\"#);
67 assert_eq!(test_wrapper("prog", &[r"2slashes\\"], false), r#""prog" 2slashes\\"#);
68 assert_eq!(test_wrapper("prog", &[r" C:\"], false), r#""prog" " C:\\""#);
69 assert_eq
!(test_wrapper("prog", &[r
" 2slashes\\"], false), r
#""prog" " 2slashes\\\\""#);
72 test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa"], false),
73 "\"C:\\Program Files\\blah\\blah.exe\" aaa"
76 test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa", "v*"], false),
77 "\"C:\\Program Files\\blah\\blah.exe\" aaa v*"
80 test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa", "v*"], true),
81 "\"C:\\Program Files\\blah\\blah.exe\" \"aaa\" \"v*\""
84 test_wrapper("C:\\Program Files\\test", &["aa\"bb"], false),
85 "\"C:\\Program Files\\test\" aa\\\"bb"
87 assert_eq
!(test_wrapper("echo", &["a b c"], false), "\"echo\" \"a b c\"");
89 test_wrapper("echo", &["\" \\\" \\", "\\"], false),
90 "\"echo\" \"\\\" \\\\\\\" \\\\\" \\"
93 test_wrapper("\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}", &[], false),
94 "\"\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}\""
98 // On Windows, environment args are case preserving but comparisons are case-insensitive.
101 fn windows_env_unicode_case() {
136 // Test that `cmd.env` matches `env::set_var` when setting two strings that
137 // may (or may not) be case-folded when compared.
138 for (a
, b
) in test_cases
.iter() {
139 let mut cmd
= Command
::new("cmd");
142 env
::set_var(a
, "1");
143 env
::set_var(b
, "2");
145 for (key
, value
) in cmd
.get_envs() {
148 value
.map(|s
| s
.to_string_lossy().into_owned()),
149 "command environment mismatch: {a} {b}",
155 // UWP applications run in a restricted environment which means this test may not work.
156 #[cfg(not(target_vendor = "uwp"))]
158 fn windows_exe_resolver() {
159 use super::resolve_exe
;
161 use crate::sys
::fs
::symlink
;
162 use crate::sys_common
::io
::test
::tmpdir
;
164 let env_paths
= || env
::var_os("PATH");
166 // Test a full path, with and without the `exe` extension.
167 let mut current_exe
= env
::current_exe().unwrap();
168 assert
!(resolve_exe(current_exe
.as_ref(), env_paths
, None
).is_ok());
169 current_exe
.set_extension("");
170 assert
!(resolve_exe(current_exe
.as_ref(), env_paths
, None
).is_ok());
172 // Test lone file names.
173 assert
!(resolve_exe(OsStr
::new("cmd"), env_paths
, None
).is_ok());
174 assert
!(resolve_exe(OsStr
::new("cmd.exe"), env_paths
, None
).is_ok());
175 assert
!(resolve_exe(OsStr
::new("cmd.EXE"), env_paths
, None
).is_ok());
176 assert
!(resolve_exe(OsStr
::new("fc"), env_paths
, None
).is_ok());
178 // Invalid file names should return InvalidInput.
180 resolve_exe(OsStr
::new(""), env_paths
, None
).unwrap_err().kind(),
181 io
::ErrorKind
::InvalidInput
184 resolve_exe(OsStr
::new("\0"), env_paths
, None
).unwrap_err().kind(),
185 io
::ErrorKind
::InvalidInput
187 // Trailing slash, therefore there's no file name component.
189 resolve_exe(OsStr
::new(r
"C:\Path\to\"), env_paths
, None
).unwrap_err().kind(),
190 io
::ErrorKind
::InvalidInput
194 Some of the following tests may need to be changed if you are deliberately
195 changing the behaviour of `resolve_exe`.
198 let empty_paths
= || None
;
200 // The resolver looks in system directories even when `PATH` is empty.
201 assert
!(resolve_exe(OsStr
::new("cmd.exe"), empty_paths
, None
).is_ok());
203 // The application's directory is also searched.
204 let current_exe
= env
::current_exe().unwrap();
205 assert
!(resolve_exe(current_exe
.file_name().unwrap().as_ref(), empty_paths
, None
).is_ok());
207 // Create a temporary path and add a broken symlink.
209 let mut exe_path
= temp
.path().to_owned();
210 exe_path
.push("exists.exe");
212 // A broken symlink should still be resolved.
213 // Skip this check if not in CI and creating symlinks isn't possible.
214 let is_ci
= env
::var("CI").is_ok();
215 let result
= symlink("<DOES NOT EXIST>".as_ref(), &exe_path
);
216 if is_ci
|| result
.is_ok() {
219 resolve_exe(OsStr
::new("exists.exe"), empty_paths
, Some(temp
.path().as_ref())).is_ok()