Merge branch 'master' into baseitemkind-fixes

This commit is contained in:
Claus Vium
2021-08-18 18:25:48 +02:00
committed by GitHub
187 changed files with 3459 additions and 2629 deletions

View File

@@ -15,9 +15,9 @@
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />

View File

@@ -171,11 +171,11 @@ namespace Jellyfin.Common.Tests.Cryptography
[InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
[InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
[InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
[InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Ends on $
[InlineData("$PBKDF2$iterations=$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Extra segment
[InlineData("$PBKDF2$iterations=$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$anotherone")] // Extra segment
[InlineData("$PBKDF2$iterations=$invalidstalt$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid salt
[InlineData("$PBKDF2$iterations=$69F420$invalid hash")] // Invalid hash
[InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Ends on $
[InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Extra segment
[InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$anotherone")] // Extra segment
[InlineData("$PBKDF2$iterations=1000$invalidstalt$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid salt
[InlineData("$PBKDF2$iterations=1000$69F420$invalid hash")] // Invalid hash
[InlineData("$PBKDF2$69F420$")] // Empty hash
public static void Parse_InvalidFormat_ThrowsFormatException(string passwordHash)
{

View File

@@ -12,11 +12,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
<PackageReference Include="FsCheck.Xunit" Version="2.16.0" />
</ItemGroup>
<!-- Code Analyzers -->

View File

@@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -17,7 +17,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
<PackageReference Include="FsCheck.Xunit" Version="2.16.0" />
</ItemGroup>
<!-- Code Analyzers -->

View File

@@ -18,7 +18,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />

View File

@@ -71,5 +71,25 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
Assert.True(res.PremiereDate.HasValue);
Assert.Equal(DateTime.Parse("2021-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate);
}
[Fact]
public void GetMediaInfo_GivenOriginalDateContainsOnlyYear_Success()
{
var bytes = File.ReadAllBytes("Test Data/Probing/music_year_only_metadata.json");
var internalMediaInfoResult = JsonSerializer.Deserialize<InternalMediaInfoResult>(bytes, _jsonOptions);
MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, null, true, "Test Data/Probing/music.flac", MediaProtocol.File);
Assert.Equal("Baker Street", res.Name);
Assert.Single(res.Artists);
Assert.Equal("Gerry Rafferty", res.Artists[0]);
Assert.Equal("City to City", res.Album);
Assert.Equal(1978, res.ProductionYear);
Assert.True(res.PremiereDate.HasValue);
Assert.Equal(DateTime.Parse("1978-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate);
Assert.Contains("Electronic", res.Genres);
Assert.Contains("Ambient", res.Genres);
Assert.Contains("Pop", res.Genres);
Assert.Contains("Jazz", res.Genres);
}
}
}

View File

@@ -0,0 +1,147 @@
{
"streams": [
{
"index": 0,
"codec_name": "flac",
"codec_long_name": "FLAC (Free Lossless Audio Codec)",
"codec_type": "audio",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"sample_fmt": "s16",
"sample_rate": "44100",
"channels": 2,
"channel_layout": "stereo",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/44100",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 16394616,
"duration": "371.760000",
"bits_per_raw_sample": "16",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
},
{
"index": 1,
"codec_name": "mjpeg",
"codec_long_name": "Motion JPEG",
"profile": "Baseline",
"codec_type": "video",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"width": 500,
"height": 498,
"coded_width": 500,
"coded_height": 498,
"closed_captions": 0,
"has_b_frames": 0,
"sample_aspect_ratio": "1:1",
"display_aspect_ratio": "250:249",
"pix_fmt": "yuvj420p",
"level": -99,
"color_range": "pc",
"color_space": "bt470bg",
"chroma_location": "center",
"refs": 1,
"r_frame_rate": "90000/1",
"avg_frame_rate": "0/0",
"time_base": "1/90000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 33458400,
"duration": "371.760000",
"bits_per_raw_sample": "8",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 1,
"timed_thumbnails": 0
},
"tags": {
"comment": "Cover (front)"
}
}
],
"format": {
"filename": "02 Baker Street.flac",
"nb_streams": 2,
"nb_programs": 0,
"format_name": "flac",
"format_long_name": "raw FLAC",
"start_time": "0.000000",
"duration": "371.760000",
"size": "37072649",
"bit_rate": "797775",
"probe_score": 100,
"tags": {
"MUSICBRAINZ_RELEASEGROUPID": "238c3fb4-5792-342b-b217-02f66298b424",
"ORIGINALDATE": "1978",
"ORIGINALYEAR": "1978",
"RELEASETYPE": "album",
"MUSICBRAINZ_ALBUMID": "30156786-e511-3106-ac95-66f0e880b24b",
"ASIN": "B000007O5H",
"MUSICBRAINZ_ALBUMARTISTID": "563201cb-721c-4cfb-acca-c1ba69e3d1fb",
"album_artist": "Gerry Rafferty",
"ALBUMARTISTSORT": "Rafferty, Gerry",
"LABEL": "Liberty EMI Records UK",
"CATALOGNUMBER": "CDP 7 46049 2",
"DATE": "1989-07-26",
"RELEASECOUNTRY": "GB",
"BARCODE": "077774604925",
"ALBUM": "City to City",
"SCRIPT": "Latn",
"RELEASESTATUS": "official",
"TOTALDISCS": "1",
"disc": "1",
"MEDIA": "CD",
"TOTALTRACKS": "10",
"MUSICBRAINZ_TRACKID": "9235e22e-afbd-48f7-b329-21dae6da2810",
"ISRC": "GBAYE1100924;GBAYE7800619",
"PERFORMER": "Hugh Burns (electric guitar);Nigel Jenkins (electric guitar);Tommy Eyre (keyboard and Moog);Glen LeFleur (percussion);Raphael Ravenscroft (saxophone);Henry Spinetti (drums (drum set));Gary Taylor (bass);Gerry Rafferty (lead vocals)",
"ARRANGER": "Graham Preskett",
"MIXER": "Declan ODoherty",
"PRODUCER": "Hugh Murphy;Gerry Rafferty",
"MUSICBRAINZ_WORKID": "a9eb3c45-784c-3c32-860c-4b406f03961b",
"LANGUAGE": "eng",
"WORK": "Baker Street",
"COMPOSER": "Gerry Rafferty",
"COMPOSERSORT": "Rafferty, Gerry",
"LYRICIST": "Gerry Rafferty",
"TITLE": "Baker Street",
"MUSICBRAINZ_ARTISTID": "563201cb-721c-4cfb-acca-c1ba69e3d1fb",
"ARTIST": "Gerry Rafferty",
"ARTISTSORT": "Rafferty, Gerry",
"ARTISTS": "Gerry Rafferty",
"MUSICBRAINZ_RELEASETRACKID": "407cf7f7-440d-3e76-8b89-8686198868ea",
"track": "2",
"GENRE": "Electronic;Ambient;Pop;Jazz",
"WEBSITE": "http://www.gerryrafferty.com/",
"ACOUSTID_ID": "68f8d979-a659-4aa0-a216-eb3721a951eb",
"MOOD": "Acoustic;Not aggressive;Not electronic;Not happy;Party;Relaxed;Not sad",
"TRACKTOTAL": "10",
"DISCTOTAL": "1"
}
}
}

View File

@@ -7,11 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
<PackageReference Include="FsCheck.Xunit" Version="2.16.0" />
</ItemGroup>
<!-- Code Analyzers -->

View File

@@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />

View File

@@ -21,7 +21,8 @@ namespace Jellyfin.Naming.Tests.TV
[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)]
// TODO: [InlineData("[Baz-Bar]Foo - 01 - 12[1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)]
[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)]
// TODO: [InlineData("E:\\Anime\\Yahari Ore no Seishun Love Comedy wa Machigatteiru\\Yahari Ore no Seishun Love Comedy wa Machigatteiru. Zoku\\Oregairu Zoku 11 - Hayama Hayato Always Renconds to Everyone's Expectations..mkv", "Yahari Ore no Seishun Love Comedy wa Machigatteiru", null, 11)]
// TODO: [InlineData(@"/Library/Series/The Grand Tour (2016)/Season 1/S01E01 The Holy Trinity.mkv", "The Grand Tour", 1, 1)]
public void TestSimple(string path, string seriesName, int? seasonNumber, int? episodeNumber)

View File

@@ -12,11 +12,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
<PackageReference Include="FsCheck.Xunit" Version="2.16.0" />
<PackageReference Include="Moq" Version="4.16.1" />
</ItemGroup>

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">

View File

@@ -21,7 +21,7 @@
<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />

View File

@@ -0,0 +1,179 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Emby.Server.Implementations.Localization;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Configuration;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
namespace Jellyfin.Server.Implementations.Tests.Localization
{
public class LocalizationManagerTests
{
[Fact]
public void GetCountries_All_Success()
{
var localizationManager = Setup(new ServerConfiguration
{
UICulture = "de-DE"
});
var countries = localizationManager.GetCountries().ToList();
Assert.Equal(139, countries.Count);
var germany = countries.FirstOrDefault(x => x.Name.Equals("DE", StringComparison.Ordinal));
Assert.NotNull(germany);
Assert.Equal("Germany", germany!.DisplayName);
Assert.Equal("DEU", germany.ThreeLetterISORegionName);
Assert.Equal("DE", germany.TwoLetterISORegionName);
}
[Fact]
public async Task GetCultures_All_Success()
{
var localizationManager = Setup(new ServerConfiguration
{
UICulture = "de-DE"
});
await localizationManager.LoadAll();
var cultures = localizationManager.GetCultures().ToList();
Assert.Equal(189, cultures.Count);
var germany = cultures.FirstOrDefault(x => x.TwoLetterISOLanguageName.Equals("de", StringComparison.Ordinal));
Assert.NotNull(germany);
Assert.Equal("ger", germany!.ThreeLetterISOLanguageName);
Assert.Equal("German", germany.DisplayName);
Assert.Equal("German", germany.Name);
Assert.Contains("deu", germany.ThreeLetterISOLanguageNames);
Assert.Contains("ger", germany.ThreeLetterISOLanguageNames);
}
[Theory]
[InlineData("de")]
[InlineData("ger")]
[InlineData("german")]
public async Task FindLanguageInfo_Valid_Success(string identifier)
{
var localizationManager = Setup(new ServerConfiguration
{
UICulture = "de-DE"
});
await localizationManager.LoadAll();
var germany = localizationManager.FindLanguageInfo(identifier);
Assert.NotNull(germany);
Assert.Equal("ger", germany!.ThreeLetterISOLanguageName);
Assert.Equal("German", germany.DisplayName);
Assert.Equal("German", germany.Name);
Assert.Contains("deu", germany.ThreeLetterISOLanguageNames);
Assert.Contains("ger", germany.ThreeLetterISOLanguageNames);
}
[Fact]
public async Task GetParentalRatings_Default_Success()
{
var localizationManager = Setup(new ServerConfiguration
{
UICulture = "de-DE"
});
await localizationManager.LoadAll();
var ratings = localizationManager.GetParentalRatings().ToList();
Assert.Equal(23, ratings.Count);
var tvma = ratings.FirstOrDefault(x => x.Name.Equals("TV-MA", StringComparison.Ordinal));
Assert.NotNull(tvma);
Assert.Equal(9, tvma!.Value);
}
[Fact]
public async Task GetParentalRatings_ConfiguredCountryCode_Success()
{
var localizationManager = Setup(new ServerConfiguration()
{
MetadataCountryCode = "DE"
});
await localizationManager.LoadAll();
var ratings = localizationManager.GetParentalRatings().ToList();
Assert.Equal(10, ratings.Count);
var fsk = ratings.FirstOrDefault(x => x.Name.Equals("FSK-12", StringComparison.Ordinal));
Assert.NotNull(fsk);
Assert.Equal(7, fsk!.Value);
}
[Theory]
[InlineData("CA-R", "CA", 10)]
[InlineData("FSK-16", "DE", 8)]
[InlineData("FSK-18", "DE", 9)]
[InlineData("FSK-18", "US", 9)]
[InlineData("TV-MA", "US", 9)]
[InlineData("XXX", "asdf", 100)]
[InlineData("Germany: FSK-18", "DE", 9)]
public async Task GetRatingLevel_GivenValidString_Success(string value, string countryCode, int expectedLevel)
{
var localizationManager = Setup(new ServerConfiguration()
{
MetadataCountryCode = countryCode
});
await localizationManager.LoadAll();
var level = localizationManager.GetRatingLevel(value);
Assert.NotNull(level);
Assert.Equal(expectedLevel, level!);
}
[Fact]
public async Task GetRatingLevel_GivenUnratedString_Success()
{
var localizationManager = Setup(new ServerConfiguration()
{
UICulture = "de-DE"
});
await localizationManager.LoadAll();
Assert.Null(localizationManager.GetRatingLevel("n/a"));
}
[Theory]
[InlineData("Default", "Default")]
[InlineData("HeaderLiveTV", "Live TV")]
public void GetLocalizedString_Valid_Success(string key, string expected)
{
var localizationManager = Setup(new ServerConfiguration()
{
UICulture = "en-US"
});
var translated = localizationManager.GetLocalizedString(key);
Assert.NotNull(translated);
Assert.Equal(expected, translated);
}
[Fact]
public void GetLocalizedString_Invalid_Success()
{
var localizationManager = Setup(new ServerConfiguration()
{
UICulture = "en-US"
});
var key = "SuperInvalidTranslationKeyThatWillNeverBeAdded";
var translated = localizationManager.GetLocalizedString(key);
Assert.NotNull(translated);
Assert.Equal(key, translated);
}
private LocalizationManager Setup(ServerConfiguration config)
{
var mockConfiguration = new Mock<IServerConfigurationManager>();
mockConfiguration.SetupGet(x => x.Configuration).Returns(config);
return new LocalizationManager(mockConfiguration.Object, new NullLogger<LocalizationManager>());
}
}
}

View File

@@ -0,0 +1,180 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Emby.Server.Implementations.Sorting;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using Xunit;
namespace Jellyfin.Server.Implementations.Tests.Sorting
{
public class AiredEpisodeOrderComparerTests
{
[Theory]
[ClassData(typeof(EpisodeBadData))]
public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem x, BaseItem y)
{
var cmp = new AiredEpisodeOrderComparer();
Assert.Throws<ArgumentNullException>(() => cmp.Compare(x, y));
}
[Theory]
[ClassData(typeof(EpisodeTestData))]
public void AiredEpisodeOrderCompareTest(BaseItem x, BaseItem y, int expected)
{
var cmp = new AiredEpisodeOrderComparer();
Assert.Equal(expected, cmp.Compare(x, y));
Assert.Equal(-expected, cmp.Compare(y, x));
}
private class EpisodeBadData : IEnumerable<object?[]>
{
public IEnumerator<object?[]> GetEnumerator()
{
yield return new object?[] { null, new Episode() };
yield return new object?[] { new Episode(), null };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
private class EpisodeTestData : IEnumerable<object?[]>
{
public IEnumerator<object?[]> GetEnumerator()
{
yield return new object?[]
{
new Movie(),
new Movie(),
0
};
yield return new object?[]
{
new Movie(),
new Episode(),
1
};
// Good cases
yield return new object?[]
{
new Episode(),
new Episode(),
0
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
0
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 2, IndexNumber = 1 },
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
1
};
// Good Specials
yield return new object?[]
{
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
0
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 0, IndexNumber = 2 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
1
};
// Specials to Episodes
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 2 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 2 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsAfterSeasonNumber = 1 },
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 3, IndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsAfterSeasonNumber = 1 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 3, IndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsAfterSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
1
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
0
};
yield return new object?[]
{
new Episode { ParentIndexNumber = 1, IndexNumber = 3 },
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
1
};
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
}

View File

@@ -9,9 +9,9 @@
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="Xunit.Priority" Version="1.1.6" />

View File

@@ -10,9 +10,9 @@
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />

View File

@@ -1,10 +1,15 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
using Jellyfin.Networking.Configuration;
using Jellyfin.Networking.Manager;
using Jellyfin.Server.Extensions;
using MediaBrowser.Common.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
@@ -13,20 +18,63 @@ namespace Jellyfin.Server.Tests
{
public class ParseNetworkTests
{
/// <summary>
/// Order of the result has always got to be hosts, then networks.
/// </summary>
/// <param name="ip4">IP4 enabled.</param>
/// <param name="ip6">IP6 enabled.</param>
/// <param name="hostList">List to parse.</param>
/// <param name="match">What it should match.</param>
public static TheoryData<bool, bool, string[], IPAddress[], IPNetwork[]> TestNetworks_TestData()
{
var data = new TheoryData<bool, bool, string[], IPAddress[], IPNetwork[]>();
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>());
data.Add(
true,
false,
new string[] { "192.168.x", "127.0.0.1", "1234.1232.12.1234" },
new IPAddress[] { IPAddress.Loopback },
Array.Empty<IPNetwork>());
data.Add(
true,
true,
new string[] { "::1" },
Array.Empty<IPAddress>(),
new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) });
data.Add(
false,
false,
new string[] { "localhost" },
Array.Empty<IPAddress>(),
Array.Empty<IPNetwork>());
data.Add(
true,
false,
new string[] { "localhost" },
new IPAddress[] { IPAddress.Loopback },
Array.Empty<IPNetwork>());
data.Add(
false,
true,
new string[] { "localhost" },
Array.Empty<IPAddress>(),
new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) });
data.Add(
true,
true,
new string[] { "localhost" },
new IPAddress[] { IPAddress.Loopback.MapToIPv6() },
new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) });
return data;
}
[Theory]
// [InlineData(true, true, "192.168.0.0/16,www.yahoo.co.uk", "::ffff:212.82.100.150,::ffff:192.168.0.0/16")] <- fails on Max. www.yahoo.co.uk resolves to a different ip address.
// [InlineData(true, false, "192.168.0.0/16,www.yahoo.co.uk", "212.82.100.150,192.168.0.0/16")]
[InlineData(true, true, "192.168.t,127.0.0.1,1234.1232.12.1234", "::ffff:127.0.0.1")]
[InlineData(true, false, "192.168.x,127.0.0.1,1234.1232.12.1234", "127.0.0.1")]
[InlineData(true, true, "::1", "::1/128")]
public void TestNetworks(bool ip4, bool ip6, string hostList, string match)
[MemberData(nameof(TestNetworks_TestData))]
public void TestNetworks(bool ip4, bool ip6, string[] hostList, IPAddress[] knownProxies, IPNetwork[] knownNetworks)
{
using var nm = CreateNetworkManager();
@@ -36,31 +84,25 @@ namespace Jellyfin.Server.Tests
EnableIPV6 = ip6
};
var result = match + ",";
ForwardedHeadersOptions options = new ForwardedHeadersOptions();
// Need this here as ::1 and 127.0.0.1 are in them by default.
options.KnownProxies.Clear();
options.KnownNetworks.Clear();
ApiServiceCollectionExtensions.AddProxyAddresses(settings, hostList.Split(','), options);
ApiServiceCollectionExtensions.AddProxyAddresses(settings, hostList, options);
var sb = new StringBuilder();
foreach (var item in options.KnownProxies)
Assert.Equal(knownProxies.Length, options.KnownProxies.Count);
foreach (var item in knownProxies)
{
sb.Append(item)
.Append(',');
Assert.True(options.KnownProxies.Contains(item));
}
foreach (var item in options.KnownNetworks)
Assert.Equal(knownNetworks.Length, options.KnownNetworks.Count);
foreach (var item in knownNetworks)
{
sb.Append(item.Prefix)
.Append('/')
.Append(item.PrefixLength.ToString(CultureInfo.InvariantCulture))
.Append(',');
Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.Prefix) && x.PrefixLength == item.PrefixLength));
}
Assert.Equal(sb.ToString(), result);
}
private static IConfigurationManager GetMockConfig(NetworkConfiguration conf)

View File

@@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />