Skip to content

Commit c28d722

Browse files
committed
Fix tests on Windows
1 parent e27337b commit c28d722

File tree

2 files changed

+114
-80
lines changed

2 files changed

+114
-80
lines changed

src/dirext.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,10 @@ mod tests {
941941
#[test]
942942
fn test_validate_relpath_no_uplinks() {
943943
let ok_cases = ["foo", "foo/bar", "foo/bar/"];
944+
#[cfg(unix)]
944945
let err_cases = ["/foo", "/", "../foo", "foo/../bar"];
946+
#[cfg(windows)]
947+
let err_cases = ["C:\\foo", "../foo", "foo/../bar"];
945948

946949
for case in ok_cases {
947950
assert!(validate_relpath_no_uplinks(Path::new(case)).is_ok());

tests/it/main.rs

Lines changed: 111 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
use anyhow::Result;
22

3-
use cap_std::fs::{Dir, File, Permissions, PermissionsExt};
3+
#[cfg(unix)]
4+
use cap_std::fs::PermissionsExt;
5+
use cap_std::fs::{Dir, File, Permissions};
6+
use cap_std_ext::cap_std;
7+
#[cfg(not(windows))]
48
use cap_std_ext::cmdext::CapStdExtCommandExt;
59
use cap_std_ext::dirext::{CapStdExtDirExt, WalkConfiguration};
6-
use cap_std_ext::{cap_std, RootDir};
10+
#[cfg(any(target_os = "android", target_os = "linux"))]
11+
use cap_std_ext::RootDir;
12+
#[cfg(unix)]
713
use rustix::path::DecInt;
814
use std::cmp::Ordering;
915
use std::ffi::OsStr;
@@ -13,6 +19,7 @@ use std::path::{Path, PathBuf};
1319
use std::{process::Command, sync::Arc};
1420

1521
#[test]
22+
#[cfg(not(windows))]
1623
fn take_fd() -> Result<()> {
1724
let mut c = Command::new("/bin/bash");
1825
c.arg("-c");
@@ -31,6 +38,7 @@ fn take_fd() -> Result<()> {
3138
}
3239

3340
#[test]
41+
#[cfg(not(windows))]
3442
fn fchdir() -> Result<()> {
3543
static CONTENTS: &[u8] = b"hello world";
3644

@@ -108,20 +116,23 @@ fn ensuredir() -> Result<()> {
108116
td.write(p, "some file contents")?;
109117
assert!(td.ensure_dir_with(p, b).is_err());
110118

111-
// Broken symlinks aren't followed and are errors
112-
let p = Path::new("linksrc");
113-
td.symlink("linkdest", p)?;
114-
assert!(td.metadata(p).is_err());
115-
assert!(td
116-
.symlink_metadata_optional(p)
117-
.unwrap()
118-
.unwrap()
119-
.is_symlink());
120-
// Non-broken symlinks are also an error
121-
assert!(td.ensure_dir_with(p, b).is_err());
122-
td.create_dir("linkdest")?;
123-
assert!(td.ensure_dir_with(p, b).is_err());
124-
assert!(td.metadata_optional(p).unwrap().unwrap().is_dir());
119+
#[cfg(not(windows))]
120+
{
121+
// Broken symlinks aren't followed and are errors
122+
let p = Path::new("linksrc");
123+
td.symlink("linkdest", p)?;
124+
assert!(td.metadata(p).is_err());
125+
assert!(td
126+
.symlink_metadata_optional(p)
127+
.unwrap()
128+
.unwrap()
129+
.is_symlink());
130+
// Non-broken symlinks are also an error
131+
assert!(td.ensure_dir_with(p, b).is_err());
132+
td.create_dir("linkdest")?;
133+
assert!(td.ensure_dir_with(p, b).is_err());
134+
assert!(td.metadata_optional(p).unwrap().unwrap().is_dir());
135+
}
125136

126137
Ok(())
127138
}
@@ -142,12 +153,15 @@ fn test_remove_all_optional() -> Result<()> {
142153
td.write(p, "test")?;
143154
assert!(td.remove_all_optional(p).unwrap());
144155

145-
// symlinks; broken and not
146-
let p = Path::new("linksrc");
147-
td.symlink("linkdest", p)?;
148-
assert!(td.remove_all_optional(p).unwrap());
149-
td.symlink("linkdest", p)?;
150-
assert!(td.remove_all_optional(p).unwrap());
156+
#[cfg(not(windows))]
157+
{
158+
// symlinks; broken and not
159+
let p = Path::new("linksrc");
160+
td.symlink("linkdest", p)?;
161+
assert!(td.remove_all_optional(p).unwrap());
162+
td.symlink("linkdest", p)?;
163+
assert!(td.remove_all_optional(p).unwrap());
164+
}
151165

152166
Ok(())
153167
}
@@ -198,50 +212,55 @@ fn link_tempfile_with() -> Result<()> {
198212
);
199213
assert_eq!(td.metadata(p)?.permissions(), default_perms);
200214

201-
td.atomic_write_with_perms(p, "atomic replacement 3\n", Permissions::from_mode(0o700))
202-
.unwrap();
203-
assert_eq!(
204-
td.read_to_string(p).unwrap().as_str(),
205-
"atomic replacement 3\n"
206-
);
207-
assert_eq!(td.metadata(p)?.permissions().mode() & 0o777, 0o700);
208-
209-
// Ensure we preserve the executable bit on an existing file
210-
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o700, 0o700);
211-
td.atomic_write(p, "atomic replacement 4\n").unwrap();
212-
assert_eq!(
213-
td.read_to_string(p).unwrap().as_str(),
214-
"atomic replacement 4\n"
215-
);
216-
assert_eq!(td.metadata(p)?.permissions().mode() & 0o777, 0o700);
217-
218-
// But we should ignore permissions on a symlink (both existing and broken)
219-
td.remove_file(p)?;
220-
let p2 = Path::new("bar");
221-
td.atomic_write_with_perms(p2, "link target", Permissions::from_mode(0o755))
222-
.unwrap();
223-
td.symlink(p2, p)?;
224-
td.atomic_write(p, "atomic replacement symlink\n").unwrap();
225-
assert_eq!(td.metadata(p)?.permissions(), default_perms);
226-
// And break the link
227-
td.remove_file(p2)?;
228-
td.atomic_write(p, "atomic replacement symlink\n").unwrap();
229-
assert_eq!(td.metadata(p)?.permissions(), default_perms);
215+
#[cfg(unix)]
216+
{
217+
td.atomic_write_with_perms(p, "atomic replacement 3\n", Permissions::from_mode(0o700))
218+
.unwrap();
219+
assert_eq!(
220+
td.read_to_string(p).unwrap().as_str(),
221+
"atomic replacement 3\n"
222+
);
223+
assert_eq!(td.metadata(p)?.permissions().mode() & 0o777, 0o700);
224+
225+
// Ensure we preserve the executable bit on an existing file
226+
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o700, 0o700);
227+
td.atomic_write(p, "atomic replacement 4\n").unwrap();
228+
assert_eq!(
229+
td.read_to_string(p).unwrap().as_str(),
230+
"atomic replacement 4\n"
231+
);
232+
assert_eq!(td.metadata(p)?.permissions().mode() & 0o777, 0o700);
233+
234+
// But we should ignore permissions on a symlink (both existing and broken)
235+
td.remove_file(p)?;
236+
let p2 = Path::new("bar");
237+
td.atomic_write_with_perms(p2, "link target", Permissions::from_mode(0o755))
238+
.unwrap();
239+
td.symlink(p2, p)?;
240+
td.atomic_write(p, "atomic replacement symlink\n").unwrap();
241+
assert_eq!(td.metadata(p)?.permissions(), default_perms);
242+
// And break the link
243+
td.remove_file(p2)?;
244+
td.atomic_write(p, "atomic replacement symlink\n").unwrap();
245+
assert_eq!(td.metadata(p)?.permissions(), default_perms);
246+
247+
// Also test with mode 0600
248+
td.atomic_write_with_perms(p, "self-only file", Permissions::from_mode(0o600))
249+
.unwrap();
250+
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o777, 0o600);
251+
td.atomic_write(p, "self-only file v2").unwrap();
252+
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o777, 0o600);
253+
// But we can override
254+
td.atomic_write_with_perms(p, "self-only file v3", Permissions::from_mode(0o640))
255+
.unwrap();
256+
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o777, 0o640);
257+
}
230258

