diff --git a/API.Benchmark/API.Benchmark.csproj b/API.Benchmark/API.Benchmark.csproj index 5461138d5..11ef151a2 100644 --- a/API.Benchmark/API.Benchmark.csproj +++ b/API.Benchmark/API.Benchmark.csproj @@ -20,5 +20,11 @@ Always + + + Data + Always + + diff --git a/API.Benchmark/ArchiveSerivceBenchmark.cs b/API.Benchmark/ArchiveSerivceBenchmark.cs deleted file mode 100644 index 11a66d7bc..000000000 --- a/API.Benchmark/ArchiveSerivceBenchmark.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace API.Benchmark; - -public class ArchiveSerivceBenchmark -{ - // Benchmark to test default GetNumberOfPages from archive - // vs a new method where I try to open the archive and return said stream -} diff --git a/API.Benchmark/ArchiveServiceBenchmark.cs b/API.Benchmark/ArchiveServiceBenchmark.cs new file mode 100644 index 000000000..d8418ee26 --- /dev/null +++ b/API.Benchmark/ArchiveServiceBenchmark.cs @@ -0,0 +1,54 @@ +using System; +using System.IO.Abstractions; +using Microsoft.Extensions.Logging.Abstractions; +using API.Services; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Order; + +namespace API.Benchmark; + +[StopOnFirstError] +[MemoryDiagnoser] +[RankColumn] +[Orderer(SummaryOrderPolicy.FastestToSlowest)] +[SimpleJob(launchCount: 1, warmupCount: 5, targetCount: 20)] +public class ArchiveServiceBenchmark +{ + private readonly ArchiveService _archiveService; + private readonly IDirectoryService _directoryService; + private readonly IImageService _imageService; + + public ArchiveServiceBenchmark() + { + _directoryService = new DirectoryService(null, new FileSystem()); + _imageService = new ImageService(null, _directoryService); + _archiveService = new ArchiveService(new NullLogger(), _directoryService, _imageService); + } + + [Benchmark(Baseline = true)] + public void TestGetComicInfo_baseline() + { + if (_archiveService.GetComicInfo("Data/ComicInfo.zip") == null) { + throw new Exception("ComicInfo not found"); + } + } + + [Benchmark] + public void TestGetComicInfo_duplicate() + { + if (_archiveService.GetComicInfo("Data/ComicInfo_duplicateInfos.zip") == null) { + throw new Exception("ComicInfo not found"); + } + } + + [Benchmark] + public void TestGetComicInfo_outside_root() + { + if (_archiveService.GetComicInfo("Data/ComicInfo_outside_root.zip") == null) { + throw new Exception("ComicInfo not found"); + } + } + + // Benchmark to test default GetNumberOfPages from archive + // vs a new method where I try to open the archive and return said stream +} diff --git a/API.Tests/Services/ArchiveServiceTests.cs b/API.Tests/Services/ArchiveServiceTests.cs index 7fc267869..f399cb790 100644 --- a/API.Tests/Services/ArchiveServiceTests.cs +++ b/API.Tests/Services/ArchiveServiceTests.cs @@ -256,17 +256,31 @@ public class ArchiveServiceTests Assert.Equal("Junya Inoue", comicInfo.Writer); } - [Fact] - public void ShouldHaveComicInfo_TopLevelFileOnly() + [Theory] + [InlineData("ComicInfo_duplicateInfos.zip")] + [InlineData("ComicInfo_duplicateInfos_reversed.zip")] + [InlineData("ComicInfo_duplicateInfos.rar")] + public void ShouldHaveComicInfo_TopLevelFileOnly(string filename) { var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/ComicInfos"); - var archive = Path.Join(testDirectory, "ComicInfo_duplicateInfos.zip"); + var archive = Path.Join(testDirectory, filename); var comicInfo = _archiveService.GetComicInfo(archive); Assert.NotNull(comicInfo); Assert.Equal("BTOOOM!", comicInfo.Series); } + [Fact] + public void ShouldHaveComicInfo_OutsideRoot() + { + var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/ComicInfos"); + var archive = Path.Join(testDirectory, "ComicInfo_outside_root.zip"); + + var comicInfo = _archiveService.GetComicInfo(archive); + Assert.NotNull(comicInfo); + Assert.Equal("BTOOOM! - Duplicate", comicInfo.Series); + } + #endregion #region CanParseComicInfo diff --git a/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_duplicateInfos.rar b/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_duplicateInfos.rar new file mode 100644 index 000000000..9d5bab5a2 Binary files /dev/null and b/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_duplicateInfos.rar differ diff --git a/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_duplicateInfos_reversed.zip b/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_duplicateInfos_reversed.zip new file mode 100644 index 000000000..f764a4a60 Binary files /dev/null and b/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_duplicateInfos_reversed.zip differ diff --git a/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_outside_root.zip b/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_outside_root.zip new file mode 100644 index 000000000..9caea5bf1 Binary files /dev/null and b/API.Tests/Services/Test Data/ArchiveService/ComicInfos/ComicInfo_outside_root.zip differ diff --git a/API/Services/ArchiveService.cs b/API/Services/ArchiveService.cs index 12c0a4029..b370f178d 100644 --- a/API/Services/ArchiveService.cs +++ b/API/Services/ArchiveService.cs @@ -328,12 +328,11 @@ public class ArchiveService : IArchiveService return false; } - private static bool ValidComicInfoArchiveEntry(string fullName, string name) + private static bool IsComicInfoArchiveEntry(string fullName, string name) { - var filenameWithoutExtension = Path.GetFileNameWithoutExtension(name).ToLower(); return !Tasks.Scanner.Parser.Parser.HasBlacklistedFolderInPath(fullName) - && (fullName.Equals(ComicInfoFilename) || (string.IsNullOrEmpty(fullName) && name.Equals(ComicInfoFilename))) - && !filenameWithoutExtension.StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith); + && name.Equals(ComicInfoFilename, StringComparison.OrdinalIgnoreCase) + && !name.StartsWith(Tasks.Scanner.Parser.Parser.MacOsMetadataFileStartsWith); } /// @@ -356,7 +355,8 @@ public class ArchiveService : IArchiveService { using var archive = ZipFile.OpenRead(archivePath); - var entry = archive.Entries.FirstOrDefault(x => ValidComicInfoArchiveEntry(x.FullName, x.Name)); + var entry = archive.Entries.FirstOrDefault(x => (x.FullName ?? x.Name) == ComicInfoFilename) ?? + archive.Entries.FirstOrDefault(x => IsComicInfoArchiveEntry(x.FullName, x.Name)); if (entry != null) { using var stream = entry.Open(); @@ -371,8 +371,9 @@ public class ArchiveService : IArchiveService case ArchiveLibrary.SharpCompress: { using var archive = ArchiveFactory.Open(archivePath); - var entry = archive.Entries.FirstOrDefault(entry => - ValidComicInfoArchiveEntry(Path.GetDirectoryName(entry.Key), entry.Key)); + var entry = archive.Entries.FirstOrDefault(entry => entry.Key == ComicInfoFilename) ?? + archive.Entries.FirstOrDefault(entry => + IsComicInfoArchiveEntry(Path.GetDirectoryName(entry.Key), entry.Key)); if (entry != null) {