From 13f522abb8ee966e82f77c5e9d3ee24a1f92c6b4 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Wed, 18 Jan 2023 15:47:05 -0700 Subject: [PATCH] Fix file extension detection error (#453) --- .../AaxcDownloadMultiConverter.cs | 3 +- Source/AaxDecrypter/AudiobookDownloadBase.cs | 2 +- Source/FileManager/FileNamingTemplate.cs | 4 +-- Source/FileManager/FileUtility.cs | 24 +++++++------ .../Dialogs/EditTemplateDialog.axaml.cs | 15 ++++---- Source/LibationFileManager/Templates.cs | 17 ++++----- .../Dialogs/EditTemplateDialog.cs | 17 ++++----- .../FileNamingTemplateTests.cs | 12 ++++--- .../FileManager.Tests/FileUtilityTests.cs | 30 ++++++++-------- .../TemplatesTests.cs | 36 ++++++++++--------- 10 files changed, 86 insertions(+), 74 deletions(-) diff --git a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs index d5a03d0e..a1fdb7bd 100644 --- a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs +++ b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs @@ -203,7 +203,8 @@ That naming may not be desirable for everyone, but it's an easy change to instea private FileStream createOutputFileStream(MultiConvertFileProperties multiConvertFileProperties) { var fileName = DownloadOptions.GetMultipartFileName(multiConvertFileProperties); - fileName = FileUtility.GetValidFilename(fileName, DownloadOptions.ReplacementCharacters); + var extension = Path.GetExtension(fileName); + fileName = FileUtility.GetValidFilename(fileName, DownloadOptions.ReplacementCharacters, extension); multiPartFilePaths.Add(fileName); diff --git a/Source/AaxDecrypter/AudiobookDownloadBase.cs b/Source/AaxDecrypter/AudiobookDownloadBase.cs index 121520e7..622142fe 100644 --- a/Source/AaxDecrypter/AudiobookDownloadBase.cs +++ b/Source/AaxDecrypter/AudiobookDownloadBase.cs @@ -93,7 +93,7 @@ namespace AaxDecrypter try { var path = Path.ChangeExtension(OutputFileName, ".cue"); - path = FileUtility.GetValidFilename(path, DownloadOptions.ReplacementCharacters); + path = FileUtility.GetValidFilename(path, DownloadOptions.ReplacementCharacters, ".cue"); File.WriteAllText(path, Cue.CreateContents(Path.GetFileName(OutputFileName), DownloadOptions.ChapterInfo)); OnFileCreated(path); } diff --git a/Source/FileManager/FileNamingTemplate.cs b/Source/FileManager/FileNamingTemplate.cs index 49270c3b..29bde7e6 100644 --- a/Source/FileManager/FileNamingTemplate.cs +++ b/Source/FileManager/FileNamingTemplate.cs @@ -13,7 +13,7 @@ namespace FileManager public FileNamingTemplate(string template) : base(template) { } /// Generate a valid path for this file or directory - public LongPath GetFilePath(ReplacementCharacters replacements, bool returnFirstExisting = false) + public LongPath GetFilePath(ReplacementCharacters replacements, string fileExtension, bool returnFirstExisting = false) { string fileName = Template.EndsWith(Path.DirectorySeparatorChar) || Template.EndsWith(Path.AltDirectorySeparatorChar) ? @@ -44,7 +44,6 @@ namespace FileManager var fileNamePart = pathParts[^1]; pathParts.Remove(fileNamePart); - var fileExtension = Path.GetExtension(fileNamePart); fileNamePart = fileNamePart[..^fileExtension.Length]; LongPath directory = Path.Join(pathParts.Select(p => replaceFileName(p, paramReplacements, LongPath.MaxFilenameLength)).ToArray()); @@ -56,6 +55,7 @@ namespace FileManager .GetValidFilename( Path.Join(directory, replaceFileName(fileNamePart, paramReplacements, LongPath.MaxFilenameLength - fileExtension.Length - 5)) + fileExtension, replacements, + fileExtension, returnFirstExisting ); } diff --git a/Source/FileManager/FileUtility.cs b/Source/FileManager/FileUtility.cs index 5efe7c69..a3f46de3 100644 --- a/Source/FileManager/FileUtility.cs +++ b/Source/FileManager/FileUtility.cs @@ -49,9 +49,11 @@ namespace FileManager ///
- ensure uniqueness ///
- enforce max file length /// - public static LongPath GetValidFilename(LongPath path, ReplacementCharacters replacements, bool returnFirstExisting = false) + public static LongPath GetValidFilename(LongPath path, ReplacementCharacters replacements, string fileExtension, bool returnFirstExisting = false) { ArgumentValidator.EnsureNotNull(path, nameof(path)); + ArgumentValidator.EnsureNotNull(fileExtension, nameof(fileExtension)); + fileExtension = GetStandardizedExtension(fileExtension); // remove invalid chars path = GetSafePath(path, replacements); @@ -60,21 +62,20 @@ namespace FileManager var dir = Path.GetDirectoryName(path); dir = dir?.TruncateFilename(LongPath.MaxDirectoryLength) ?? string.Empty; - var extension = Path.GetExtension(path); + var fileName = Path.GetFileName(path); + var extIndex = fileName.LastIndexOf(fileExtension, StringComparison.OrdinalIgnoreCase); + var filenameWithoutExtension = extIndex >= 0 ? fileName.Remove(extIndex, fileExtension.Length) : fileName; + var fileStem + = Path.Combine(dir, filenameWithoutExtension.TruncateFilename(LongPath.MaxFilenameLength - fileExtension.Length)) + .TruncateFilename(LongPath.MaxPathLength - fileExtension.Length); - var filename = Path.GetFileNameWithoutExtension(path).TruncateFilename(LongPath.MaxFilenameLength - extension.Length); - var fileStem = Path.Combine(dir, filename); - - - var fullfilename = fileStem.TruncateFilename(LongPath.MaxPathLength - extension.Length) + extension; - - fullfilename = removeInvalidWhitespace(fullfilename); + var fullfilename = removeInvalidWhitespace(fileStem) + fileExtension; var i = 0; while (File.Exists(fullfilename) && !returnFirstExisting) { var increm = $" ({++i})"; - fullfilename = fileStem.TruncateFilename(LongPath.MaxPathLength - increm.Length - extension.Length) + increm + extension; + fullfilename = fileStem.TruncateFilename(LongPath.MaxPathLength - increm.Length - fileExtension.Length) + increm + fileExtension; } return fullfilename; @@ -152,7 +153,8 @@ namespace FileManager /// public static string SaferMoveToValidPath(LongPath source, LongPath destination, ReplacementCharacters replacements) { - destination = GetValidFilename(destination, replacements); + var extension = Path.GetExtension(source); + destination = GetValidFilename(destination, replacements, extension); SaferMove(source, destination); return destination; } diff --git a/Source/LibationAvalonia/Dialogs/EditTemplateDialog.axaml.cs b/Source/LibationAvalonia/Dialogs/EditTemplateDialog.axaml.cs index 6a3b7213..14c7ce99 100644 --- a/Source/LibationAvalonia/Dialogs/EditTemplateDialog.axaml.cs +++ b/Source/LibationAvalonia/Dialogs/EditTemplateDialog.axaml.cs @@ -162,14 +162,17 @@ namespace LibationAvalonia.Dialogs Title = chapterName }; + /* + * Path must be rooted for windows to allow long file paths. This is + * only necessary for folder templates because they may contain several + * subdirectories. Without rooting, we won't be allowed to create a + * relative path longer than MAX_PATH. + */ + var books = config.Books; var folder = Templates.Folder.GetPortionFilename( libraryBookDto, - //Path must be rooted for windows to allow long file paths. This is - //only necessary for folder templates because they may contain several - //subdirectories. Without rooting, we won't be allowed to create a - //relative path longer than MAX_PATH - Path.Combine(books, isFolder ? workingTemplateText : config.FolderTemplate)); + Path.Combine(books, isFolder ? workingTemplateText : config.FolderTemplate), ""); folder = Path.GetRelativePath(books, folder); @@ -182,7 +185,7 @@ namespace LibationAvalonia.Dialogs "") : Templates.File.GetPortionFilename( libraryBookDto, - isFolder ? config.FileTemplate : workingTemplateText); + isFolder ? config.FileTemplate : workingTemplateText, ""); var ext = config.DecryptToLossy ? "mp3" : "m4b"; var chapterTitle = Templates.ChapterTitle.GetPortionTitle(libraryBookDto, workingTemplateText, partFileProperties); diff --git a/Source/LibationFileManager/Templates.cs b/Source/LibationFileManager/Templates.cs index df1fa290..99d3181b 100644 --- a/Source/LibationFileManager/Templates.cs +++ b/Source/LibationFileManager/Templates.cs @@ -99,11 +99,11 @@ namespace LibationFileManager /// /// EditTemplateDialog: Get template generated filename for portion of path /// - public string GetPortionFilename(LibraryBookDto libraryBookDto, string template) + public string GetPortionFilename(LibraryBookDto libraryBookDto, string template, string fileExtension) => string.IsNullOrWhiteSpace(template) ? "" - : getFileNamingTemplate(libraryBookDto, template, null, null) - .GetFilePath(Configuration.Instance.ReplacementCharacters).PathWithoutPrefix; + : getFileNamingTemplate(libraryBookDto, template, null, fileExtension) + .GetFilePath(Configuration.Instance.ReplacementCharacters, fileExtension).PathWithoutPrefix; private static Regex ifSeriesRegex { get; } = new Regex("(.*?)<-if series>", RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -215,7 +215,7 @@ namespace LibationFileManager /// USES LIVE CONFIGURATION VALUES public string GetFilename(LibraryBookDto libraryBookDto, string baseDir = null) => getFileNamingTemplate(libraryBookDto, Configuration.Instance.FolderTemplate, baseDir ?? AudibleFileStorage.BooksDirectory, null) - .GetFilePath(Configuration.Instance.ReplacementCharacters); + .GetFilePath(Configuration.Instance.ReplacementCharacters, string.Empty); #endregion } @@ -238,7 +238,7 @@ namespace LibationFileManager /// USES LIVE CONFIGURATION VALUES public string GetFilename(LibraryBookDto libraryBookDto, string dirFullPath, string extension, bool returnFirstExisting = false) => getFileNamingTemplate(libraryBookDto, Configuration.Instance.FileTemplate, dirFullPath, extension) - .GetFilePath(Configuration.Instance.ReplacementCharacters, returnFirstExisting); + .GetFilePath(Configuration.Instance.ReplacementCharacters, extension, returnFirstExisting); #endregion } @@ -273,19 +273,20 @@ namespace LibationFileManager public string GetFilename(LibraryBookDto libraryBookDto, AaxDecrypter.MultiConvertFileProperties props) => GetPortionFilename(libraryBookDto, Configuration.Instance.ChapterFileTemplate, props, AudibleFileStorage.DecryptInProgressDirectory); - public string GetPortionFilename(LibraryBookDto libraryBookDto, string template, AaxDecrypter.MultiConvertFileProperties props, string fullDirPath, ReplacementCharacters replacements = null) + public string GetPortionFilename(LibraryBookDto libraryBookDto, string template, AaxDecrypter.MultiConvertFileProperties props, string fullDirPath, ReplacementCharacters replacements = null) { if (string.IsNullOrWhiteSpace(template)) return string.Empty; replacements ??= Configuration.Instance.ReplacementCharacters; - var fileNamingTemplate = getFileNamingTemplate(libraryBookDto, template, fullDirPath, Path.GetExtension(props.OutputFileName)); + var fileExtension = Path.GetExtension(props.OutputFileName); + var fileNamingTemplate = getFileNamingTemplate(libraryBookDto, template, fullDirPath, fileExtension); fileNamingTemplate.AddParameterReplacement(TemplateTags.ChCount, props.PartsTotal); fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber, props.PartsPosition); fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber0, FileUtility.GetSequenceFormatted(props.PartsPosition, props.PartsTotal)); fileNamingTemplate.AddParameterReplacement(TemplateTags.ChTitle, props.Title ?? ""); - return fileNamingTemplate.GetFilePath(replacements).PathWithoutPrefix; + return fileNamingTemplate.GetFilePath(replacements, fileExtension).PathWithoutPrefix; } #endregion } diff --git a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs index 3a937855..a14005d0 100644 --- a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs +++ b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs @@ -98,15 +98,16 @@ namespace LibationWinForms.Dialogs }; - + /* + * Path must be rooted for windows to allow long file paths. This is + * only necessary for folder templates because they may contain several + * subdirectories. Without rooting, we won't be allowed to create a + * relative path longer than MAX_PATH. + */ var books = config.Books; var folder = Templates.Folder.GetPortionFilename( - libraryBookDto, - //Path must be rooted for windows to allow long file paths. This is - //only necessary for folder templates because they may contain several - //subdirectories. Without rooting, we won't be allowed to create a - //relative path longer than MAX_PATH - Path.Combine(books, isFolder ? workingTemplateText : config.FolderTemplate)); + libraryBookDto, + Path.Combine(books, isFolder ? workingTemplateText : config.FolderTemplate), ""); folder = Path.GetRelativePath(books, folder); @@ -119,7 +120,7 @@ namespace LibationWinForms.Dialogs "") : Templates.File.GetPortionFilename( libraryBookDto, - isFolder ? config.FileTemplate : workingTemplateText); + isFolder ? config.FileTemplate : workingTemplateText, ""); var ext = config.DecryptToLossy ? "mp3" : "m4b"; var chapterTitle = Templates.ChapterTitle.GetPortionTitle(libraryBookDto, workingTemplateText, partFileProperties); diff --git a/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs b/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs index f98868cf..54b0c375 100644 --- a/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs +++ b/Source/_Tests/FileManager.Tests/FileNamingTemplateTests.cs @@ -33,12 +33,13 @@ namespace FileNamingTemplateTests { var template = $" [<id>]"; - var fullfilename = Path.Combine(dirFullPath, template + FileUtility.GetStandardizedExtension(extension)); + extension = FileUtility.GetStandardizedExtension(extension); + var fullfilename = Path.Combine(dirFullPath, template + extension); var fileNamingTemplate = new FileNamingTemplate(fullfilename); fileNamingTemplate.AddParameterReplacement("title", filename); fileNamingTemplate.AddParameterReplacement("id", metadataSuffix); - return fileNamingTemplate.GetFilePath(Replacements).PathWithoutPrefix; + return fileNamingTemplate.GetFilePath(Replacements, extension).PathWithoutPrefix; } [TestMethod] @@ -57,12 +58,13 @@ namespace FileNamingTemplateTests // 100-999 => 001-999 var chapterCountLeadingZeros = partsPosition.ToString().PadLeft(partsTotal.ToString().Length, '0'); - var t = Path.ChangeExtension(originalPath, null) + " - <chapter> - <title>" + Path.GetExtension(originalPath); + var estension = Path.GetExtension(originalPath); + var t = Path.ChangeExtension(originalPath, null) + " - <chapter> - <title>" + estension; var fileNamingTemplate = new FileNamingTemplate(t); fileNamingTemplate.AddParameterReplacement("chapter", chapterCountLeadingZeros); fileNamingTemplate.AddParameterReplacement("title", suffix); - return fileNamingTemplate.GetFilePath(Replacements).PathWithoutPrefix; + return fileNamingTemplate.GetFilePath(Replacements, estension).PathWithoutPrefix; } [TestMethod] @@ -74,7 +76,7 @@ namespace FileNamingTemplateTests { var fileNamingTemplate = new FileNamingTemplate(inStr); fileNamingTemplate.AddParameterReplacement("title", @"s\l/a\s/h\e/s"); - fileNamingTemplate.GetFilePath(Replacements).PathWithoutPrefix.Should().Be(outStr); + fileNamingTemplate.GetFilePath(Replacements, "txt").PathWithoutPrefix.Should().Be(outStr); } } } diff --git a/Source/_Tests/FileManager.Tests/FileUtilityTests.cs b/Source/_Tests/FileManager.Tests/FileUtilityTests.cs index 325113af..4055938c 100644 --- a/Source/_Tests/FileManager.Tests/FileUtilityTests.cs +++ b/Source/_Tests/FileManager.Tests/FileUtilityTests.cs @@ -197,30 +197,30 @@ namespace FileUtilityTests [TestMethod] // dot-files - [DataRow(@"C:\a bc\x y z\.f i l e.txt", PlatformID.Win32NT)] - [DataRow(@"/a bc/x y z/.f i l e.txt", PlatformID.Unix)] + [DataRow(@"C:\a bc\x y z\.f i l e.txt", "txt", PlatformID.Win32NT)] + [DataRow(@"/a bc/x y z/.f i l e.txt", "txt", PlatformID.Unix)] // dot-folders - [DataRow(@"C:\a bc\.x y z\f i l e.txt", PlatformID.Win32NT)] - [DataRow(@"/a bc/.x y z/f i l e.txt", PlatformID.Unix)] - public void Valid(string input, PlatformID platformID) => Tests(input, input, platformID); + [DataRow(@"C:\a bc\.x y z\f i l e.txt", "txt", PlatformID.Win32NT)] + [DataRow(@"/a bc/.x y z/f i l e.txt", "txt", PlatformID.Unix)] + public void Valid(string input, string extension, PlatformID platformID) => Tests(input, extension, input, platformID); [TestMethod] // folder spaces - [DataRow(@"C:\ a bc \x y z ", @"C:\a bc\x y z", PlatformID.Win32NT)] - [DataRow(@"/ a bc /x y z ", @"/a bc/x y z", PlatformID.Unix)] + [DataRow(@"C:\ a bc \x y z ","", @"C:\a bc\x y z", PlatformID.Win32NT)] + [DataRow(@"/ a bc /x y z ", "", @"/a bc/x y z", PlatformID.Unix)] // file spaces - [DataRow(@"C:\a bc\x y z\ f i l e.txt ", @"C:\a bc\x y z\f i l e.txt", PlatformID.Win32NT)] - [DataRow(@"/a bc/x y z/ f i l e.txt ", @"/a bc/x y z/f i l e.txt", PlatformID.Unix)] + [DataRow(@"C:\a bc\x y z\ f i l e.txt ", "txt", @"C:\a bc\x y z\f i l e.txt", PlatformID.Win32NT)] + [DataRow(@"/a bc/x y z/ f i l e.txt ", "txt", @"/a bc/x y z/f i l e.txt", PlatformID.Unix)] // eliminate beginning space and end dots and spaces - [DataRow(@"C:\a bc\ . . . x y z . . . \f i l e.txt", @"C:\a bc\. . . x y z\f i l e.txt", PlatformID.Win32NT)] - [DataRow(@"/a bc/ . . . x y z . . . /f i l e.txt", @"/a bc/. . . x y z/f i l e.txt", PlatformID.Unix)] + [DataRow(@"C:\a bc\ . . . x y z . . . \f i l e.txt", "txt", @"C:\a bc\. . . x y z\f i l e.txt", PlatformID.Win32NT)] + [DataRow(@"/a bc/ . . . x y z . . . /f i l e.txt", "txt", @"/a bc/. . . x y z/f i l e.txt", PlatformID.Unix)] // file end dots - [DataRow(@"C:\a bc\x y z\f i l e.txt . . .", @"C:\a bc\x y z\f i l e.txt", PlatformID.Win32NT)] - [DataRow(@"/a bc/x y z/f i l e.txt . . .", @"/a bc/x y z/f i l e.txt", PlatformID.Unix)] - public void Tests(string input, string expected, PlatformID platformID) + [DataRow(@"C:\a bc\x y z\f i l e.txt . . .", "txt", @"C:\a bc\x y z\f i l e.txt", PlatformID.Win32NT)] + [DataRow(@"/a bc/x y z/f i l e.txt . . .", "txt", @"/a bc/x y z/f i l e.txt", PlatformID.Unix)] + public void Tests(string input, string extension, string expected, PlatformID platformID) { if (Environment.OSVersion.Platform == platformID) - FileUtility.GetValidFilename(input, Replacements).PathWithoutPrefix.Should().Be(expected); + FileUtility.GetValidFilename(input, Replacements, extension).PathWithoutPrefix.Should().Be(expected); } } diff --git a/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs b/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs index 33681b6b..98a562f2 100644 --- a/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs +++ b/Source/_Tests/LibationFileManager.Tests/TemplatesTests.cs @@ -81,23 +81,25 @@ namespace TemplatesTests => Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension); [TestMethod] - [DataRow("f.txt", @"C:\foo\bar", null, @"C:\foo\bar\f.txt", PlatformID.Win32NT)] - [DataRow("f.txt", @"/foo/bar", null, @"/foo/bar/f.txt", PlatformID.Unix)] - [DataRow("f.txt", @"C:\foo\bar", "ext", @"C:\foo\bar\f.txt.ext", PlatformID.Win32NT)] - [DataRow("f.txt", @"/foo/bar", "ext", @"/foo/bar/f.txt.ext", PlatformID.Unix)] - [DataRow("f", @"C:\foo\bar", "ext", @"C:\foo\bar\f.ext", PlatformID.Win32NT)] - [DataRow("f", @"/foo/bar", "ext", @"/foo/bar/f.ext", PlatformID.Unix)] - [DataRow("<id>", @"C:\foo\bar", "ext", @"C:\foo\bar\asin.ext", PlatformID.Win32NT)] - [DataRow("<id>", @"/foo/bar", "ext", @"/foo/bar/asin.ext", PlatformID.Unix)] - [DataRow("<bitrate> - <samplerate> - <channels>", @"C:\foo\bar", "ext", @"C:\foo\bar\128 - 44100 - 2.ext", PlatformID.Win32NT)] - [DataRow("<bitrate> - <samplerate> - <channels>", @"/foo/bar", "ext", @"/foo/bar/128 - 44100 - 2.ext", PlatformID.Unix)] - [DataRow("<year> - <channels>", @"C:\foo\bar", "ext", @"C:\foo\bar\2017 - 2.ext", PlatformID.Win32NT)] - [DataRow("<year> - <channels>", @"/foo/bar", "ext", @"/foo/bar/2017 - 2.ext", PlatformID.Unix)] - public void Tests(string template, string dirFullPath, string extension, string expected, PlatformID platformID) + [DataRow("f.txt", @"C:\foo\bar", "", @"C:\foo\bar\f.txt", PlatformID.Win32NT)] + [DataRow("f.txt", @"/foo/bar", "", @"/foo/bar/f.txt", PlatformID.Unix)] + [DataRow("f.txt", @"C:\foo\bar", ".ext", @"C:\foo\bar\f.txt.ext", PlatformID.Win32NT)] + [DataRow("f.txt", @"/foo/bar", ".ext", @"/foo/bar/f.txt.ext", PlatformID.Unix)] + [DataRow("f", @"C:\foo\bar", ".ext", @"C:\foo\bar\f.ext", PlatformID.Win32NT)] + [DataRow("f", @"/foo/bar", ".ext", @"/foo/bar/f.ext", PlatformID.Unix)] + [DataRow("<id>", @"C:\foo\bar", ".ext", @"C:\foo\bar\asin.ext", PlatformID.Win32NT)] + [DataRow("<id>", @"/foo/bar", ".ext", @"/foo/bar/asin.ext", PlatformID.Unix)] + [DataRow("<bitrate> - <samplerate> - <channels>", @"C:\foo\bar", ".ext", @"C:\foo\bar\128 - 44100 - 2.ext", PlatformID.Win32NT)] + [DataRow("<bitrate> - <samplerate> - <channels>", @"/foo/bar", ".ext", @"/foo/bar/128 - 44100 - 2.ext", PlatformID.Unix)] + [DataRow("<year> - <channels>", @"C:\foo\bar", ".ext", @"C:\foo\bar\2017 - 2.ext", PlatformID.Win32NT)] + [DataRow("<year> - <channels>", @"/foo/bar", ".ext", @"/foo/bar/2017 - 2.ext", PlatformID.Unix)] + [DataRow("(000.0) <year> - <channels>", @"C:\foo\bar", "ext", @"C:\foo\bar\(000.0) 2017 - 2.ext", PlatformID.Win32NT)] + [DataRow("(000.0) <year> - <channels>", @"/foo/bar", ".ext", @"/foo/bar/(000.0) 2017 - 2.ext", PlatformID.Unix)] + public void Tests(string template, string dirFullPath, string extension, string expected, PlatformID platformID) { if (Environment.OSVersion.Platform == platformID) Templates.getFileNamingTemplate(GetLibraryBook(), template, dirFullPath, extension) - .GetFilePath(Replacements) + .GetFilePath(Replacements, extension) .PathWithoutPrefix .Should().Be(expected); } @@ -109,7 +111,7 @@ namespace TemplatesTests { if (Environment.OSVersion.Platform == platformID) Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series-><-if series>bar", directory, "ext") - .GetFilePath(Replacements) + .GetFilePath(Replacements, ".ext") .PathWithoutPrefix .Should().Be(expected); } @@ -121,7 +123,7 @@ namespace TemplatesTests { if (Environment.OSVersion.Platform == platformID) Templates.getFileNamingTemplate(GetLibraryBook(null), "foo<if series->-<series>-<id>-<-if series>bar", directory, "ext") - .GetFilePath(Replacements) + .GetFilePath(Replacements, ".ext") .PathWithoutPrefix .Should().Be(expected); } @@ -133,7 +135,7 @@ namespace TemplatesTests { if (Environment.OSVersion.Platform == platformID) Templates.getFileNamingTemplate(GetLibraryBook(), "foo<if series->-<series>-<id>-<-if series>bar", directory, "ext") - .GetFilePath(Replacements) + .GetFilePath(Replacements, ".ext") .PathWithoutPrefix .Should().Be(expected); }