test(TASK-047): split the ntfs short-name guard test by platform reality

On NTFS the fixture self-collides: .builtin-manifest auto-generates the
8.3 short name BUILTI~1, so writing that fixture file opens the manifest
through its alias and clobbers it -- the exact threat the guard models.
Gate the fixture-based test to unix, and add a windows counterpart that
proves the collision where 8.3 generation is enabled and asserts the
filter invariant (alias-shaped entries are neither removal candidates
nor claimed) either way.
This commit is contained in:
Dark-Alex-17 committed 2026-09-16 23:24:18 -06:00
1 parent c2e30c12a6
commit bf10aeb74d
1 file changed
+60
+60
View File
@@ -320,6 +320,15 @@ mod tests {
assert!(!is_ntfs_short_name_alias(".builtin-manifest")); assert!(!is_ntfs_short_name_alias(".builtin-manifest"));
} }
/// This fixture is unrealizable on NTFS: `.builtin-manifest` gets an
/// auto-generated 8.3 short name of exactly this shape (`BUILTI~1`), so
/// writing `dir/BUILTI~1` opens the manifest through its alias and
/// clobbers it instead of creating a distinct file — the precise
/// collision [`is_ntfs_short_name_alias`] defends against. Only
/// filesystems without 8.3 aliasing can host alias-shaped names as real,
/// distinct files; Windows coverage lives in
/// `ntfs_short_name_entries_never_accepted_on_windows` below.
#[cfg(unix)]
#[test] #[test]
fn ntfs_short_name_entries_never_direct_deletions() { fn ntfs_short_name_entries_never_direct_deletions() {
let dir = fresh_dir("builtin-manifest-shortname-"); let dir = fresh_dir("builtin-manifest-shortname-");
@@ -335,4 +344,55 @@ mod tests {
); );
let _ = fs::remove_dir_all(&dir); let _ = fs::remove_dir_all(&dir);
} }
/// Windows counterpart of `ntfs_short_name_entries_never_direct_deletions`:
/// alias-shaped files cannot exist as distinct fixtures here, so the guard
/// invariant is proven through the manifest filter instead. Only entries
/// accepted into the previous-manifest set can become removal candidates
/// (`previous.difference(shipped)`) or be claimed as owned
/// (`shipped ∩ previous`); listing the alias names in `shipped` makes the
/// second path observable in the rewritten manifest — a broken guard
/// would claim them. Where the volume generates 8.3 short names, the
/// self-collision that makes the unix fixture unrealizable is also
/// asserted directly; where generation is disabled, the alias simply
/// never materializes and the invariant assertions stand on their own.
#[cfg(windows)]
#[test]
fn ntfs_short_name_entries_never_accepted_on_windows() {
let dir = fresh_dir("builtin-manifest-shortname-win-");
fs::write(
dir.join(BUILTIN_MANIFEST_FILE),
"BUILTI~1\nbuilti~1.sh\nkept.sh\n",
)
.unwrap();
fs::write(dir.join("kept.sh"), "current").unwrap();
let alias = dir.join("BUILTI~1");
if alias.exists() {
assert_eq!(
fs::read_to_string(&alias).unwrap(),
fs::read_to_string(dir.join(BUILTIN_MANIFEST_FILE)).unwrap(),
"the 8.3 alias opens the manifest itself, not a distinct file"
);
}
reconcile_builtin_dir(
&dir,
&shipped(&["BUILTI~1", "builti~1.sh", "kept.sh"]),
&shipped(&[]),
)
.unwrap();
assert!(dir.join("kept.sh").exists(), "real shipped file untouched");
assert!(
dir.join(BUILTIN_MANIFEST_FILE).exists(),
"manifest survives reconciliation"
);
assert_eq!(
fs::read_to_string(dir.join(BUILTIN_MANIFEST_FILE)).unwrap(),
"kept.sh\n",
"alias-shaped entries are never accepted: neither removal candidates nor claimed"
);
let _ = fs::remove_dir_all(&dir);
}
} }