using VFXReviewWorker; using Xunit; namespace VFXReviewWorker.Tests; public class PathMapperTests { private static PathMapper Mapper(params (string from, string to)[] maps) => new(maps.Select(m => new PathMapping { From = m.from, To = m.to })); [Fact] public void MapsUncToDriveLetter() { var mapper = Mapper(("//SAN/", "S:/")); Assert.Equal(@"S:\renders\UNG_S1\106\shot\v004", mapper.Map("//SAN/renders/UNG_S1/106/shot/v004")); } [Fact] public void MapsBackslashInputToo() { var mapper = Mapper(("//SAN/", "S:/")); Assert.Equal(@"S:\projects\a.aep", mapper.Map(@"\\SAN\projects\a.aep")); } [Fact] public void CaseInsensitiveMatch() { var mapper = Mapper(("//SAN/", "S:/")); Assert.Equal(@"S:\x", mapper.Map("//san/x")); } [Fact] public void FirstMatchingMappingWins() { var mapper = Mapper(("//SAN/renders/", "R:/"), ("//SAN/", "S:/")); Assert.Equal(@"R:\a", mapper.Map("//SAN/renders/a")); Assert.Equal(@"S:\projects\a", mapper.Map("//SAN/projects/a")); } [Fact] public void UnmappedPathPassesThroughWithLocalSeparators() { var mapper = Mapper(("//SAN/", "S:/")); Assert.Equal(@"D:\local\thing", mapper.Map("D:/local/thing")); } } public class PrepareOutputDirTests { [Fact] public void ClearsOnlyFilesMatchingPatternPrefix() { var dir = Path.Combine(Path.GetTempPath(), "vfxr-test-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(dir); try { File.WriteAllText(Path.Combine(dir, "SHOT_cmp_TT_v004.1001.exr"), "old"); File.WriteAllText(Path.Combine(dir, "SHOT_cmp_TT_v004.1002.exr"), "old"); File.WriteAllText(Path.Combine(dir, "unrelated-notes.txt"), "keep me"); AerenderRunner.PrepareOutputDir(dir, "SHOT_cmp_TT_v004.[####].exr"); Assert.False(File.Exists(Path.Combine(dir, "SHOT_cmp_TT_v004.1001.exr"))); Assert.False(File.Exists(Path.Combine(dir, "SHOT_cmp_TT_v004.1002.exr"))); Assert.True(File.Exists(Path.Combine(dir, "unrelated-notes.txt"))); } finally { Directory.Delete(dir, recursive: true); } } /// /// The version folder holds the preview MOV/MP4 built from the same /// basename. A shot re-rendered at the same version — the "No preview" /// workflow, where the EXRs are re-exported unscaled and the earlier MOV is /// inherited as the review media — must not have that MOV cleared out from /// under it before aerender starts. /// [Fact] public void KeepsPreviewMediaSharingThePatternPrefix() { var dir = Path.Combine(Path.GetTempPath(), "vfxr-test-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(dir); try { File.WriteAllText(Path.Combine(dir, "SHOT_cmp_TT_v004.1001.exr"), "old"); File.WriteAllText(Path.Combine(dir, "SHOT_cmp_TT_v004.mov"), "delivery mov"); File.WriteAllText(Path.Combine(dir, "SHOT_cmp_TT_v004.mp4"), "review mp4"); AerenderRunner.PrepareOutputDir(dir, "SHOT_cmp_TT_v004.[####].exr"); Assert.False(File.Exists(Path.Combine(dir, "SHOT_cmp_TT_v004.1001.exr"))); Assert.True(File.Exists(Path.Combine(dir, "SHOT_cmp_TT_v004.mov"))); Assert.True(File.Exists(Path.Combine(dir, "SHOT_cmp_TT_v004.mp4"))); } finally { Directory.Delete(dir, recursive: true); } } [Fact] public void ClearsOnlyThisVersionsFrames() { var dir = Path.Combine(Path.GetTempPath(), "vfxr-test-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(dir); try { File.WriteAllText(Path.Combine(dir, "SHOT_cmp_TT_v004.1001.exr"), "old"); File.WriteAllText(Path.Combine(dir, "SHOT_cmp_TT_v005.1001.exr"), "other version"); File.WriteAllText(Path.Combine(dir, "OTHERSHOT_cmp_TT_v004.1001.exr"), "other shot"); AerenderRunner.PrepareOutputDir(dir, "SHOT_cmp_TT_v004.[####].exr"); Assert.False(File.Exists(Path.Combine(dir, "SHOT_cmp_TT_v004.1001.exr"))); Assert.True(File.Exists(Path.Combine(dir, "SHOT_cmp_TT_v005.1001.exr"))); Assert.True(File.Exists(Path.Combine(dir, "OTHERSHOT_cmp_TT_v004.1001.exr"))); } finally { Directory.Delete(dir, recursive: true); } } [Fact] public void CreatesMissingDirectory() { var dir = Path.Combine(Path.GetTempPath(), "vfxr-test-" + Guid.NewGuid().ToString("N"), "v001"); try { AerenderRunner.PrepareOutputDir(dir, "X.[####].exr"); Assert.True(Directory.Exists(dir)); } finally { Directory.Delete(Path.GetDirectoryName(dir)!, recursive: true); } } }