diff --git a/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll b/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll index a40ec022..5f6f2076 100644 Binary files a/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll and b/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll differ diff --git a/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb b/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb index bb671259..3382da4f 100644 Binary files a/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb and b/src/Jellyfin.CodeAnalysis/bin/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb differ diff --git a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfo.cs b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfo.cs index 06971691..e7bcaae5 100644 --- a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfo.cs +++ b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfo.cs @@ -1,6 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -13,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Jellyfin.CodeAnalysis")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e8873563856ad813cb4b7695b0aaa85c32729a4c")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+48569427a5cba735184e017148b7c71f665279bc")] [assembly: System.Reflection.AssemblyProductAttribute("Jellyfin.CodeAnalysis")] [assembly: System.Reflection.AssemblyTitleAttribute("Jellyfin.CodeAnalysis")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfoInputs.cache b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfoInputs.cache index 802bf3a3..fea0801d 100644 --- a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfoInputs.cache +++ b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.AssemblyInfoInputs.cache @@ -1 +1 @@ -4aa28b28b5f36d3ba59b76bc7e3a9a39544dcee89f6b8e3632f4df17d7b042d4 +5afb18d45c1a1f35abd23adbc2ff716c2f51ec4673ea08b8765ec2e818a59a28 diff --git a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.csproj.AssemblyReference.cache b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.csproj.AssemblyReference.cache index 4c5b9dad..1fd0093c 100644 Binary files a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.csproj.AssemblyReference.cache and b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.csproj.AssemblyReference.cache differ diff --git a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll index a40ec022..5f6f2076 100644 Binary files a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll and b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.dll differ diff --git a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb index bb671259..3382da4f 100644 Binary files a/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb and b/src/Jellyfin.CodeAnalysis/obj/Debug/netstandard2.0/Jellyfin.CodeAnalysis.pdb differ diff --git a/src/Jellyfin.Drawing/ImageProcessor.cs b/src/Jellyfin.Drawing/ImageProcessor.cs index a84f0034..12450cb0 100644 --- a/src/Jellyfin.Drawing/ImageProcessor.cs +++ b/src/Jellyfin.Drawing/ImageProcessor.cs @@ -64,10 +64,10 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable IImageEncoder imageEncoder, IServerConfigurationManager config) { - _logger = logger; - _fileSystem = fileSystem; - _imageEncoder = imageEncoder; - _appPaths = appPaths; + this._logger = logger; + this._fileSystem = fileSystem; + this._imageEncoder = imageEncoder; + this._appPaths = appPaths; var semaphoreCount = config.Configuration.ParallelImageEncodingLimit; if (semaphoreCount < 1) @@ -75,10 +75,10 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable semaphoreCount = Environment.ProcessorCount; } - _parallelEncodingLimit = new(semaphoreCount); + this._parallelEncodingLimit = new(semaphoreCount); } - private string ResizedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "resized-images"); + private string ResizedImageCachePath => Path.Combine(this._appPaths.ImageCachePath, "resized-images"); /// public IReadOnlyCollection SupportedInputFormats => @@ -113,11 +113,11 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable }; /// - public bool SupportsImageCollageCreation => _imageEncoder.SupportsImageCollageCreation; + public bool SupportsImageCollageCreation => this._imageEncoder.SupportsImageCollageCreation; /// public IReadOnlyCollection GetSupportedImageOutputFormats() - => _imageEncoder.SupportedOutputFormats; + => this._imageEncoder.SupportedOutputFormats; /// public async Task<(string Path, string? MimeType, DateTime DateModified)> ProcessImage(ImageProcessingOptions options) @@ -134,12 +134,12 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable } var mimeType = MimeTypes.GetMimeType(originalImagePath); - if (!_imageEncoder.SupportsImageEncoding) + if (!this._imageEncoder.SupportsImageEncoding) { return (originalImagePath, mimeType, dateModified); } - var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false); + var supportedImageInfo = await this.GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false); originalImagePath = supportedImageInfo.Path; // Original file doesn't exist, or original file is gif. @@ -179,8 +179,8 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable int quality = options.Quality; - ImageFormat outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); - string cacheFilePath = GetCacheFilePath( + ImageFormat outputFormat = this.GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); + string cacheFilePath = this.GetCacheFilePath( originalImagePath, options.Width, options.Height, @@ -204,9 +204,9 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable string resultPath; // Limit number of parallel (more precisely: concurrent) image encodings to prevent a high memory usage - using (await _parallelEncodingLimit.LockAsync().ConfigureAwait(false)) + using (await this._parallelEncodingLimit.LockAsync().ConfigureAwait(false)) { - resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat); + resultPath = this._imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat); } if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase)) @@ -215,19 +215,19 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable } } - return (cacheFilePath, outputFormat.GetMimeType(), _fileSystem.GetLastWriteTimeUtc(cacheFilePath)); + return (cacheFilePath, outputFormat.GetMimeType(), this._fileSystem.GetLastWriteTimeUtc(cacheFilePath)); } catch (Exception ex) { // If it fails for whatever reason, return the original image - _logger.LogError(ex, "Error encoding image"); + this._logger.LogError(ex, "Error encoding image"); return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); } } private ImageFormat GetOutputFormat(IReadOnlyCollection clientSupportedFormats, bool requiresTransparency) { - var serverFormats = GetSupportedImageOutputFormats(); + var serverFormats = this.GetSupportedImageOutputFormats(); // Client doesn't care about format, so start with webp if supported if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp)) @@ -354,7 +354,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable filename.Append(",v="); filename.Append(Version); - return GetCachePath(ResizedImageCachePath, filename.ToString(), format.GetExtension()); + return this.GetCachePath(this.ResizedImageCachePath, filename.ToString(), format.GetExtension()); } /// @@ -369,9 +369,9 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable } string path = info.Path; - _logger.LogDebug("Getting image size for item {ItemType} {Path}", item.GetType().Name, path); + this._logger.LogDebug("Getting image size for item {ItemType} {Path}", item.GetType().Name, path); - ImageDimensions size = GetImageDimensions(path); + ImageDimensions size = this.GetImageDimensions(path); info.Width = size.Width; info.Height = size.Height; @@ -380,13 +380,13 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable /// public ImageDimensions GetImageDimensions(string path) - => _imageEncoder.GetImageSize(path); + => this._imageEncoder.GetImageSize(path); /// public string GetImageBlurHash(string path) { - var size = GetImageDimensions(path); - return GetImageBlurHash(path, size); + var size = this.GetImageDimensions(path); + return this.GetImageBlurHash(path, size); } /// @@ -406,7 +406,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable int xComp = Math.Min((int)xCompF + 1, 9); int yComp = Math.Min((int)yCompF + 1, 9); - return _imageEncoder.GetImageBlurHash(xComp, yComp, path); + return this._imageEncoder.GetImageBlurHash(xComp, yComp, path); } /// @@ -415,11 +415,11 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable /// public string GetImageCacheTag(BaseItem item, ItemImageInfo image) - => GetImageCacheTag(item.Path, image.DateModified); + => this.GetImageCacheTag(item.Path, image.DateModified); /// public string GetImageCacheTag(BaseItemDto item, ItemImageInfo image) - => GetImageCacheTag(item.Path, image.DateModified); + => this.GetImageCacheTag(item.Path, image.DateModified); /// public string? GetImageCacheTag(BaseItemDto item, ChapterInfo chapter) @@ -429,7 +429,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable return null; } - return GetImageCacheTag(item.Path, chapter.ImageDateModified); + return this.GetImageCacheTag(item.Path, chapter.ImageDateModified); } /// @@ -440,7 +440,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable return null; } - return GetImageCacheTag(item, new ItemImageInfo + return this.GetImageCacheTag(item, new ItemImageInfo { Path = chapter.ImagePath, Type = ImageType.Chapter, @@ -456,7 +456,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable return null; } - return GetImageCacheTag(user.ProfileImage.Path, user.ProfileImage.LastModified); + return this.GetImageCacheTag(user.ProfileImage.Path, user.ProfileImage.LastModified); } private Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified) @@ -494,7 +494,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable var filename = uniqueName.GetMD5() + fileExtension; - return GetCachePath(path, filename); + return this.GetCachePath(path, filename); } /// @@ -528,28 +528,28 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable /// public void CreateImageCollage(ImageCollageOptions options, string? libraryName) { - _logger.LogDebug("Creating image collage and saving to {Path}", options.OutputPath); + this._logger.LogDebug("Creating image collage and saving to {Path}", options.OutputPath); - _imageEncoder.CreateImageCollage(options, libraryName); + this._imageEncoder.CreateImageCollage(options, libraryName); - _logger.LogDebug("Completed creation of image collage and saved to {Path}", options.OutputPath); + this._logger.LogDebug("Completed creation of image collage and saved to {Path}", options.OutputPath); } /// public void Dispose() { - if (_disposed) + if (this._disposed) { return; } - if (_imageEncoder is IDisposable disposable) + if (this._imageEncoder is IDisposable disposable) { disposable.Dispose(); } - _parallelEncodingLimit?.Dispose(); + this._parallelEncodingLimit?.Dispose(); - _disposed = true; + this._disposed = true; } } diff --git a/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs b/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs index 0e1e1c63..97b1610a 100644 --- a/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs +++ b/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs @@ -13,8 +13,17 @@ namespace Jellyfin.Controller.Tests using Moq; using Xunit; + /// + /// Tests for . + /// public class BaseItemManagerTests { + /// + /// Tests that IsMetadataFetcherEnabled checks library and server configuration options. + /// + /// The type of item to test. + /// The name of the metadata fetcher. + /// The expected result. [Theory] [InlineData(typeof(Book), "LibraryEnabled", true)] [InlineData(typeof(Book), "LibraryDisabled", false)] @@ -24,30 +33,36 @@ namespace Jellyfin.Controller.Tests { BaseItem item = (BaseItem)Activator.CreateInstance(itemType)!; - var libraryTypeOptions = itemType == typeof(Book) + TypeOptions? libraryTypeOptions = itemType == typeof(Book) ? new TypeOptions { Type = "Book", - MetadataFetchers = new[] { "LibraryEnabled" } + MetadataFetchers = ["LibraryEnabled"], } : null; - var serverConfiguration = new ServerConfiguration(); - foreach (var typeConfig in serverConfiguration.MetadataOptions) + ServerConfiguration serverConfiguration = new(); + foreach (MetadataOptions typeConfig in serverConfiguration.MetadataOptions) { - typeConfig.DisabledMetadataFetchers = new[] { "ServerDisabled" }; + typeConfig.DisabledMetadataFetchers = ["ServerDisabled"]; } - var serverConfigurationManager = new Mock(); - serverConfigurationManager.Setup(scm => scm.Configuration) + Mock serverConfigurationManager = new(); + _ = serverConfigurationManager.Setup(scm => scm.Configuration) .Returns(serverConfiguration); - var baseItemManager = new BaseItemManager(serverConfigurationManager.Object); - var actual = baseItemManager.IsMetadataFetcherEnabled(item, libraryTypeOptions, fetcherName); + BaseItemManager baseItemManager = new(serverConfigurationManager.Object); + bool actual = baseItemManager.IsMetadataFetcherEnabled(item, libraryTypeOptions, fetcherName); Assert.Equal(expected, actual); } + /// + /// Tests that IsImageFetcherEnabled checks library and server configuration options. + /// + /// The type of item to test. + /// The name of the image fetcher. + /// The expected result. [Theory] [InlineData(typeof(Book), "LibraryEnabled", true)] [InlineData(typeof(Book), "LibraryDisabled", false)] @@ -57,26 +72,26 @@ namespace Jellyfin.Controller.Tests { BaseItem item = (BaseItem)Activator.CreateInstance(itemType)!; - var libraryTypeOptions = itemType == typeof(Book) + TypeOptions? libraryTypeOptions = itemType == typeof(Book) ? new TypeOptions { Type = "Book", - ImageFetchers = new[] { "LibraryEnabled" } + ImageFetchers = ["LibraryEnabled"], } : null; - var serverConfiguration = new ServerConfiguration(); - foreach (var typeConfig in serverConfiguration.MetadataOptions) + ServerConfiguration serverConfiguration = new(); + foreach (MetadataOptions typeConfig in serverConfiguration.MetadataOptions) { - typeConfig.DisabledImageFetchers = new[] { "ServerDisabled" }; + typeConfig.DisabledImageFetchers = ["ServerDisabled"]; } - var serverConfigurationManager = new Mock(); - serverConfigurationManager.Setup(scm => scm.Configuration) + Mock serverConfigurationManager = new(); + _ = serverConfigurationManager.Setup(scm => scm.Configuration) .Returns(serverConfiguration); - var baseItemManager = new BaseItemManager(serverConfigurationManager.Object); - var actual = baseItemManager.IsImageFetcherEnabled(item, libraryTypeOptions, fetcherName); + BaseItemManager baseItemManager = new(serverConfigurationManager.Object); + bool actual = baseItemManager.IsImageFetcherEnabled(item, libraryTypeOptions, fetcherName); Assert.Equal(expected, actual); } diff --git a/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs b/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs index 319dcec2..a11859d3 100644 --- a/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs +++ b/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs @@ -4,124 +4,140 @@ namespace Jellyfin.Controller.Tests { + using System.Collections.Generic; using System.Linq; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.IO; using Moq; using Xunit; + /// + /// Tests for . + /// public class DirectoryServiceTests { private const string LowerCasePath = "/music/someartist"; private const string UpperCasePath = "/music/SOMEARTIST"; - private static readonly FileSystemMetadata[] _lowerCaseFileSystemMetadata = - { + private static readonly FileSystemMetadata[] LowerCaseFileSystemMetadata = + [ new() { FullName = LowerCasePath + "/Artwork", - IsDirectory = true + IsDirectory = true, }, new() { FullName = LowerCasePath + "/Some Other Folder", - IsDirectory = true + IsDirectory = true, }, new() { FullName = LowerCasePath + "/Song 2.mp3", - IsDirectory = false + IsDirectory = false, }, new() { FullName = LowerCasePath + "/Song 3.mp3", - IsDirectory = false - } - }; + IsDirectory = false, + }, + ]; - private static readonly FileSystemMetadata[] _upperCaseFileSystemMetadata = - { + private static readonly FileSystemMetadata[] UpperCaseFileSystemMetadata = + [ new() { FullName = UpperCasePath + "/Lyrics", - IsDirectory = true + IsDirectory = true, }, new() { FullName = UpperCasePath + "/Song 1.mp3", - IsDirectory = false - } - }; + IsDirectory = false, + }, + ]; + /// + /// Tests that GetFileSystemEntries caches entries for paths with different casing. + /// [Fact] public void GetFileSystemEntries_GivenPathsWithDifferentCasing_CachesAll() { - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == UpperCasePath), false)).Returns(_upperCaseFileSystemMetadata); - fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == LowerCasePath), false)).Returns(_lowerCaseFileSystemMetadata); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == UpperCasePath), false)).Returns(UpperCaseFileSystemMetadata); + _ = fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == LowerCasePath), false)).Returns(LowerCaseFileSystemMetadata); + DirectoryService directoryService = new(fileSystemMock.Object); - var upperCaseResult = directoryService.GetFileSystemEntries(UpperCasePath); - var lowerCaseResult = directoryService.GetFileSystemEntries(LowerCasePath); + FileSystemMetadata[] upperCaseResult = directoryService.GetFileSystemEntries(UpperCasePath); + FileSystemMetadata[] lowerCaseResult = directoryService.GetFileSystemEntries(LowerCasePath); - Assert.Equal(_upperCaseFileSystemMetadata, upperCaseResult); - Assert.Equal(_lowerCaseFileSystemMetadata, lowerCaseResult); + Assert.Equal(UpperCaseFileSystemMetadata, upperCaseResult); + Assert.Equal(LowerCaseFileSystemMetadata, lowerCaseResult); } + /// + /// Tests that GetFiles returns correct files for paths with different casing. + /// [Fact] public void GetFiles_GivenPathsWithDifferentCasing_ReturnsCorrectFiles() { - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == UpperCasePath), false)).Returns(_upperCaseFileSystemMetadata); - fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == LowerCasePath), false)).Returns(_lowerCaseFileSystemMetadata); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == UpperCasePath), false)).Returns(UpperCaseFileSystemMetadata); + _ = fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == LowerCasePath), false)).Returns(LowerCaseFileSystemMetadata); + DirectoryService directoryService = new(fileSystemMock.Object); - var upperCaseResult = directoryService.GetFiles(UpperCasePath); - var lowerCaseResult = directoryService.GetFiles(LowerCasePath); + List upperCaseResult = directoryService.GetFiles(UpperCasePath); + List lowerCaseResult = directoryService.GetFiles(LowerCasePath); - Assert.Equal(_upperCaseFileSystemMetadata.Where(f => !f.IsDirectory), upperCaseResult); - Assert.Equal(_lowerCaseFileSystemMetadata.Where(f => !f.IsDirectory), lowerCaseResult); + Assert.Equal(UpperCaseFileSystemMetadata.Where(f => !f.IsDirectory), upperCaseResult); + Assert.Equal(LowerCaseFileSystemMetadata.Where(f => !f.IsDirectory), lowerCaseResult); } + /// + /// Tests that GetDirectories returns correct directories for paths with different casing. + /// [Fact] public void GetDirectories_GivenPathsWithDifferentCasing_ReturnsCorrectDirectories() { - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == UpperCasePath), false)).Returns(_upperCaseFileSystemMetadata); - fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == LowerCasePath), false)).Returns(_lowerCaseFileSystemMetadata); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == UpperCasePath), false)).Returns(UpperCaseFileSystemMetadata); + _ = fileSystemMock.Setup(f => f.GetFileSystemEntries(It.Is(x => x == LowerCasePath), false)).Returns(LowerCaseFileSystemMetadata); + DirectoryService directoryService = new(fileSystemMock.Object); - var upperCaseResult = directoryService.GetDirectories(UpperCasePath); - var lowerCaseResult = directoryService.GetDirectories(LowerCasePath); + List upperCaseResult = directoryService.GetDirectories(UpperCasePath); + List lowerCaseResult = directoryService.GetDirectories(LowerCasePath); - Assert.Equal(_upperCaseFileSystemMetadata.Where(f => f.IsDirectory), upperCaseResult); - Assert.Equal(_lowerCaseFileSystemMetadata.Where(f => f.IsDirectory), lowerCaseResult); + Assert.Equal(UpperCaseFileSystemMetadata.Where(f => f.IsDirectory), upperCaseResult); + Assert.Equal(LowerCaseFileSystemMetadata.Where(f => f.IsDirectory), lowerCaseResult); } + /// + /// Tests that GetFile returns correct file for paths with different casing. + /// [Fact] public void GetFile_GivenFilePathsWithDifferentCasing_ReturnsCorrectFile() { const string lowerCasePath = "/music/someartist/song 1.mp3"; - var lowerCaseFileSystemMetadata = new FileSystemMetadata + FileSystemMetadata lowerCaseFileSystemMetadata = new() { FullName = lowerCasePath, - Exists = true + Exists = true, }; const string upperCasePath = "/music/SOMEARTIST/SONG 1.mp3"; - var upperCaseFileSystemMetadata = new FileSystemMetadata + FileSystemMetadata upperCaseFileSystemMetadata = new() { FullName = upperCasePath, - Exists = false + Exists = false, }; - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == upperCasePath))).Returns(upperCaseFileSystemMetadata); - fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == lowerCasePath))).Returns(lowerCaseFileSystemMetadata); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == upperCasePath))).Returns(upperCaseFileSystemMetadata); + _ = fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == lowerCasePath))).Returns(lowerCaseFileSystemMetadata); + DirectoryService directoryService = new(fileSystemMock.Object); - var lowerCaseDirResult = directoryService.GetDirectory(lowerCasePath); - var lowerCaseFileResult = directoryService.GetFile(lowerCasePath); - var upperCaseDirResult = directoryService.GetDirectory(upperCasePath); - var upperCaseFileResult = directoryService.GetFile(upperCasePath); + FileSystemMetadata? lowerCaseDirResult = directoryService.GetDirectory(lowerCasePath); + FileSystemMetadata? lowerCaseFileResult = directoryService.GetFile(lowerCasePath); + FileSystemMetadata? upperCaseDirResult = directoryService.GetDirectory(upperCasePath); + FileSystemMetadata? upperCaseFileResult = directoryService.GetFile(upperCasePath); Assert.Null(lowerCaseDirResult); Assert.Equal(lowerCaseFileSystemMetadata, lowerCaseFileResult); @@ -129,32 +145,35 @@ namespace Jellyfin.Controller.Tests Assert.Null(upperCaseFileResult); } + /// + /// Tests that GetDirectory returns correct directory for paths with different casing. + /// [Fact] public void GetDirectory_GivenFilePathsWithDifferentCasing_ReturnsCorrectDirectory() { const string lowerCasePath = "/music/someartist/Lyrics"; - var lowerCaseFileSystemMetadata = new FileSystemMetadata + FileSystemMetadata lowerCaseFileSystemMetadata = new() { FullName = lowerCasePath, IsDirectory = true, - Exists = true + Exists = true, }; const string upperCasePath = "/music/SOMEARTIST/LYRICS"; - var upperCaseFileSystemMetadata = new FileSystemMetadata + FileSystemMetadata upperCaseFileSystemMetadata = new() { FullName = upperCasePath, IsDirectory = true, - Exists = false + Exists = false, }; - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == upperCasePath))).Returns(upperCaseFileSystemMetadata); - fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == lowerCasePath))).Returns(lowerCaseFileSystemMetadata); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == upperCasePath))).Returns(upperCaseFileSystemMetadata); + _ = fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == lowerCasePath))).Returns(lowerCaseFileSystemMetadata); + DirectoryService directoryService = new(fileSystemMock.Object); - var lowerCaseDirResult = directoryService.GetDirectory(lowerCasePath); - var lowerCaseFileResult = directoryService.GetFile(lowerCasePath); - var upperCaseDirResult = directoryService.GetDirectory(upperCasePath); - var upperCaseFileResult = directoryService.GetFile(upperCasePath); + FileSystemMetadata? lowerCaseDirResult = directoryService.GetDirectory(lowerCasePath); + FileSystemMetadata? lowerCaseFileResult = directoryService.GetFile(lowerCasePath); + FileSystemMetadata? upperCaseDirResult = directoryService.GetDirectory(upperCasePath); + FileSystemMetadata? upperCaseFileResult = directoryService.GetFile(upperCasePath); Assert.Equal(lowerCaseFileSystemMetadata, lowerCaseDirResult); Assert.Null(lowerCaseFileResult); @@ -162,92 +181,101 @@ namespace Jellyfin.Controller.Tests Assert.Null(upperCaseFileResult); } + /// + /// Tests that GetFile returns cached file when the path is already cached. + /// [Fact] public void GetFile_GivenCachedPath_ReturnsCachedFile() { const string path = "/music/someartist/song 1.mp3"; - var cachedFileSystemMetadata = new FileSystemMetadata + FileSystemMetadata cachedFileSystemMetadata = new() { FullName = path, - Exists = true + Exists = true, }; - var newFileSystemMetadata = new FileSystemMetadata + FileSystemMetadata newFileSystemMetadata = new() { FullName = "/music/SOMEARTIST/song 1.mp3", - Exists = true + Exists = true, }; - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == path))).Returns(cachedFileSystemMetadata); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == path))).Returns(cachedFileSystemMetadata); + DirectoryService directoryService = new(fileSystemMock.Object); - var result = directoryService.GetFile(path); - fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == path))).Returns(newFileSystemMetadata); - var secondResult = directoryService.GetFile(path); + FileSystemMetadata? result = directoryService.GetFile(path); + _ = fileSystemMock.Setup(f => f.GetFileSystemInfo(It.Is(x => x == path))).Returns(newFileSystemMetadata); + FileSystemMetadata? secondResult = directoryService.GetFile(path); Assert.Equivalent(cachedFileSystemMetadata, result); Assert.Equivalent(cachedFileSystemMetadata, secondResult); } + /// + /// Tests that GetFilePaths returns only cached paths when clear is not called. + /// [Fact] public void GetFilePaths_GivenCachedFilePathWithoutClear_ReturnsOnlyCachedPaths() { const string path = "/music/someartist"; - var cachedPaths = new[] - { + string[] cachedPaths = + [ "/music/someartist/song 1.mp3", "/music/someartist/song 2.mp3", "/music/someartist/song 3.mp3", "/music/someartist/song 4.mp3", - }; - var newPaths = new[] - { + ]; + string[] newPaths = + [ "/music/someartist/song 5.mp3", "/music/someartist/song 6.mp3", "/music/someartist/song 7.mp3", "/music/someartist/song 8.mp3", - }; + ]; - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(cachedPaths); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(cachedPaths); + DirectoryService directoryService = new(fileSystemMock.Object); - var result = directoryService.GetFilePaths(path); - fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(newPaths); - var secondResult = directoryService.GetFilePaths(path); + IReadOnlyList result = directoryService.GetFilePaths(path); + _ = fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(newPaths); + IReadOnlyList secondResult = directoryService.GetFilePaths(path); Assert.Equal(cachedPaths, result); Assert.Equal(cachedPaths, secondResult); } + /// + /// Tests that GetFilePaths returns new paths when clear is called. + /// [Fact] public void GetFilePaths_GivenCachedFilePathWithClear_ReturnsNewPaths() { const string path = "/music/someartist"; - var cachedPaths = new[] - { + string[] cachedPaths = + [ "/music/someartist/song 1.mp3", "/music/someartist/song 2.mp3", "/music/someartist/song 3.mp3", "/music/someartist/song 4.mp3", - }; - var newPaths = new[] - { + ]; + string[] newPaths = + [ "/music/someartist/song 5.mp3", "/music/someartist/song 6.mp3", "/music/someartist/song 7.mp3", "/music/someartist/song 8.mp3", - }; + ]; - var fileSystemMock = new Mock(); - fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(cachedPaths); - var directoryService = new DirectoryService(fileSystemMock.Object); + Mock fileSystemMock = new(); + _ = fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(cachedPaths); + DirectoryService directoryService = new(fileSystemMock.Object); - var result = directoryService.GetFilePaths(path); - fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(newPaths); - var secondResult = directoryService.GetFilePaths(path, true); + IReadOnlyList result = directoryService.GetFilePaths(path); + _ = fileSystemMock.Setup(f => f.GetFilePaths(It.Is(x => x == path), false)).Returns(newPaths); + IReadOnlyList secondResult = directoryService.GetFilePaths(path, true); Assert.Equal(cachedPaths, result); Assert.Equal(newPaths, secondResult); diff --git a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs index 8cb83f17..9e530e79 100644 --- a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs +++ b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs @@ -2,49 +2,67 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // -namespace Jellyfin.Controller.Tests.Entities; - -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.MediaInfo; -using Moq; -using Xunit; - -public class BaseItemTests +namespace Jellyfin.Controller.Tests.Entities { - [Theory] - [InlineData("", "")] - [InlineData("1", "0000000001")] - [InlineData("t", "t")] - [InlineData("test", "test")] - [InlineData("test1", "test0000000001")] - [InlineData("1test 2", "0000000001test 0000000002")] - public void BaseItem_ModifySortChunks_Valid(string input, string expected) - => Assert.Equal(expected, BaseItem.ModifySortChunks(input)); + using MediaBrowser.Controller.Entities; + using MediaBrowser.Controller.Library; + using MediaBrowser.Model.MediaInfo; + using Moq; + using Xunit; - [Theory] - [InlineData("/Movies/Ted/Ted.mp4", "/Movies/Ted/Ted - Unrated Edition.mp4", "Ted", "Unrated Edition")] - [InlineData("/Movies/Deadpool 2 (2018)/Deadpool 2 (2018).mkv", "/Movies/Deadpool 2 (2018)/Deadpool 2 (2018) - Super Duper Cut.mkv", "Deadpool 2 (2018)", "Super Duper Cut")] - public void GetMediaSourceName_Valid(string primaryPath, string altPath, string name, string altName) + /// + /// Tests for . + /// + public class BaseItemTests { - var mediaSourceManager = new Mock(); - mediaSourceManager.Setup(x => x.GetPathProtocol(It.IsAny())) - .Returns((string x) => MediaProtocol.File); - BaseItem.MediaSourceManager = mediaSourceManager.Object; - - var video = new Video() + /// + /// Tests that ModifySortChunks correctly modifies sort chunks. + /// + /// The input string. + /// The expected output string. + [Theory] + [InlineData("", "")] + [InlineData("1", "0000000001")] + [InlineData("t", "t")] + [InlineData("test", "test")] + [InlineData("test1", "test0000000001")] + [InlineData("1test 2", "0000000001test 0000000002")] + public void BaseItem_ModifySortChunks_Valid(string input, string expected) { - Path = primaryPath - }; + Assert.Equal(expected, BaseItem.ModifySortChunks(input)); + } - var videoAlt = new Video() + /// + /// Tests that GetMediaSourceName returns the correct name for media sources. + /// + /// The primary path. + /// The alternate path. + /// The expected name for the primary path. + /// The expected name for the alternate path. + [Theory] + [InlineData("/Movies/Ted/Ted.mp4", "/Movies/Ted/Ted - Unrated Edition.mp4", "Ted", "Unrated Edition")] + [InlineData("/Movies/Deadpool 2 (2018)/Deadpool 2 (2018).mkv", "/Movies/Deadpool 2 (2018)/Deadpool 2 (2018) - Super Duper Cut.mkv", "Deadpool 2 (2018)", "Super Duper Cut")] + public void GetMediaSourceName_Valid(string primaryPath, string altPath, string name, string altName) { - Path = altPath, - }; + Mock mediaSourceManager = new(); + _ = mediaSourceManager.Setup(x => x.GetPathProtocol(It.IsAny())) + .Returns((string x) => MediaProtocol.File); + BaseItem.MediaSourceManager = mediaSourceManager.Object; - video.LocalAlternateVersions = [videoAlt.Path]; + Video video = new() + { + Path = primaryPath, + }; - Assert.Equal(name, video.GetMediaSourceName(video)); - Assert.Equal(altName, video.GetMediaSourceName(videoAlt)); + Video videoAlt = new() + { + Path = altPath, + }; + + video.LocalAlternateVersions = [videoAlt.Path]; + + Assert.Equal(name, video.GetMediaSourceName(video)); + Assert.Equal(altName, video.GetMediaSourceName(videoAlt)); + } } } diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index c81c0a04..ee30ed70 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -4,6 +4,7 @@ {462584F7-5023-4019-9EAC-B98CA458C0A0} net11.0 + true