Three test-side assumptions that only hold on POSIX. Each is small and independent, grouped because they are the same class of thing: the test, not the code under test, is what assumes a platform.
All three surface only now that the Rust suite can start on Windows — see #98.
1. A filename containing a tab — Windows cannot create it at all
tests/workdir.rs, stage_file_accepts_a_tab_containing_filename (:733)
called `Result::unwrap()` on an `Err` value: Os { code: 123, kind: InvalidFilename, ... }
A tab is not a legal character in a Windows filename, so the file the test needs cannot exist. The premise does not hold; the assertion is fine. Fix: #[cfg(unix)] with a line saying why, in the shape tests/submodule.rs already uses for its two POSIX-only cases.
2. An assertion compares a raw path against the escaped form git config writes
tests/submodule.rs, submodule_sync_rewrites_git_config_url_after_gitmodules_is_hand_edited (:1052)
parent.must(&["config", "-f", ".gitmodules", "submodule.sub.url", &child_new.path()]);
...
assert!(gitmodules.contains(&child_new.path()), "expected .gitmodules to record the new url");
git config escapes backslashes when it writes a value, so a Windows path goes in doubled. Reproduced directly:
$ git config -f .gitmodules submodule.sub.url 'C:\Temp\GitCat\child'
$ cat .gitmodules
[submodule "sub"]
url = C:\\Temp\\GitCat\\child
contains(&child_new.path()) looks for the single-backslash form and can never match. Fix: read the value back with git config --get -f .gitmodules (which unescapes) instead of substring-matching the file text — that also makes the assertion about the recorded value rather than about the file's formatting.
3. A rename target with no uniqueness, that nothing cleans up
tests/submodule.rs, submodule_deinit_recovers_offline_via_init_and_update (:1287)
let moved_away = child.dir.with_file_name("submodule_deinit_offline_child_GONE");
std::fs::rename(&child.dir, &moved_away).expect("simulate the origin going away");
Every other temp path in the suite carries pid + nanos + a counter. This one is a fixed name, and once the rename succeeds nothing owns the result — TempRepo::drop removes child.dir, which no longer exists, so the renamed copy leaks. I found a full leaked repo sitting there (42 entries, three read-only git objects).
That leak then poisons every later run, because rename onto an existing non-empty directory fails — ENOTEMPTY on unix, ERROR_DIR_NOT_EMPTY on Windows. CI never sees it: a fresh runner always starts with an empty temp dir.
Fix: give the target the same uniqueness as every other temp path, and let a TempRepo own it so Drop cleans it up.
Not fully explained: after deleting the leaked directory (including clearing the read-only attribute git leaves on objects), this test still fails with ERROR_DIR_NOT_EMPTY on Windows, while renaming an unrelated git repo directory on the same machine works. So there is something else about the repo's state at that moment. The fixed name is a real bug regardless, but fixing it may not be sufficient here.
Found while making cargo test runnable on Windows (#98). Each of the three was reproduced directly rather than inferred from the failure text.
Three test-side assumptions that only hold on POSIX. Each is small and independent, grouped because they are the same class of thing: the test, not the code under test, is what assumes a platform.
All three surface only now that the Rust suite can start on Windows — see #98.
1. A filename containing a tab — Windows cannot create it at all
tests/workdir.rs,stage_file_accepts_a_tab_containing_filename(:733)A tab is not a legal character in a Windows filename, so the file the test needs cannot exist. The premise does not hold; the assertion is fine. Fix:
#[cfg(unix)]with a line saying why, in the shapetests/submodule.rsalready uses for its two POSIX-only cases.2. An assertion compares a raw path against the escaped form
git configwritestests/submodule.rs,submodule_sync_rewrites_git_config_url_after_gitmodules_is_hand_edited(:1052)git configescapes backslashes when it writes a value, so a Windows path goes in doubled. Reproduced directly:contains(&child_new.path())looks for the single-backslash form and can never match. Fix: read the value back withgit config --get -f .gitmodules(which unescapes) instead of substring-matching the file text — that also makes the assertion about the recorded value rather than about the file's formatting.3. A rename target with no uniqueness, that nothing cleans up
tests/submodule.rs,submodule_deinit_recovers_offline_via_init_and_update(:1287)Every other temp path in the suite carries pid + nanos + a counter. This one is a fixed name, and once the rename succeeds nothing owns the result —
TempRepo::dropremoveschild.dir, which no longer exists, so the renamed copy leaks. I found a full leaked repo sitting there (42 entries, three read-only git objects).That leak then poisons every later run, because
renameonto an existing non-empty directory fails —ENOTEMPTYon unix,ERROR_DIR_NOT_EMPTYon Windows. CI never sees it: a fresh runner always starts with an empty temp dir.Fix: give the target the same uniqueness as every other temp path, and let a
TempRepoown it soDropcleans it up.Not fully explained: after deleting the leaked directory (including clearing the read-only attribute git leaves on objects), this test still fails with
ERROR_DIR_NOT_EMPTYon Windows, while renaming an unrelated git repo directory on the same machine works. So there is something else about the repo's state at that moment. The fixed name is a real bug regardless, but fixing it may not be sufficient here.Found while making
cargo testrunnable on Windows (#98). Each of the three was reproduced directly rather than inferred from the failure text.