Skip to content

Commit 299d0e3

Browse files
committed
test: cover mtime-stable watch fingerprints
1 parent 80735ba commit 299d0e3

4 files changed

Lines changed: 62 additions & 1 deletion

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ tokio-serial = "5"
3838
serialport = { version = "4", default-features = false }
3939
pyo3 = { version = "0.22", features = ["abi3-py310"] }
4040
tempfile = "3"
41+
filetime = "0.2"
4142
sha2 = "0.10"
4243
regex = "1"
4344
walkdir = "2"

crates/fbuild-build/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ blake3 = { workspace = true }
2424
tempfile = { workspace = true }
2525

2626
[dev-dependencies]
27+
filetime = { workspace = true }

crates/fbuild-build/src/build_fingerprint/mod.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use walkdir::WalkDir;
1616
use crate::zccache::FingerprintWatch;
1717

1818
pub const BUILD_FINGERPRINT_VERSION: u32 = 2;
19-
const WATCH_STAMP_CACHE_VERSION: u32 = 1;
19+
const WATCH_STAMP_CACHE_VERSION: u32 = 2;
2020

2121
#[derive(Debug, Clone, Serialize, Deserialize)]
2222
pub struct PersistedBuildFingerprint {
@@ -456,6 +456,10 @@ mod tests {
456456
.unwrap()
457457
}
458458

459+
fn set_file_mtime(path: &Path, secs: i64) {
460+
filetime::set_file_mtime(path, filetime::FileTime::from_unix_time(secs, 0)).unwrap();
461+
}
462+
459463
#[test]
460464
fn test_hash_files_changes_when_contents_change() {
461465
let tmp = tempfile::TempDir::new().unwrap();
@@ -568,6 +572,60 @@ mod tests {
568572
assert_eq!(first, second);
569573
}
570574

575+
#[test]
576+
fn test_hash_watch_set_stamps_survives_mtime_reset_without_rewrite() {
577+
let tmp = tempfile::TempDir::new().unwrap();
578+
let src = tmp.path().join("src");
579+
fs::create_dir_all(&src).unwrap();
580+
let main = src.join("main.cpp");
581+
fs::write(&main, "int main() { return 1; }\n").unwrap();
582+
set_file_mtime(&main, 1_700_000_000);
583+
584+
let watch = make_watch(&src, &tmp.path().join(".project.zccache_fp.json"));
585+
let hash_count = Cell::new(0usize);
586+
587+
let first = hash_watch_with_counter(&watch, &hash_count);
588+
set_file_mtime(&main, 1_700_000_123);
589+
let second = hash_watch_with_counter(&watch, &hash_count);
590+
let after_second = hash_count.get();
591+
let third = hash_watch_with_counter(&watch, &hash_count);
592+
593+
assert_eq!(first, second);
594+
assert_eq!(second, third);
595+
assert_eq!(
596+
after_second, 2,
597+
"mtime reset should rehash once to prove byte identity"
598+
);
599+
assert_eq!(
600+
hash_count.get(),
601+
after_second,
602+
"updated stamp cache should restore the stat-only fast path"
603+
);
604+
}
605+
606+
#[test]
607+
fn test_hash_watch_set_stamps_detects_same_length_content_change_after_mtime_reset() {
608+
let tmp = tempfile::TempDir::new().unwrap();
609+
let src = tmp.path().join("src");
610+
fs::create_dir_all(&src).unwrap();
611+
let main = src.join("main.cpp");
612+
fs::write(&main, "int main() { return 1; }\n").unwrap();
613+
set_file_mtime(&main, 1_700_000_000);
614+
615+
let watch = make_watch(&src, &tmp.path().join(".project.zccache_fp.json"));
616+
617+
let first = hash_watch_set_stamps(std::slice::from_ref(&watch)).unwrap();
618+
fs::write(&main, "int main() { return 2; }\n").unwrap();
619+
set_file_mtime(&main, 1_700_000_123);
620+
let second = hash_watch_set_stamps(std::slice::from_ref(&watch)).unwrap();
621+
622+
assert_eq!(
623+
fs::metadata(&main).unwrap().len(),
624+
"int main() { return 1; }\n".len() as u64
625+
);
626+
assert_ne!(first, second);
627+
}
628+
571629
#[test]
572630
fn test_hash_watch_set_stamps_skips_rehash_when_stamp_unchanged() {
573631
let tmp = tempfile::TempDir::new().unwrap();

0 commit comments

Comments
 (0)