summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/test_stat.rs53
1 files changed, 50 insertions, 3 deletions
diff --git a/test/test_stat.rs b/test/test_stat.rs
index 4135052e..49cc49fd 100644
--- a/test/test_stat.rs
+++ b/test/test_stat.rs
@@ -1,12 +1,14 @@
-use std::fs::File;
+use std::fs::{self, File};
use std::os::unix::fs::symlink;
use std::os::unix::prelude::AsRawFd;
+use std::time::{Duration, UNIX_EPOCH};
use libc::{S_IFMT, S_IFLNK};
use nix::fcntl;
-use nix::sys::stat::{self, fchmod, fchmodat, fstat, lstat, stat};
-use nix::sys::stat::{FileStat, Mode, FchmodatFlags};
+use nix::sys::stat::{self, fchmod, fchmodat, fstat, futimens, lstat, stat, utimensat};
+use nix::sys::stat::{FileStat, Mode, FchmodatFlags, UtimensatFlags};
+use nix::sys::time::{TimeSpec, TimeValLike};
use nix::unistd::chdir;
use nix::Result;
use tempfile;
@@ -152,3 +154,48 @@ fn test_fchmodat() {
let file_stat2 = stat(&fullpath).unwrap();
assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
}
+
+/// Asserts that the atime and mtime in a file's metadata match expected values.
+///
+/// The atime and mtime are expressed with a resolution of seconds because some file systems
+/// (like macOS's HFS+) do not have higher granularity.
+fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata) {
+ assert_eq!(
+ Duration::new(exp_atime_sec, 0),
+ attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap());
+ assert_eq!(
+ Duration::new(exp_mtime_sec, 0),
+ attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap());
+}
+
+#[test]
+fn test_futimens() {
+ let tempdir = tempfile::tempdir().unwrap();
+ let fullpath = tempdir.path().join("file");
+ drop(File::create(&fullpath).unwrap());
+
+ let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
+
+ futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap();
+ assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap());
+}
+
+#[test]
+fn test_utimensat() {
+ let tempdir = tempfile::tempdir().unwrap();
+ let filename = "foo.txt";
+ let fullpath = tempdir.path().join(filename);
+ drop(File::create(&fullpath).unwrap());
+
+ let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
+
+ utimensat(Some(dirfd), filename, &TimeSpec::seconds(12345), &TimeSpec::seconds(678),
+ UtimensatFlags::FollowSymlink).unwrap();
+ assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap());
+
+ chdir(tempdir.path()).unwrap();
+
+ utimensat(None, filename, &TimeSpec::seconds(500), &TimeSpec::seconds(800),
+ UtimensatFlags::FollowSymlink).unwrap();
+ assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
+}