diff options
| author | Nick <20588554+nicknsy@users.noreply.github.com> | 2023-10-18 19:27:05 -0700 |
|---|---|---|
| committer | Nick <20588554+nicknsy@users.noreply.github.com> | 2023-10-18 19:27:05 -0700 |
| commit | cd662506a1f63f9b20e7f5caa9b671eb3d71ea5a (patch) | |
| tree | b58f7158e21e7ed21d77b0f0abfce23d796b3fe3 /tests | |
| parent | c7feea27fde8af60984c8fe41444dc245dbde395 (diff) | |
| parent | de08d38a6f2a6e773fa1000574e08322605b56d3 (diff) | |
Merge branch 'master' into trickplay
Diffstat (limited to 'tests')
69 files changed, 854 insertions, 928 deletions
diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs index ad8a051fd..f4f661147 100644 --- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs @@ -66,7 +66,7 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy _userManagerMock .Setup(u => u.GetUserById(It.IsAny<Guid>())) - .Returns<User>(null); + .Returns<User?>(null); var claims = new[] { diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs index fe0d7fc90..1f908d7e0 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs @@ -12,17 +12,16 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests [Fact] public void Parse_Valid_Success() { - using (var stream = File.OpenRead("Test Data/example.ass")) - { - var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "ass"); - Assert.Single(parsed.TrackEvents); - var trackEvent = parsed.TrackEvents[0]; + using var stream = File.OpenRead("Test Data/example.ass"); - Assert.Equal("1", trackEvent.Id); - Assert.Equal(TimeSpan.Parse("00:00:01.18", CultureInfo.InvariantCulture).Ticks, trackEvent.StartPositionTicks); - Assert.Equal(TimeSpan.Parse("00:00:06.85", CultureInfo.InvariantCulture).Ticks, trackEvent.EndPositionTicks); - Assert.Equal("{\\pos(400,570)}Like an Angel with pity on nobody" + Environment.NewLine + "The second line in subtitle", trackEvent.Text); - } + var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "ass"); + Assert.Single(parsed.TrackEvents); + var trackEvent = parsed.TrackEvents[0]; + + Assert.Equal("1", trackEvent.Id); + Assert.Equal(TimeSpan.Parse("00:00:01.18", CultureInfo.InvariantCulture).Ticks, trackEvent.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:00:06.85", CultureInfo.InvariantCulture).Ticks, trackEvent.EndPositionTicks); + Assert.Equal("{\\pos(400,570)}Like an Angel with pity on nobody" + Environment.NewLine + "The second line in subtitle", trackEvent.Text); } } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs index 2aebee556..b7152961c 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -12,45 +12,43 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests [Fact] public void Parse_Valid_Success() { - using (var stream = File.OpenRead("Test Data/example.srt")) - { - var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt"); - Assert.Equal(2, parsed.TrackEvents.Count); - - var trackEvent1 = parsed.TrackEvents[0]; - Assert.Equal("1", trackEvent1.Id); - Assert.Equal(TimeSpan.Parse("00:02:17.440", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks); - Assert.Equal(TimeSpan.Parse("00:02:20.375", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks); - Assert.Equal("Senator, we're making" + Environment.NewLine + "our final approach into Coruscant.", trackEvent1.Text); - - var trackEvent2 = parsed.TrackEvents[1]; - Assert.Equal("2", trackEvent2.Id); - Assert.Equal(TimeSpan.Parse("00:02:20.476", CultureInfo.InvariantCulture).Ticks, trackEvent2.StartPositionTicks); - Assert.Equal(TimeSpan.Parse("00:02:22.501", CultureInfo.InvariantCulture).Ticks, trackEvent2.EndPositionTicks); - Assert.Equal("Very good, Lieutenant.", trackEvent2.Text); - } + using var stream = File.OpenRead("Test Data/example.srt"); + + var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt"); + Assert.Equal(2, parsed.TrackEvents.Count); + + var trackEvent1 = parsed.TrackEvents[0]; + Assert.Equal("1", trackEvent1.Id); + Assert.Equal(TimeSpan.Parse("00:02:17.440", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:02:20.375", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks); + Assert.Equal("Senator, we're making" + Environment.NewLine + "our final approach into Coruscant.", trackEvent1.Text); + + var trackEvent2 = parsed.TrackEvents[1]; + Assert.Equal("2", trackEvent2.Id); + Assert.Equal(TimeSpan.Parse("00:02:20.476", CultureInfo.InvariantCulture).Ticks, trackEvent2.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:02:22.501", CultureInfo.InvariantCulture).Ticks, trackEvent2.EndPositionTicks); + Assert.Equal("Very good, Lieutenant.", trackEvent2.Text); } [Fact] public void Parse_EmptyNewlineBetweenText_Success() { - using (var stream = File.OpenRead("Test Data/example2.srt")) - { - var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt"); - Assert.Equal(2, parsed.TrackEvents.Count); - - var trackEvent1 = parsed.TrackEvents[0]; - Assert.Equal("311", trackEvent1.Id); - Assert.Equal(TimeSpan.Parse("00:16:46.465", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks); - Assert.Equal(TimeSpan.Parse("00:16:49.009", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks); - Assert.Equal("Una vez que la gente se entere" + Environment.NewLine + Environment.NewLine + "de que ustedes están aquí,", trackEvent1.Text); - - var trackEvent2 = parsed.TrackEvents[1]; - Assert.Equal("312", trackEvent2.Id); - Assert.Equal(TimeSpan.Parse("00:16:49.092", CultureInfo.InvariantCulture).Ticks, trackEvent2.StartPositionTicks); - Assert.Equal(TimeSpan.Parse("00:16:51.470", CultureInfo.InvariantCulture).Ticks, trackEvent2.EndPositionTicks); - Assert.Equal("este lugar se convertirá" + Environment.NewLine + Environment.NewLine + "en un maldito zoológico.", trackEvent2.Text); - } + using var stream = File.OpenRead("Test Data/example2.srt"); + + var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt"); + Assert.Equal(2, parsed.TrackEvents.Count); + + var trackEvent1 = parsed.TrackEvents[0]; + Assert.Equal("311", trackEvent1.Id); + Assert.Equal(TimeSpan.Parse("00:16:46.465", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:16:49.009", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks); + Assert.Equal("Una vez que la gente se entere" + Environment.NewLine + Environment.NewLine + "de que ustedes están aquí,", trackEvent1.Text); + + var trackEvent2 = parsed.TrackEvents[1]; + Assert.Equal("312", trackEvent2.Id); + Assert.Equal(TimeSpan.Parse("00:16:49.092", CultureInfo.InvariantCulture).Ticks, trackEvent2.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:16:51.470", CultureInfo.InvariantCulture).Ticks, trackEvent2.EndPositionTicks); + Assert.Equal("este lugar se convertirá" + Environment.NewLine + Environment.NewLine + "en un maldito zoológico.", trackEvent2.Text); } } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs index 6abf2d26c..5b7aa7eaa 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs @@ -18,22 +18,21 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests [MemberData(nameof(Parse_MultipleDialogues_TestData))] public void Parse_MultipleDialogues_Success(string ssa, IReadOnlyList<SubtitleTrackEvent> expectedSubtitleTrackEvents) { - using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa))) - { - SubtitleTrackInfo subtitleTrackInfo = _parser.Parse(stream, "ssa"); + using Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa)); - Assert.Equal(expectedSubtitleTrackEvents.Count, subtitleTrackInfo.TrackEvents.Count); + SubtitleTrackInfo subtitleTrackInfo = _parser.Parse(stream, "ssa"); - for (int i = 0; i < expectedSubtitleTrackEvents.Count; ++i) - { - SubtitleTrackEvent expected = expectedSubtitleTrackEvents[i]; - SubtitleTrackEvent actual = subtitleTrackInfo.TrackEvents[i]; + Assert.Equal(expectedSubtitleTrackEvents.Count, subtitleTrackInfo.TrackEvents.Count); + + for (int i = 0; i < expectedSubtitleTrackEvents.Count; ++i) + { + SubtitleTrackEvent expected = expectedSubtitleTrackEvents[i]; + SubtitleTrackEvent actual = subtitleTrackInfo.TrackEvents[i]; - Assert.Equal(expected.Id, actual.Id); - Assert.Equal(expected.Text, actual.Text); - Assert.Equal(expected.StartPositionTicks, actual.StartPositionTicks); - Assert.Equal(expected.EndPositionTicks, actual.EndPositionTicks); - } + Assert.Equal(expected.Id, actual.Id); + Assert.Equal(expected.Text, actual.Text); + Assert.Equal(expected.StartPositionTicks, actual.StartPositionTicks); + Assert.Equal(expected.EndPositionTicks, actual.EndPositionTicks); } } @@ -73,17 +72,16 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests [Fact] public void Parse_Valid_Success() { - using (var stream = File.OpenRead("Test Data/example.ssa")) - { - var parsed = _parser.Parse(stream, "ssa"); - Assert.Single(parsed.TrackEvents); - var trackEvent = parsed.TrackEvents[0]; + using var stream = File.OpenRead("Test Data/example.ssa"); - Assert.Equal("1", trackEvent.Id); - Assert.Equal(TimeSpan.Parse("00:00:01.18", CultureInfo.InvariantCulture).Ticks, trackEvent.StartPositionTicks); - Assert.Equal(TimeSpan.Parse("00:00:06.85", CultureInfo.InvariantCulture).Ticks, trackEvent.EndPositionTicks); - Assert.Equal("{\\pos(400,570)}Like an angel with pity on nobody", trackEvent.Text); - } + var parsed = _parser.Parse(stream, "ssa"); + Assert.Single(parsed.TrackEvents); + var trackEvent = parsed.TrackEvents[0]; + + Assert.Equal("1", trackEvent.Id); + Assert.Equal(TimeSpan.Parse("00:00:01.18", CultureInfo.InvariantCulture).Ticks, trackEvent.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:00:06.85", CultureInfo.InvariantCulture).Ticks, trackEvent.EndPositionTicks); + Assert.Equal("{\\pos(400,570)}Like an angel with pity on nobody", trackEvent.Text); } } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs index 9ace80bbd..ce1f005f4 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs @@ -97,7 +97,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests { var fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); var subtitleEncoder = fixture.Create<SubtitleEncoder>(); - var result = await subtitleEncoder.GetReadableFile(mediaSource, subtitleStream, CancellationToken.None).ConfigureAwait(false); + var result = await subtitleEncoder.GetReadableFile(mediaSource, subtitleStream, CancellationToken.None); Assert.Equal(subtitleInfo.Path, result.Path); Assert.Equal(subtitleInfo.Protocol, result.Protocol); Assert.Equal(subtitleInfo.Format, result.Format); diff --git a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs index c30dad6f9..210ce4a47 100644 --- a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs +++ b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs @@ -351,11 +351,11 @@ namespace Jellyfin.Model.Tests // Assert.Contains(uri.Extension, containers); // Check expected video codec (1) - Assert.Contains(targetVideoStream.Codec, streamInfo.TargetVideoCodec); + Assert.Contains(targetVideoStream?.Codec, streamInfo.TargetVideoCodec); Assert.Single(streamInfo.TargetVideoCodec); // Check expected audio codecs (1) - Assert.Contains(targetAudioStream.Codec, streamInfo.TargetAudioCodec); + Assert.Contains(targetAudioStream?.Codec, streamInfo.TargetAudioCodec); Assert.Single(streamInfo.TargetAudioCodec); // Assert.Single(val.AudioCodecs); @@ -410,13 +410,13 @@ namespace Jellyfin.Model.Tests else { // Check expected video codec (1) - Assert.Contains(targetVideoStream.Codec, streamInfo.TargetVideoCodec); + Assert.Contains(targetVideoStream?.Codec, streamInfo.TargetVideoCodec); Assert.Single(streamInfo.TargetVideoCodec); if (transcodeMode.Equals("DirectStream", StringComparison.Ordinal)) { // Check expected audio codecs (1) - if (!targetAudioStream.IsExternal) + if (targetAudioStream?.IsExternal == false) { // Check expected audio codecs (1) if (streamInfo.TranscodeReasons.HasFlag(TranscodeReason.ContainerNotSupported)) @@ -432,7 +432,7 @@ namespace Jellyfin.Model.Tests else if (transcodeMode.Equals("Remux", StringComparison.Ordinal)) { // Check expected audio codecs (1) - Assert.Contains(targetAudioStream.Codec, streamInfo.AudioCodecs); + Assert.Contains(targetAudioStream?.Codec, streamInfo.AudioCodecs); Assert.Single(streamInfo.AudioCodecs); } @@ -440,10 +440,10 @@ namespace Jellyfin.Model.Tests var videoStream = targetVideoStream; Assert.False(streamInfo.EstimateContentLength); Assert.Equal(TranscodeSeekInfo.Auto, streamInfo.TranscodeSeekInfo); - Assert.Contains(videoStream.Profile?.ToLowerInvariant() ?? string.Empty, streamInfo.TargetVideoProfile?.Split(",").Select(s => s.ToLowerInvariant()) ?? Array.Empty<string>()); - Assert.Equal(videoStream.Level, streamInfo.TargetVideoLevel); - Assert.Equal(videoStream.BitDepth, streamInfo.TargetVideoBitDepth); - Assert.InRange(streamInfo.VideoBitrate.GetValueOrDefault(), videoStream.BitRate.GetValueOrDefault(), int.MaxValue); + Assert.Contains(videoStream?.Profile?.ToLowerInvariant() ?? string.Empty, streamInfo.TargetVideoProfile?.Split(",").Select(s => s.ToLowerInvariant()) ?? Array.Empty<string>()); + Assert.Equal(videoStream?.Level, streamInfo.TargetVideoLevel); + Assert.Equal(videoStream?.BitDepth, streamInfo.TargetVideoBitDepth); + Assert.InRange(streamInfo.VideoBitrate.GetValueOrDefault(), videoStream?.BitRate.GetValueOrDefault() ?? 0, int.MaxValue); // Audio codec not supported if ((why & TranscodeReason.AudioCodecNotSupported) != 0) @@ -452,7 +452,7 @@ namespace Jellyfin.Model.Tests if (options.AudioStreamIndex >= 0) { // TODO:fixme - if (!targetAudioStream.IsExternal) + if (targetAudioStream?.IsExternal == false) { Assert.DoesNotContain(targetAudioStream.Codec, streamInfo.AudioCodecs); } @@ -488,16 +488,16 @@ namespace Jellyfin.Model.Tests private static async ValueTask<T> TestData<T>(string name) { var path = Path.Join("Test Data", typeof(T).Name + "-" + name + ".json"); - using (var stream = File.OpenRead(path)) - { - var value = await JsonSerializer.DeserializeAsync<T>(stream, JsonDefaults.Options); - if (value is not null) - { - return value; - } - throw new SerializationException("Invalid test data: " + name); + using var stream = File.OpenRead(path); + + var value = await JsonSerializer.DeserializeAsync<T>(stream, JsonDefaults.Options); + if (value is not null) + { + return value; } + + throw new SerializationException("Invalid test data: " + name); } private StreamBuilder GetStreamBuilder() diff --git a/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs b/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs index a5bdb42d8..198ad5a27 100644 --- a/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs +++ b/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs @@ -30,4 +30,17 @@ public static class ImageFormatExtensionsTests [InlineData((ImageFormat)5)] public static void GetMimeType_Valid_ThrowsInvalidEnumArgumentException(ImageFormat format) => Assert.Throws<InvalidEnumArgumentException>(() => format.GetMimeType()); + + [Theory] + [MemberData(nameof(GetAllImageFormats))] + public static void GetExtension_Valid_Valid(ImageFormat format) + => Assert.Null(Record.Exception(() => format.GetExtension())); + + [Theory] + [InlineData((ImageFormat)int.MinValue)] + [InlineData((ImageFormat)int.MaxValue)] + [InlineData((ImageFormat)(-1))] + [InlineData((ImageFormat)5)] + public static void GetExtension_Valid_ThrowsInvalidEnumArgumentException(ImageFormat format) + => Assert.Throws<InvalidEnumArgumentException>(() => format.GetExtension()); } diff --git a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs index c72a3315e..9b9c1ec34 100644 --- a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs @@ -14,18 +14,18 @@ namespace Jellyfin.Naming.Tests.AudioBook data.Add( new AudioBookFileInfo( - @"/server/AudioBooks/Larry Potter/Larry Potter.mp3", + "/server/AudioBooks/Larry Potter/Larry Potter.mp3", "mp3")); data.Add( new AudioBookFileInfo( - @"/server/AudioBooks/Berry Potter/Chapter 1 .ogg", + "/server/AudioBooks/Berry Potter/Chapter 1 .ogg", "ogg", chapterNumber: 1)); data.Add( new AudioBookFileInfo( - @"/server/AudioBooks/Nerry Potter/Part 3 - Chapter 2.mp3", + "/server/AudioBooks/Nerry Potter/Part 3 - Chapter 2.mp3", "mp3", chapterNumber: 2, partNumber: 3)); @@ -49,7 +49,7 @@ namespace Jellyfin.Naming.Tests.AudioBook [Fact] public void Resolve_InvalidExtension() { - var result = new AudioBookResolver(_namingOptions).Resolve(@"/server/AudioBooks/Larry Potter/Larry Potter.mp9"); + var result = new AudioBookResolver(_namingOptions).Resolve("/server/AudioBooks/Larry Potter/Larry Potter.mp9"); Assert.Null(result); } diff --git a/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs b/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs index 97949adff..ba602b5d2 100644 --- a/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs +++ b/tests/Jellyfin.Naming.Tests/ExternalFiles/ExternalPathParserTests.cs @@ -20,11 +20,11 @@ public class ExternalPathParserTests var hindiCultureDto = new CultureDto("Hindi", "Hindi", "hi", new[] { "hin" }); var localizationManager = new Mock<ILocalizationManager>(MockBehavior.Loose); - localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex(@"en.*", RegexOptions.IgnoreCase))) + localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex("en.*", RegexOptions.IgnoreCase))) .Returns(englishCultureDto); - localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex(@"fr.*", RegexOptions.IgnoreCase))) + localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex("fr.*", RegexOptions.IgnoreCase))) .Returns(frenchCultureDto); - localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex(@"hi.*", RegexOptions.IgnoreCase))) + localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex("hi.*", RegexOptions.IgnoreCase))) .Returns(hindiCultureDto); _audioPathParser = new ExternalPathParser(new NamingOptions(), localizationManager.Object, DlnaProfileType.Audio); diff --git a/tests/Jellyfin.Naming.Tests/Music/MultiDiscAlbumTests.cs b/tests/Jellyfin.Naming.Tests/Music/MultiDiscAlbumTests.cs index c9a295a4c..471616797 100644 --- a/tests/Jellyfin.Naming.Tests/Music/MultiDiscAlbumTests.cs +++ b/tests/Jellyfin.Naming.Tests/Music/MultiDiscAlbumTests.cs @@ -12,34 +12,34 @@ namespace Jellyfin.Naming.Tests.Music [InlineData("", false)] [InlineData("C:/", false)] [InlineData("/home/", false)] - [InlineData(@"blah blah", false)] - [InlineData(@"D:/music/weezer/03 Pinkerton", false)] - [InlineData(@"D:/music/michael jackson/Bad (2012 Remaster)", false)] - [InlineData(@"cd1", true)] - [InlineData(@"disc18", true)] - [InlineData(@"disk10", true)] - [InlineData(@"vol7", true)] - [InlineData(@"volume1", true)] - [InlineData(@"cd 1", true)] - [InlineData(@"disc 1", true)] - [InlineData(@"disk 1", true)] - [InlineData(@"disk", false)] - [InlineData(@"disk ·", false)] - [InlineData(@"disk a", false)] - [InlineData(@"disk volume", false)] - [InlineData(@"disc disc", false)] - [InlineData(@"disk disc 6", false)] - [InlineData(@"cd - 1", true)] - [InlineData(@"disc- 1", true)] - [InlineData(@"disk - 1", true)] - [InlineData(@"Disc 01 (Hugo Wolf · 24 Lieder)", true)] - [InlineData(@"Disc 04 (Encores and Folk Songs)", true)] - [InlineData(@"Disc04 (Encores and Folk Songs)", true)] - [InlineData(@"Disc 04(Encores and Folk Songs)", true)] - [InlineData(@"Disc04(Encores and Folk Songs)", true)] - [InlineData(@"D:/Video/MBTestLibrary/VideoTest/music/.38 special/anth/Disc 2", true)] - [InlineData(@"[1985] Opportunities (Let's make lots of money) (1985)", false)] - [InlineData(@"Blah 04(Encores and Folk Songs)", false)] + [InlineData("blah blah", false)] + [InlineData("D:/music/weezer/03 Pinkerton", false)] + [InlineData("D:/music/michael jackson/Bad (2012 Remaster)", false)] + [InlineData("cd1", true)] + [InlineData("disc18", true)] + [InlineData("disk10", true)] + [InlineData("vol7", true)] + [InlineData("volume1", true)] + [InlineData("cd 1", true)] + [InlineData("disc 1", true)] + [InlineData("disk 1", true)] + [InlineData("disk", false)] + [InlineData("disk ·", false)] + [InlineData("disk a", false)] + [InlineData("disk volume", false)] + [InlineData("disc disc", false)] + [InlineData("disk disc 6", false)] + [InlineData("cd - 1", true)] + [InlineData("disc- 1", true)] + [InlineData("disk - 1", true)] + [InlineData("Disc 01 (Hugo Wolf · 24 Lieder)", true)] + [InlineData("Disc 04 (Encores and Folk Songs)", true)] + [InlineData("Disc04 (Encores and Folk Songs)", true)] + [InlineData("Disc 04(Encores and Folk Songs)", true)] + [InlineData("Disc04(Encores and Folk Songs)", true)] + [InlineData("D:/Video/MBTestLibrary/VideoTest/music/.38 special/anth/Disc 2", true)] + [InlineData("[1985] Opportunities (Let's make lots of money) (1985)", false)] + [InlineData("Blah 04(Encores and Folk Songs)", false)] public void AlbumParser_MultidiscPath_Identifies(string path, bool result) { var parser = new AlbumParser(_namingOptions); diff --git a/tests/Jellyfin.Naming.Tests/TV/DailyEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/DailyEpisodeTests.cs index 72052a23c..f2cd360e5 100644 --- a/tests/Jellyfin.Naming.Tests/TV/DailyEpisodeTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/DailyEpisodeTests.cs @@ -9,10 +9,11 @@ namespace Jellyfin.Naming.Tests.TV private readonly EpisodeResolver _resolver = new EpisodeResolver(new NamingOptions()); [Theory] - [InlineData(@"/server/anything_1996.11.14.mp4", "anything", 1996, 11, 14)] - [InlineData(@"/server/anything_1996-11-14.mp4", "anything", 1996, 11, 14)] - [InlineData(@"/server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv", "james.corden", 2017, 04, 20)] - [InlineData(@"/server/ABC News 2018_03_24_19_00_00.mkv", "ABC News", 2018, 03, 24)] + [InlineData("/server/anything_1996.11.14.mp4", "anything", 1996, 11, 14)] + [InlineData("/server/anything_1996-11-14.mp4", "anything", 1996, 11, 14)] + [InlineData("/server/james.corden.2017.04.20.anne.hathaway.720p.hdtv.x264-crooks.mkv", "james.corden", 2017, 04, 20)] + [InlineData("/server/ABC News 2018_03_24_19_00_00.mkv", "ABC News", 2018, 03, 24)] + [InlineData("/server/Jeopardy 2023 07 14 HDTV x264 AC3.mkv", "Jeopardy", 2023, 07, 14)] // TODO: [InlineData(@"/server/anything_14.11.1996.mp4", "anything", 1996, 11, 14)] // TODO: [InlineData(@"/server/A Daily Show - (2015-01-15) - Episode Name - [720p].mkv", "A Daily Show", 2015, 01, 15)] // TODO: [InlineData(@"/server/Last Man Standing_KTLADT_2018_05_25_01_28_00.wtv", "Last Man Standing", 2018, 05, 25)] diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberWithoutSeasonTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberWithoutSeasonTests.cs index 1da5a30a8..1727b2247 100644 --- a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberWithoutSeasonTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberWithoutSeasonTests.cs @@ -9,16 +9,16 @@ namespace Jellyfin.Naming.Tests.TV private readonly EpisodeResolver _resolver = new EpisodeResolver(new NamingOptions()); [Theory] - [InlineData(8, @"The Simpsons/The Simpsons.S25E08.Steal this episode.mp4")] - [InlineData(2, @"The Simpsons/The Simpsons - 02 - Ep Name.avi")] - [InlineData(2, @"The Simpsons/02.avi")] - [InlineData(2, @"The Simpsons/02 - Ep Name.avi")] - [InlineData(2, @"The Simpsons/02-Ep Name.avi")] - [InlineData(2, @"The Simpsons/02.EpName.avi")] - [InlineData(2, @"The Simpsons/The Simpsons - 02.avi")] - [InlineData(2, @"The Simpsons/The Simpsons - 02 Ep Name.avi")] - [InlineData(7, @"GJ Club (2013)/GJ Club - 07.mkv")] - [InlineData(17, @"Case Closed (1996-2007)/Case Closed - 317.mkv")] + [InlineData(8, "The Simpsons/The Simpsons.S25E08.Steal this episode.mp4")] + [InlineData(2, "The Simpsons/The Simpsons - 02 - Ep Name.avi")] + [InlineData(2, "The Simpsons/02.avi")] + [InlineData(2, "The Simpsons/02 - Ep Name.avi")] + [InlineData(2, "The Simpsons/02-Ep Name.avi")] + [InlineData(2, "The Simpsons/02.EpName.avi")] + [InlineData(2, "The Simpsons/The Simpsons - 02.avi")] + [InlineData(2, "The Simpsons/The Simpsons - 02 Ep Name.avi")] + [InlineData(7, "GJ Club (2013)/GJ Club - 07.mkv")] + [InlineData(17, "Case Closed (1996-2007)/Case Closed - 317.mkv")] // TODO: [InlineData(2, @"The Simpsons/The Simpsons 5 - 02 - Ep Name.avi")] // TODO: [InlineData(2, @"The Simpsons/The Simpsons 5 - 02 Ep Name.avi")] // TODO: [InlineData(7, @"Seinfeld/Seinfeld 0807 The Checks.avi")] diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs index 7604ddc80..5397f1371 100644 --- a/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs @@ -13,10 +13,10 @@ namespace Jellyfin.Naming.Tests.TV [InlineData("/media/Foo - S04E011", true, "Foo", 4, 11)] [InlineData("/media/Foo/Foo s01x01", true, "Foo", 1, 1)] [InlineData("/media/Foo (2019)/Season 4/Foo (2019).S04E03", true, "Foo (2019)", 4, 3)] - [InlineData("D:\\media\\Foo\\Foo-S01E01", true, "Foo", 1, 1)] - [InlineData("D:\\media\\Foo - S04E011", true, "Foo", 4, 11)] - [InlineData("D:\\media\\Foo\\Foo s01x01", true, "Foo", 1, 1)] - [InlineData("D:\\media\\Foo (2019)\\Season 4\\Foo (2019).S04E03", true, "Foo (2019)", 4, 3)] + [InlineData(@"D:\media\Foo\Foo-S01E01", true, "Foo", 1, 1)] + [InlineData(@"D:\media\Foo - S04E011", true, "Foo", 4, 11)] + [InlineData(@"D:\media\Foo\Foo s01x01", true, "Foo", 1, 1)] + [InlineData(@"D:\media\Foo (2019)\Season 4\Foo (2019).S04E03", true, "Foo (2019)", 4, 3)] [InlineData("/Season 2/Elementary - 02x03-04-15 - Ep Name.mp4", false, "Elementary", 2, 3)] [InlineData("/Season 1/seriesname S01E02 blah.avi", false, "seriesname", 1, 2)] [InlineData("/Running Man/Running Man S2017E368.mkv", false, "Running Man", 2017, 368)] diff --git a/tests/Jellyfin.Naming.Tests/TV/MultiEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/MultiEpisodeTests.cs index ffaa64c3f..6d6591abf 100644 --- a/tests/Jellyfin.Naming.Tests/TV/MultiEpisodeTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/MultiEpisodeTests.cs @@ -9,66 +9,66 @@ namespace Jellyfin.Naming.Tests.TV private readonly EpisodePathParser _episodePathParser = new EpisodePathParser(new NamingOptions()); [Theory] - [InlineData(@"Season 1/4x01 – 20 Hours in America (1).mkv", null)] - [InlineData(@"Season 1/01x02 blah.avi", null)] - [InlineData(@"Season 1/S01x02 blah.avi", null)] - [InlineData(@"Season 1/S01E02 blah.avi", null)] - [InlineData(@"Season 1/S01xE02 blah.avi", null)] - [InlineData(@"Season 1/seriesname 01x02 blah.avi", null)] - [InlineData(@"Season 1/seriesname S01x02 blah.avi", null)] - [InlineData(@"Season 1/seriesname S01E02 blah.avi", null)] - [InlineData(@"Season 1/seriesname S01xE02 blah.avi", null)] - [InlineData(@"Season 2/02x03 - 04 Ep Name.mp4", null)] - [InlineData(@"Season 2/My show name 02x03 - 04 Ep Name.mp4", null)] - [InlineData(@"Season 2/Elementary - 02x03 - 02x04 - 02x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2/02x03-04-15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2/Elementary - 02x03-04-15 - Ep Name.mp4", 15)] - [InlineData(@"Season 02/02x03-E15 - Ep Name.mp4", 15)] - [InlineData(@"Season 02/Elementary - 02x03-E15 - Ep Name.mp4", 15)] - [InlineData(@"Season 02/02x03 - x04 - x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 02/Elementary - 02x03 - x04 - x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 02/02x03x04x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 02/Elementary - 02x03x04x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 1/Elementary - S01E23-E24-E26 - The Woman.mp4", 26)] - [InlineData(@"Season 1/S01E23-E24-E26 - The Woman.mp4", 26)] + [InlineData("Season 1/4x01 – 20 Hours in America (1).mkv", null)] + [InlineData("Season 1/01x02 blah.avi", null)] + [InlineData("Season 1/S01x02 blah.avi", null)] + [InlineData("Season 1/S01E02 blah.avi", null)] + [InlineData("Season 1/S01xE02 blah.avi", null)] + [InlineData("Season 1/seriesname 01x02 blah.avi", null)] + [InlineData("Season 1/seriesname S01x02 blah.avi", null)] + [InlineData("Season 1/seriesname S01E02 blah.avi", null)] + [InlineData("Season 1/seriesname S01xE02 blah.avi", null)] + [InlineData("Season 2/02x03 - 04 Ep Name.mp4", null)] + [InlineData("Season 2/My show name 02x03 - 04 Ep Name.mp4", null)] + [InlineData("Season 2/Elementary - 02x03 - 02x04 - 02x15 - Ep Name.mp4", 15)] + [InlineData("Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4", 15)] + [InlineData("Season 2/02x03-04-15 - Ep Name.mp4", 15)] + [InlineData("Season 2/Elementary - 02x03-04-15 - Ep Name.mp4", 15)] + [InlineData("Season 02/02x03-E15 - Ep Name.mp4", 15)] + [InlineData("Season 02/Elementary - 02x03-E15 - Ep Name.mp4", 15)] + [InlineData("Season 02/02x03 - x04 - x15 - Ep Name.mp4", 15)] + [InlineData("Season 02/Elementary - 02x03 - x04 - x15 - Ep Name.mp4", 15)] + [InlineData("Season 02/02x03x04x15 - Ep Name.mp4", 15)] + [InlineData("Season 02/Elementary - 02x03x04x15 - Ep Name.mp4", 15)] + [InlineData("Season 1/Elementary - S01E23-E24-E26 - The Woman.mp4", 26)] + [InlineData("Season 1/S01E23-E24-E26 - The Woman.mp4", 26)] // Four Digits seasons - [InlineData(@"Season 2009/2009x02 blah.avi", null)] - [InlineData(@"Season 2009/S2009x02 blah.avi", null)] - [InlineData(@"Season 2009/S2009E02 blah.avi", null)] - [InlineData(@"Season 2009/S2009xE02 blah.avi", null)] - [InlineData(@"Season 2009/seriesname 2009x02 blah.avi", null)] - [InlineData(@"Season 2009/seriesname S2009x02 blah.avi", null)] - [InlineData(@"Season 2009/seriesname S2009E02 blah.avi", null)] - [InlineData(@"Season 2009/seriesname S2009xE02 blah.avi", null)] - [InlineData(@"Season 2009/Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/2009x03 - 2009x04 - 2009x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/2009x03-04-15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/Elementary - 2009x03-04-15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/2009x03-E15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/Elementary - 2009x03-E15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/2009x03 - x04 - x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/2009x03x04x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4", 15)] - [InlineData(@"Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4", 26)] - [InlineData(@"Season 2009/S2009E23-E24-E26 - The Woman.mp4", 26)] + [InlineData("Season 2009/2009x02 blah.avi", null)] + [InlineData("Season 2009/S2009x02 blah.avi", null)] + [InlineData("Season 2009/S2009E02 blah.avi", null)] + [InlineData("Season 2009/S2009xE02 blah.avi", null)] + [InlineData("Season 2009/seriesname 2009x02 blah.avi", null)] + [InlineData("Season 2009/seriesname S2009x02 blah.avi", null)] + [InlineData("Season 2009/seriesname S2009E02 blah.avi", null)] + [InlineData("Season 2009/seriesname S2009xE02 blah.avi", null)] + [InlineData("Season 2009/Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/2009x03 - 2009x04 - 2009x15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/2009x03-04-15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/Elementary - 2009x03-04-15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/2009x03-E15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/Elementary - 2009x03-E15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/2009x03 - x04 - x15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/2009x03x04x15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4", 15)] + [InlineData("Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4", 26)] + [InlineData("Season 2009/S2009E23-E24-E26 - The Woman.mp4", 26)] // Without season number - [InlineData(@"Season 1/02 - blah.avi", null)] - [InlineData(@"Season 2/02 - blah 14 blah.avi", null)] - [InlineData(@"Season 1/02 - blah-02 a.avi", null)] - [InlineData(@"Season 2/02.avi", null)] - [InlineData(@"Season 1/02-03 - blah.avi", 3)] - [InlineData(@"Season 2/02-04 - blah 14 blah.avi", 4)] - [InlineData(@"Season 1/02-05 - blah-02 a.avi", 5)] - [InlineData(@"Season 2/02-04.avi", 4)] - [InlineData(@"Season 2 /[HorribleSubs] Hunter X Hunter - 136[720p].mkv", null)] + [InlineData("Season 1/02 - blah.avi", null)] + [InlineData("Season 2/02 - blah 14 blah.avi", null)] + [InlineData("Season 1/02 - blah-02 a.avi", null)] + [InlineData("Season 2/02.avi", null)] + [InlineData("Season 1/02-03 - blah.avi", 3)] + [InlineData("Season 2/02-04 - blah 14 blah.avi", 4)] + [InlineData("Season 1/02-05 - blah-02 a.avi", 5)] + [InlineData("Season 2/02-04.avi", 4)] + [InlineData("Season 2 /[HorribleSubs] Hunter X Hunter - 136[720p].mkv", null)] // With format specification that must not be detected as ending episode number - [InlineData(@"Season 1/series-s09e14-1080p.mkv", null)] - [InlineData(@"Season 1/series-s09e14-720p.mkv", null)] - [InlineData(@"Season 1/series-s09e14-720i.mkv", null)] - [InlineData(@"Season 1/MOONLIGHTING_s01e01-e04.mkv", 4)] - [InlineData(@"Season 1/MOONLIGHTING_s01e01-e04", 4)] + [InlineData("Season 1/series-s09e14-1080p.mkv", null)] + [InlineData("Season 1/series-s09e14-720p.mkv", null)] + [InlineData("Season 1/series-s09e14-720i.mkv", null)] + [InlineData("Season 1/MOONLIGHTING_s01e01-e04.mkv", 4)] + [InlineData("Season 1/MOONLIGHTING_s01e01-e04", 4)] public void TestGetEndingEpisodeNumberFromFile(string filename, int? endingEpisodeNumber) { var result = _episodePathParser.Parse(filename, false); diff --git a/tests/Jellyfin.Naming.Tests/TV/SeasonFolderTests.cs b/tests/Jellyfin.Naming.Tests/TV/SeasonFolderTests.cs index 55af33836..6773bbeb1 100644 --- a/tests/Jellyfin.Naming.Tests/TV/SeasonFolderTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/SeasonFolderTests.cs @@ -6,23 +6,23 @@ namespace Jellyfin.Naming.Tests.TV public class SeasonFolderTests { [Theory] - [InlineData(@"/Drive/Season 1", 1, true)] - [InlineData(@"/Drive/Season 2", 2, true)] - [InlineData(@"/Drive/Season 02", 2, true)] - [InlineData(@"/Drive/Seinfeld/S02", 2, true)] - [InlineData(@"/Drive/Seinfeld/2", 2, true)] - [InlineData(@"/Drive/Season 2009", 2009, true)] - [InlineData(@"/Drive/Season1", 1, true)] - [InlineData(@"The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH", 4, true)] - [InlineData(@"/Drive/Season 7 (2016)", 7, false)] - [InlineData(@"/Drive/Staffel 7 (2016)", 7, false)] - [InlineData(@"/Drive/Stagione 7 (2016)", 7, false)] - [InlineData(@"/Drive/Season (8)", null, false)] - [InlineData(@"/Drive/3.Staffel", 3, false)] - [InlineData(@"/Drive/s06e05", null, false)] - [InlineData(@"/Drive/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv", null, false)] - [InlineData(@"/Drive/extras", 0, true)] - [InlineData(@"/Drive/specials", 0, true)] + [InlineData("/Drive/Season 1", 1, true)] + [InlineData("/Drive/Season 2", 2, true)] + [InlineData("/Drive/Season 02", 2, true)] + [InlineData("/Drive/Seinfeld/S02", 2, true)] + [InlineData("/Drive/Seinfeld/2", 2, true)] + [InlineData("/Drive/Season 2009", 2009, true)] + [InlineData("/Drive/Season1", 1, true)] + [InlineData("The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH", 4, true)] + [InlineData("/Drive/Season 7 (2016)", 7, false)] + [InlineData("/Drive/Staffel 7 (2016)", 7, false)] + [InlineData("/Drive/Stagione 7 (2016)", 7, false)] + [InlineData("/Drive/Season (8)", null, false)] + [InlineData("/Drive/3.Staffel", 3, false)] + [InlineData("/Drive/s06e05", null, false)] + [InlineData("/Drive/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv", null, false)] + [InlineData("/Drive/extras", 0, true)] + [InlineData("/Drive/specials", 0, true)] public void GetSeasonNumberFromPathTest(string path, int? seasonNumber, bool isSeasonDirectory) { var result = SeasonPathParser.Parse(path, true, true); diff --git a/tests/Jellyfin.Naming.Tests/TV/SeasonNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/SeasonNumberTests.cs index 58ec1b5d2..94a953de3 100644 --- a/tests/Jellyfin.Naming.Tests/TV/SeasonNumberTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/SeasonNumberTests.cs @@ -51,8 +51,8 @@ namespace Jellyfin.Naming.Tests.TV [InlineData("Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4", 2009)] [InlineData("Season 2009/S2009E23-E24-E26 - The Woman.mp4", 2009)] [InlineData("Series/1-12 - The Woman.mp4", 1)] - [InlineData(@"Running Man/Running Man S2017E368.mkv", 2017)] - [InlineData(@"Case Closed (1996-2007)/Case Closed - 317.mkv", 3)] + [InlineData("Running Man/Running Man S2017E368.mkv", 2017)] + [InlineData("Case Closed (1996-2007)/Case Closed - 317.mkv", 3)] // TODO: [InlineData(@"Seinfeld/Seinfeld 0807 The Checks.avi", 8)] public void GetSeasonNumberFromEpisodeFileTest(string path, int? expected) { diff --git a/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs index fa46ecc3a..3721cd28c 100644 --- a/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs @@ -21,8 +21,8 @@ namespace Jellyfin.Naming.Tests.TV [InlineData("Series/4x12 - The Woman.mp4", "", 4, 12)] [InlineData("Series/LA X, Pt. 1_s06e32.mp4", "LA X, Pt. 1", 6, 32)] [InlineData("[Baz-Bar]Foo - [1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)] - [InlineData(@"/Foo/The.Series.Name.S01E04.WEBRip.x264-Baz[Bar]/the.series.name.s01e04.webrip.x264-Baz[Bar].mkv", "The.Series.Name", 1, 4)] - [InlineData(@"Love.Death.and.Robots.S01.1080p.NF.WEB-DL.DDP5.1.x264-NTG/Love.Death.and.Robots.S01E01.Sonnies.Edge.1080p.NF.WEB-DL.DDP5.1.x264-NTG.mkv", "Love.Death.and.Robots", 1, 1)] + [InlineData("/Foo/The.Series.Name.S01E04.WEBRip.x264-Baz[Bar]/the.series.name.s01e04.webrip.x264-Baz[Bar].mkv", "The.Series.Name", 1, 4)] + [InlineData("Love.Death.and.Robots.S01.1080p.NF.WEB-DL.DDP5.1.x264-NTG/Love.Death.and.Robots.S01E01.Sonnies.Edge.1080p.NF.WEB-DL.DDP5.1.x264-NTG.mkv", "Love.Death.and.Robots", 1, 1)] [InlineData("[YuiSubs] Tensura Nikki - Tensei Shitara Slime Datta Ken/[YuiSubs] Tensura Nikki - Tensei Shitara Slime Datta Ken - 12 (NVENC H.265 1080p).mkv", "Tensura Nikki - Tensei Shitara Slime Datta Ken", null, 12)] [InlineData("[Baz-Bar]Foo - 01 - 12[1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)] [InlineData("Series/4-12 - The Woman.mp4", "", 4, 12, 12)] diff --git a/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs index b1141df47..62d60e5a4 100644 --- a/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs @@ -10,34 +10,34 @@ namespace Jellyfin.Naming.Tests.Video private readonly NamingOptions _namingOptions = new NamingOptions(); [Theory] - [InlineData(@"The Wolf of Wall Street (2013).mkv", "The Wolf of Wall Street", 2013)] - [InlineData(@"The Wolf of Wall Street 2 (2013).mkv", "The Wolf of Wall Street 2", 2013)] - [InlineData(@"The Wolf of Wall Street - 2 (2013).mkv", "The Wolf of Wall Street - 2", 2013)] - [InlineData(@"The Wolf of Wall Street 2001 (2013).mkv", "The Wolf of Wall Street 2001", 2013)] - [InlineData(@"300 (2006).mkv", "300", 2006)] - [InlineData(@"d:/movies/300 (2006).mkv", "300", 2006)] - [InlineData(@"300 2 (2006).mkv", "300 2", 2006)] - [InlineData(@"300 - 2 (2006).mkv", "300 - 2", 2006)] - [InlineData(@"300 2001 (2006).mkv", "300 2001", 2006)] - [InlineData(@"curse.of.chucky.2013.stv.unrated.multi.1080p.bluray.x264-rough", "curse.of.chucky", 2013)] - [InlineData(@"curse.of.chucky.2013.stv.unrated.multi.2160p.bluray.x264-rough", "curse.of.chucky", 2013)] - [InlineData(@"/server/Movies/300 (2007)/300 (2006).bluray.disc", "300", 2006)] - [InlineData(@"Arrival.2016.2160p.Blu-Ray.HEVC.mkv", "Arrival", 2016)] - [InlineData(@"The Wolf of Wall Street (2013)", "The Wolf of Wall Street", 2013)] - [InlineData(@"The Wolf of Wall Street 2 (2013)", "The Wolf of Wall Street 2", 2013)] - [InlineData(@"The Wolf of Wall Street - 2 (2013)", "The Wolf of Wall Street - 2", 2013)] - [InlineData(@"The Wolf of Wall Street 2001 (2013)", "The Wolf of Wall Street 2001", 2013)] - [InlineData(@"300 (2006)", "300", 2006)] - [InlineData(@"d:/movies/300 (2006)", "300", 2006)] - [InlineData(@"300 2 (2006)", "300 2", 2006)] - [InlineData(@"300 - 2 (2006)", "300 - 2", 2006)] - [InlineData(@"300 2001 (2006)", "300 2001", 2006)] - [InlineData(@"/server/Movies/300 (2007)/300 (2006)", "300", 2006)] - [InlineData(@"/server/Movies/300 (2007)/300 (2006).mkv", "300", 2006)] - [InlineData(@"American.Psycho.mkv", "American.Psycho.mkv", null)] - [InlineData(@"American Psycho.mkv", "American Psycho.mkv", null)] - [InlineData(@"[rec].mkv", "[rec].mkv", null)] - [InlineData(@"St. Vincent (2014)", "St. Vincent", 2014)] + [InlineData("The Wolf of Wall Street (2013).mkv", "The Wolf of Wall Street", 2013)] + [InlineData("The Wolf of Wall Street 2 (2013).mkv", "The Wolf of Wall Street 2", 2013)] + [InlineData("The Wolf of Wall Street - 2 (2013).mkv", "The Wolf of Wall Street - 2", 2013)] + [InlineData("The Wolf of Wall Street 2001 (2013).mkv", "The Wolf of Wall Street 2001", 2013)] + [InlineData("300 (2006).mkv", "300", 2006)] + [InlineData("d:/movies/300 (2006).mkv", "300", 2006)] + [InlineData("300 2 (2006).mkv", "300 2", 2006)] + [InlineData("300 - 2 (2006).mkv", "300 - 2", 2006)] + [InlineData("300 2001 (2006).mkv", "300 2001", 2006)] + [InlineData("curse.of.chucky.2013.stv.unrated.multi.1080p.bluray.x264-rough", "curse.of.chucky", 2013)] + [InlineData("curse.of.chucky.2013.stv.unrated.multi.2160p.bluray.x264-rough", "curse.of.chucky", 2013)] + [InlineData("/server/Movies/300 (2007)/300 (2006).bluray.disc", "300", 2006)] + [InlineData("Arrival.2016.2160p.Blu-Ray.HEVC.mkv", "Arrival", 2016)] + [InlineData("The Wolf of Wall Street (2013)", "The Wolf of Wall Street", 2013)] + [InlineData("The Wolf of Wall Street 2 (2013)", "The Wolf of Wall Street 2", 2013)] + [InlineData("The Wolf of Wall Street - 2 (2013)", "The Wolf of Wall Street - 2", 2013)] + [InlineData("The Wolf of Wall Street 2001 (2013)", "The Wolf of Wall Street 2001", 2013)] + [InlineData("300 (2006)", "300", 2006)] + [InlineData("d:/movies/300 (2006)", "300", 2006)] + [InlineData("300 2 (2006)", "300 2", 2006)] + [InlineData("300 - 2 (2006)", "300 - 2", 2006)] + [InlineData("300 2001 (2006)", "300 2001", 2006)] + [InlineData("/server/Movies/300 (2007)/300 (2006)", "300", 2006)] + [InlineData("/server/Movies/300 (2007)/300 (2006).mkv", "300", 2006)] + [InlineData("American.Psycho.mkv", "American.Psycho.mkv", null)] + [InlineData("American Psycho.mkv", "American Psycho.mkv", null)] + [InlineData("[rec].mkv", "[rec].mkv", null)] + [InlineData("St. Vincent (2014)", "St. Vincent", 2014)] [InlineData("Super movie(2009).mp4", "Super movie", 2009)] [InlineData("Drug War 2013.mp4", "Drug War", 2013)] [InlineData("My Movie (1997) - GreatestReleaseGroup 2019.mp4", "My Movie", 1997)] @@ -45,9 +45,9 @@ namespace Jellyfin.Naming.Tests.Video [InlineData("First Man (2018) 1080p.mkv", "First Man", 2018)] [InlineData("Maximum Ride - 2016 - WEBDL-1080p - x264 AC3.mkv", "Maximum Ride", 2016)] // FIXME: [InlineData("Robin Hood [Multi-Subs] [2018].mkv", "Robin Hood", 2018)] - [InlineData(@"3.Days.to.Kill.2014.720p.BluRay.x264.YIFY.mkv", "3.Days.to.Kill", 2014)] // In this test case, running CleanDateTime first produces no date, so it will attempt to run CleanString first and then CleanDateTime again + [InlineData("3.Days.to.Kill.2014.720p.BluRay.x264.YIFY.mkv", "3.Days.to.Kill", 2014)] // In this test case, running CleanDateTime first produces no date, so it will attempt to run CleanString first and then CleanDateTime again [InlineData("3 days to kill (2005).mkv", "3 days to kill", 2005)] - [InlineData(@"Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - Ozlem.mp4", "Rain Man", 1988)] + [InlineData("Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - Ozlem.mp4", "Rain Man", 1988)] [InlineData("My Movie 2013.12.09", "My Movie 2013.12.09", null)] [InlineData("My Movie 2013-12-09", "My Movie 2013-12-09", null)] [InlineData("My Movie 20131209", "My Movie 20131209", null)] diff --git a/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs b/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs index 511a014a6..fccce5bff 100644 --- a/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs @@ -22,7 +22,7 @@ namespace Jellyfin.Naming.Tests.Video [Fact] public void Test3DName() { - var result = VideoResolver.ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.3d.hsbs.mkv", _namingOptions); + var result = VideoResolver.ResolveFile("C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.3d.hsbs.mkv", _namingOptions); Assert.Equal("hsbs", result?.Format3D); Assert.Equal("Oblivion", result?.Name); diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs index 294f11ee7..183ec8984 100644 --- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -15,10 +15,10 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - 1080p.mkv", - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past-trailer.mp4", - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - [hsbs].mkv", - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past [hsbs].mkv" + "/movies/X-Men Days of Future Past/X-Men Days of Future Past - 1080p.mkv", + "/movies/X-Men Days of Future Past/X-Men Days of Future Past-trailer.mp4", + "/movies/X-Men Days of Future Past/X-Men Days of Future Past - [hsbs].mkv", + "/movies/X-Men Days of Future Past/X-Men Days of Future Past [hsbs].mkv" }; var result = VideoListResolver.Resolve( @@ -34,10 +34,10 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - apple.mkv", - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past-trailer.mp4", - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past - banana.mkv", - @"/movies/X-Men Days of Future Past/X-Men Days of Future Past [banana].mp4" + "/movies/X-Men Days of Future Past/X-Men Days of Future Past - apple.mkv", + "/movies/X-Men Days of Future Past/X-Men Days of Future Past-trailer.mp4", + "/movies/X-Men Days of Future Past/X-Men Days of Future Past - banana.mkv", + "/movies/X-Men Days of Future Past/X-Men Days of Future Past [banana].mp4" }; var result = VideoListResolver.Resolve( @@ -54,8 +54,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/The Phantom of the Opera (1925)/The Phantom of the Opera (1925) - 1925 version.mkv", - @"/movies/The Phantom of the Opera (1925)/The Phantom of the Opera (1925) - 1929 version.mkv" + "/movies/The Phantom of the Opera (1925)/The Phantom of the Opera (1925) - 1925 version.mkv", + "/movies/The Phantom of the Opera (1925)/The Phantom of the Opera (1925) - 1929 version.mkv" }; var result = VideoListResolver.Resolve( @@ -71,13 +71,13 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/M/Movie 1.mkv", - @"/movies/M/Movie 2.mkv", - @"/movies/M/Movie 3.mkv", - @"/movies/M/Movie 4.mkv", - @"/movies/M/Movie 5.mkv", - @"/movies/M/Movie 6.mkv", - @"/movies/M/Movie 7.mkv" + "/movies/M/Movie 1.mkv", + "/movies/M/Movie 2.mkv", + "/movies/M/Movie 3.mkv", + "/movies/M/Movie 4.mkv", + "/movies/M/Movie 5.mkv", + "/movies/M/Movie 6.mkv", + "/movies/M/Movie 7.mkv" }; var result = VideoListResolver.Resolve( @@ -93,14 +93,14 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Movie/Movie.mkv", - @"/movies/Movie/Movie-2.mkv", - @"/movies/Movie/Movie-3.mkv", - @"/movies/Movie/Movie-4.mkv", - @"/movies/Movie/Movie-5.mkv", - @"/movies/Movie/Movie-6.mkv", - @"/movies/Movie/Movie-7.mkv", - @"/movies/Movie/Movie-8.mkv" + "/movies/Movie/Movie.mkv", + "/movies/Movie/Movie-2.mkv", + "/movies/Movie/Movie-3.mkv", + "/movies/Movie/Movie-4.mkv", + "/movies/Movie/Movie-5.mkv", + "/movies/Movie/Movie-6.mkv", + "/movies/Movie/Movie-7.mkv", + "/movies/Movie/Movie-8.mkv" }; var result = VideoListResolver.Resolve( @@ -116,15 +116,15 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Mo/Movie 1.mkv", - @"/movies/Mo/Movie 2.mkv", - @"/movies/Mo/Movie 3.mkv", - @"/movies/Mo/Movie 4.mkv", - @"/movies/Mo/Movie 5.mkv", - @"/movies/Mo/Movie 6.mkv", - @"/movies/Mo/Movie 7.mkv", - @"/movies/Mo/Movie 8.mkv", - @"/movies/Mo/Movie 9.mkv" + "/movies/Mo/Movie 1.mkv", + "/movies/Mo/Movie 2.mkv", + "/movies/Mo/Movie 3.mkv", + "/movies/Mo/Movie 4.mkv", + "/movies/Mo/Movie 5.mkv", + "/movies/Mo/Movie 6.mkv", + "/movies/Mo/Movie 7.mkv", + "/movies/Mo/Movie 8.mkv", + "/movies/Mo/Movie 9.mkv" }; var result = VideoListResolver.Resolve( @@ -140,11 +140,11 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Movie/Movie 1.mkv", - @"/movies/Movie/Movie 2.mkv", - @"/movies/Movie/Movie 3.mkv", - @"/movies/Movie/Movie 4.mkv", - @"/movies/Movie/Movie 5.mkv" + "/movies/Movie/Movie 1.mkv", + "/movies/Movie/Movie 2.mkv", + "/movies/Movie/Movie 3.mkv", + "/movies/Movie/Movie 4.mkv", + "/movies/Movie/Movie 5.mkv" }; var result = VideoListResolver.Resolve( @@ -162,11 +162,11 @@ namespace Jellyfin.Naming.Tests.Video var files = new[] { - @"/movies/Iron Man/Iron Man.mkv", - @"/movies/Iron Man/Iron Man (2008).mkv", - @"/movies/Iron Man/Iron Man (2009).mkv", - @"/movies/Iron Man/Iron Man (2010).mkv", - @"/movies/Iron Man/Iron Man (2011).mkv" + "/movies/Iron Man/Iron Man.mkv", + "/movies/Iron Man/Iron Man (2008).mkv", + "/movies/Iron Man/Iron Man (2009).mkv", + "/movies/Iron Man/Iron Man (2010).mkv", + "/movies/Iron Man/Iron Man (2011).mkv" }; var result = VideoListResolver.Resolve( @@ -182,13 +182,13 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Iron Man/Iron Man.mkv", - @"/movies/Iron Man/Iron Man-720p.mkv", - @"/movies/Iron Man/Iron Man-test.mkv", - @"/movies/Iron Man/Iron Man-bluray.mkv", - @"/movies/Iron Man/Iron Man-3d.mkv", - @"/movies/Iron Man/Iron Man-3d-hsbs.mkv", - @"/movies/Iron Man/Iron Man[test].mkv" + "/movies/Iron Man/Iron Man.mkv", + "/movies/Iron Man/Iron Man-720p.mkv", + "/movies/Iron Man/Iron Man-test.mkv", + "/movies/Iron Man/Iron Man-bluray.mkv", + "/movies/Iron Man/Iron Man-3d.mkv", + "/movies/Iron Man/Iron Man-3d-hsbs.mkv", + "/movies/Iron Man/Iron Man[test].mkv" }; var result = VideoListResolver.Resolve( @@ -211,13 +211,13 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Iron Man/Iron Man.mkv", - @"/movies/Iron Man/Iron Man - 720p.mkv", - @"/movies/Iron Man/Iron Man - test.mkv", - @"/movies/Iron Man/Iron Man - bluray.mkv", - @"/movies/Iron Man/Iron Man - 3d.mkv", - @"/movies/Iron Man/Iron Man - 3d-hsbs.mkv", - @"/movies/Iron Man/Iron Man [test].mkv" + "/movies/Iron Man/Iron Man.mkv", + "/movies/Iron Man/Iron Man - 720p.mkv", + "/movies/Iron Man/Iron Man - test.mkv", + "/movies/Iron Man/Iron Man - bluray.mkv", + "/movies/Iron Man/Iron Man - 3d.mkv", + "/movies/Iron Man/Iron Man - 3d-hsbs.mkv", + "/movies/Iron Man/Iron Man [test].mkv" }; var result = VideoListResolver.Resolve( @@ -240,8 +240,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Iron Man/Iron Man - B (2006).mkv", - @"/movies/Iron Man/Iron Man - C (2007).mkv" + "/movies/Iron Man/Iron Man - B (2006).mkv", + "/movies/Iron Man/Iron Man - C (2007).mkv" }; var result = VideoListResolver.Resolve( @@ -256,13 +256,13 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Iron Man/Iron Man.mkv", - @"/movies/Iron Man/Iron Man_720p.mkv", - @"/movies/Iron Man/Iron Man_test.mkv", - @"/movies/Iron Man/Iron Man_bluray.mkv", - @"/movies/Iron Man/Iron Man_3d.mkv", - @"/movies/Iron Man/Iron Man_3d-hsbs.mkv", - @"/movies/Iron Man/Iron Man_3d.hsbs.mkv" + "/movies/Iron Man/Iron Man.mkv", + "/movies/Iron Man/Iron Man_720p.mkv", + "/movies/Iron Man/Iron Man_test.mkv", + "/movies/Iron Man/Iron Man_bluray.mkv", + "/movies/Iron Man/Iron Man_3d.mkv", + "/movies/Iron Man/Iron Man_3d-hsbs.mkv", + "/movies/Iron Man/Iron Man_3d.hsbs.mkv" }; var result = VideoListResolver.Resolve( @@ -280,11 +280,11 @@ namespace Jellyfin.Naming.Tests.Video var files = new[] { - @"/movies/Iron Man/Iron Man (2007).mkv", - @"/movies/Iron Man/Iron Man (2008).mkv", - @"/movies/Iron Man/Iron Man (2009).mkv", - @"/movies/Iron Man/Iron Man (2010).mkv", - @"/movies/Iron Man/Iron Man (2011).mkv" + "/movies/Iron Man/Iron Man (2007).mkv", + "/movies/Iron Man/Iron Man (2008).mkv", + "/movies/Iron Man/Iron Man (2009).mkv", + "/movies/Iron Man/Iron Man (2010).mkv", + "/movies/Iron Man/Iron Man (2011).mkv" }; var result = VideoListResolver.Resolve( @@ -300,8 +300,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/Blade Runner (1982)/Blade Runner (1982) [Final Cut] [1080p HEVC AAC].mkv", - @"/movies/Blade Runner (1982)/Blade Runner (1982) [EE by ADM] [480p HEVC AAC,AAC,AAC].mkv" + "/movies/Blade Runner (1982)/Blade Runner (1982) [Final Cut] [1080p HEVC AAC].mkv", + "/movies/Blade Runner (1982)/Blade Runner (1982) [EE by ADM] [480p HEVC AAC,AAC,AAC].mkv" }; var result = VideoListResolver.Resolve( @@ -317,8 +317,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) [1080p] Blu-ray.x264.DTS.mkv", - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) [2160p] Blu-ray.x265.AAC.mkv" + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) [1080p] Blu-ray.x264.DTS.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) [2160p] Blu-ray.x265.AAC.mkv" }; var result = VideoListResolver.Resolve( @@ -334,12 +334,12 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Theatrical Release.mkv", - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Directors Cut.mkv", - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p.mkv", - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 2160p.mkv", - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 720p.mkv", - @"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016).mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Theatrical Release.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Directors Cut.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 2160p.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 720p.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016).mkv", }; var result = VideoListResolver.Resolve( @@ -361,8 +361,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/John Wick - Kapitel 3 (2019) [imdbid=tt6146586]/John Wick - Kapitel 3 (2019) [imdbid=tt6146586] - Version 1.mkv", - @"/movies/John Wick - Kapitel 3 (2019) [imdbid=tt6146586]/John Wick - Kapitel 3 (2019) [imdbid=tt6146586] - Version 2.mkv" + "/movies/John Wick - Kapitel 3 (2019) [imdbid=tt6146586]/John Wick - Kapitel 3 (2019) [imdbid=tt6146586] - Version 1.mkv", + "/movies/John Wick - Kapitel 3 (2019) [imdbid=tt6146586]/John Wick - Kapitel 3 (2019) [imdbid=tt6146586] - Version 2.mkv" }; var result = VideoListResolver.Resolve( @@ -378,8 +378,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/movies/John Wick - Chapter 3 (2019)/John Wick - Chapter 3 (2019) [Version 1].mkv", - @"/movies/John Wick - Chapter 3 (2019)/John Wick - Chapter 3 (2019) [Version 2.mkv" + "/movies/John Wick - Chapter 3 (2019)/John Wick - Chapter 3 (2019) [Version 1].mkv", + "/movies/John Wick - Chapter 3 (2019)/John Wick - Chapter 3 (2019) [Version 2.mkv" }; var result = VideoListResolver.Resolve( diff --git a/tests/Jellyfin.Naming.Tests/Video/StackTests.cs b/tests/Jellyfin.Naming.Tests/Video/StackTests.cs index 97b52f749..c95703f53 100644 --- a/tests/Jellyfin.Naming.Tests/Video/StackTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/StackTests.cs @@ -384,8 +384,8 @@ namespace Jellyfin.Naming.Tests.Video // No stacking here because there is no part/disc/etc var files = new[] { - @"M:/Movies (DVD)/Movies (Musical)/The Sound of Music/The Sound of Music (1965) (Disc 01)", - @"M:/Movies (DVD)/Movies (Musical)/The Sound of Music/The Sound of Music (1965) (Disc 02)" + "M:/Movies (DVD)/Movies (Musical)/The Sound of Music/The Sound of Music (1965) (Disc 01)", + "M:/Movies (DVD)/Movies (Musical)/The Sound of Music/The Sound of Music (1965) (Disc 02)" }; var result = StackResolver.ResolveDirectories(files, _namingOptions).ToList(); diff --git a/tests/Jellyfin.Naming.Tests/Video/StubTests.cs b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs index 1d50df7a6..fc852ae85 100644 --- a/tests/Jellyfin.Naming.Tests/Video/StubTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs @@ -29,7 +29,7 @@ namespace Jellyfin.Naming.Tests.Video [Fact] public void TestStubName() { - var result = VideoResolver.ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.dvd.disc", _namingOptions); + var result = VideoResolver.ResolveFile("C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.dvd.disc", _namingOptions); Assert.Equal("Oblivion", result?.Name); } diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs index 0316377d4..377f82eac 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs @@ -200,8 +200,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"M:/Movies (DVD)/Movies (Musical)/Sound of Music (1965)/Sound of Music Disc 1", - @"M:/Movies (DVD)/Movies (Musical)/Sound of Music (1965)/Sound of Music Disc 2" + "M:/Movies (DVD)/Movies (Musical)/Sound of Music (1965)/Sound of Music Disc 1", + "M:/Movies (DVD)/Movies (Musical)/Sound of Music (1965)/Sound of Music Disc 2" }; var result = VideoListResolver.Resolve( @@ -217,8 +217,8 @@ namespace Jellyfin.Naming.Tests.Video // These should be considered separate, unrelated videos var files = new[] { - @"My movie #1.mp4", - @"My movie #2.mp4" + "My movie #1.mp4", + "My movie #2.mp4" }; var result = VideoListResolver.Resolve( @@ -233,10 +233,10 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"No (2012) part1.mp4", - @"No (2012) part2.mp4", - @"No (2012) part1-trailer.mp4", - @"No (2012)-trailer.mp4" + "No (2012) part1.mp4", + "No (2012) part2.mp4", + "No (2012) part1-trailer.mp4", + "No (2012)-trailer.mp4" }; var result = VideoListResolver.Resolve( @@ -254,10 +254,10 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/Movies/Top Gun (1984)/movie.mp4", - @"/Movies/Top Gun (1984)/Top Gun (1984)-trailer.mp4", - @"/Movies/Top Gun (1984)/Top Gun (1984)-trailer2.mp4", - @"/Movies/trailer.mp4" + "/Movies/Top Gun (1984)/movie.mp4", + "/Movies/Top Gun (1984)/Top Gun (1984)-trailer.mp4", + "/Movies/Top Gun (1984)/Top Gun (1984)-trailer2.mp4", + "/Movies/trailer.mp4" }; var result = VideoListResolver.Resolve( @@ -276,10 +276,10 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Counterfeit Racks (2011) Disc 1 cd1.avi", - @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Counterfeit Racks (2011) Disc 1 cd2.avi", - @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Disc 2 cd1.avi", - @"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Disc 2 cd2.avi" + "/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Counterfeit Racks (2011) Disc 1 cd1.avi", + "/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Counterfeit Racks (2011) Disc 1 cd2.avi", + "/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Disc 2 cd1.avi", + "/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Disc 2 cd2.avi" }; var result = VideoListResolver.Resolve( @@ -294,7 +294,7 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/nas-markrobbo78/Videos/INDEX HTPC/Movies/Watched/3 - ACTION/Argo (2012)/movie.mkv" + "/nas-markrobbo78/Videos/INDEX HTPC/Movies/Watched/3 - ACTION/Argo (2012)/movie.mkv" }; var result = VideoListResolver.Resolve( @@ -309,7 +309,7 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"The Colony.mkv" + "The Colony.mkv" }; var result = VideoListResolver.Resolve( @@ -324,8 +324,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"Four Sisters and a Wedding - A.avi", - @"Four Sisters and a Wedding - B.avi" + "Four Sisters and a Wedding - A.avi", + "Four Sisters and a Wedding - B.avi" }; var result = VideoListResolver.Resolve( @@ -342,8 +342,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"Four Rooms - A.avi", - @"Four Rooms - A.mp4" + "Four Rooms - A.avi", + "Four Rooms - A.mp4" }; var result = VideoListResolver.Resolve( @@ -358,8 +358,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/Server/Despicable Me/Despicable Me (2010).mkv", - @"/Server/Despicable Me/trailer.mkv" + "/Server/Despicable Me/Despicable Me (2010).mkv", + "/Server/Despicable Me/trailer.mkv" }; var result = VideoListResolver.Resolve( @@ -376,8 +376,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/Server/Despicable Me/Despicable Me (2010).mkv", - @"/Server/Despicable Me/trailers/some title.mkv" + "/Server/Despicable Me/Despicable Me (2010).mkv", + "/Server/Despicable Me/trailers/some title.mkv" }; var result = VideoListResolver.Resolve( @@ -394,8 +394,8 @@ namespace Jellyfin.Naming.Tests.Video { var files = new[] { - @"/Movies/Despicable Me/Despicable Me.mkv", - @"/Movies/Despicable Me/trailers/trailer.mkv" + "/Movies/Despicable Me/Despicable Me.mkv", + "/Movies/Despicable Me/trailers/trailer.mkv" }; var result = VideoListResolver.Resolve( diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs index 33a99e107..8455a56a1 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs @@ -15,26 +15,26 @@ namespace Jellyfin.Naming.Tests.Video var data = new TheoryData<VideoFileInfo>(); data.Add( new VideoFileInfo( - path: @"/server/Movies/7 Psychos.mkv/7 Psychos.mkv", + path: "/server/Movies/7 Psychos.mkv/7 Psychos.mkv", container: "mkv", name: "7 Psychos")); data.Add( new VideoFileInfo( - path: @"/server/Movies/3 days to kill (2005)/3 days to kill (2005).mkv", + path: "/server/Movies/3 days to kill (2005)/3 days to kill (2005).mkv", container: "mkv", name: "3 days to kill", year: 2005)); data.Add( new VideoFileInfo( - path: @"/server/Movies/American Psycho/American.Psycho.mkv", + path: "/server/Movies/American Psycho/American.Psycho.mkv", container: "mkv", name: "American.Psycho")); data.Add( new VideoFileInfo( - path: @"/server/Movies/brave (2007)/brave (2006).3d.sbs.mkv", + path: "/server/Movies/brave (2007)/brave (2006).3d.sbs.mkv", container: "mkv", name: "brave", year: 2006, @@ -43,14 +43,14 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/300 (2007)/300 (2006).3d1.sbas.mkv", + path: "/server/Movies/300 (2007)/300 (2006).3d1.sbas.mkv", container: "mkv", name: "300", year: 2006)); data.Add( new VideoFileInfo( - path: @"/server/Movies/300 (2007)/300 (2006).3d.sbs.mkv", + path: "/server/Movies/300 (2007)/300 (2006).3d.sbs.mkv", container: "mkv", name: "300", year: 2006, @@ -59,7 +59,7 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/brave (2007)/brave (2006)-trailer.bluray.disc", + path: "/server/Movies/brave (2007)/brave (2006)-trailer.bluray.disc", container: "disc", name: "brave", year: 2006, @@ -68,7 +68,7 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/300 (2007)/300 (2006)-trailer.bluray.disc", + path: "/server/Movies/300 (2007)/300 (2006)-trailer.bluray.disc", container: "disc", name: "300", year: 2006, @@ -77,7 +77,7 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/Brave (2007)/Brave (2006).bluray.disc", + path: "/server/Movies/Brave (2007)/Brave (2006).bluray.disc", container: "disc", name: "Brave", year: 2006, @@ -86,7 +86,7 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/300 (2007)/300 (2006).bluray.disc", + path: "/server/Movies/300 (2007)/300 (2006).bluray.disc", container: "disc", name: "300", year: 2006, @@ -95,7 +95,7 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/300 (2007)/300 (2006)-trailer.mkv", + path: "/server/Movies/300 (2007)/300 (2006)-trailer.mkv", container: "mkv", name: "300", year: 2006, @@ -103,7 +103,7 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/Brave (2007)/Brave (2006)-trailer.mkv", + path: "/server/Movies/Brave (2007)/Brave (2006)-trailer.mkv", container: "mkv", name: "Brave", year: 2006, @@ -111,28 +111,28 @@ namespace Jellyfin.Naming.Tests.Video data.Add( new VideoFileInfo( - path: @"/server/Movies/300 (2007)/300 (2006).mkv", + path: "/server/Movies/300 (2007)/300 (2006).mkv", container: "mkv", name: "300", year: 2006)); data.Add( new VideoFileInfo( - path: @"/server/Movies/Bad Boys (1995)/Bad Boys (1995).mkv", + path: "/server/Movies/Bad Boys (1995)/Bad Boys (1995).mkv", container: "mkv", name: "Bad Boys", year: 1995)); data.Add( new VideoFileInfo( - path: @"/server/Movies/Brave (2007)/Brave (2006).mkv", + path: "/server/Movies/Brave (2007)/Brave (2006).mkv", container: "mkv", name: "Brave", year: 2006)); data.Add( new VideoFileInfo( - path: @"/server/Movies/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF.mp4", + path: "/server/Movies/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF.mp4", container: "mp4", name: "Rain Man", year: 1988)); @@ -174,8 +174,8 @@ namespace Jellyfin.Naming.Tests.Video { var paths = new[] { - @"/Server/Iron Man", - @"Batman", + "/Server/Iron Man", + "Batman", string.Empty }; diff --git a/tests/Jellyfin.Networking.Tests/IPNetAddressTests.cs b/tests/Jellyfin.Networking.Tests/IPNetAddressTests.cs deleted file mode 100644 index aa2dbc57a..000000000 --- a/tests/Jellyfin.Networking.Tests/IPNetAddressTests.cs +++ /dev/null @@ -1,49 +0,0 @@ -using FsCheck; -using FsCheck.Xunit; -using MediaBrowser.Common.Net; -using Xunit; - -namespace Jellyfin.Networking.Tests -{ - public static class IPNetAddressTests - { - /// <summary> - /// Checks IP address formats. - /// </summary> - /// <param name="address">IP Address.</param> - [Theory] - [InlineData("127.0.0.1")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")] - [InlineData("fe80::7add:12ff:febb:c67b%16")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] - [InlineData("fe80::7add:12ff:febb:c67b%16:123")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]")] - [InlineData("192.168.1.2/255.255.255.0")] - [InlineData("192.168.1.2/24")] - public static void TryParse_ValidIPStrings_True(string address) - => Assert.True(IPNetAddress.TryParse(address, out _)); - - [Property] - public static Property TryParse_IPv4Address_True(IPv4Address address) - => IPNetAddress.TryParse(address.Item.ToString(), out _).ToProperty(); - - [Property] - public static Property TryParse_IPv6Address_True(IPv6Address address) - => IPNetAddress.TryParse(address.Item.ToString(), out _).ToProperty(); - - /// <summary> - /// All should be invalid address strings. - /// </summary> - /// <param name="address">Invalid address strings.</param> - [Theory] - [InlineData("256.128.0.0.0.1")] - [InlineData("127.0.0.1#")] - [InlineData("localhost!")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] - public static void TryParse_InvalidAddressString_False(string address) - => Assert.False(IPNetAddress.TryParse(address, out _)); - } -} diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 4b4bdd2a5..3747db3bb 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -18,12 +18,7 @@ </ItemGroup> <ItemGroup> - <ProjectReference Include="../../Emby.Server.Implementations/Emby.Server.Implementations.csproj" /> - <ProjectReference Include="../../MediaBrowser.Common/MediaBrowser.Common.csproj" /> + <ProjectReference Include="../../Jellyfin.Networking/Jellyfin.Networking.csproj" /> </ItemGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> - <DefineConstants>DEBUG</DefineConstants> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.Networking.Tests/IPHostTests.cs b/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs index ec3a1300c..072e0a8c5 100644 --- a/tests/Jellyfin.Networking.Tests/IPHostTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs @@ -1,11 +1,11 @@ using FsCheck; using FsCheck.Xunit; -using MediaBrowser.Common.Net; +using Jellyfin.Networking.Extensions; using Xunit; namespace Jellyfin.Networking.Tests { - public static class IPHostTests + public static class NetworkExtensionsTests { /// <summary> /// Checks IP address formats. @@ -16,7 +16,6 @@ namespace Jellyfin.Networking.Tests [InlineData("127.0.0.1:123")] [InlineData("localhost")] [InlineData("localhost:1345")] - [InlineData("www.google.co.uk")] [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]:124")] @@ -27,15 +26,15 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.2/255.255.255.0")] [InlineData("192.168.1.2/24")] public static void TryParse_ValidHostStrings_True(string address) - => Assert.True(IPHost.TryParse(address, out _)); + => Assert.True(NetworkExtensions.TryParseHost(address, out _, true, true)); [Property] public static Property TryParse_IPv4Address_True(IPv4Address address) - => IPHost.TryParse(address.Item.ToString(), out _).ToProperty(); + => NetworkExtensions.TryParseHost(address.Item.ToString(), out _, true, true).ToProperty(); [Property] public static Property TryParse_IPv6Address_True(IPv6Address address) - => IPHost.TryParse(address.Item.ToString(), out _).ToProperty(); + => NetworkExtensions.TryParseHost(address.Item.ToString(), out _, true, true).ToProperty(); /// <summary> /// All should be invalid address strings. @@ -48,6 +47,6 @@ namespace Jellyfin.Networking.Tests [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] public static void TryParse_InvalidAddressString_False(string address) - => Assert.False(IPHost.TryParse(address, out _)); + => Assert.False(NetworkExtensions.TryParseHost(address, out _, true, true)); } } diff --git a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs index df2a2ca70..2302f90b8 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs @@ -1,7 +1,9 @@ using System.Net; using Jellyfin.Networking.Configuration; using Jellyfin.Networking.Manager; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; +using Moq; using Xunit; namespace Jellyfin.Networking.Tests @@ -23,12 +25,13 @@ namespace Jellyfin.Networking.Tests var ip = IPAddress.Parse(value); var conf = new NetworkConfiguration() { - EnableIPV6 = true, - EnableIPV4 = true, + EnableIPv6 = true, + EnableIPv4 = true, LocalNetworkSubnets = network.Split(',') }; - using var networkManager = new NetworkManager(NetworkParseTests.GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var networkManager = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); Assert.True(networkManager.IsInLocalNetwork(ip)); } @@ -51,14 +54,15 @@ namespace Jellyfin.Networking.Tests var ip = IPAddress.Parse(value); var conf = new NetworkConfiguration() { - EnableIPV6 = true, - EnableIPV4 = true, + EnableIPv6 = true, + EnableIPv4 = true, LocalNetworkSubnets = network.Split(',') }; - using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var networkManager = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); - Assert.False(nm.IsInLocalNetwork(ip)); + Assert.False(networkManager.IsInLocalNetwork(ip)); } } } diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 8174632bb..022b8a3d0 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -1,10 +1,13 @@ using System; -using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.Linq; using System.Net; using Jellyfin.Networking.Configuration; +using Jellyfin.Networking.Extensions; using Jellyfin.Networking.Manager; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; +using MediaBrowser.Model.Net; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -34,6 +37,8 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.0/24", "[192.168.1.208/24,200.200.200.200/24]")] // eth16 only [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.208/24]")] + // eth16 only without mask + [InlineData("192.168.1.208,-16,eth16|200.200.200.200,11,eth11", "192.168.1.0/24", "[192.168.1.208/32]")] // All interfaces excluded. (including loopbacks) [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")] // vEthernet1 and vEthernet212 should be excluded. @@ -44,171 +49,107 @@ namespace Jellyfin.Networking.Tests { var conf = new NetworkConfiguration() { - EnableIPV6 = true, - EnableIPV4 = true, + EnableIPv6 = true, + EnableIPv4 = true, LocalNetworkSubnets = lan?.Split(';') ?? throw new ArgumentNullException(nameof(lan)) }; NetworkManager.MockNetworkSettings = interfaces; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); NetworkManager.MockNetworkSettings = string.Empty; - Assert.Equal(nm.GetInternalBindAddresses().AsString(), value); + Assert.Equal(value, "[" + string.Join(",", nm.GetInternalBindAddresses().Select(x => x.Address + "/" + x.Subnet.PrefixLength)) + "]"); } /// <summary> - /// Test collection parsing. + /// Checks valid IP address formats. /// </summary> - /// <param name="settings">Collection to parse.</param> - /// <param name="result1">Included addresses from the collection.</param> - /// <param name="result2">Included IP4 addresses from the collection.</param> - /// <param name="result3">Excluded addresses from the collection.</param> - /// <param name="result4">Excluded IP4 addresses from the collection.</param> - /// <param name="result5">Network addresses of the collection.</param> + /// <param name="address">IP Address.</param> [Theory] - [InlineData( - "127.0.0.1#", - "[]", - "[]", - "[]", - "[]", - "[]")] - [InlineData( - "!127.0.0.1", - "[]", - "[]", - "[127.0.0.1/32]", - "[127.0.0.1/32]", - "[]")] - [InlineData( - "", - "[]", - "[]", - "[]", - "[]", - "[]")] - [InlineData( - "192.158.1.2/16, localhost, fd23:184f:2029:0:3139:7386:67d7:d517, !10.10.10.10", - "[192.158.1.2/16,[127.0.0.1/32,::1/128],fd23:184f:2029:0:3139:7386:67d7:d517/128]", - "[192.158.1.2/16,127.0.0.1/32]", - "[10.10.10.10/32]", - "[10.10.10.10/32]", - "[192.158.0.0/16,127.0.0.1/32,::1/128,fd23:184f:2029:0:3139:7386:67d7:d517/128]")] - [InlineData( - "192.158.1.2/255.255.0.0,192.169.1.2/8", - "[192.158.1.2/16,192.169.1.2/8]", - "[192.158.1.2/16,192.169.1.2/8]", - "[]", - "[]", - "[192.158.0.0/16,192.0.0.0/8]")] - public void TestCollections(string settings, string result1, string result2, string result3, string result4, string result5) - { - ArgumentNullException.ThrowIfNull(settings); - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - - // Test included. - Collection<IPObject> nc = nm.CreateIPCollection(settings.Split(','), false); - Assert.Equal(nc.AsString(), result1); - - // Test excluded. - nc = nm.CreateIPCollection(settings.Split(','), true); - Assert.Equal(nc.AsString(), result3); - - conf.EnableIPV6 = false; - nm.UpdateSettings(conf); - - // Test IP4 included. - nc = nm.CreateIPCollection(settings.Split(','), false); - Assert.Equal(nc.AsString(), result2); - - // Test IP4 excluded. - nc = nm.CreateIPCollection(settings.Split(','), true); - Assert.Equal(nc.AsString(), result4); - - conf.EnableIPV6 = true; - nm.UpdateSettings(conf); - - // Test network addresses of collection. - nc = nm.CreateIPCollection(settings.Split(','), false); - nc = nc.AsNetworks(); - Assert.Equal(nc.AsString(), result5); - } + [InlineData("127.0.0.1")] + [InlineData("127.0.0.1/8")] + [InlineData("192.168.1.2")] + [InlineData("192.168.1.2/24")] + [InlineData("192.168.1.2/255.255.255.0")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")] + [InlineData("fe80::7add:12ff:febb:c67b%16")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] + [InlineData("fe80::7add:12ff:febb:c67b%16:123")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] + public static void TryParseValidIPStringsTrue(string address) + => Assert.True(NetworkExtensions.TryParseToSubnet(address, out _)); /// <summary> - /// Union two collections. + /// Checks invalid IP address formats. /// </summary> - /// <param name="settings">Source.</param> - /// <param name="compare">Destination.</param> - /// <param name="result">Result.</param> + /// <param name="address">IP Address.</param> [Theory] - [InlineData("127.0.0.1", "fd23:184f:2029:0:3139:7386:67d7:d517/64,fd23:184f:2029:0:c0f0:8a8a:7605:fffa/128,fe80::3139:7386:67d7:d517%16/64,192.168.1.208/24,::1/128,127.0.0.1/8", "[127.0.0.1/32]")] - [InlineData("127.0.0.1", "127.0.0.1/8", "[127.0.0.1/32]")] - public void UnionCheck(string settings, string compare, string result) - { - ArgumentNullException.ThrowIfNull(settings); - - ArgumentNullException.ThrowIfNull(compare); - - ArgumentNullException.ThrowIfNull(result); - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - - Collection<IPObject> nc1 = nm.CreateIPCollection(settings.Split(','), false); - Collection<IPObject> nc2 = nm.CreateIPCollection(compare.Split(','), false); - - Assert.Equal(nc1.ThatAreContainedInNetworks(nc2).AsString(), result); - } + [InlineData("127.0.0.1#")] + [InlineData("localhost!")] + [InlineData("256.128.0.0.0.1")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] + public static void TryParseInvalidIPStringsFalse(string address) + => Assert.False(NetworkExtensions.TryParseToSubnet(address, out _)); + /// <summary> + /// Checks if IPv4 address is within a defined subnet. + /// </summary> + /// <param name="netMask">Network mask.</param> + /// <param name="ipAddress">IP Address.</param> [Theory] [InlineData("192.168.5.85/24", "192.168.5.1")] [InlineData("192.168.5.85/24", "192.168.5.254")] + [InlineData("192.168.5.85/255.255.255.0", "192.168.5.254")] [InlineData("10.128.240.50/30", "10.128.240.48")] [InlineData("10.128.240.50/30", "10.128.240.49")] [InlineData("10.128.240.50/30", "10.128.240.50")] [InlineData("10.128.240.50/30", "10.128.240.51")] + [InlineData("10.128.240.50/255.255.255.252", "10.128.240.51")] [InlineData("127.0.0.1/8", "127.0.0.1")] - public void IpV4SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) + public void IPv4SubnetMaskMatchesValidIPAddress(string netMask, string ipAddress) { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + var ipa = IPAddress.Parse(ipAddress); + Assert.True(NetworkExtensions.TryParseToSubnet(netMask, out var subnet) && subnet.Contains(IPAddress.Parse(ipAddress))); } + /// <summary> + /// Checks if IPv4 address is not within a defined subnet. + /// </summary> + /// <param name="netMask">Network mask.</param> + /// <param name="ipAddress">IP Address.</param> [Theory] [InlineData("192.168.5.85/24", "192.168.4.254")] [InlineData("192.168.5.85/24", "191.168.5.254")] + [InlineData("192.168.5.85/255.255.255.252", "192.168.4.254")] [InlineData("10.128.240.50/30", "10.128.240.47")] [InlineData("10.128.240.50/30", "10.128.240.52")] [InlineData("10.128.240.50/30", "10.128.239.50")] [InlineData("10.128.240.50/30", "10.127.240.51")] - public void IpV4SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) + [InlineData("10.128.240.50/255.255.255.252", "10.127.240.51")] + public void IPv4SubnetMaskDoesNotMatchInvalidIPAddress(string netMask, string ipAddress) { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + var ipa = IPAddress.Parse(ipAddress); + Assert.False(NetworkExtensions.TryParseToSubnet(netMask, out var subnet) && subnet.Contains(IPAddress.Parse(ipAddress))); } + /// <summary> + /// Checks if IPv6 address is within a defined subnet. + /// </summary> + /// <param name="netMask">Network mask.</param> + /// <param name="ipAddress">IP Address.</param> [Theory] [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF")] [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0001:0000:0000:0000")] [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFF0")] [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] - public void IpV6SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) + public void IPv6SubnetMaskMatchesValidIPAddress(string netMask, string ipAddress) { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + Assert.True(NetworkExtensions.TryParseToSubnet(netMask, out var subnet) && subnet.Contains(IPAddress.Parse(ipAddress))); } [Theory] @@ -217,79 +158,16 @@ namespace Jellyfin.Networking.Tests [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0001:0000:0000:0000")] [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFF0")] [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0001")] - public void IpV6SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1/32")] - [InlineData("10.0.0.0/8", "10.10.10.1/32")] - [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1")] - - [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1/32")] - [InlineData("10.10.0.0/16", "10.10.10.1/32")] - [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1")] - - [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1/32")] - [InlineData("10.10.10.0/24", "10.10.10.1/32")] - [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1")] - - public void TestSubnetContains(string network, string ip) + public void IPv6SubnetMaskDoesNotMatchInvalidIPAddress(string netMask, string ipAddress) { - Assert.True(IPNetAddress.TryParse(network, out var networkObj)); - Assert.True(IPNetAddress.TryParse(ip, out var ipObj)); - Assert.True(networkObj.Contains(ipObj)); + Assert.False(NetworkExtensions.TryParseToSubnet(netMask, out var subnet) && subnet.Contains(IPAddress.Parse(ipAddress))); } [Theory] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24", "172.168.1.2/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24, 10.10.10.1", "172.168.1.2/24,10.10.10.1/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/255.255.255.0, 10.10.10.1", "192.168.1.2/24,10.10.10.1/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/24, 100.10.10.1", "192.168.1.2/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "194.168.1.2/24, 100.10.10.1", "")] - - public void TestCollectionEquality(string source, string dest, string result) - { - ArgumentNullException.ThrowIfNull(source); - - ArgumentNullException.ThrowIfNull(dest); - - ArgumentNullException.ThrowIfNull(result); - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - - // Test included, IP6. - Collection<IPObject> ncSource = nm.CreateIPCollection(source.Split(',')); - Collection<IPObject> ncDest = nm.CreateIPCollection(dest.Split(',')); - Collection<IPObject> ncResult = ncSource.ThatAreContainedInNetworks(ncDest); - Collection<IPObject> resultCollection = nm.CreateIPCollection(result.Split(',')); - Assert.True(ncResult.Compare(resultCollection)); - } - - [Theory] - [InlineData("10.1.1.1/32", "10.1.1.1")] - [InlineData("192.168.1.254/32", "192.168.1.254/255.255.255.255")] - - public void TestEquals(string source, string dest) - { - Assert.True(IPNetAddress.Parse(source).Equals(IPNetAddress.Parse(dest))); - Assert.True(IPNetAddress.Parse(dest).Equals(IPNetAddress.Parse(source))); - } - - [Theory] - // Testing bind interfaces. // On my system eth16 is internal, eth11 external (Windows defines the indexes). // - // This test is to replicate how DNLA requests work throughout the system. + // This test is to replicate how DLNA requests work throughout the system. // User on internal network, we're bound internal and external - so result is internal. [InlineData("192.168.1.1", "eth16,eth11", false, "eth16")] @@ -319,23 +197,25 @@ namespace Jellyfin.Networking.Tests var conf = new NetworkConfiguration() { LocalNetworkAddresses = bindAddresses.Split(','), - EnableIPV6 = ipv6enabled, - EnableIPV4 = true + EnableIPv6 = ipv6enabled, + EnableIPv4 = true }; NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); NetworkManager.MockNetworkSettings = string.Empty; - _ = nm.TryParseInterface(result, out Collection<IPObject>? resultObj); - - // Check to see if dns resolution is working. If not, skip test. - _ = IPHost.TryParse(source, out var host); + // Check to see if DNS resolution is working. If not, skip test. + if (!NetworkExtensions.TryParseHost(source, out var host)) + { + return; + } - if (resultObj is not null && host?.HasAddress == true) + if (nm.TryParseInterface(result, out var resultObj)) { - result = ((IPNetAddress)resultObj[0]).ToString(true); - var intf = nm.GetBindInterface(source, out _); + result = resultObj[0].Address.ToString(); + var intf = nm.GetBindAddress(source, out _); Assert.Equal(intf, result); } @@ -352,24 +232,24 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.1", "192.168.1.0/24", "eth16,eth11", false, "192.168.1.0/24=internal.jellyfin", "internal.jellyfin")] // User on external network, we're bound internal and external - so result is override. - [InlineData("8.8.8.8", "192.168.1.0/24", "eth16,eth11", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] + [InlineData("8.8.8.8", "192.168.1.0/24", "eth16,eth11", false, "all=http://helloworld.com", "http://helloworld.com")] // User on internal network, we're bound internal only, but the address isn't in the LAN - so return the override. - [InlineData("10.10.10.10", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://internalButNotDefinedAsLan.com", "http://internalButNotDefinedAsLan.com")] + [InlineData("10.10.10.10", "192.168.1.0/24", "eth16", false, "external=http://internalButNotDefinedAsLan.com", "http://internalButNotDefinedAsLan.com")] // User on internal network, no binding specified - so result is the 1st internal. - [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] + [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "external=http://helloworld.com", "eth16")] // User on external network, internal binding only - so assumption is a proxy forward, return external override. - [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] + [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "external=http://helloworld.com", "http://helloworld.com")] - // User on external network, no binding - so result is the 1st external which is overridden. - [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "0.0.0.0 = http://helloworld.com", "http://helloworld.com")] + // User on external network, no binding - so result is the 1st external which is overriden. + [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "external=http://helloworld.com", "http://helloworld.com")] - // User assumed to be internal, no binding - so result is the 1st internal. - [InlineData("", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] + // User assumed to be internal, no binding - so result is the 1st matching interface. + [InlineData("", "192.168.1.0/24", "", false, "all=http://helloworld.com", "eth16")] - // User is internal, no binding - so result is the 1st internal, which is then overridden. + // User is internal, no binding - so result is the 1st internal interface, which is then overridden. [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "eth16=http://helloworld.com", "http://helloworld.com")] public void TestBindInterfaceOverrides(string source, string lan, string bindAddresses, bool ipv6enabled, string publishedServers, string result) { @@ -381,24 +261,25 @@ namespace Jellyfin.Networking.Tests { LocalNetworkSubnets = lan.Split(','), LocalNetworkAddresses = bindAddresses.Split(','), - EnableIPV6 = ipv6enabled, - EnableIPV4 = true, + EnableIPv6 = ipv6enabled, + EnableIPv4 = true, PublishedServerUriBySubnet = new string[] { publishedServers } }; NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); NetworkManager.MockNetworkSettings = string.Empty; - if (nm.TryParseInterface(result, out Collection<IPObject>? resultObj) && resultObj is not null) + if (nm.TryParseInterface(result, out IReadOnlyList<IPData>? resultObj) && resultObj is not null) { - // Parse out IPAddresses so we can do a string comparison. (Ignore subnet masks). - result = ((IPNetAddress)resultObj[0]).ToString(true); + // Parse out IPAddresses so we can do a string comparison (ignore subnet masks). + result = resultObj[0].Address.ToString(); } - var intf = nm.GetBindInterface(source, out int? _); + var intf = nm.GetBindAddress(source, out int? _); - Assert.Equal(intf, result); + Assert.Equal(result, intf); } [Theory] @@ -406,39 +287,43 @@ namespace Jellyfin.Networking.Tests [InlineData("185.10.10.10", "185.10.10.10", false)] [InlineData("", "100.100.100.100", false)] - public void HasRemoteAccess_GivenWhitelist_AllowsOnlyIpsInWhitelist(string addresses, string remoteIp, bool denied) + public void HasRemoteAccess_GivenWhitelist_AllowsOnlyIPsInWhitelist(string addresses, string remoteIP, bool denied) { // Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely. // If left blank, all remote addresses will be allowed. var conf = new NetworkConfiguration() { - EnableIPV4 = true, + EnableIPv4 = true, RemoteIPFilter = addresses.Split(','), IsRemoteIPFilterBlacklist = false }; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIp)), denied); + var startupConf = new Mock<IConfiguration>(); + using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); + + Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIP)), denied); } [Theory] [InlineData("185.10.10.10", "79.2.3.4", false)] [InlineData("185.10.10.10", "185.10.10.10", true)] [InlineData("", "100.100.100.100", false)] - public void HasRemoteAccess_GivenBlacklist_BlacklistTheIps(string addresses, string remoteIp, bool denied) + + public void HasRemoteAccess_GivenBlacklist_BlacklistTheIPs(string addresses, string remoteIP, bool denied) { // Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely. // If left blank, all remote addresses will be allowed. var conf = new NetworkConfiguration() { - EnableIPV4 = true, + EnableIPv4 = true, RemoteIPFilter = addresses.Split(','), IsRemoteIPFilterBlacklist = true }; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); - Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIp)), denied); + Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIP)), denied); } [Theory] @@ -450,15 +335,16 @@ namespace Jellyfin.Networking.Tests { var conf = new NetworkConfiguration { - EnableIPV4 = true, + EnableIPv4 = true, LocalNetworkSubnets = lan.Split(','), LocalNetworkAddresses = bind.Split(',') }; NetworkManager.MockNetworkSettings = interfaces; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); - var interfaceToUse = nm.GetBindInterface(string.Empty, out _); + var interfaceToUse = nm.GetBindAddress(string.Empty, out _); Assert.Equal(result, interfaceToUse); } @@ -474,15 +360,16 @@ namespace Jellyfin.Networking.Tests { var conf = new NetworkConfiguration { - EnableIPV4 = true, + EnableIPv4 = true, LocalNetworkSubnets = lan.Split(','), LocalNetworkAddresses = bind.Split(',') }; NetworkManager.MockNetworkSettings = interfaces; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + using var nm = new NetworkManager(NetworkParseTests.GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); - var interfaceToUse = nm.GetBindInterface(source, out _); + var interfaceToUse = nm.GetBindAddress(source, out _); Assert.Equal(result, interfaceToUse); } diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index c12f0cd68..1263043a5 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -7,6 +7,9 @@ </ItemGroup> <ItemGroup> + <PackageReference Include="AutoFixture" /> + <PackageReference Include="AutoFixture.AutoMoq" /> + <PackageReference Include="AutoFixture.Xunit2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> <PackageReference Include="xunit" /> diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 925e8fa19..d5ab6ab4b 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -25,10 +25,13 @@ using Xunit; namespace Jellyfin.Providers.Tests.Manager { - public class ItemImageProviderTests + public partial class ItemImageProviderTests { private const string TestDataImagePath = "Test Data/Images/blank{0}.jpg"; + [GeneratedRegex("[0-9]+")] + private static partial Regex NumbersRegex(); + [Fact] public void ValidateImages_PhotoEmptyProviders_NoChange() { @@ -349,11 +352,11 @@ namespace Jellyfin.Providers.Tests.Manager { if (forceRefresh) { - Assert.Matches(@"image url [0-9]", image.Path); + Assert.Matches("image url [0-9]", image.Path); } else { - Assert.DoesNotMatch(@"image url [0-9]", image.Path); + Assert.DoesNotMatch("image url [0-9]", image.Path); } } } @@ -463,7 +466,7 @@ namespace Jellyfin.Providers.Tests.Manager // images from the provider manager are sorted by preference (earlier images are higher priority) so we can verify that low url numbers are chosen foreach (var image in actualImages) { - var index = int.Parse(Regex.Match(image.Path, @"[0-9]+").Value, NumberStyles.Integer, CultureInfo.InvariantCulture); + var index = int.Parse(NumbersRegex().Match(image.Path).ValueSpan, NumberStyles.Integer, CultureInfo.InvariantCulture); Assert.True(index < imageCount); } } diff --git a/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs index 400e30bd6..1e0851993 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs @@ -82,7 +82,7 @@ namespace Jellyfin.Providers.Tests.Manager AddParts(providerManager, metadataServices: servicesList.Select(s => s.Object).ToArray()); var refreshOptions = new MetadataRefreshOptions(Mock.Of<IDirectoryService>(MockBehavior.Strict)); - var actual = await providerManager.RefreshSingleItem(item, refreshOptions, CancellationToken.None).ConfigureAwait(false); + var actual = await providerManager.RefreshSingleItem(item, refreshOptions, CancellationToken.None); Assert.Equal(ItemUpdateType.MetadataDownload, actual); for (var i = 0; i < servicesList.Length; i++) @@ -105,7 +105,7 @@ namespace Jellyfin.Providers.Tests.Manager AddParts(providerManager, metadataServices: servicesList.Select(s => s.Object).ToArray()); var refreshOptions = new MetadataRefreshOptions(Mock.Of<IDirectoryService>(MockBehavior.Strict)); - var actual = await providerManager.RefreshSingleItem(item, refreshOptions, CancellationToken.None).ConfigureAwait(false); + var actual = await providerManager.RefreshSingleItem(item, refreshOptions, CancellationToken.None); var expectedResult = serviceFound ? ItemUpdateType.MetadataDownload : ItemUpdateType.None; Assert.Equal(expectedResult, actual); diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs index 6b2d9021c..2bc686a33 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs @@ -98,9 +98,11 @@ namespace Jellyfin.Providers.Tests.MediaInfo [InlineData(null, null, 1, ImageType.Primary, ImageFormat.Jpg)] // no label, finds primary [InlineData("backdrop", null, 2, ImageType.Backdrop, ImageFormat.Jpg)] // uses label to find index 2, not just pulling first stream [InlineData("cover", null, 2, ImageType.Primary, ImageFormat.Jpg)] // uses label to find index 2, not just pulling first stream + [InlineData(null, "bmp", 1, ImageType.Primary, ImageFormat.Bmp)] + [InlineData(null, "gif", 1, ImageType.Primary, ImageFormat.Gif)] [InlineData(null, "mjpeg", 1, ImageType.Primary, ImageFormat.Jpg)] [InlineData(null, "png", 1, ImageType.Primary, ImageFormat.Png)] - [InlineData(null, "gif", 1, ImageType.Primary, ImageFormat.Gif)] + [InlineData(null, "webp", 1, ImageType.Primary, ImageFormat.Webp)] public async void GetImage_Embedded_ReturnsCorrectSelection(string label, string? codec, int targetIndex, ImageType type, ImageFormat? expectedFormat) { var streams = new List<MediaStream>(); diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs new file mode 100644 index 000000000..76922af8d --- /dev/null +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs @@ -0,0 +1,61 @@ +using System; +using AutoFixture; +using AutoFixture.AutoMoq; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Providers.MediaInfo; +using Moq; +using Xunit; + +namespace Jellyfin.Providers.Tests.MediaInfo; + +public class FFProbeVideoInfoTests +{ + private readonly FFProbeVideoInfo _fFProbeVideoInfo; + + public FFProbeVideoInfoTests() + { + var serverConfiguration = new ServerConfiguration() + { + DummyChapterDuration = (int)TimeSpan.FromMinutes(5).TotalSeconds + }; + var serverConfig = new Mock<IServerConfigurationManager>(); + serverConfig.Setup(c => c.Configuration) + .Returns(serverConfiguration); + + IFixture fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); + fixture.Inject(serverConfig); + _fFProbeVideoInfo = fixture.Create<FFProbeVideoInfo>(); + } + + [Theory] + [InlineData(-1L)] + [InlineData(long.MinValue)] + [InlineData(long.MaxValue)] + public void CreateDummyChapters_InvalidRuntime_ThrowsArgumentException(long? runtime) + { + Assert.Throws<ArgumentException>( + () => _fFProbeVideoInfo.CreateDummyChapters(new Video() + { + RunTimeTicks = runtime + })); + } + + [Theory] + [InlineData(null, 0)] + [InlineData(0L, 0)] + [InlineData(1L, 0)] + [InlineData(TimeSpan.TicksPerMinute * 5, 0)] + [InlineData((TimeSpan.TicksPerMinute * 5) + 1, 1)] + [InlineData(TimeSpan.TicksPerMinute * 50, 10)] + public void CreateDummyChapters_ValidRuntime_CorrectChaptersCount(long? runtime, int chaptersCount) + { + var chapters = _fFProbeVideoInfo.CreateDummyChapters(new Video() + { + RunTimeTicks = runtime + }); + + Assert.Equal(chaptersCount, chapters.Length); + } +} diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs index 6ee4b8ef2..2b3867512 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs @@ -29,7 +29,7 @@ public class MediaInfoResolverTests public const string VideoDirectoryPath = "Test Data/Video"; public const string VideoDirectoryRegex = @"Test Data[/\\]Video"; public const string MetadataDirectoryPath = "library/00/00000000000000000000000000000000"; - public const string MetadataDirectoryRegex = @"library.*"; + public const string MetadataDirectoryRegex = "library.*"; private readonly ILocalizationManager _localizationManager; private readonly MediaInfoResolver _subtitleResolver; @@ -49,7 +49,7 @@ public class MediaInfoResolverTests var englishCultureDto = new CultureDto("English", "English", "en", new[] { "eng" }); var localizationManager = new Mock<ILocalizationManager>(MockBehavior.Loose); - localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex(@"en.*", RegexOptions.IgnoreCase))) + localizationManager.Setup(lm => lm.FindLanguageInfo(It.IsRegex("en.*", RegexOptions.IgnoreCase))) .Returns(englishCultureDto); _localizationManager = localizationManager.Object; @@ -79,7 +79,7 @@ public class MediaInfoResolverTests { // need a media source manager capable of returning something other than file protocol var mediaSourceManager = new Mock<IMediaSourceManager>(); - mediaSourceManager.Setup(m => m.GetPathProtocol(It.IsRegex(@"http.*"))) + mediaSourceManager.Setup(m => m.GetPathProtocol(It.IsRegex("http.*"))) .Returns(MediaProtocol.Http); BaseItem.MediaSourceManager = mediaSourceManager.Object; @@ -186,7 +186,7 @@ public class MediaInfoResolverTests { // need a media source manager capable of returning something other than file protocol var mediaSourceManager = new Mock<IMediaSourceManager>(); - mediaSourceManager.Setup(m => m.GetPathProtocol(It.IsRegex(@"http.*"))) + mediaSourceManager.Setup(m => m.GetPathProtocol(It.IsRegex("http.*"))) .Returns(MediaProtocol.Http); BaseItem.MediaSourceManager = mediaSourceManager.Object; diff --git a/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs b/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs index f01611819..22667ee82 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer [Fact] public void DeserializeWebSocketMessage_SingleSegment_Success() { - var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!); + var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!, null!); var bytes = File.ReadAllBytes("Test Data/HttpServer/ForceKeepAlive.json"); con.DeserializeWebSocketMessage(new ReadOnlySequence<byte>(bytes), out var bytesConsumed); Assert.Equal(109, bytesConsumed); @@ -23,7 +23,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer public void DeserializeWebSocketMessage_MultipleSegments_Success() { const int SplitPos = 64; - var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!); + var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!, null!); var bytes = File.ReadAllBytes("Test Data/HttpServer/ForceKeepAlive.json"); var seg1 = new BufferSegment(new Memory<byte>(bytes, 0, SplitPos)); var seg2 = seg1.Append(new Memory<byte>(bytes, SplitPos, bytes.Length - SplitPos)); @@ -34,7 +34,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer [Fact] public void DeserializeWebSocketMessage_ValidPartial_Success() { - var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!); + var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!, null!); var bytes = File.ReadAllBytes("Test Data/HttpServer/ValidPartial.json"); con.DeserializeWebSocketMessage(new ReadOnlySequence<byte>(bytes), out var bytesConsumed); Assert.Equal(109, bytesConsumed); @@ -43,7 +43,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer [Fact] public void DeserializeWebSocketMessage_Partial_ThrowJsonException() { - var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!); + var con = new WebSocketConnection(new NullLogger<WebSocketConnection>(), null!, null!, null!); var bytes = File.ReadAllBytes("Test Data/HttpServer/Partial.json"); Assert.Throws<JsonException>(() => con.DeserializeWebSocketMessage(new ReadOnlySequence<byte>(bytes), out var bytesConsumed)); } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/IgnorePatternsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/IgnorePatternsTests.cs index 09eb22328..07061cfc7 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/IgnorePatternsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/IgnorePatternsTests.cs @@ -31,6 +31,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library [InlineData("/media/music/Foo B.A.R./epic.flac", false)] [InlineData("/media/music/Foo B.A.R", false)] [InlineData("/media/music/Foo B.A.R.", false)] + [InlineData("/movies/.zfs/snapshot/AutoM-2023-09", true)] public void PathIgnored(string path, bool expected) { Assert.Equal(expected, IgnorePatterns.ShouldIgnore(path)); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs index c33a957e6..1c35eb3f5 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs @@ -48,10 +48,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff/", "/home/jeff", "/home/jeff/myfile.mkv")] [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/jeff's band", "/home/not jeff", "/home/not jeff/consistently inconsistent.mp3")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")] [InlineData("/o", "/o", "/s", "/s")] // regression test for #5977 public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, string? expectedResult) { @@ -78,10 +78,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library [Theory] [InlineData(null, '/', null)] [InlineData(null, '\\', null)] - [InlineData("/home/jeff/myfile.mkv", '\\', "\\home\\jeff\\myfile.mkv")] - [InlineData("C:\\Users\\Jeff\\myfile.mkv", '/', "C:/Users/Jeff/myfile.mkv")] - [InlineData("\\home/jeff\\myfile.mkv", '\\', "\\home\\jeff\\myfile.mkv")] - [InlineData("\\home/jeff\\myfile.mkv", '/', "/home/jeff/myfile.mkv")] + [InlineData("/home/jeff/myfile.mkv", '\\', @"\home\jeff\myfile.mkv")] + [InlineData(@"C:\Users\Jeff\myfile.mkv", '/', "C:/Users/Jeff/myfile.mkv")] + [InlineData(@"\home/jeff\myfile.mkv", '\\', @"\home\jeff\myfile.mkv")] + [InlineData(@"\home/jeff\myfile.mkv", '/', "/home/jeff/myfile.mkv")] [InlineData("", '/', "")] public void NormalizePath_SpecifyingSeparator_Normalizes(string path, char separator, string expectedPath) { @@ -90,8 +90,8 @@ namespace Jellyfin.Server.Implementations.Tests.Library [Theory] [InlineData("/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\Jeff\\myfile.mkv")] - [InlineData("\\home/jeff\\myfile.mkv")] + [InlineData(@"C:\Users\Jeff\myfile.mkv")] + [InlineData(@"\home/jeff\myfile.mkv")] public void NormalizePath_NoArgs_UsesDirectorySeparatorChar(string path) { var separator = Path.DirectorySeparatorChar; @@ -101,8 +101,8 @@ namespace Jellyfin.Server.Implementations.Tests.Library [Theory] [InlineData("/home/jeff/myfile.mkv", '/')] - [InlineData("C:\\Users\\Jeff\\myfile.mkv", '\\')] - [InlineData("\\home/jeff\\myfile.mkv", '/')] + [InlineData(@"C:\Users\Jeff\myfile.mkv", '\\')] + [InlineData(@"\home/jeff\myfile.mkv", '/')] public void NormalizePath_OutVar_Correct(string path, char expectedSeparator) { var result = path.NormalizePath(out var separator); diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs index c859d11c6..13ac3ddb0 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs @@ -52,7 +52,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Url = "192.168.1.182" }; - var modelInfo = await _hdHomerunHost.GetModelInfo(host, true, CancellationToken.None).ConfigureAwait(false); + var modelInfo = await _hdHomerunHost.GetModelInfo(host, true, CancellationToken.None); Assert.Equal("HDHomeRun PRIME", modelInfo.FriendlyName); Assert.Equal("HDHR3-CC", modelInfo.ModelNumber); Assert.Equal("hdhomerun3_cablecard", modelInfo.FirmwareName); @@ -72,7 +72,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Url = "10.10.10.100" }; - var modelInfo = await _hdHomerunHost.GetModelInfo(host, true, CancellationToken.None).ConfigureAwait(false); + var modelInfo = await _hdHomerunHost.GetModelInfo(host, true, CancellationToken.None); Assert.Equal("HDHomeRun DUAL", modelInfo.FriendlyName); Assert.Equal("HDHR3-US", modelInfo.ModelNumber); Assert.Equal("hdhomerun3_atsc", modelInfo.FirmwareName); @@ -103,7 +103,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv Url = "192.168.1.182" }; - var channels = await _hdHomerunHost.GetLineup(host, CancellationToken.None).ConfigureAwait(false); + var channels = await _hdHomerunHost.GetLineup(host, CancellationToken.None); Assert.Equal(6, channels.Count); Assert.Equal("4.1", channels[0].GuideNumber); Assert.Equal("WCMH-DT", channels[0].GuideName); @@ -133,7 +133,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv ImportFavoritesOnly = true }; - var channels = await _hdHomerunHost.GetLineup(host, CancellationToken.None).ConfigureAwait(false); + var channels = await _hdHomerunHost.GetLineup(host, CancellationToken.None); Assert.Single(channels); Assert.Equal("4.1", channels[0].GuideNumber); Assert.Equal("WCMH-DT", channels[0].GuideName); @@ -145,7 +145,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv [Fact] public async Task TryGetTunerHostInfo_Valid_Success() { - var host = await _hdHomerunHost.TryGetTunerHostInfo("192.168.1.182", CancellationToken.None).ConfigureAwait(false); + var host = await _hdHomerunHost.TryGetTunerHostInfo("192.168.1.182", CancellationToken.None); Assert.Equal(_hdHomerunHost.Type, host.Type); Assert.Equal("192.168.1.182", host.Url); Assert.Equal("HDHomeRun PRIME", host.FriendlyName); diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs index e1d2bb2d5..d4f28f327 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs @@ -96,7 +96,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect var days = JsonSerializer.Deserialize<IReadOnlyList<DayDto>>(bytes, _jsonOptions); Assert.NotNull(days); - Assert.Equal(1, days!.Count); + Assert.Single(days); var dayDto = days[0]; Assert.Equal("20454", dayDto.StationId); @@ -110,7 +110,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect Assert.Equal(2, dayDto.Programs[0].AudioProperties.Count); Assert.Equal("stereo", dayDto.Programs[0].AudioProperties[0]); Assert.Equal("cc", dayDto.Programs[0].AudioProperties[1]); - Assert.Equal(1, dayDto.Programs[0].VideoProperties.Count); + Assert.Single(dayDto.Programs[0].VideoProperties); Assert.Equal("hdtv", dayDto.Programs[0].VideoProperties[0]); } @@ -126,13 +126,13 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect Assert.NotNull(programDtos); Assert.Equal(2, programDtos!.Count); Assert.Equal("EP000000060003", programDtos[0].ProgramId); - Assert.Equal(1, programDtos[0].Titles.Count); + Assert.Single(programDtos[0].Titles); Assert.Equal("'Allo 'Allo!", programDtos[0].Titles[0].Title120); Assert.Equal("Series", programDtos[0].EventDetails?.SubType); Assert.Equal("en", programDtos[0].Descriptions?.Description1000[0].DescriptionLanguage); Assert.Equal("A disguised British Intelligence officer is sent to help the airmen.", programDtos[0].Descriptions?.Description1000[0].Description); Assert.Equal(new DateTime(1985, 11, 04), programDtos[0].OriginalAirDate); - Assert.Equal(1, programDtos[0].Genres.Count); + Assert.Single(programDtos[0].Genres); Assert.Equal("Sitcom", programDtos[0].Genres[0]); Assert.Equal("The Poloceman Cometh", programDtos[0].EpisodeTitle150); Assert.Equal(2, programDtos[0].Metadata[0].Gracenote?.Season); @@ -161,7 +161,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect var showImagesDtos = JsonSerializer.Deserialize<IReadOnlyList<ShowImagesDto>>(bytes, _jsonOptions); Assert.NotNull(showImagesDtos); - Assert.Equal(1, showImagesDtos!.Count); + Assert.Single(showImagesDtos!); Assert.Equal("SH00712240", showImagesDtos[0].ProgramId); Assert.Equal(4, showImagesDtos[0].Data.Count); Assert.Equal("135", showImagesDtos[0].Data[0].Width); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs index 7fabe9904..09e4709da 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs @@ -100,7 +100,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization await localizationManager.LoadAll(); var ratings = localizationManager.GetParentalRatings().ToList(); - Assert.Equal(19, ratings.Count); + Assert.Equal(24, ratings.Count); var fsk = ratings.FirstOrDefault(x => x.Name.Equals("FSK-12", StringComparison.Ordinal)); Assert.NotNull(fsk); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs index d4b90dac0..934024826 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs @@ -119,8 +119,8 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins [InlineData("C:\\some.dll")] // Windows root path. [InlineData("test.txt")] // Not a DLL [InlineData(".././.././../some.dll")] // Traversal with current and parent - [InlineData("..\\.\\..\\.\\..\\some.dll")] // Windows traversal with current and parent - [InlineData("\\\\network\\resource.dll")] // UNC Path + [InlineData(@"..\.\..\.\..\some.dll")] // Windows traversal with current and parent + [InlineData(@"\\network\resource.dll")] // UNC Path [InlineData("https://jellyfin.org/some.dll")] // URL [InlineData("~/some.dll")] // Tilde poses a shell expansion risk, but is a valid path character. public void Constructor_DiscoversUnsafePluginAssembly_Status_Malfunctioned(string unsafePath) @@ -191,13 +191,13 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins }; var metafilePath = Path.Combine(_pluginPath, "meta.json"); - File.WriteAllText(metafilePath, JsonSerializer.Serialize(partial, _options)); + await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options)); var pluginManager = new PluginManager(new NullLogger<PluginManager>(), null!, null!, _tempPath, new Version(1, 0)); await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); - var resultBytes = File.ReadAllBytes(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); @@ -231,7 +231,7 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); var metafilePath = Path.Combine(_pluginPath, "meta.json"); - var resultBytes = File.ReadAllBytes(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); @@ -251,13 +251,13 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins }; var metafilePath = Path.Combine(_pluginPath, "meta.json"); - File.WriteAllText(metafilePath, JsonSerializer.Serialize(partial, _options)); + await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options)); var pluginManager = new PluginManager(new NullLogger<PluginManager>(), null!, null!, _tempPath, new Version(1, 0)); await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); - var resultBytes = File.ReadAllBytes(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); @@ -277,13 +277,13 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins }; var metafilePath = Path.Combine(_pluginPath, "meta.json"); - File.WriteAllText(metafilePath, JsonSerializer.Serialize(partial, _options)); + await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options)); var pluginManager = new PluginManager(new NullLogger<PluginManager>(), null!, null!, _tempPath, new Version(1, 0)); await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); - var resultBytes = File.ReadAllBytes(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs index 7abd2e685..5caf7d124 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs @@ -90,7 +90,7 @@ namespace Jellyfin.Server.Implementations.Tests.Updates Checksum = "InvalidChecksum" }; - await Assert.ThrowsAsync<InvalidDataException>(() => _installationManager.InstallPackage(packageInfo, CancellationToken.None)).ConfigureAwait(false); + await Assert.ThrowsAsync<InvalidDataException>(() => _installationManager.InstallPackage(packageInfo, CancellationToken.None)); } [Fact] @@ -103,7 +103,7 @@ namespace Jellyfin.Server.Implementations.Tests.Updates Checksum = "11b5b2f1a9ebc4f66d6ef19018543361" }; - var ex = await Record.ExceptionAsync(() => _installationManager.InstallPackage(packageInfo, CancellationToken.None)).ConfigureAwait(false); + var ex = await Record.ExceptionAsync(() => _installationManager.InstallPackage(packageInfo, CancellationToken.None)); Assert.Null(ex); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs index 3737fee0a..4e8aec9f1 100644 --- a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs +++ b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs @@ -15,41 +15,41 @@ namespace Jellyfin.Server.Integration.Tests { public static class AuthHelper { - public const string AuthHeaderName = "X-Emby-Authorization"; - public const string DummyAuthHeader = "MediaBrowser Client=\"Jellyfin.Server Integration Tests\", DeviceId=\"69420\", Device=\"Apple II\", Version=\"10.8.0\""; + public const string AuthHeaderName = "Authorization"; + public const string DummyAuthHeader = "MediaBrowser Client=\"Jellyfin.Server%20Integration%20Tests\", DeviceId=\"69420\", Device=\"Apple%20II\", Version=\"10.8.0\""; public static async Task<string> CompleteStartupAsync(HttpClient client) { var jsonOptions = JsonDefaults.Options; - var userResponse = await client.GetByteArrayAsync("/Startup/User").ConfigureAwait(false); + var userResponse = await client.GetByteArrayAsync("/Startup/User"); var user = JsonSerializer.Deserialize<StartupUserDto>(userResponse, jsonOptions); - using var completeResponse = await client.PostAsync("/Startup/Complete", new ByteArrayContent(Array.Empty<byte>())).ConfigureAwait(false); + using var completeResponse = await client.PostAsync("/Startup/Complete", new ByteArrayContent(Array.Empty<byte>())); Assert.Equal(HttpStatusCode.NoContent, completeResponse.StatusCode); - using var content = JsonContent.Create( + using var httpRequest = new HttpRequestMessage(HttpMethod.Post, "/Users/AuthenticateByName"); + httpRequest.Headers.TryAddWithoutValidation(AuthHeaderName, DummyAuthHeader); + httpRequest.Content = JsonContent.Create( new AuthenticateUserByName() { Username = user!.Name, Pw = user.Password, }, options: jsonOptions); - content.Headers.Add("X-Emby-Authorization", DummyAuthHeader); - using var authResponse = await client.PostAsync("/Users/AuthenticateByName", content).ConfigureAwait(false); - var auth = await JsonSerializer.DeserializeAsync<AuthenticationResultDto>( - await authResponse.Content.ReadAsStreamAsync().ConfigureAwait(false), - jsonOptions).ConfigureAwait(false); + using var authResponse = await client.SendAsync(httpRequest); + authResponse.EnsureSuccessStatusCode(); + + var auth = await authResponse.Content.ReadFromJsonAsync<AuthenticationResultDto>(jsonOptions); return auth!.AccessToken; } public static async Task<UserDto> GetUserDtoAsync(HttpClient client) { - using var response = await client.GetAsync("Users/Me").ConfigureAwait(false); + using var response = await client.GetAsync("Users/Me"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var userDto = await JsonSerializer.DeserializeAsync<UserDto>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), JsonDefaults.Options).ConfigureAwait(false); + var userDto = await response.Content.ReadFromJsonAsync<UserDto>(JsonDefaults.Options); Assert.NotNull(userDto); return userDto; } @@ -58,15 +58,13 @@ namespace Jellyfin.Server.Integration.Tests { if (userId.Equals(default)) { - var userDto = await GetUserDtoAsync(client).ConfigureAwait(false); + var userDto = await GetUserDtoAsync(client); userId = userDto.Id; } - var response = await client.GetAsync($"Users/{userId}/Items/Root").ConfigureAwait(false); + var response = await client.GetAsync($"Users/{userId}/Items/Root"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await JsonSerializer.DeserializeAsync<BaseItemDto>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - JsonDefaults.Options).ConfigureAwait(false); + var rootDto = await response.Content.ReadFromJsonAsync<BaseItemDto>(JsonDefaults.Options); Assert.NotNull(rootDto); return rootDto; } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs index be89fbc9a..96ca96558 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs @@ -19,9 +19,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task ActivityLog_GetEntries_Ok() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("System/ActivityLog/Entries").ConfigureAwait(false); + var response = await client.GetAsync("System/ActivityLog/Entries"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs index 87136dfc8..8761cf69b 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs @@ -1,4 +1,5 @@ using System.Net; +using System.Net.Http.Json; using System.Net.Mime; using System.Text; using System.Text.Json; @@ -30,8 +31,7 @@ namespace Jellyfin.Server.Integration.Tests Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var responseBody = await response.Content.ReadAsStreamAsync(); - _ = await JsonSerializer.DeserializeAsync<BrandingOptions>(responseBody); + await response.Content.ReadFromJsonAsync<BrandingOptions>(); } [Theory] diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index 52df1cd60..39d449e27 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -1,5 +1,6 @@ using System.IO; using System.Net; +using System.Net.Http.Json; using System.Net.Mime; using System.Text; using System.Text.Json; @@ -26,7 +27,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.GetAsync("web/ConfigurationPage?name=ThisPageDoesntExists").ConfigureAwait(false); + var response = await client.GetAsync("web/ConfigurationPage?name=ThisPageDoesntExists"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -36,12 +37,12 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.GetAsync("/web/ConfigurationPage?name=TestPlugin").ConfigureAwait(false); + var response = await client.GetAsync("/web/ConfigurationPage?name=TestPlugin"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Text.Html, response.Content.Headers.ContentType?.MediaType); StreamReader reader = new StreamReader(typeof(TestPlugin).Assembly.GetManifestResourceStream("Jellyfin.Server.Integration.Tests.TestPage.html")!); - Assert.Equal(await response.Content.ReadAsStringAsync().ConfigureAwait(false), await reader.ReadToEndAsync().ConfigureAwait(false)); + Assert.Equal(await response.Content.ReadAsStringAsync(), await reader.ReadToEndAsync()); } [Fact] @@ -49,7 +50,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.GetAsync("/web/ConfigurationPage?name=BrokenPage").ConfigureAwait(false); + var response = await client.GetAsync("/web/ConfigurationPage?name=BrokenPage"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -58,14 +59,13 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task GetConfigurationPages_NoParams_AllConfigurationPages() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("/web/ConfigurationPages").ConfigureAwait(false); + var response = await client.GetAsync("/web/ConfigurationPages"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var res = await response.Content.ReadAsStreamAsync(); - _ = await JsonSerializer.DeserializeAsync<ConfigurationPageInfo[]>(res, _jsonOpions); + _ = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOpions); // TODO: check content } @@ -73,16 +73,15 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task GetConfigurationPages_True_MainMenuConfigurationPages() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("/web/ConfigurationPages?enableInMainMenu=true").ConfigureAwait(false); + var response = await client.GetAsync("/web/ConfigurationPages?enableInMainMenu=true"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var res = await response.Content.ReadAsStreamAsync(); - var data = await JsonSerializer.DeserializeAsync<ConfigurationPageInfo[]>(res, _jsonOpions); + var data = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOpions); Assert.NotNull(data); Assert.Empty(data); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs index a65f65bb2..e5d5e785c 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs @@ -32,9 +32,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task GetProfile_DoesNotExist_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false); + using var response = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -43,9 +43,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task DeleteProfile_DoesNotExist_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false); + using var response = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -54,14 +54,14 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task UpdateProfile_DoesNotExist_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); var deviceProfile = new DeviceProfile() { Name = "ThisProfileDoesNotExist" }; - using var response = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions).ConfigureAwait(false); + using var response = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -70,14 +70,14 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task CreateProfile_Valid_NoContent() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); var deviceProfile = new DeviceProfile() { Name = "ThisProfileIsNew" }; - using var response = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions).ConfigureAwait(false); + using var response = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); } @@ -86,16 +86,14 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task GetProfileInfos_Valid_ContainsThisProfileIsNew() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false); + using var response = await client.GetAsync("/Dlna/ProfileInfos"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - _jsonOptions).ConfigureAwait(false); + var profiles = await response.Content.ReadFromJsonAsync<DeviceProfileInfo[]>(_jsonOptions); var newProfile = profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsNew", StringComparison.Ordinal)); Assert.NotNull(newProfile); @@ -107,7 +105,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task UpdateProfile_Valid_NoContent() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); var updatedProfile = new DeviceProfile() { @@ -115,18 +113,16 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Id = _newDeviceProfileId }; - using var postResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + _newDeviceProfileId, updatedProfile, _jsonOptions).ConfigureAwait(false); + using var postResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + _newDeviceProfileId, updatedProfile, _jsonOptions); Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode); // Verify that the profile got updated - using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false); + using var response = await client.GetAsync("/Dlna/ProfileInfos"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - _jsonOptions).ConfigureAwait(false); + var profiles = await response.Content.ReadFromJsonAsync<DeviceProfileInfo[]>(_jsonOptions); Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsNew", StringComparison.Ordinal))); var newProfile = profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal)); @@ -139,20 +135,18 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task DeleteProfile_Valid_NoContent() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var deleteResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId).ConfigureAwait(false); + using var deleteResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId); Assert.Equal(HttpStatusCode.NoContent, deleteResponse.StatusCode); // Verify that the profile got deleted - using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false); + using var response = await client.GetAsync("/Dlna/ProfileInfos"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - _jsonOptions).ConfigureAwait(false); + var profiles = await response.Content.ReadFromJsonAsync<DeviceProfileInfo[]>(_jsonOptions); Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal))); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs index 078002994..23de2489e 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Net; +using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Extensions.Json; @@ -25,9 +26,9 @@ public sealed class ItemsControllerTests : IClassFixture<JellyfinApplicationFact public async Task GetItems_NoApiKeyOrUserId_Success() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Items").ConfigureAwait(false); + var response = await client.GetAsync("Items"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } @@ -37,9 +38,9 @@ public sealed class ItemsControllerTests : IClassFixture<JellyfinApplicationFact public async Task GetUserItems_NonExistentUserId_NotFound(string format) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())).ConfigureAwait(false); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -50,15 +51,13 @@ public sealed class ItemsControllerTests : IClassFixture<JellyfinApplicationFact public async Task GetItems_UserId_Ok(string format) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var userDto = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); + var userDto = await AuthHelper.GetUserDtoAsync(client); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id)).ConfigureAwait(false); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id)); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var items = await JsonSerializer.DeserializeAsync<QueryResult<BaseItemDto>>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - _jsonOptions).ConfigureAwait(false); + var items = await response.Content.ReadFromJsonAsync<QueryResult<BaseItemDto>>(_jsonOptions); Assert.NotNull(items); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs index 8998683a7..06abae14c 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs @@ -32,9 +32,9 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa public async Task Get_NonExistentItemId_NotFound(string format) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())).ConfigureAwait(false); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -45,7 +45,7 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa { var client = _factory.CreateClient(); - var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())).ConfigureAwait(false); + var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } @@ -55,9 +55,9 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa public async Task Delete_NonExistentItemId_NotFound(string format) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())).ConfigureAwait(false); + var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs index 34d26680a..abc8b6009 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs @@ -20,9 +20,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task BitrateTest_Default_Ok() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Playback/BitrateTest").ConfigureAwait(false); + var response = await client.GetAsync("Playback/BitrateTest"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); @@ -34,9 +34,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task BitrateTest_WithValidParam_Ok(int size) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false); + var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); @@ -51,9 +51,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task BitrateTest_InvalidValue_BadRequest(int size) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false); + var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs index 24251013c..6699c6834 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs @@ -26,10 +26,10 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task RenameVirtualFolder_WhiteSpaceName_ReturnsBadRequest() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); using var postContent = new ByteArrayContent(Array.Empty<byte>()); - var response = await client.PostAsync("Library/VirtualFolders/Name?name=+&newName=test", postContent).ConfigureAwait(false); + var response = await client.PostAsync("Library/VirtualFolders/Name?name=+&newName=test", postContent); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -38,10 +38,10 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task RenameVirtualFolder_WhiteSpaceNewName_ReturnsBadRequest() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); using var postContent = new ByteArrayContent(Array.Empty<byte>()); - var response = await client.PostAsync("Library/VirtualFolders/Name?name=test&newName=+", postContent).ConfigureAwait(false); + var response = await client.PostAsync("Library/VirtualFolders/Name?name=test&newName=+", postContent); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -50,10 +50,10 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task RenameVirtualFolder_NameDoesntExist_ReturnsNotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); using var postContent = new ByteArrayContent(Array.Empty<byte>()); - var response = await client.PostAsync("Library/VirtualFolders/Name?name=doesnt+exist&newName=test", postContent).ConfigureAwait(false); + var response = await client.PostAsync("Library/VirtualFolders/Name?name=doesnt+exist&newName=test", postContent); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -62,7 +62,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task AddMediaPath_PathDoesntExist_ReturnsNotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); var data = new MediaPathDto() { @@ -70,7 +70,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Path = "/this/path/doesnt/exist" }; - var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths", data, _jsonOptions).ConfigureAwait(false); + var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths", data, _jsonOptions); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -79,7 +79,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task UpdateMediaPath_WhiteSpaceName_ReturnsBadRequest() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); var data = new UpdateMediaPathRequestDto() { @@ -87,7 +87,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers PathInfo = new MediaPathInfo("test") }; - var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths/Update", data, _jsonOptions).ConfigureAwait(false); + var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths/Update", data, _jsonOptions); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -96,9 +96,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task RemoveMediaPath_WhiteSpaceName_ReturnsBadRequest() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=+").ConfigureAwait(false); + var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=+"); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -107,9 +107,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task RemoveMediaPath_PathDoesntExist_ReturnsNotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=none&path=%2Fthis%2Fpath%2Fdoesnt%2Fexist").ConfigureAwait(false); + var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=none&path=%2Fthis%2Fpath%2Fdoesnt%2Fexist"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs index 17f3dc99f..f9982cf12 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs @@ -18,9 +18,9 @@ public sealed class MusicGenreControllerTests : IClassFixture<JellyfinApplicatio public async Task MusicGenres_FakeMusicGenre_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("MusicGenres/Fake-MusicGenre").ConfigureAwait(false); + var response = await client.GetAsync("MusicGenres/Fake-MusicGenre"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs new file mode 100644 index 000000000..38c64547c --- /dev/null +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs @@ -0,0 +1,26 @@ +using System.Net; +using System.Threading.Tasks; +using Xunit; + +namespace Jellyfin.Server.Integration.Tests.Controllers; + +public class PersonsControllerTests : IClassFixture<JellyfinApplicationFactory> +{ + private readonly JellyfinApplicationFactory _factory; + private static string? _accessToken; + + public PersonsControllerTests(JellyfinApplicationFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task GetPerson_DoesntExist_NotFound() + { + var client = _factory.CreateClient(); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); + + using var response = await client.GetAsync($"Persons/DoesntExist"); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } +} diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs index 868ecd53f..9554d3ebc 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs @@ -19,9 +19,9 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory public async Task DeleteMarkUnplayedItem_NonExistentUserId_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.DeleteAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}").ConfigureAwait(false); + using var response = await client.DeleteAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -29,9 +29,9 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory public async Task PostMarkPlayedItem_NonExistentUserId_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.PostAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}", null).ConfigureAwait(false); + using var response = await client.PostAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}", null); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -39,11 +39,11 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory public async Task DeleteMarkUnplayedItem_NonExistentItemId_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var userDto = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); + var userDto = await AuthHelper.GetUserDtoAsync(client); - using var response = await client.DeleteAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}").ConfigureAwait(false); + using var response = await client.DeleteAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -51,11 +51,11 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory public async Task PostMarkPlayedItem_NonExistentItemId_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var userDto = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); + var userDto = await AuthHelper.GetUserDtoAsync(client); - using var response = await client.PostAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}", null).ConfigureAwait(false); + using var response = await client.PostAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}", null); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs index cb0a829e8..b9def13f8 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs @@ -19,9 +19,9 @@ public class SessionControllerTests : IClassFixture<JellyfinApplicationFactory> public async Task GetSessions_NonExistentUserId_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.GetAsync($"Session/Sessions?userId={Guid.NewGuid()}").ConfigureAwait(false); + using var response = await client.GetAsync($"Session/Sessions?userId={Guid.NewGuid()}"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs index 0dd22644a..36861294b 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs @@ -36,15 +36,14 @@ namespace Jellyfin.Server.Integration.Tests.Controllers PreferredMetadataLanguage = "nl" }; - using var postResponse = await client.PostAsJsonAsync("/Startup/Configuration", config, _jsonOptions).ConfigureAwait(false); + using var postResponse = await client.PostAsJsonAsync("/Startup/Configuration", config, _jsonOptions); Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode); - using var getResponse = await client.GetAsync("/Startup/Configuration").ConfigureAwait(false); + using var getResponse = await client.GetAsync("/Startup/Configuration"); Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, getResponse.Content.Headers.ContentType?.MediaType); - using var responseStream = await getResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); - var newConfig = await JsonSerializer.DeserializeAsync<StartupConfigurationDto>(responseStream, _jsonOptions).ConfigureAwait(false); + var newConfig = await getResponse.Content.ReadFromJsonAsync<StartupConfigurationDto>(_jsonOptions); Assert.Equal(config.UICulture, newConfig!.UICulture); Assert.Equal(config.MetadataCountryCode, newConfig.MetadataCountryCode); Assert.Equal(config.PreferredMetadataLanguage, newConfig.PreferredMetadataLanguage); @@ -56,12 +55,11 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - using var response = await client.GetAsync("/Startup/User").ConfigureAwait(false); + using var response = await client.GetAsync("/Startup/User"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); - using var contentStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - var user = await JsonSerializer.DeserializeAsync<StartupUserDto>(contentStream, _jsonOptions).ConfigureAwait(false); + var user = await response.Content.ReadFromJsonAsync<StartupUserDto>(_jsonOptions); Assert.NotNull(user); Assert.NotNull(user.Name); Assert.NotEmpty(user.Name); @@ -80,15 +78,14 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Password = "NewPassword" }; - var postResponse = await client.PostAsJsonAsync("/Startup/User", user, _jsonOptions).ConfigureAwait(false); + var postResponse = await client.PostAsJsonAsync("/Startup/User", user, _jsonOptions); Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode); - var getResponse = await client.GetAsync("/Startup/User").ConfigureAwait(false); + var getResponse = await client.GetAsync("/Startup/User"); Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, getResponse.Content.Headers.ContentType?.MediaType); - var contentStream = await getResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); - var newUser = await JsonSerializer.DeserializeAsync<StartupUserDto>(contentStream, _jsonOptions).ConfigureAwait(false); + var newUser = await getResponse.Content.ReadFromJsonAsync<StartupUserDto>(_jsonOptions); Assert.NotNull(newUser); Assert.Equal(user.Name, newUser.Name); Assert.NotNull(newUser.Password); @@ -102,7 +99,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.PostAsync("/Startup/Complete", new ByteArrayContent(Array.Empty<byte>())).ConfigureAwait(false); + var response = await client.PostAsync("/Startup/Complete", new ByteArrayContent(Array.Empty<byte>())); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); } @@ -112,7 +109,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - using var response = await client.GetAsync("/Startup/User").ConfigureAwait(false); + using var response = await client.GetAsync("/Startup/User"); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs index 2a3c53dbe..4fcacd2ca 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs @@ -41,10 +41,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - using var response = await client.GetAsync("Users/Public").ConfigureAwait(false); + using var response = await client.GetAsync("Users/Public"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await JsonSerializer.DeserializeAsync<UserDto[]>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), _jsonOpions).ConfigureAwait(false); + var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOpions); // User are hidden by default Assert.NotNull(users); Assert.Empty(users); @@ -55,12 +54,11 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task GetUsers_Valid_Success() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.GetAsync("Users").ConfigureAwait(false); + using var response = await client.GetAsync("Users"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await JsonSerializer.DeserializeAsync<UserDto[]>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), _jsonOpions).ConfigureAwait(false); + var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOpions); Assert.NotNull(users); Assert.Single(users); Assert.False(users![0].HasConfiguredPassword); @@ -71,9 +69,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public async Task Me_Valid_Success() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - _ = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); + _ = await AuthHelper.GetUserDtoAsync(client); } [Fact] @@ -90,10 +88,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Name = TestUsername }; - using var response = await CreateUserByName(client, createRequest).ConfigureAwait(false); + using var response = await CreateUserByName(client, createRequest); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var user = await JsonSerializer.DeserializeAsync<UserDto>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), _jsonOpions).ConfigureAwait(false); + var user = await response.Content.ReadFromJsonAsync<UserDto>(_jsonOpions); Assert.Equal(TestUsername, user!.Name); Assert.False(user.HasPassword); Assert.False(user.HasConfiguredPassword); @@ -121,7 +118,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Name = username! }; - using var response = await CreateUserByName(client, createRequest).ConfigureAwait(false); + using var response = await CreateUserByName(client, createRequest); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -134,7 +131,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers // access token can't be null here as the previous test populated it client.DefaultRequestHeaders.AddAuthHeader(_accessToken!); - using var response = await client.DeleteAsync($"User/{Guid.NewGuid()}").ConfigureAwait(false); + using var response = await client.DeleteAsync($"User/{Guid.NewGuid()}"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -150,11 +147,11 @@ namespace Jellyfin.Server.Integration.Tests.Controllers NewPw = "4randomPa$$word" }; - using var response = await UpdateUserPassword(client, _testUserId, createRequest).ConfigureAwait(false); + using var response = await UpdateUserPassword(client, _testUserId, createRequest); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); var users = await JsonSerializer.DeserializeAsync<UserDto[]>( - await client.GetStreamAsync("Users").ConfigureAwait(false), _jsonOpions).ConfigureAwait(false); + await client.GetStreamAsync("Users"), _jsonOpions); var user = users!.First(x => x.Id.Equals(_testUserId)); Assert.True(user.HasPassword); Assert.True(user.HasConfiguredPassword); @@ -173,11 +170,11 @@ namespace Jellyfin.Server.Integration.Tests.Controllers CurrentPw = "4randomPa$$word", }; - using var response = await UpdateUserPassword(client, _testUserId, createRequest).ConfigureAwait(false); + using var response = await UpdateUserPassword(client, _testUserId, createRequest); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); var users = await JsonSerializer.DeserializeAsync<UserDto[]>( - await client.GetStreamAsync("Users").ConfigureAwait(false), _jsonOpions).ConfigureAwait(false); + await client.GetStreamAsync("Users"), _jsonOpions); var user = users!.First(x => x.Id.Equals(_testUserId)); Assert.False(user.HasPassword); Assert.False(user.HasConfiguredPassword); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs index 69f2ccf33..130281c6d 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Net; +using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Extensions.Json; @@ -25,9 +26,9 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati public async Task GetRootFolder_NonExistenUserId_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync($"Users/{Guid.NewGuid()}/Items/Root").ConfigureAwait(false); + var response = await client.GetAsync($"Users/{Guid.NewGuid()}/Items/Root"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -35,9 +36,9 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati public async Task GetRootFolder_UserId_Valid() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - _ = await AuthHelper.GetRootFolderDtoAsync(client).ConfigureAwait(false); + _ = await AuthHelper.GetRootFolderDtoAsync(client); } [Theory] @@ -49,11 +50,11 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati public async Task GetItem_NonExistenUserId_NotFound(string format) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client).ConfigureAwait(false); + var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid(), rootFolderDto.Id)).ConfigureAwait(false); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid(), rootFolderDto.Id)); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -66,11 +67,11 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati public async Task GetItem_NonExistentItemId_NotFound(string format) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var userDto = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); + var userDto = await AuthHelper.GetUserDtoAsync(client); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, Guid.NewGuid())).ConfigureAwait(false); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, Guid.NewGuid())); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -78,16 +79,14 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati public async Task GetItem_UserIdAndItemId_Valid() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var userDto = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); - var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id).ConfigureAwait(false); + var userDto = await AuthHelper.GetUserDtoAsync(client); + var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id); - var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}").ConfigureAwait(false); + var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await JsonSerializer.DeserializeAsync<BaseItemDto>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - _jsonOptions).ConfigureAwait(false); + var rootDto = await response.Content.ReadFromJsonAsync<BaseItemDto>(_jsonOptions); Assert.NotNull(rootDto); } @@ -95,16 +94,14 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati public async Task GetIntros_UserIdAndItemId_Valid() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var userDto = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); - var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id).ConfigureAwait(false); + var userDto = await AuthHelper.GetUserDtoAsync(client); + var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id); - var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}/Intros").ConfigureAwait(false); + var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}/Intros"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await JsonSerializer.DeserializeAsync<QueryResult<BaseItemDto>>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - _jsonOptions).ConfigureAwait(false); + var rootDto = await response.Content.ReadFromJsonAsync<QueryResult<BaseItemDto>>(_jsonOptions); Assert.NotNull(rootDto); } @@ -114,16 +111,14 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati public async Task LocalTrailersAndSpecialFeatures_UserIdAndItemId_Valid(string format) { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var userDto = await AuthHelper.GetUserDtoAsync(client).ConfigureAwait(false); - var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id).ConfigureAwait(false); + var userDto = await AuthHelper.GetUserDtoAsync(client); + var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, rootFolderDto.Id)).ConfigureAwait(false); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, rootFolderDto.Id)); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await JsonSerializer.DeserializeAsync<BaseItemDto[]>( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), - _jsonOptions).ConfigureAwait(false); + var rootDto = await response.Content.ReadFromJsonAsync<BaseItemDto[]>(_jsonOptions); Assert.NotNull(rootDto); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs index 0f9a2e90a..47bec5d79 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs @@ -19,9 +19,9 @@ public sealed class VideosControllerTests : IClassFixture<JellyfinApplicationFac public async Task DeleteAlternateSources_NonExistentItemId_NotFound() { var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false)); + client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync($"Videos/{Guid.NewGuid()}").ConfigureAwait(false); + var response = await client.DeleteAsync($"Videos/{Guid.NewGuid()}"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs index 2361e4aa4..d2249cdc3 100644 --- a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs +++ b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs @@ -27,9 +27,9 @@ namespace Jellyfin.Server.Integration.Tests { var client = _factory.CreateClient(); - var response = await client.GetAsync("Encoder/UrlDecode?" + sourceUrl).ConfigureAwait(false); + var response = await client.GetAsync("Encoder/UrlDecode?" + sourceUrl); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - string reply = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + string reply = await response.Content.ReadAsStringAsync(); Assert.Equal(unencodedUrl, reply); } @@ -40,9 +40,9 @@ namespace Jellyfin.Server.Integration.Tests { var client = _factory.CreateClient(); - var response = await client.GetAsync("Encoder/UrlArrayDecode?" + sourceUrl).ConfigureAwait(false); + var response = await client.GetAsync("Encoder/UrlArrayDecode?" + sourceUrl); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - string reply = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + string reply = await response.Content.ReadAsStringAsync(); Assert.Equal(unencodedUrl, reply); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs index 55bc43455..1c87d11f1 100644 --- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Concurrent; using System.Globalization; using System.IO; -using System.Threading; using Emby.Server.Implementations; using Jellyfin.Server.Extensions; using Jellyfin.Server.Helpers; @@ -105,7 +104,7 @@ namespace Jellyfin.Server.Integration.Tests var appHost = (TestAppHost)testServer.Services.GetRequiredService<IApplicationHost>(); appHost.ServiceProvider = testServer.Services; appHost.InitializeServices().GetAwaiter().GetResult(); - appHost.RunStartupTasksAsync(CancellationToken.None).GetAwaiter().GetResult(); + appHost.RunStartupTasksAsync().GetAwaiter().GetResult(); return testServer; } diff --git a/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs index 8c49a2e2b..c8ad9d2a1 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Server.Integration.Tests.Middleware AllowAutoRedirect = false }); - var response = await client.GetAsync("robots.txt").ConfigureAwait(false); + var response = await client.GetAsync("robots.txt"); Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); Assert.Equal("web/robots.txt", response.Headers.Location?.ToString()); diff --git a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs index 0ade345a1..98195a294 100644 --- a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs @@ -31,10 +31,10 @@ namespace Jellyfin.Server.Integration.Tests Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType?.ToString()); // Write out for publishing - var responseBody = await response.Content.ReadAsStringAsync(); string outputPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "openapi.json")); _outputHelper.WriteLine("Writing OpenAPI Spec JSON to '{0}'.", outputPath); - File.WriteAllText(outputPath, responseBody); + await using var fs = File.Create(outputPath); + await response.Content.CopyToAsync(fs); } } } diff --git a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index a1bdfa31b..288102037 100644 --- a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -7,6 +7,7 @@ using Jellyfin.Server.Extensions; using MediaBrowser.Common.Configuration; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; @@ -21,9 +22,9 @@ namespace Jellyfin.Server.Tests data.Add( true, true, - new string[] { "192.168.t", "127.0.0.1", "1234.1232.12.1234" }, - new IPAddress[] { IPAddress.Loopback.MapToIPv6() }, - Array.Empty<IPNetwork>()); + new string[] { "192.168.t", "127.0.0.1", "::1", "1234.1232.12.1234" }, + new IPAddress[] { IPAddress.Loopback }, + new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) }); data.Add( true, @@ -64,7 +65,7 @@ namespace Jellyfin.Server.Tests true, true, new string[] { "localhost" }, - new IPAddress[] { IPAddress.Loopback.MapToIPv6() }, + new IPAddress[] { IPAddress.Loopback }, new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) }); return data; } @@ -77,8 +78,8 @@ namespace Jellyfin.Server.Tests var settings = new NetworkConfiguration { - EnableIPV4 = ip4, - EnableIPV6 = ip6 + EnableIPv4 = ip4, + EnableIPv6 = ip6 }; ForwardedHeadersOptions options = new ForwardedHeadersOptions(); @@ -116,11 +117,11 @@ namespace Jellyfin.Server.Tests { var conf = new NetworkConfiguration() { - EnableIPV6 = true, - EnableIPV4 = true, + EnableIPv6 = true, + EnableIPv4 = true, }; - - return new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + var startupConf = new Mock<IConfiguration>(); + return new NetworkManager(GetMockConfig(conf), startupConf.Object, new NullLogger<NetworkManager>()); } } } diff --git a/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs b/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs index 797fc8f64..93e065685 100644 --- a/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs +++ b/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs @@ -22,7 +22,7 @@ namespace Jellyfin.Server.Tests Assert.Single(test.Query); var (k, v) = test.Query.First(); Assert.Equal(key, k); - Assert.Empty(v); + Assert.True(StringValues.IsNullOrEmpty(v)); } } } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs index f63bc0e1b..c0d06116b 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading; using Jellyfin.Data.Enums; @@ -114,11 +114,11 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _parser.Fetch(result, "Test Data/Rising.nfo", CancellationToken.None); var item = result.Item; - Assert.Equal("Rising (1)", item.Name); + Assert.Equal("Rising (1) / Rising (2)", item.Name); Assert.Equal(1, item.IndexNumber); Assert.Equal(2, item.IndexNumberEnd); Assert.Equal(1, item.ParentIndexNumber); - Assert.Equal("A new Stargate team embarks on a dangerous mission to a distant galaxy, where they discover a mythical lost city -- and a deadly new enemy.", item.Overview); + Assert.Equal("A new Stargate team embarks on a dangerous mission to a distant galaxy, where they discover a mythical lost city -- and a deadly new enemy. / Sheppard tries to convince Weir to mount a rescue mission to free Colonel Sumner, Teyla, and the others captured by the Wraith.", item.Overview); Assert.Equal(new DateTime(2004, 7, 16), item.PremiereDate); Assert.Equal(2004, item.ProductionYear); } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index f56f58c6f..0a153b9cc 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -60,7 +60,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers { Exists = true, FullName = OperatingSystem.IsWindows() ? - "C:\\media\\movies\\Justice League (2017).jpg" + @"C:\media\movies\Justice League (2017).jpg" : "/media/movies/Justice League (2017).jpg" }; directoryService.Setup(x => x.GetFile(_localImageFileMetadata.FullName)) diff --git a/tests/jellyfin-tests.ruleset b/tests/jellyfin-tests.ruleset index e2abaf5bb..9d133da56 100644 --- a/tests/jellyfin-tests.ruleset +++ b/tests/jellyfin-tests.ruleset @@ -19,4 +19,10 @@ <!-- CA2234: Pass system uri objects instead of strings --> <Rule Id="CA2234" Action="Info" /> </Rules> + + <!-- xUnit --> + <Rules AnalyzerId="xUnit" RuleNamespace="xUnit"> + <!-- Test methods must have a supported return type. --> + <Rule Id="xUnit1028" Action="None" /> + </Rules> </RuleSet> |
