Skip to content

Commit d4a8d79

Browse files
committed
Improve filesystem timestamp granularity check
This avoids false positives for the check of whether we can proceed to run the filesystem snapshot `journey` test, by making a hundred files about as fast as we can using ordinary non-parallelized techniques, then checking if all their timestamps are distinct. This carries a small risk of false negatives, but experiments on macOS, where the `journey` test is typically able to run, suggest that the rate of false negatives will be low. (False positive are also, in theory, possible, but should be extremely rare or never happen.)
1 parent bf45023 commit d4a8d79

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

gix-fs/tests/fs/snapshot.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn journey() -> Result<(), Box<dyn std::error::Error>> {
1111

1212
fn do_journey() -> Result<(), Box<dyn std::error::Error>> {
1313
let tmp = tempfile::tempdir().unwrap();
14-
if !has_nanosecond_times(tmp.path())? {
14+
if !has_granular_times(tmp.path())? {
1515
return Ok(());
1616
}
1717

@@ -48,17 +48,21 @@ fn do_journey() -> Result<(), Box<dyn std::error::Error>> {
4848
Ok(())
4949
}
5050

51-
fn has_nanosecond_times(root: &Path) -> std::io::Result<bool> {
52-
let test_file = root.join("nanosecond-test");
51+
fn has_granular_times(root: &Path) -> std::io::Result<bool> {
52+
let n = 100;
5353

54-
std::fs::write(&test_file, "a")?;
55-
let first_time = test_file.metadata()?.modified()?;
56-
57-
std::fs::write(&test_file, "b")?;
58-
let second_time = test_file.metadata()?.modified()?;
54+
let names: Vec<_> = (0..n).map(|i| format!("{i:03}")).collect();
55+
for name in &names {
56+
std::fs::write(root.join(name), name)?;
57+
}
58+
let mut times = Vec::new();
59+
for name in names {
60+
times.push(root.join(name).symlink_metadata()?.modified()?);
61+
}
62+
times.sort();
63+
times.dedup();
5964

60-
Ok(second_time.duration_since(first_time).is_ok_and(|d|
61-
// This can be falsely false if a filesystem would be ridiculously fast,
62-
// which means a test won't run even though it could. But that's OK, and unlikely.
63-
d.subsec_nanos() != 0))
65+
// This could be wrongly false if a filesystem has very precise timings yet is ridiculously
66+
// fast. Then the `journey` test wouldn't run, though it could. But that's OK, and unlikely.
67+
Ok(times.len() == n)
6468
}

0 commit comments

Comments
 (0)