From 732a290012e155f0b1532b081e1395d1f0c85966 Mon Sep 17 00:00:00 2001 From: Dion Date: Tue, 21 Jan 2025 18:36:04 +0100 Subject: [PATCH] #1833 add tests --- .../Thumbnails/ThumbnailSizes.cs | 12 --- .../Testers/PreflightThumbnailGeneration.cs | 4 +- .../Process/VideoProcessThumbnailPost.cs | 11 ++- .../FakeMocks/FakeIThumbnailGenerator.cs | 36 ++++++++ .../HealthCheck/DiskStorageHealthCheckTest.cs | 24 +++++ .../Thumbnails/ThumbnailSizesTests.cs | 38 ++++++++ .../CompositeThumbnailGeneratorTests.cs | 90 +++++++++++++++++++ .../ThumbnailGeneratorFactoryTests.cs | 34 +++++++ .../Process/VideoProcessThumbnailPostTests.cs | 78 ++++++++++++++++ 9 files changed, 311 insertions(+), 16 deletions(-) create mode 100644 starsky/starskytest/FakeMocks/FakeIThumbnailGenerator.cs create mode 100644 starsky/starskytest/starsky.foundation.platform/Thumbnails/ThumbnailSizesTests.cs create mode 100644 starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/CompositeThumbnailGeneratorTests.cs create mode 100644 starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/ThumbnailGeneratorFactoryTests.cs create mode 100644 starsky/starskytest/starsky.foundation.video/Process/VideoProcessThumbnailPostTests.cs diff --git a/starsky/starsky.foundation.platform/Thumbnails/ThumbnailSizes.cs b/starsky/starsky.foundation.platform/Thumbnails/ThumbnailSizes.cs index bdfd7ac61..1d74f826b 100644 --- a/starsky/starsky.foundation.platform/Thumbnails/ThumbnailSizes.cs +++ b/starsky/starsky.foundation.platform/Thumbnails/ThumbnailSizes.cs @@ -4,18 +4,6 @@ namespace starsky.foundation.platform.Thumbnails; public static class ThumbnailSizes { - public static List GetSizes(bool skipExtraLarge) - { - var sizesList = new List { ThumbnailSize.Small, ThumbnailSize.Large }; - - if ( !skipExtraLarge ) - { - sizesList.Add(ThumbnailSize.ExtraLarge); - } - - return sizesList; - } - public static List GetLargeToSmallSizes(bool skipExtraLarge) { var sizesList = new List(); diff --git a/starsky/starsky.foundation.thumbnailgeneration/GenerationFactory/Testers/PreflightThumbnailGeneration.cs b/starsky/starsky.foundation.thumbnailgeneration/GenerationFactory/Testers/PreflightThumbnailGeneration.cs index 399226304..9a27a49a9 100644 --- a/starsky/starsky.foundation.thumbnailgeneration/GenerationFactory/Testers/PreflightThumbnailGeneration.cs +++ b/starsky/starsky.foundation.thumbnailgeneration/GenerationFactory/Testers/PreflightThumbnailGeneration.cs @@ -32,7 +32,7 @@ public List Preflight( if ( thumbnailSizes.Count == 0 ) { return ErrorGenerationResultModel.FailedResult( - ThumbnailSizes.GetSizes(true), + ThumbnailSizes.GetLargeToSmallSizes(true), subPath, fileHash, false, $"No thumbnail sizes are given for {subPath}"); } @@ -40,7 +40,7 @@ public List Preflight( if ( imageFormat == ThumbnailImageFormat.unknown ) { return ErrorGenerationResultModel.FailedResult( - ThumbnailSizes.GetSizes(true), + ThumbnailSizes.GetLargeToSmallSizes(true), subPath, fileHash, false, $"No valid image format is given for {subPath}"); } diff --git a/starsky/starsky.foundation.video/Process/VideoProcessThumbnailPost.cs b/starsky/starsky.foundation.video/Process/VideoProcessThumbnailPost.cs index e33fceda6..e5c48143a 100644 --- a/starsky/starsky.foundation.video/Process/VideoProcessThumbnailPost.cs +++ b/starsky/starsky.foundation.video/Process/VideoProcessThumbnailPost.cs @@ -47,8 +47,15 @@ public async Task PostPrepThumbnail(VideoResult runResult, private static string GetJpegInFolderSubPath(string subPath) { - return $"{FilenamesHelper.GetParentPath(subPath)}/" + - $"{FilenamesHelper.GetFileNameWithoutExtension(subPath)}.jpg"; + const string extension = "jpg"; + var parentPath = FilenamesHelper.GetParentPath(subPath); + if ( parentPath == "/" ) + { + return $"/{FilenamesHelper.GetFileNameWithoutExtension(subPath)}.{extension}"; + } + + return $"{parentPath}/" + + $"{FilenamesHelper.GetFileNameWithoutExtension(subPath)}.{extension}"; } private async Task WriteStreamInFolderSubPathAsync(Stream stream, string subPath, diff --git a/starsky/starskytest/FakeMocks/FakeIThumbnailGenerator.cs b/starsky/starskytest/FakeMocks/FakeIThumbnailGenerator.cs new file mode 100644 index 000000000..e800e9302 --- /dev/null +++ b/starsky/starskytest/FakeMocks/FakeIThumbnailGenerator.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using starsky.foundation.platform.Enums; +using starsky.foundation.platform.Thumbnails; +using starsky.foundation.thumbnailgeneration.GenerationFactory.Generators.Interfaces; +using starsky.foundation.thumbnailgeneration.Models; + +namespace starskytest.FakeMocks; + +public class FakeThumbnailGenerator : IThumbnailGenerator +{ + private Exception? _exception; + private IEnumerable _results = new List(); + + public Task> GenerateThumbnail(string singleSubPath, + string fileHash, ThumbnailImageFormat imageFormat, List thumbnailSizes) + { + if ( _exception != null ) + { + throw _exception; + } + + return Task.FromResult(_results); + } + + public void SetResults(IEnumerable results) + { + _results = results; + } + + public void SetException(Exception exception) + { + _exception = exception; + } +} diff --git a/starsky/starskytest/starsky.feature.health/HealthCheck/DiskStorageHealthCheckTest.cs b/starsky/starskytest/starsky.feature.health/HealthCheck/DiskStorageHealthCheckTest.cs index 363f2f3ef..e6b0710b2 100644 --- a/starsky/starskytest/starsky.feature.health/HealthCheck/DiskStorageHealthCheckTest.cs +++ b/starsky/starskytest/starsky.feature.health/HealthCheck/DiskStorageHealthCheckTest.cs @@ -11,6 +11,30 @@ namespace starskytest.starsky.feature.health.HealthCheck; [TestClass] public sealed class DiskStorageHealthCheckTest { + [TestMethod] + public void Constructor_NullOptions_ThrowsArgumentNullException() + { + // Arrange + DiskStorageOptions? options = null; + var logger = new FakeIWebLogger(); + + // Act & Assert + Assert.ThrowsException(() => + new DiskStorageHealthCheck(options, logger)); + } + + [TestMethod] + public void Constructor_ValidParameters_DoesNotThrow() + { + // Arrange + var options = new DiskStorageOptions(); + var logger = new FakeIWebLogger(); + + // Act & Assert + var healthCheck = new DiskStorageHealthCheck(options, logger); + Assert.IsNotNull(healthCheck); + } + [TestMethod] public async Task RunSuccessful() { diff --git a/starsky/starskytest/starsky.foundation.platform/Thumbnails/ThumbnailSizesTests.cs b/starsky/starskytest/starsky.foundation.platform/Thumbnails/ThumbnailSizesTests.cs new file mode 100644 index 000000000..8f0232d3b --- /dev/null +++ b/starsky/starskytest/starsky.foundation.platform/Thumbnails/ThumbnailSizesTests.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using starsky.foundation.platform.Thumbnails; + +namespace starskytest.starsky.foundation.platform.Thumbnails; + +[TestClass] +public class ThumbnailSizesTests +{ + [TestMethod] + public void GetLargeToSmallSizes_WithExtraLarge() + { + // Arrange + var expectedSizes = new List + { + ThumbnailSize.ExtraLarge, ThumbnailSize.Large, ThumbnailSize.Small + }; + + // Act + var result = ThumbnailSizes.GetLargeToSmallSizes(false); + + // Assert + CollectionAssert.AreEqual(expectedSizes, result); + } + + [TestMethod] + public void GetLargeToSmallSizes_WithoutExtraLarge() + { + // Arrange + var expectedSizes = new List { ThumbnailSize.Large, ThumbnailSize.Small }; + + // Act + var result = ThumbnailSizes.GetLargeToSmallSizes(true); + + // Assert + CollectionAssert.AreEqual(expectedSizes, result); + } +} diff --git a/starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/CompositeThumbnailGeneratorTests.cs b/starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/CompositeThumbnailGeneratorTests.cs new file mode 100644 index 000000000..175ac63e6 --- /dev/null +++ b/starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/CompositeThumbnailGeneratorTests.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using starsky.foundation.platform.Enums; +using starsky.foundation.platform.Thumbnails; +using starsky.foundation.thumbnailgeneration.GenerationFactory; +using starsky.foundation.thumbnailgeneration.GenerationFactory.Generators.Interfaces; +using starsky.foundation.thumbnailgeneration.Models; +using starskytest.FakeMocks; + +namespace starskytest.starsky.foundation.thumbnailgeneration.GenerationFactory; + +[TestClass] +public class CompositeThumbnailGeneratorTests +{ + private readonly FakeIWebLogger _logger; + private readonly CompositeThumbnailGenerator _compositeGenerator; + private readonly List _generatorMocks; + + public CompositeThumbnailGeneratorTests() + { + _logger = new FakeIWebLogger(); + _generatorMocks = + [ + new FakeThumbnailGenerator(), + new FakeThumbnailGenerator() + ]; + _compositeGenerator = new CompositeThumbnailGenerator( + _generatorMocks.Cast().ToList(), _logger); + } + + [TestMethod] + [DataRow(true, true, true)] + [DataRow(false, true, true)] + [DataRow(false, false, false)] + public async Task GenerateThumbnail_VariousScenarios_ReturnsExpectedResults(bool firstSuccess, + bool secondSuccess, bool expectedSuccess) + { + // Arrange + const string singleSubPath = "test.jpg"; + const string fileHash = "hash"; + const ThumbnailImageFormat imageFormat = ThumbnailImageFormat.jpg; + var thumbnailSizes = new List { ThumbnailSize.Small }; + + var firstResults = new List { new() { Success = firstSuccess } }; + + var secondResults = new List { new() { Success = secondSuccess } }; + + _generatorMocks[0].SetResults(firstResults); + _generatorMocks[1].SetResults(secondResults); + + // Act + var results = + await _compositeGenerator.GenerateThumbnail(singleSubPath, fileHash, imageFormat, + thumbnailSizes); + + // Assert + Assert.AreEqual(expectedSuccess, results.All(r => r.Success)); + } + + [TestMethod] + [DataRow(true)] + [DataRow(false)] + public async Task GenerateThumbnail_GeneratorThrowsException_LogsError(bool secondSuccess) + { + // Arrange + const string singleSubPath = "test.jpg"; + const string fileHash = "hash"; + const ThumbnailImageFormat imageFormat = ThumbnailImageFormat.jpg; + var thumbnailSizes = new List { ThumbnailSize.Small }; + + _generatorMocks[0].SetException(new Exception("Test exception")); + + var secondResults = new List { new() { Success = secondSuccess } }; + + _generatorMocks[1].SetResults(secondResults); + + // Act + var results = + await _compositeGenerator.GenerateThumbnail(singleSubPath, fileHash, imageFormat, + thumbnailSizes); + + // Assert + Assert.IsTrue( + _logger.TrackedExceptions.Any(log => log.Item2?.Contains("Test exception") == true)); + Assert.AreEqual(secondSuccess, results.All(r => r.Success)); + } +} diff --git a/starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/ThumbnailGeneratorFactoryTests.cs b/starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/ThumbnailGeneratorFactoryTests.cs new file mode 100644 index 000000000..6d0f221da --- /dev/null +++ b/starsky/starskytest/starsky.foundation.thumbnailgeneration/GenerationFactory/ThumbnailGeneratorFactoryTests.cs @@ -0,0 +1,34 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using starsky.foundation.thumbnailgeneration.GenerationFactory; +using starsky.foundation.thumbnailgeneration.GenerationFactory.Generators; +using starskytest.FakeMocks; + +namespace starskytest.starsky.foundation.thumbnailgeneration.GenerationFactory; + +[TestClass] +public class ThumbnailGeneratorFactoryTests +{ + private readonly ThumbnailGeneratorFactory _factory; + + public ThumbnailGeneratorFactoryTests() + { + var selectorStorageMock = new FakeSelectorStorage(); + var loggerMock = new FakeIWebLogger(); + var videoProcessMock = new FakeIVideoProcess(selectorStorageMock); + _factory = new ThumbnailGeneratorFactory(selectorStorageMock, loggerMock, videoProcessMock); + } + + [TestMethod] + [DataRow("test.jpg", typeof(CompositeThumbnailGenerator))] + [DataRow("test.mp4", typeof(CompositeThumbnailGenerator))] + [DataRow("test.txt", typeof(NotSupportedFallbackThumbnailGenerator))] + public void GetGenerator_ReturnsCorrectGenerator(string filePath, Type expectedType) + { + // Act + var generator = _factory.GetGenerator(filePath); + + // Assert + Assert.IsInstanceOfType(generator, expectedType); + } +} diff --git a/starsky/starskytest/starsky.foundation.video/Process/VideoProcessThumbnailPostTests.cs b/starsky/starskytest/starsky.foundation.video/Process/VideoProcessThumbnailPostTests.cs new file mode 100644 index 000000000..bf934fd85 --- /dev/null +++ b/starsky/starskytest/starsky.foundation.video/Process/VideoProcessThumbnailPostTests.cs @@ -0,0 +1,78 @@ +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using MetadataExtractor; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using starsky.foundation.platform.Models; +using starsky.foundation.readmeta.ReadMetaHelpers; +using starsky.foundation.video.Process; +using starskytest.FakeCreateAn; +using starskytest.FakeMocks; + +namespace starskytest.starsky.foundation.video.Process; + +[TestClass] +public class VideoProcessThumbnailPostTests +{ + private readonly VideoProcessThumbnailPost _videoProcessThumbnailPost; + private readonly FakeIStorage _storage; + + public VideoProcessThumbnailPostTests() + { + _storage = new FakeIStorage(); + + var selectorStorage = new FakeSelectorStorage(_storage); + var exifTool = new FakeExifTool(_storage, new AppSettings()); + var logger = new FakeIWebLogger(); + var thumbnailQuery = new FakeIThumbnailQuery(); + + var appSettings = new AppSettings(); + _videoProcessThumbnailPost = new VideoProcessThumbnailPost( + selectorStorage, appSettings, exifTool, logger, thumbnailQuery); + } + + [DataTestMethod] + [DataRow("/test.mp4", "/test.jpg")] + [DataRow("/test/test.mov", "/test/test.jpg")] + public async Task PostPrepThumbnail_Success_ReturnsVideoResult(string subPath, + string jpegInFolderSubPath) + { + // Arrange + var runResult = new VideoResult(true, subPath); + var stream = new MemoryStream([.. CreateAnImageNoExif.Bytes]); + + // Act + var result = await _videoProcessThumbnailPost.PostPrepThumbnail(runResult, + stream, jpegInFolderSubPath); + + // Assert + Assert.IsTrue(result.IsSuccess); + Assert.AreEqual(jpegInFolderSubPath, result.ResultPath); + + Assert.IsTrue(_storage.ExistFile(result.ResultPath ?? "")); + + var writtenStream = _storage.ReadStream(result.ResultPath ?? ""); + var meta = ImageMetadataReader.ReadMetadata(writtenStream).ToList(); + await writtenStream.DisposeAsync(); + + Assert.AreEqual(3, ReadMetaExif.GetImageWidthHeight(meta, true)); + Assert.AreEqual(2, ReadMetaExif.GetImageWidthHeight(meta, false)); + } + + [DataTestMethod] + [DataRow("/test.mp4")] + [DataRow("/test/test.mov")] + public async Task PostPrepThumbnail_Failure_ReturnsOriginalResult(string subPath) + { + // Arrange + var runResult = new VideoResult(false, subPath); + var stream = new MemoryStream(); + + // Act + var result = await _videoProcessThumbnailPost.PostPrepThumbnail(runResult, stream, subPath); + + // Assert + Assert.IsFalse(result.IsSuccess); + Assert.AreEqual(subPath, result.ResultPath); + } +}