diff options
Diffstat (limited to 'tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs')
| -rw-r--r-- | tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs new file mode 100644 index 0000000000..839925dd10 --- /dev/null +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Providers.MediaInfo; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.Providers.Tests.MediaInfo +{ + public class VideoImageProviderTests + { + private static TheoryData<Video> GetImage_UnsupportedInput_ReturnsNoImage_TestData() + { + return new () + { + new Movie { IsPlaceHolder = true }, + + new Movie { DefaultVideoStreamIndex = null }, + + // set a default index but don't put anything there (invalid input, but provider shouldn't break) + new Movie { DefaultVideoStreamIndex = 0 } + }; + } + + [Theory] + [MemberData(nameof(GetImage_UnsupportedInput_ReturnsNoImage_TestData))] + public async void GetImage_UnsupportedInput_ReturnsNoImage(Video input) + { + var mediaSourceManager = GetMediaSourceManager(input, null, new List<MediaStream>()); + var videoImageProvider = new VideoImageProvider(mediaSourceManager, Mock.Of<IMediaEncoder>(), new NullLogger<VideoImageProvider>()); + + var actual = await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Theory] + [InlineData(1, 1)] // default not first stream + [InlineData(5, 0)] // default out of valid range + public async void GetImage_DefaultVideoStreams_ReturnsCorrectStreamImage(int defaultIndex, int targetIndex) + { + var input = new Movie { DefaultVideoStreamIndex = defaultIndex }; + + string targetPath = "path.jpg"; + var mediaStreams = new List<MediaStream>(); + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + + for (int i = 0; i <= targetIndex; i++) + { + var mediaStream = new MediaStream { Type = MediaStreamType.Video, Index = i }; + mediaStreams.Add(mediaStream); + + var path = i == targetIndex ? targetPath : "wrong stream called!"; + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), mediaStream, It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), It.IsAny<CancellationToken>())) + .Returns(Task.FromResult(path)); + } + + var defaultStream = defaultIndex < mediaStreams.Count ? mediaStreams[targetIndex] : null; + var mediaSourceManager = GetMediaSourceManager(input, defaultStream, mediaStreams); + + var videoImageProvider = new VideoImageProvider(mediaSourceManager, mediaEncoder.Object, new NullLogger<VideoImageProvider>()); + + var actual = await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.True(actual.HasImage); + Assert.Equal(targetPath, actual.Path); + Assert.Equal(ImageFormat.Jpg, actual.Format); + } + + [Theory] + [InlineData(null, 10)] // default time + [InlineData(500, 50)] // calculated time + public async void GetImage_TimeSpan_SelectsCorrectTime(int? runTimeSeconds, long expectedSeconds) + { + MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; + var input = new Movie + { + DefaultVideoStreamIndex = 0, + RunTimeTicks = runTimeSeconds * TimeSpan.TicksPerSecond + }; + + var mediaSourceManager = GetMediaSourceManager(input, targetStream, new List<MediaStream> { targetStream }); + + // use a callback to catch the actual value + // provides more information on failure than verifying a specific input was called on the mock + TimeSpan? actualTimeSpan = null; + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), CancellationToken.None)) + .Callback<string, string, MediaSourceInfo, MediaStream, Video3DFormat?, TimeSpan?, CancellationToken>((_, _, _, _, _, timeSpan, _) => actualTimeSpan = timeSpan) + .Returns(Task.FromResult("path")); + + var videoImageProvider = new VideoImageProvider(mediaSourceManager, mediaEncoder.Object, new NullLogger<VideoImageProvider>()); + + // not testing return, just verifying what gets requested for time span + await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); + + Assert.Equal(TimeSpan.FromSeconds(expectedSeconds), actualTimeSpan); + } + + private static IMediaSourceManager GetMediaSourceManager(Video item, MediaStream? defaultStream, List<MediaStream> mediaStreams) + { + var defaultStreamList = new List<MediaStream>(); + if (defaultStream != null) + { + defaultStreamList.Add(defaultStream); + } + + var mediaSourceManager = new Mock<IMediaSourceManager>(MockBehavior.Strict); + mediaSourceManager.Setup(i => i.GetMediaStreams(It.Is<MediaStreamQuery>(q => q.ItemId == item.Id && q.Index == item.DefaultVideoStreamIndex))) + .Returns(defaultStreamList); + mediaSourceManager.Setup(i => i.GetMediaStreams(It.Is<MediaStreamQuery>(q => q.ItemId == item.Id && q.Type == MediaStreamType.Video))) + .Returns(mediaStreams); + return mediaSourceManager.Object; + } + } +} |
