fix(m10): item-scope take-FX fingerprint; Windows path case-fold; comments

Item scope now reads the active take's FX chain via TakeFX_* (new
fxChainIdentityForItems helper), not the owning track's chain.
normalizeSlashes lowercases on _WIN32 for detectParent. Stale
comments corrected; case-fold tests added.
This commit is contained in:
2026-07-26 18:03:20 -04:00
parent 20018c1df2
commit 7d0fcc49ac
8 changed files with 177 additions and 38 deletions
+54 -5
View File
@@ -18,12 +18,40 @@ static int g_fail = 0;
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
static void testNormalizeSlashes() {
#ifdef _WIN32
// On Windows paths are lowercased for case-insensitive comparison.
CHECK(normalizeSlashes("C:\\a\\b") == "c:/a/b");
CHECK(normalizeSlashes("a/b/c") == "a/b/c");
CHECK(normalizeSlashes("a/b/") == "a/b"); // trailing slash stripped
CHECK(normalizeSlashes("a\\b\\") == "a/b"); // backslash + trailing
CHECK(normalizeSlashes("/") == "/"); // lone root preserved
CHECK(normalizeSlashes("") == ""); // empty stays empty
#else
CHECK(normalizeSlashes("C:\\a\\b") == "C:/a/b");
CHECK(normalizeSlashes("a/b/c") == "a/b/c");
CHECK(normalizeSlashes("a/b/") == "a/b"); // trailing slash stripped
CHECK(normalizeSlashes("a\\b\\") == "a/b"); // backslash + trailing
CHECK(normalizeSlashes("/") == "/"); // lone root preserved
CHECK(normalizeSlashes("") == ""); // empty stays empty
CHECK(normalizeSlashes("a/b/") == "a/b");
CHECK(normalizeSlashes("a\\b\\") == "a/b");
CHECK(normalizeSlashes("/") == "/");
CHECK(normalizeSlashes("") == "");
#endif
}
// Windows case-folding: paths differing only in casing must compare equal after
// normalizeSlashes, since Windows paths are case-insensitive. On non-Windows the
// function is case-preserving (filesystem is case-sensitive).
static void testNormalizeSlashesCaseFolding() {
#ifdef _WIN32
// Drive letter and component casing differences are neutralized.
CHECK(normalizeSlashes("C:/Foo/BAR.wav") == normalizeSlashes("c:/foo/bar.wav"));
CHECK(normalizeSlashes("C:/Foo/BAR.wav") == "c:/foo/bar.wav");
// Mixed-case input produces consistently lowercase output.
CHECK(normalizeSlashes("C:\\Users\\Daniel\\Proj\\File.WAV")
== "c:/users/daniel/proj/file.wav");
#else
// Non-Windows: case is preserved exactly (case-sensitive filesystem).
CHECK(normalizeSlashes("C:/Foo/BAR.wav") != normalizeSlashes("c:/foo/bar.wav"));
CHECK(normalizeSlashes("C:/Foo/BAR.wav") == "C:/Foo/BAR.wav");
#endif
}
static void testSanitizeStem() {
@@ -57,7 +85,12 @@ static void testDeriveRelativePathIsProjectRelative() {
static void testDeriveAbsoluteDirJoinsProjectDir() {
BankPaths p = deriveBankPaths("C:\\Users\\d\\proj", "kick", "");
// Backslashes normalized; bank subfolder appended; no trailing slash.
// On Windows the drive-letter + components are lowercased by normalizeSlashes.
#ifdef _WIN32
CHECK(p.absoluteDir == "c:/users/d/proj/reasampler_bank");
#else
CHECK(p.absoluteDir == "C:/Users/d/proj/reasampler_bank");
#endif
// No unique tag -> stem has no trailing "_".
CHECK(p.fileName == "kick.wav");
CHECK(p.relativePath == "reasampler_bank/kick.wav");
@@ -116,7 +149,15 @@ static void testFileStem() {
static void testResolveBankFileAgainstProjectDir() {
// A relative index entry resolves to <projectDir>/<relativePath>, forward-
// slashed, regardless of the input slash style.
// slashed, regardless of the input slash style. On Windows the result is also
// lowercased (Windows paths are case-insensitive; normalizeSlashes folds them).
#ifdef _WIN32
CHECK(resolveBankFile("C:\\Users\\d\\proj", "reasampler_bank/kick.wav")
== "c:/users/d/proj/reasampler_bank/kick.wav");
// Backslashes in the stored relative path are normalized on resolution.
CHECK(resolveBankFile("C:/p", "reasampler_bank\\a.wav")
== "c:/p/reasampler_bank/a.wav");
#else
CHECK(resolveBankFile("C:\\Users\\d\\proj", "reasampler_bank/kick.wav")
== "C:/Users/d/proj/reasampler_bank/kick.wav");
CHECK(resolveBankFile("/home/d/proj", "reasampler_bank/mix.wav")
@@ -127,6 +168,7 @@ static void testResolveBankFileAgainstProjectDir() {
// Backslashes in the stored relative path are normalized on resolution.
CHECK(resolveBankFile("/p", "reasampler_bank\\a.wav")
== "/p/reasampler_bank/a.wav");
#endif
}
static void testResolveBankFileRejectsEmptyInputs() {
@@ -159,10 +201,16 @@ static void testResolveAgainstNewProjectDirAfterSaveAs() {
static void testRelocationPlanForSaveAs() {
// Save-As to a different directory: relocation is needed; both bank dirs are
// <projectDir>/reasampler_bank, forward-slashed, no trailing slash.
// On Windows the drive-letter and path components are lowercased.
BankRelocation r = deriveRelocationPlan("C:\\old\\proj", "C:/new/proj");
CHECK(r.needed);
#ifdef _WIN32
CHECK(r.oldBankDir == "c:/old/proj/reasampler_bank");
CHECK(r.newBankDir == "c:/new/proj/reasampler_bank");
#else
CHECK(r.oldBankDir == "C:/old/proj/reasampler_bank");
CHECK(r.newBankDir == "C:/new/proj/reasampler_bank");
#endif
}
static void testRelocationPlanNotNeededForSaveInPlace() {
@@ -501,6 +549,7 @@ static void testHashWavContentDomainSeparationFromWholeFile() {
int main() {
testNormalizeSlashes();
testNormalizeSlashesCaseFolding();
testSanitizeStem();
testDeriveRelativePathIsProjectRelative();
testDeriveAbsoluteDirJoinsProjectDir();