231-
// Also test with mode 0600
232-
td.atomic_write_with_perms(p, "self-only file", Permissions::from_mode(0o600))
233-
.unwrap();
234-
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o777, 0o600);
235-
td.atomic_write(p, "self-only file v2").unwrap();
236-
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o777, 0o600);
237-
// But we can override
238-
td.atomic_write_with_perms(p, "self-only file v3", Permissions::from_mode(0o640))
239-
.unwrap();
240-
assert_eq!(td.metadata(p).unwrap().permissions().mode() & 0o777, 0o640);
241259
Ok(())
242260
}
243261

244262
#[test]
263+
#[cfg(unix)]
245264
fn test_timestamps() -> Result<()> {
246265
let td = cap_tempfile::tempdir(cap_std::ambient_authority())?;
247266
let p = Path::new("foo");
@@ -292,20 +311,23 @@ fn ensuredir_utf8() -> Result<()> {
292311
td.write(p, "some file contents")?;
293312
assert!(td.ensure_dir_with(p, b).is_err());
294313

295-
// Broken symlinks aren't followed and are errors
296-
let p = Utf8Path::new("linksrc");
297-
td.symlink("linkdest", p)?;
298-
assert!(td.metadata(p).is_err());
299-
assert!(td
300-
.symlink_metadata_optional(p)
301-
.unwrap()
302-
.unwrap()
303-
.is_symlink());
304-
// Non-broken symlinks are also an error
305-
assert!(td.ensure_dir_with(p, b).is_err());
306-
td.create_dir("linkdest")?;
307-
assert!(td.ensure_dir_with(p, b).is_err());
308-
assert!(td.metadata_optional(p).unwrap().unwrap().is_dir());
314+
#[cfg(not(windows))]
315+
{
316+
// Broken symlinks aren't followed and are errors
317+
let p = Utf8Path::new("linksrc");
318+
td.symlink("linkdest", p)?;
319+
assert!(td.metadata(p).is_err());
320+
assert!(td
321+
.symlink_metadata_optional(p)
322+
.unwrap()
323+
.unwrap()
324+
.is_symlink());
325+
// Non-broken symlinks are also an error
326+
assert!(td.ensure_dir_with(p, b).is_err());
327+
td.create_dir("linkdest")?;
328+
assert!(td.ensure_dir_with(p, b).is_err());
329+
assert!(td.metadata_optional(p).unwrap().unwrap().is_dir());
330+
}
309331

310332
Ok(())
311333
}
@@ -345,6 +367,7 @@ fn filenames_utf8() -> Result<()> {
345367
}
346368

347369
#[test]
370+
#[cfg(any(target_os = "android", target_os = "linux"))]
348371
fn test_rootdir_open() -> Result<()> {
349372
let td = &cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
350373
let root = RootDir::new(td, ".").unwrap();
@@ -373,6 +396,7 @@ fn test_rootdir_open() -> Result<()> {
373396
}
374397

375398
#[test]
399+
#[cfg(any(target_os = "android", target_os = "linux"))]
376400
fn test_rootdir_entries() -> Result<()> {
377401
let td = &cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
378402
let root = RootDir::new(td, ".").unwrap();
@@ -389,6 +413,7 @@ fn test_rootdir_entries() -> Result<()> {
389413
}
390414

391415
#[test]
416+
#[cfg(any(target_os = "android", target_os = "linux"))]
392417
fn test_mountpoint() -> Result<()> {
393418
let root = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
394419
assert_eq!(root.is_mountpoint(".").unwrap(), Some(true));
@@ -413,7 +438,7 @@ fn test_open_noxdev() -> Result<()> {
413438
// This hard requires the host setup to have /usr/bin on the same filesystem as /
414439
let usr = Dir::open_ambient_dir("/usr", cap_std::ambient_authority())?;
415440
assert!(usr.open_dir_noxdev("bin").unwrap().is_some());
416-
// Requires a mounted /proc, but that also seems ane.
441+
// Requires a mounted /proc, but that also seems sane.
417442
assert!(root.open_dir_noxdev("proc").unwrap().is_none());
418443
// Test an error case
419444
let td = cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
@@ -433,10 +458,13 @@ fn test_walk() -> std::io::Result<()> {
433458
td.write("usr/bin/true", b"true")?;
434459
td.write("usr/lib/foo/libfoo.so", b"libfoo")?;
435460
td.write("usr/lib/libbar.so", b"libbar")?;
436-
// Broken link
437-
td.symlink("usr/share/timezone", "usr/share/EST")?;
438-
// Symlink to self
439-
td.symlink(".", "usr/bin/selflink")?;
461+
#[cfg(not(windows))]
462+
{
463+
// Broken link
464+
td.symlink("usr/share/timezone", "usr/share/EST")?;
465+
// Symlink to self
466+
td.symlink(".", "usr/bin/selflink")?;
467+
}
440468
td.write("etc/foo.conf", b"fooconf")?;
441469
td.write("etc/blah.conf", b"blahconf")?;
442470

@@ -466,6 +494,7 @@ fn test_walk() -> std::io::Result<()> {
466494
})
467495
.unwrap();
468496
assert_eq!(n_dirs, 4);
497+
#[cfg(not(windows))]
469498
assert_eq!(n_symlinks, 2);
470499
assert_eq!(n_regfiles, 4);
471500
}
@@ -488,6 +517,7 @@ fn test_walk() -> std::io::Result<()> {
488517
}
489518

490519
#[test]
520+
#[cfg(unix)]
491521
fn test_walk_sorted() -> Result<()> {
492522
let td = cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
493523

@@ -536,6 +566,7 @@ fn test_walk_sorted() -> Result<()> {
536566
}
537567

538568
#[test]
569+
#[cfg(any(target_os = "android", target_os = "linux"))]
539570
fn test_walk_noxdev() -> Result<()> {
540571
let rootfs = Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
541572

0 commit comments

Comments
 (0)