1b3ba51a1Sopenharmony_ciextern crate which;
2b3ba51a1Sopenharmony_ci
3b3ba51a1Sopenharmony_ci#[cfg(all(unix, feature = "regex"))]
4b3ba51a1Sopenharmony_ciuse regex::Regex;
5b3ba51a1Sopenharmony_ciuse std::ffi::{OsStr, OsString};
6b3ba51a1Sopenharmony_ciuse std::fs;
7b3ba51a1Sopenharmony_ciuse std::io;
8b3ba51a1Sopenharmony_ciuse std::path::{Path, PathBuf};
9b3ba51a1Sopenharmony_ciuse std::{env, vec};
10b3ba51a1Sopenharmony_ciuse tempfile::TempDir;
11b3ba51a1Sopenharmony_ci
12b3ba51a1Sopenharmony_cistruct TestFixture {
13b3ba51a1Sopenharmony_ci    /// Temp directory.
14b3ba51a1Sopenharmony_ci    pub tempdir: TempDir,
15b3ba51a1Sopenharmony_ci    /// $PATH
16b3ba51a1Sopenharmony_ci    pub paths: OsString,
17b3ba51a1Sopenharmony_ci    /// Binaries created in $PATH
18b3ba51a1Sopenharmony_ci    pub bins: Vec<PathBuf>,
19b3ba51a1Sopenharmony_ci}
20b3ba51a1Sopenharmony_ci
21b3ba51a1Sopenharmony_ciconst SUBDIRS: &[&str] = &["a", "b", "c"];
22b3ba51a1Sopenharmony_ciconst BIN_NAME: &str = "bin";
23b3ba51a1Sopenharmony_ci
24b3ba51a1Sopenharmony_ci#[cfg(unix)]
25b3ba51a1Sopenharmony_cifn mk_bin(dir: &Path, path: &str, extension: &str) -> io::Result<PathBuf> {
26b3ba51a1Sopenharmony_ci    use std::os::unix::fs::OpenOptionsExt;
27b3ba51a1Sopenharmony_ci    let bin = dir.join(path).with_extension(extension);
28b3ba51a1Sopenharmony_ci    fs::OpenOptions::new()
29b3ba51a1Sopenharmony_ci        .write(true)
30b3ba51a1Sopenharmony_ci        .create(true)
31b3ba51a1Sopenharmony_ci        .mode(0o666 | (libc::S_IXUSR as u32))
32b3ba51a1Sopenharmony_ci        .open(&bin)
33b3ba51a1Sopenharmony_ci        .and_then(|_f| bin.canonicalize())
34b3ba51a1Sopenharmony_ci}
35b3ba51a1Sopenharmony_ci
36b3ba51a1Sopenharmony_cifn touch(dir: &Path, path: &str, extension: &str) -> io::Result<PathBuf> {
37b3ba51a1Sopenharmony_ci    let b = dir.join(path).with_extension(extension);
38b3ba51a1Sopenharmony_ci    fs::File::create(&b).and_then(|_f| b.canonicalize())
39b3ba51a1Sopenharmony_ci}
40b3ba51a1Sopenharmony_ci
41b3ba51a1Sopenharmony_ci#[cfg(windows)]
42b3ba51a1Sopenharmony_cifn mk_bin(dir: &Path, path: &str, extension: &str) -> io::Result<PathBuf> {
43b3ba51a1Sopenharmony_ci    touch(dir, path, extension)
44b3ba51a1Sopenharmony_ci}
45b3ba51a1Sopenharmony_ci
46b3ba51a1Sopenharmony_ciimpl TestFixture {
47b3ba51a1Sopenharmony_ci    // tmp/a/bin
48b3ba51a1Sopenharmony_ci    // tmp/a/bin.exe
49b3ba51a1Sopenharmony_ci    // tmp/a/bin.cmd
50b3ba51a1Sopenharmony_ci    // tmp/b/bin
51b3ba51a1Sopenharmony_ci    // tmp/b/bin.exe
52b3ba51a1Sopenharmony_ci    // tmp/b/bin.cmd
53b3ba51a1Sopenharmony_ci    // tmp/c/bin
54b3ba51a1Sopenharmony_ci    // tmp/c/bin.exe
55b3ba51a1Sopenharmony_ci    // tmp/c/bin.cmd
56b3ba51a1Sopenharmony_ci    pub fn new() -> TestFixture {
57b3ba51a1Sopenharmony_ci        let tempdir = tempfile::tempdir().unwrap();
58b3ba51a1Sopenharmony_ci        let mut builder = fs::DirBuilder::new();
59b3ba51a1Sopenharmony_ci        builder.recursive(true);
60b3ba51a1Sopenharmony_ci        let mut paths = vec![];
61b3ba51a1Sopenharmony_ci        let mut bins = vec![];
62b3ba51a1Sopenharmony_ci        for d in SUBDIRS.iter() {
63b3ba51a1Sopenharmony_ci            let p = tempdir.path().join(d);
64b3ba51a1Sopenharmony_ci            builder.create(&p).unwrap();
65b3ba51a1Sopenharmony_ci            bins.push(mk_bin(&p, BIN_NAME, "").unwrap());
66b3ba51a1Sopenharmony_ci            bins.push(mk_bin(&p, BIN_NAME, "exe").unwrap());
67b3ba51a1Sopenharmony_ci            bins.push(mk_bin(&p, BIN_NAME, "cmd").unwrap());
68b3ba51a1Sopenharmony_ci            paths.push(p);
69b3ba51a1Sopenharmony_ci        }
70b3ba51a1Sopenharmony_ci        let p = tempdir.path().join("win-bin");
71b3ba51a1Sopenharmony_ci        builder.create(&p).unwrap();
72b3ba51a1Sopenharmony_ci        bins.push(mk_bin(&p, "win-bin", "exe").unwrap());
73b3ba51a1Sopenharmony_ci        paths.push(p);
74b3ba51a1Sopenharmony_ci        TestFixture {
75b3ba51a1Sopenharmony_ci            tempdir,
76b3ba51a1Sopenharmony_ci            paths: env::join_paths(paths).unwrap(),
77b3ba51a1Sopenharmony_ci            bins,
78b3ba51a1Sopenharmony_ci        }
79b3ba51a1Sopenharmony_ci    }
80b3ba51a1Sopenharmony_ci
81b3ba51a1Sopenharmony_ci    #[allow(dead_code)]
82b3ba51a1Sopenharmony_ci    pub fn touch(&self, path: &str, extension: &str) -> io::Result<PathBuf> {
83b3ba51a1Sopenharmony_ci        touch(self.tempdir.path(), path, extension)
84b3ba51a1Sopenharmony_ci    }
85b3ba51a1Sopenharmony_ci
86b3ba51a1Sopenharmony_ci    pub fn mk_bin(&self, path: &str, extension: &str) -> io::Result<PathBuf> {
87b3ba51a1Sopenharmony_ci        mk_bin(self.tempdir.path(), path, extension)
88b3ba51a1Sopenharmony_ci    }
89b3ba51a1Sopenharmony_ci}
90b3ba51a1Sopenharmony_ci
91b3ba51a1Sopenharmony_cifn _which<T: AsRef<OsStr>>(f: &TestFixture, path: T) -> which::Result<which::CanonicalPath> {
92b3ba51a1Sopenharmony_ci    which::CanonicalPath::new_in(path, Some(f.paths.clone()), f.tempdir.path())
93b3ba51a1Sopenharmony_ci}
94b3ba51a1Sopenharmony_ci
95b3ba51a1Sopenharmony_cifn _which_all<'a, T: AsRef<OsStr> + 'a>(
96b3ba51a1Sopenharmony_ci    f: &'a TestFixture,
97b3ba51a1Sopenharmony_ci    path: T,
98b3ba51a1Sopenharmony_ci) -> which::Result<impl Iterator<Item = which::Result<which::CanonicalPath>> + '_> {
99b3ba51a1Sopenharmony_ci    which::CanonicalPath::all_in(path, Some(f.paths.clone()), f.tempdir.path())
100b3ba51a1Sopenharmony_ci}
101b3ba51a1Sopenharmony_ci
102b3ba51a1Sopenharmony_ci#[test]
103b3ba51a1Sopenharmony_ci#[cfg(unix)]
104b3ba51a1Sopenharmony_cifn it_works() {
105b3ba51a1Sopenharmony_ci    use std::process::Command;
106b3ba51a1Sopenharmony_ci    let result = which::Path::new("rustc");
107b3ba51a1Sopenharmony_ci    assert!(result.is_ok());
108b3ba51a1Sopenharmony_ci
109b3ba51a1Sopenharmony_ci    let which_result = Command::new("which").arg("rustc").output();
110b3ba51a1Sopenharmony_ci
111b3ba51a1Sopenharmony_ci    assert_eq!(
112b3ba51a1Sopenharmony_ci        String::from(result.unwrap().to_str().unwrap()),
113b3ba51a1Sopenharmony_ci        String::from_utf8(which_result.unwrap().stdout)
114b3ba51a1Sopenharmony_ci            .unwrap()
115b3ba51a1Sopenharmony_ci            .trim()
116b3ba51a1Sopenharmony_ci    );
117b3ba51a1Sopenharmony_ci}
118b3ba51a1Sopenharmony_ci
119b3ba51a1Sopenharmony_ci#[test]
120b3ba51a1Sopenharmony_ci#[cfg(unix)]
121b3ba51a1Sopenharmony_cifn test_which() {
122b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
123b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &BIN_NAME).unwrap(), f.bins[0])
124b3ba51a1Sopenharmony_ci}
125b3ba51a1Sopenharmony_ci
126b3ba51a1Sopenharmony_ci#[test]
127b3ba51a1Sopenharmony_ci#[cfg(windows)]
128b3ba51a1Sopenharmony_cifn test_which() {
129b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
130b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &BIN_NAME).unwrap(), f.bins[1])
131b3ba51a1Sopenharmony_ci}
132b3ba51a1Sopenharmony_ci
133b3ba51a1Sopenharmony_ci#[test]
134b3ba51a1Sopenharmony_ci#[cfg(all(unix, feature = "regex"))]
135b3ba51a1Sopenharmony_cifn test_which_re_in_with_matches() {
136b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
137b3ba51a1Sopenharmony_ci    f.mk_bin("a/bin_0", "").unwrap();
138b3ba51a1Sopenharmony_ci    f.mk_bin("b/bin_1", "").unwrap();
139b3ba51a1Sopenharmony_ci    let re = Regex::new(r"bin_\d").unwrap();
140b3ba51a1Sopenharmony_ci
141b3ba51a1Sopenharmony_ci    let result: Vec<PathBuf> = which::which_re_in(re, Some(f.paths))
142b3ba51a1Sopenharmony_ci        .unwrap()
143b3ba51a1Sopenharmony_ci        .into_iter()
144b3ba51a1Sopenharmony_ci        .collect();
145b3ba51a1Sopenharmony_ci
146b3ba51a1Sopenharmony_ci    let temp = f.tempdir;
147b3ba51a1Sopenharmony_ci
148b3ba51a1Sopenharmony_ci    assert_eq!(
149b3ba51a1Sopenharmony_ci        result,
150b3ba51a1Sopenharmony_ci        vec![temp.path().join("a/bin_0"), temp.path().join("b/bin_1")]
151b3ba51a1Sopenharmony_ci    )
152b3ba51a1Sopenharmony_ci}
153b3ba51a1Sopenharmony_ci
154b3ba51a1Sopenharmony_ci#[test]
155b3ba51a1Sopenharmony_ci#[cfg(all(unix, feature = "regex"))]
156b3ba51a1Sopenharmony_cifn test_which_re_in_without_matches() {
157b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
158b3ba51a1Sopenharmony_ci    let re = Regex::new(r"bi[^n]").unwrap();
159b3ba51a1Sopenharmony_ci
160b3ba51a1Sopenharmony_ci    let result: Vec<PathBuf> = which::which_re_in(re, Some(f.paths))
161b3ba51a1Sopenharmony_ci        .unwrap()
162b3ba51a1Sopenharmony_ci        .into_iter()
163b3ba51a1Sopenharmony_ci        .collect();
164b3ba51a1Sopenharmony_ci
165b3ba51a1Sopenharmony_ci    assert_eq!(result, Vec::<PathBuf>::new())
166b3ba51a1Sopenharmony_ci}
167b3ba51a1Sopenharmony_ci
168b3ba51a1Sopenharmony_ci#[test]
169b3ba51a1Sopenharmony_ci#[cfg(all(unix, feature = "regex"))]
170b3ba51a1Sopenharmony_cifn test_which_re_accepts_owned_and_borrow() {
171b3ba51a1Sopenharmony_ci    which::which_re(Regex::new(r".").unwrap())
172b3ba51a1Sopenharmony_ci        .unwrap()
173b3ba51a1Sopenharmony_ci        .for_each(drop);
174b3ba51a1Sopenharmony_ci    which::which_re(&Regex::new(r".").unwrap())
175b3ba51a1Sopenharmony_ci        .unwrap()
176b3ba51a1Sopenharmony_ci        .for_each(drop);
177b3ba51a1Sopenharmony_ci    which::which_re_in(Regex::new(r".").unwrap(), Some("pth"))
178b3ba51a1Sopenharmony_ci        .unwrap()
179b3ba51a1Sopenharmony_ci        .for_each(drop);
180b3ba51a1Sopenharmony_ci    which::which_re_in(&Regex::new(r".").unwrap(), Some("pth"))
181b3ba51a1Sopenharmony_ci        .unwrap()
182b3ba51a1Sopenharmony_ci        .for_each(drop);
183b3ba51a1Sopenharmony_ci}
184b3ba51a1Sopenharmony_ci
185b3ba51a1Sopenharmony_ci#[test]
186b3ba51a1Sopenharmony_ci#[cfg(unix)]
187b3ba51a1Sopenharmony_cifn test_which_extension() {
188b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
189b3ba51a1Sopenharmony_ci    let b = Path::new(&BIN_NAME).with_extension("");
190b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &b).unwrap(), f.bins[0])
191b3ba51a1Sopenharmony_ci}
192b3ba51a1Sopenharmony_ci
193b3ba51a1Sopenharmony_ci#[test]
194b3ba51a1Sopenharmony_ci#[cfg(windows)]
195b3ba51a1Sopenharmony_cifn test_which_extension() {
196b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
197b3ba51a1Sopenharmony_ci    let b = Path::new(&BIN_NAME).with_extension("cmd");
198b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &b).unwrap(), f.bins[2])
199b3ba51a1Sopenharmony_ci}
200b3ba51a1Sopenharmony_ci
201b3ba51a1Sopenharmony_ci#[test]
202b3ba51a1Sopenharmony_ci#[cfg(windows)]
203b3ba51a1Sopenharmony_cifn test_which_no_extension() {
204b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
205b3ba51a1Sopenharmony_ci    let b = Path::new("win-bin");
206b3ba51a1Sopenharmony_ci    let which_result = which::which_in(&b, Some(&f.paths), ".").unwrap();
207b3ba51a1Sopenharmony_ci    // Make sure the extension is the correct case.
208b3ba51a1Sopenharmony_ci    assert_eq!(which_result.extension(), f.bins[9].extension());
209b3ba51a1Sopenharmony_ci    assert_eq!(fs::canonicalize(&which_result).unwrap(), f.bins[9])
210b3ba51a1Sopenharmony_ci}
211b3ba51a1Sopenharmony_ci
212b3ba51a1Sopenharmony_ci#[test]
213b3ba51a1Sopenharmony_cifn test_which_not_found() {
214b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
215b3ba51a1Sopenharmony_ci    assert!(_which(&f, "a").is_err());
216b3ba51a1Sopenharmony_ci}
217b3ba51a1Sopenharmony_ci
218b3ba51a1Sopenharmony_ci#[test]
219b3ba51a1Sopenharmony_cifn test_which_second() {
220b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
221b3ba51a1Sopenharmony_ci    let b = f.mk_bin("b/another", env::consts::EXE_EXTENSION).unwrap();
222b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, "another").unwrap(), b);
223b3ba51a1Sopenharmony_ci}
224b3ba51a1Sopenharmony_ci
225b3ba51a1Sopenharmony_ci#[test]
226b3ba51a1Sopenharmony_cifn test_which_all() {
227b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
228b3ba51a1Sopenharmony_ci    let actual = _which_all(&f, BIN_NAME)
229b3ba51a1Sopenharmony_ci        .unwrap()
230b3ba51a1Sopenharmony_ci        .map(|c| c.unwrap())
231b3ba51a1Sopenharmony_ci        .collect::<Vec<_>>();
232b3ba51a1Sopenharmony_ci    let mut expected = f
233b3ba51a1Sopenharmony_ci        .bins
234b3ba51a1Sopenharmony_ci        .iter()
235b3ba51a1Sopenharmony_ci        .map(|p| p.canonicalize().unwrap())
236b3ba51a1Sopenharmony_ci        .collect::<Vec<_>>();
237b3ba51a1Sopenharmony_ci    #[cfg(windows)]
238b3ba51a1Sopenharmony_ci    {
239b3ba51a1Sopenharmony_ci        expected.retain(|p| p.file_stem().unwrap() == BIN_NAME);
240b3ba51a1Sopenharmony_ci        expected.retain(|p| p.extension().map(|ext| ext == "exe" || ext == "cmd") == Some(true));
241b3ba51a1Sopenharmony_ci    }
242b3ba51a1Sopenharmony_ci    #[cfg(not(windows))]
243b3ba51a1Sopenharmony_ci    {
244b3ba51a1Sopenharmony_ci        expected.retain(|p| p.file_name().unwrap() == BIN_NAME);
245b3ba51a1Sopenharmony_ci    }
246b3ba51a1Sopenharmony_ci    assert_eq!(actual, expected);
247b3ba51a1Sopenharmony_ci}
248b3ba51a1Sopenharmony_ci
249b3ba51a1Sopenharmony_ci#[test]
250b3ba51a1Sopenharmony_ci#[cfg(unix)]
251b3ba51a1Sopenharmony_cifn test_which_absolute() {
252b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
253b3ba51a1Sopenharmony_ci    assert_eq!(
254b3ba51a1Sopenharmony_ci        _which(&f, &f.bins[3]).unwrap(),
255b3ba51a1Sopenharmony_ci        f.bins[3].canonicalize().unwrap()
256b3ba51a1Sopenharmony_ci    );
257b3ba51a1Sopenharmony_ci}
258b3ba51a1Sopenharmony_ci
259b3ba51a1Sopenharmony_ci#[test]
260b3ba51a1Sopenharmony_ci#[cfg(windows)]
261b3ba51a1Sopenharmony_cifn test_which_absolute() {
262b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
263b3ba51a1Sopenharmony_ci    assert_eq!(
264b3ba51a1Sopenharmony_ci        _which(&f, &f.bins[4]).unwrap(),
265b3ba51a1Sopenharmony_ci        f.bins[4].canonicalize().unwrap()
266b3ba51a1Sopenharmony_ci    );
267b3ba51a1Sopenharmony_ci}
268b3ba51a1Sopenharmony_ci
269b3ba51a1Sopenharmony_ci#[test]
270b3ba51a1Sopenharmony_ci#[cfg(windows)]
271b3ba51a1Sopenharmony_cifn test_which_absolute_path_case() {
272b3ba51a1Sopenharmony_ci    // Test that an absolute path with an uppercase extension
273b3ba51a1Sopenharmony_ci    // is accepted.
274b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
275b3ba51a1Sopenharmony_ci    let p = &f.bins[4];
276b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &p).unwrap(), f.bins[4].canonicalize().unwrap());
277b3ba51a1Sopenharmony_ci}
278b3ba51a1Sopenharmony_ci
279b3ba51a1Sopenharmony_ci#[test]
280b3ba51a1Sopenharmony_ci#[cfg(unix)]
281b3ba51a1Sopenharmony_cifn test_which_absolute_extension() {
282b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
283b3ba51a1Sopenharmony_ci    // Don't append EXE_EXTENSION here.
284b3ba51a1Sopenharmony_ci    let b = f.bins[3].parent().unwrap().join(&BIN_NAME);
285b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &b).unwrap(), f.bins[3].canonicalize().unwrap());
286b3ba51a1Sopenharmony_ci}
287b3ba51a1Sopenharmony_ci
288b3ba51a1Sopenharmony_ci#[test]
289b3ba51a1Sopenharmony_ci#[cfg(windows)]
290b3ba51a1Sopenharmony_cifn test_which_absolute_extension() {
291b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
292b3ba51a1Sopenharmony_ci    // Don't append EXE_EXTENSION here.
293b3ba51a1Sopenharmony_ci    let b = f.bins[4].parent().unwrap().join(&BIN_NAME);
294b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &b).unwrap(), f.bins[4].canonicalize().unwrap());
295b3ba51a1Sopenharmony_ci}
296b3ba51a1Sopenharmony_ci
297b3ba51a1Sopenharmony_ci#[test]
298b3ba51a1Sopenharmony_ci#[cfg(unix)]
299b3ba51a1Sopenharmony_cifn test_which_relative() {
300b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
301b3ba51a1Sopenharmony_ci    assert_eq!(
302b3ba51a1Sopenharmony_ci        _which(&f, "b/bin").unwrap(),
303b3ba51a1Sopenharmony_ci        f.bins[3].canonicalize().unwrap()
304b3ba51a1Sopenharmony_ci    );
305b3ba51a1Sopenharmony_ci}
306b3ba51a1Sopenharmony_ci
307b3ba51a1Sopenharmony_ci#[test]
308b3ba51a1Sopenharmony_ci#[cfg(windows)]
309b3ba51a1Sopenharmony_cifn test_which_relative() {
310b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
311b3ba51a1Sopenharmony_ci    assert_eq!(
312b3ba51a1Sopenharmony_ci        _which(&f, "b/bin").unwrap(),
313b3ba51a1Sopenharmony_ci        f.bins[4].canonicalize().unwrap()
314b3ba51a1Sopenharmony_ci    );
315b3ba51a1Sopenharmony_ci}
316b3ba51a1Sopenharmony_ci
317b3ba51a1Sopenharmony_ci#[test]
318b3ba51a1Sopenharmony_ci#[cfg(unix)]
319b3ba51a1Sopenharmony_cifn test_which_relative_extension() {
320b3ba51a1Sopenharmony_ci    // test_which_relative tests a relative path without an extension,
321b3ba51a1Sopenharmony_ci    // so test a relative path with an extension here.
322b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
323b3ba51a1Sopenharmony_ci    let b = Path::new("b/bin").with_extension(env::consts::EXE_EXTENSION);
324b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &b).unwrap(), f.bins[3].canonicalize().unwrap());
325b3ba51a1Sopenharmony_ci}
326b3ba51a1Sopenharmony_ci
327b3ba51a1Sopenharmony_ci#[test]
328b3ba51a1Sopenharmony_ci#[cfg(windows)]
329b3ba51a1Sopenharmony_cifn test_which_relative_extension() {
330b3ba51a1Sopenharmony_ci    // test_which_relative tests a relative path without an extension,
331b3ba51a1Sopenharmony_ci    // so test a relative path with an extension here.
332b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
333b3ba51a1Sopenharmony_ci    let b = Path::new("b/bin").with_extension("cmd");
334b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &b).unwrap(), f.bins[5].canonicalize().unwrap());
335b3ba51a1Sopenharmony_ci}
336b3ba51a1Sopenharmony_ci
337b3ba51a1Sopenharmony_ci#[test]
338b3ba51a1Sopenharmony_ci#[cfg(windows)]
339b3ba51a1Sopenharmony_cifn test_which_relative_extension_case() {
340b3ba51a1Sopenharmony_ci    // Test that a relative path with an uppercase extension
341b3ba51a1Sopenharmony_ci    // is accepted.
342b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
343b3ba51a1Sopenharmony_ci    let b = Path::new("b/bin").with_extension("EXE");
344b3ba51a1Sopenharmony_ci    assert_eq!(_which(&f, &b).unwrap(), f.bins[4].canonicalize().unwrap());
345b3ba51a1Sopenharmony_ci}
346b3ba51a1Sopenharmony_ci
347b3ba51a1Sopenharmony_ci#[test]
348b3ba51a1Sopenharmony_ci#[cfg(unix)]
349b3ba51a1Sopenharmony_cifn test_which_relative_leading_dot() {
350b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
351b3ba51a1Sopenharmony_ci    assert_eq!(
352b3ba51a1Sopenharmony_ci        _which(&f, "./b/bin").unwrap(),
353b3ba51a1Sopenharmony_ci        f.bins[3].canonicalize().unwrap()
354b3ba51a1Sopenharmony_ci    );
355b3ba51a1Sopenharmony_ci}
356b3ba51a1Sopenharmony_ci
357b3ba51a1Sopenharmony_ci#[test]
358b3ba51a1Sopenharmony_ci#[cfg(windows)]
359b3ba51a1Sopenharmony_cifn test_which_relative_leading_dot() {
360b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
361b3ba51a1Sopenharmony_ci    assert_eq!(
362b3ba51a1Sopenharmony_ci        _which(&f, "./b/bin").unwrap(),
363b3ba51a1Sopenharmony_ci        f.bins[4].canonicalize().unwrap()
364b3ba51a1Sopenharmony_ci    );
365b3ba51a1Sopenharmony_ci}
366b3ba51a1Sopenharmony_ci
367b3ba51a1Sopenharmony_ci#[test]
368b3ba51a1Sopenharmony_ci#[cfg(unix)]
369b3ba51a1Sopenharmony_cifn test_which_non_executable() {
370b3ba51a1Sopenharmony_ci    // Shouldn't return non-executable files.
371b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
372b3ba51a1Sopenharmony_ci    f.touch("b/another", "").unwrap();
373b3ba51a1Sopenharmony_ci    assert!(_which(&f, "another").is_err());
374b3ba51a1Sopenharmony_ci}
375b3ba51a1Sopenharmony_ci
376b3ba51a1Sopenharmony_ci#[test]
377b3ba51a1Sopenharmony_ci#[cfg(unix)]
378b3ba51a1Sopenharmony_cifn test_which_absolute_non_executable() {
379b3ba51a1Sopenharmony_ci    // Shouldn't return non-executable files, even if given an absolute path.
380b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
381b3ba51a1Sopenharmony_ci    let b = f.touch("b/another", "").unwrap();
382b3ba51a1Sopenharmony_ci    assert!(_which(&f, &b).is_err());
383b3ba51a1Sopenharmony_ci}
384b3ba51a1Sopenharmony_ci
385b3ba51a1Sopenharmony_ci#[test]
386b3ba51a1Sopenharmony_ci#[cfg(unix)]
387b3ba51a1Sopenharmony_cifn test_which_relative_non_executable() {
388b3ba51a1Sopenharmony_ci    // Shouldn't return non-executable files.
389b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
390b3ba51a1Sopenharmony_ci    f.touch("b/another", "").unwrap();
391b3ba51a1Sopenharmony_ci    assert!(_which(&f, "b/another").is_err());
392b3ba51a1Sopenharmony_ci}
393b3ba51a1Sopenharmony_ci
394b3ba51a1Sopenharmony_ci#[test]
395b3ba51a1Sopenharmony_cifn test_failure() {
396b3ba51a1Sopenharmony_ci    let f = TestFixture::new();
397b3ba51a1Sopenharmony_ci
398b3ba51a1Sopenharmony_ci    let run = || -> which::Result<PathBuf> {
399b3ba51a1Sopenharmony_ci        let p = _which(&f, "./b/bin")?;
400b3ba51a1Sopenharmony_ci        Ok(p.into_path_buf())
401b3ba51a1Sopenharmony_ci    };
402b3ba51a1Sopenharmony_ci
403b3ba51a1Sopenharmony_ci    let _ = run();
404b3ba51a1Sopenharmony_ci}
405