aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs2
-rw-r--r--tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj15
-rw-r--r--tests/Jellyfin.Api.Tests/ModelBinders/CommaDelimitedArrayModelBinderTests.cs8
-rw-r--r--tests/Jellyfin.Api.Tests/ModelBinders/PipeDelimitedArrayModelBinderTests.cs8
-rw-r--r--tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj13
-rw-r--r--tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj13
-rw-r--r--tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj13
-rw-r--r--tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj8
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs2
-rw-r--r--tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs32
-rw-r--r--tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj8
-rw-r--r--tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs4
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj8
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj13
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs8
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs3
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs5
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs7
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs2
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json15
-rw-r--r--tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs6
-rw-r--r--tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs129
-rw-r--r--tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs2
-rw-r--r--tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs46
-rw-r--r--tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj15
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-AndroidTVExoPlayer.json216
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json526
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json499
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-dts-srt-2600k.json70
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-hevc-truehd-srt-15200k.json74
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-no-streams.json17
-rw-r--r--tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj13
-rw-r--r--tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs3
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs1
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs1
-rw-r--r--tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj15
-rw-r--r--tests/Jellyfin.Networking.Tests/NetworkParseTests.cs62
-rw-r--r--tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj10
-rw-r--r--tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs2
-rw-r--r--tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs2
-rw-r--r--tests/Jellyfin.Providers.Tests/MediaInfo/AudioResolverTests.cs6
-rw-r--r--tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs16
-rw-r--r--tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs6
-rw-r--r--tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs2
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj13
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Library/MediaStreamSelectorTests.cs36
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs11
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs2
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs25
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs49
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs49
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs1
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs8
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj15
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs1
-rw-r--r--tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj15
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj13
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs1
60 files changed, 1947 insertions, 222 deletions
diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs
index 23c51999f..7c85ddd62 100644
--- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs
+++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs
@@ -62,7 +62,7 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy
}
}
- private static TheoryData<string, Dictionary<string, string>> GetParts_ValidAuthHeader_Success_Data()
+ public static TheoryData<string, Dictionary<string, string>> GetParts_ValidAuthHeader_Success_Data()
{
var data = new TheoryData<string, Dictionary<string, string>>();
diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
index 6f3b83455..a20c9690f 100644
--- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
+++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
@@ -15,13 +15,16 @@
<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="6.0.3" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
- <PackageReference Include="Moq" Version="4.17.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
</ItemGroup>
<!-- Code Analyzers -->
@@ -31,7 +34,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Api.Tests/ModelBinders/CommaDelimitedArrayModelBinderTests.cs b/tests/Jellyfin.Api.Tests/ModelBinders/CommaDelimitedArrayModelBinderTests.cs
index 3ae6ae5bd..e37c9d91f 100644
--- a/tests/Jellyfin.Api.Tests/ModelBinders/CommaDelimitedArrayModelBinderTests.cs
+++ b/tests/Jellyfin.Api.Tests/ModelBinders/CommaDelimitedArrayModelBinderTests.cs
@@ -192,7 +192,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
await modelBinder.BindModelAsync(bindingContextMock.Object);
Assert.True(bindingContextMock.Object.Result.IsModelSet);
- Assert.Empty((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
+ var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
+ Assert.NotNull(listResult);
+ Assert.Empty(listResult);
}
[Fact]
@@ -220,7 +222,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
await modelBinder.BindModelAsync(bindingContextMock.Object);
Assert.True(bindingContextMock.Object.Result.IsModelSet);
- Assert.Single((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
+ var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
+ Assert.NotNull(listResult);
+ Assert.Single(listResult);
}
}
}
diff --git a/tests/Jellyfin.Api.Tests/ModelBinders/PipeDelimitedArrayModelBinderTests.cs b/tests/Jellyfin.Api.Tests/ModelBinders/PipeDelimitedArrayModelBinderTests.cs
index 938d19a15..7c05ee036 100644
--- a/tests/Jellyfin.Api.Tests/ModelBinders/PipeDelimitedArrayModelBinderTests.cs
+++ b/tests/Jellyfin.Api.Tests/ModelBinders/PipeDelimitedArrayModelBinderTests.cs
@@ -192,7 +192,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
await modelBinder.BindModelAsync(bindingContextMock.Object);
Assert.True(bindingContextMock.Object.Result.IsModelSet);
- Assert.Empty((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
+ var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
+ Assert.NotNull(listResult);
+ Assert.Empty(listResult);
}
[Fact]
@@ -220,7 +222,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
await modelBinder.BindModelAsync(bindingContextMock.Object);
Assert.True(bindingContextMock.Object.Result.IsModelSet);
- Assert.Single((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
+ var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;
+ Assert.NotNull(listResult);
+ Assert.Single(listResult);
}
}
}
diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
index 1ad0f4e00..95fc1d917 100644
--- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
+++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
@@ -12,11 +12,14 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
- <PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
+ <PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
</ItemGroup>
<!-- Code Analyzers -->
@@ -26,7 +29,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
index 9e6f7c0c1..d95747206 100644
--- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
+++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
@@ -12,10 +12,13 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
@@ -26,7 +29,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
index 4918e2e82..1444d6faf 100644
--- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
+++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
@@ -7,10 +7,13 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
@@ -21,7 +24,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
index 55125eb11..9e3bef881 100644
--- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
+++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
@@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@@ -17,7 +17,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
- <PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
+ <PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
</ItemGroup>
<!-- Code Analyzers -->
@@ -27,7 +27,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs
index 345f37cbe..77717af70 100644
--- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs
@@ -32,7 +32,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
const string? input = "123";
const int output = 123;
var deserialized = JsonSerializer.Deserialize<int>(input, _jsonSerializerOptions);
- Assert.Equal(deserialized, output);
+ Assert.Equal(output, deserialized);
}
}
}
diff --git a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs
index 7186cc023..903d88caa 100644
--- a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs
@@ -6,6 +6,38 @@ namespace Jellyfin.Extensions.Tests
public class StringExtensionsTests
{
[Theory]
+ [InlineData("", "")] // Identity edge-case (no diactritics)
+ [InlineData("Indiana Jones", "Indiana Jones")] // Identity (no diactritics)
+ [InlineData("a\ud800b", "ab")] // Invalid UTF-16 char stripping
+ [InlineData("Jön", "Jon")] // Issue #7484
+ [InlineData("Jönssonligan", "Jonssonligan")] // Issue #7484
+ [InlineData("Kieślowski", "Kieslowski")] // Issue #7450
+ [InlineData("Cidadão Kane", "Cidadao Kane")] // Issue #7560
+ [InlineData("운명처럼 널 사랑해", "운명처럼 널 사랑해")] // Issue #6393 (Korean language support)
+ [InlineData("애타는 로맨스", "애타는 로맨스")] // Issue #6393
+ public void RemoveDiacritics_ValidInput_Corrects(string input, string expectedResult)
+ {
+ string result = input.RemoveDiacritics();
+ Assert.Equal(expectedResult, result);
+ }
+
+ [Theory]
+ [InlineData("", false)] // Identity edge-case (no diactritics)
+ [InlineData("Indiana Jones", false)] // Identity (no diactritics)
+ [InlineData("a\ud800b", true)] // Invalid UTF-16 char stripping
+ [InlineData("Jön", true)] // Issue #7484
+ [InlineData("Jönssonligan", true)] // Issue #7484
+ [InlineData("Kieślowski", true)] // Issue #7450
+ [InlineData("Cidadão Kane", true)] // Issue #7560
+ [InlineData("운명처럼 널 사랑해", false)] // Issue #6393 (Korean language support)
+ [InlineData("애타는 로맨스", false)] // Issue #6393
+ public void HasDiacritics_ValidInput_Corrects(string input, bool expectedResult)
+ {
+ bool result = input.HasDiacritics();
+ Assert.Equal(expectedResult, result);
+ }
+
+ [Theory]
[InlineData("", '_', 0)]
[InlineData("___", '_', 3)]
[InlineData("test\x00", '\x00', 1)]
diff --git a/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj
index c53dab6d8..83ea1907c 100644
--- a/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj
+++ b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj
@@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@@ -26,7 +26,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
diff --git a/tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs b/tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs
index 79648c4f6..bbacdcd62 100644
--- a/tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs
@@ -53,7 +53,7 @@ namespace Jellyfin.MediaEncoding.Hls.Tests.Playlist
Assert.False(DynamicHlsPlaylistGenerator.IsExtractionAllowedForFile(filePath, allowedExtensions));
}
- private static TheoryData<int, long, double[]> ComputeEqualLengthSegments_Valid_Success_Data()
+ public static TheoryData<int, long, double[]> ComputeEqualLengthSegments_Valid_Success_Data()
{
var data = new TheoryData<int, long, double[]>
{
@@ -67,7 +67,7 @@ namespace Jellyfin.MediaEncoding.Hls.Tests.Playlist
return data;
}
- private static TheoryData<KeyframeData, int, double[]> ComputeSegments_Valid_Success_Data()
+ public static TheoryData<KeyframeData, int, double[]> ComputeSegments_Valid_Success_Data()
{
var data = new TheoryData<KeyframeData, int, double[]>
{
diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj
index 268631e58..84a069424 100644
--- a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj
+++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj
@@ -8,9 +8,9 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@@ -27,7 +27,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
index 1a7c21084..4cff2143c 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
+++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
@@ -22,10 +22,13 @@
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
</ItemGroup>
<!-- Code Analyzers -->
@@ -35,7 +38,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
index 53e1550ed..13cfe885f 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
@@ -75,6 +75,14 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
Assert.Equal(1, res.VideoStream.RefFrames);
Assert.Equal("1/1000", res.VideoStream.TimeBase);
Assert.Equal(MediaStreamType.Video, res.VideoStream.Type);
+ Assert.Equal(1, res.VideoStream.DvVersionMajor);
+ Assert.Equal(0, res.VideoStream.DvVersionMinor);
+ Assert.Equal(5, res.VideoStream.DvProfile);
+ Assert.Equal(6, res.VideoStream.DvLevel);
+ Assert.Equal(1, res.VideoStream.RpuPresentFlag);
+ Assert.Equal(0, res.VideoStream.ElPresentFlag);
+ Assert.Equal(1, res.VideoStream.BlPresentFlag);
+ Assert.Equal(0, res.VideoStream.DvBlSignalCompatibilityId);
Assert.Empty(res.Chapters);
Assert.Equal("Just color bars", res.Overview);
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs
index 3775555de..fe0d7fc90 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs
@@ -1,7 +1,6 @@
using System;
using System.Globalization;
using System.IO;
-using System.Threading;
using MediaBrowser.MediaEncoding.Subtitles;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit;
@@ -15,7 +14,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
{
using (var stream = File.OpenRead("Test Data/example.ass"))
{
- var parsed = new AssParser(new NullLogger<AssParser>()).Parse(stream, CancellationToken.None);
+ var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "ass");
Assert.Single(parsed.TrackEvents);
var trackEvent = parsed.TrackEvents[0];
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs
index c07c9ea7d..2aebee556 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs
@@ -1,7 +1,6 @@
using System;
using System.Globalization;
using System.IO;
-using System.Threading;
using MediaBrowser.MediaEncoding.Subtitles;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit;
@@ -15,7 +14,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
{
using (var stream = File.OpenRead("Test Data/example.srt"))
{
- var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None);
+ var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt");
Assert.Equal(2, parsed.TrackEvents.Count);
var trackEvent1 = parsed.TrackEvents[0];
@@ -37,7 +36,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
{
using (var stream = File.OpenRead("Test Data/example2.srt"))
{
- var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None);
+ var parsed = new SubtitleEditParser(new NullLogger<SubtitleEditParser>()).Parse(stream, "srt");
Assert.Equal(2, parsed.TrackEvents.Count);
var trackEvent1 = parsed.TrackEvents[0];
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs
index 56649db8f..6abf2d26c 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
-using System.Threading;
using MediaBrowser.MediaEncoding.Subtitles;
using MediaBrowser.Model.MediaInfo;
using Microsoft.Extensions.Logging.Abstractions;
@@ -13,7 +12,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
{
public class SsaParserTests
{
- private readonly SsaParser _parser = new SsaParser(new NullLogger<AssParser>());
+ private readonly SubtitleEditParser _parser = new SubtitleEditParser(new NullLogger<SubtitleEditParser>());
[Theory]
[MemberData(nameof(Parse_MultipleDialogues_TestData))]
@@ -21,7 +20,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
{
using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa)))
{
- SubtitleTrackInfo subtitleTrackInfo = _parser.Parse(stream, CancellationToken.None);
+ SubtitleTrackInfo subtitleTrackInfo = _parser.Parse(stream, "ssa");
Assert.Equal(expectedSubtitleTrackEvents.Count, subtitleTrackInfo.TrackEvents.Count);
@@ -76,7 +75,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
{
using (var stream = File.OpenRead("Test Data/example.ssa"))
{
- var parsed = _parser.Parse(stream, CancellationToken.None);
+ var parsed = _parser.Parse(stream, "ssa");
Assert.Single(parsed.TrackEvents);
var trackEvent = parsed.TrackEvents[0];
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs
index 639c364df..243127438 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs
@@ -12,7 +12,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
{
public class SubtitleEncoderTests
{
- internal static TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo> GetReadableFile_Valid_TestData()
+ public static TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo> GetReadableFile_Valid_TestData()
{
var data = new TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo>();
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
index 720fc5c8f..519d81179 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
+++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
@@ -47,7 +47,20 @@
"tags": {
"ENCODER": "Lavc57.107.100 libx264",
"DURATION": "00:00:01.000000000"
- }
+ },
+ "side_data_list": [
+ {
+ "side_data_type": "DOVI configuration record",
+ "dv_version_major": 1,
+ "dv_version_minor": 0,
+ "dv_profile": 5,
+ "dv_level": 6,
+ "rpu_present_flag": 1,
+ "el_present_flag": 0,
+ "bl_present_flag": 1,
+ "dv_bl_signal_compatibility_id": 0
+ }
+ ]
}
],
"chapters": [
diff --git a/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs b/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs
index 6948280a3..162f53e56 100644
--- a/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs
+++ b/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs
@@ -152,9 +152,9 @@ namespace Jellyfin.Model.Tests.Cryptography
[InlineData("$PBKDF2$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty segment
[InlineData("$PBKDF2$iterations=1000$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty salt segment
[InlineData("$PBKDF2$iterations=1000$69F420$")] // Empty hash segment
- [InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
- [InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
- [InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter
+ [InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter
+ [InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter
+ [InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter
[InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Ends on $
[InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Extra segment
[InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$anotherone")] // Extra segment
diff --git a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
index 4748f3497..9baf6877d 100644
--- a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
+++ b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
@@ -27,7 +27,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
- [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
+ [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
[InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Firefox
@@ -38,7 +38,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
- [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
+ [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
[InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Safari
@@ -89,7 +89,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Chrome-NoHLS", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome-NoHLS", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")]
[InlineData("Chrome-NoHLS", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")]
- [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
+ [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
[InlineData("Chrome-NoHLS", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome-NoHLS", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// TranscodeMedia
@@ -131,6 +131,37 @@ namespace Jellyfin.Model.Tests
[InlineData("Null", "mkv-vp9-aac-srt-2600k", null, TranscodeReason.ContainerBitrateExceedsLimit)]
[InlineData("Null", "mkv-vp9-ac3-srt-2600k", null, TranscodeReason.ContainerBitrateExceedsLimit)]
[InlineData("Null", "mkv-vp9-vorbis-vtt-2600k", null, TranscodeReason.ContainerBitrateExceedsLimit)]
+ // AndroidTV
+ [InlineData("AndroidTVExoPlayer", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ // Tizen 3 Stereo
+ [InlineData("Tizen3-stereo", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-h264-dts-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ [InlineData("Tizen3-stereo", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
+ // Tizen 4 4K 5.1
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
public async Task BuildVideoItemSimple(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "")
{
var options = await GetVideoOptions(deviceName, mediaSource);
@@ -146,7 +177,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
- [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
+ [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
[InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Firefox
@@ -156,7 +187,7 @@ namespace Jellyfin.Model.Tests
[InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
[InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
- [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
+ [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
[InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
[InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
// Safari
@@ -198,6 +229,37 @@ namespace Jellyfin.Model.Tests
[InlineData("JellyfinMediaPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] // #6450
[InlineData("JellyfinMediaPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] // #6450
[InlineData("JellyfinMediaPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] // #6450
+ // AndroidTV
+ [InlineData("AndroidTVExoPlayer", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ // Tizen 3 Stereo
+ [InlineData("Tizen3-stereo", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-h264-dts-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ [InlineData("Tizen3-stereo", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen3-stereo", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
+ // Tizen 4 4K 5.1
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)]
+ [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)]
+ [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)]
public async Task BuildVideoItemWithFirstExplicitStream(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "")
{
var options = await GetVideoOptions(deviceName, mediaSource);
@@ -223,12 +285,26 @@ namespace Jellyfin.Model.Tests
// RokuSSPlus
[InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
[InlineData("RokuSSPlus", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
+ // no streams
+ [InlineData("Chrome", "no-streams", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")] // #6450
+ // AndroidTV
+ [InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
+ [InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
+ // Tizen 3 Stereo
+ [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
+ [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
+ // Tizen 4 4K 5.1
+ [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
+ [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")]
public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = (TranscodeReason)0, string transcodeMode = "DirectStream", string transcodeProtocol = "")
{
var options = await GetVideoOptions(deviceName, mediaSource);
var streamCount = options.MediaSources[0].MediaStreams.Count;
- options.AudioStreamIndex = streamCount - 2;
- options.SubtitleStreamIndex = streamCount - 1;
+ if (streamCount > 0)
+ {
+ options.AudioStreamIndex = streamCount - 2;
+ options.SubtitleStreamIndex = streamCount - 1;
+ }
var streamInfo = BuildVideoItemSimpleTest(options, playMethod, why, transcodeMode, transcodeProtocol);
Assert.Equal(streamInfo?.AudioStreamIndex, options.AudioStreamIndex);
@@ -262,23 +338,23 @@ namespace Jellyfin.Model.Tests
Assert.NotNull(mediaSource);
var videoStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Video);
var audioStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio);
- // TODO: check AudioStreamIndex vs options.AudioStreamIndex
+ // TODO: Check AudioStreamIndex vs options.AudioStreamIndex
var inputAudioStream = mediaSource.GetDefaultAudioStream(audioStreamIndexInput ?? mediaSource.DefaultAudioStreamIndex);
var uri = ParseUri(val);
if (playMethod == PlayMethod.DirectPlay)
{
- // check expected container
+ // Check expected container
var containers = ContainerProfile.SplitValue(mediaSource.Container);
- // TODO: test transcode too
+ // TODO: Test transcode too
// Assert.Contains(uri.Extension, containers);
- // check expected video codec (1)
+ // Check expected video codec (1)
Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
Assert.Single(val.TargetVideoCodec);
- // check expected audio codecs (1)
+ // Check expected audio codecs (1)
Assert.Contains(targetAudioStream.Codec, val.TargetAudioCodec);
Assert.Single(val.TargetAudioCodec);
// Assert.Single(val.AudioCodecs);
@@ -294,7 +370,7 @@ namespace Jellyfin.Model.Tests
Assert.NotEmpty(val.VideoCodecs);
Assert.NotEmpty(val.AudioCodecs);
- // check expected container (todo: this could be a test param)
+ // Check expected container (todo: this could be a test param)
if (transcodeProtocol == "http")
{
// Assert.Equal("webm", val.Container);
@@ -327,32 +403,39 @@ namespace Jellyfin.Model.Tests
stream => Assert.DoesNotContain(stream.Codec, val.VideoCodecs));
}
- // todo: fill out tests here
+ // TODO: Fill out tests here
}
// DirectStream and Remux
else
{
- // check expected video codec (1)
+ // Check expected video codec (1)
Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
Assert.Single(val.TargetVideoCodec);
if (transcodeMode == "DirectStream")
{
+ // Check expected audio codecs (1)
if (!targetAudioStream.IsExternal)
{
- // check expected audio codecs (1)
- Assert.DoesNotContain(targetAudioStream.Codec, val.AudioCodecs);
+ if (val.TranscodeReasons.HasFlag(TranscodeReason.ContainerNotSupported))
+ {
+ Assert.Contains(targetAudioStream.Codec, val.AudioCodecs);
+ }
+ else
+ {
+ Assert.DoesNotContain(targetAudioStream.Codec, val.AudioCodecs);
+ }
}
}
else if (transcodeMode == "Remux")
{
- // check expected audio codecs (1)
+ // Check expected audio codecs (1)
Assert.Contains(targetAudioStream.Codec, val.AudioCodecs);
Assert.Single(val.AudioCodecs);
}
- // video details
+ // Video details
var videoStream = targetVideoStream;
Assert.False(val.EstimateContentLength);
Assert.Equal(TranscodeSeekInfo.Auto, val.TranscodeSeekInfo);
@@ -361,10 +444,10 @@ namespace Jellyfin.Model.Tests
Assert.Equal(videoStream.BitDepth, val.TargetVideoBitDepth);
Assert.InRange(val.VideoBitrate.GetValueOrDefault(), videoStream.BitRate.GetValueOrDefault(), int.MaxValue);
- // audio codec not supported
+ // Audio codec not supported
if ((why & TranscodeReason.AudioCodecNotSupported) != 0)
{
- // audio stream specified
+ // Audio stream specified
if (options.AudioStreamIndex >= 0)
{
// TODO:fixme
@@ -374,10 +457,10 @@ namespace Jellyfin.Model.Tests
}
}
- // audio stream not specified
+ // Audio stream not specified
else
{
- // TODO:fixme
+ // TODO: Fixme
Assert.All(audioStreams, stream =>
{
if (!stream.IsExternal)
diff --git a/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs b/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs
index 7c3a7ff6c..a5bdb42d8 100644
--- a/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs
+++ b/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs
@@ -7,7 +7,7 @@ namespace Jellyfin.Model.Drawing;
public static class ImageFormatExtensionsTests
{
- private static TheoryData<ImageFormat> GetAllImageFormats()
+ public static TheoryData<ImageFormat> GetAllImageFormats()
{
var theoryTypes = new TheoryData<ImageFormat>();
foreach (var x in Enum.GetValues<ImageFormat>())
diff --git a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
index 9fcf8189f..80c38affe 100644
--- a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
+++ b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
@@ -109,26 +109,37 @@ namespace Jellyfin.Model.Tests.Entities
[InlineData(null, null, false, null)]
[InlineData(null, 0, false, null)]
[InlineData(0, null, false, null)]
- [InlineData(640, 480, false, "480p")]
- [InlineData(640, 480, true, "480i")]
- [InlineData(720, 576, false, "576p")]
- [InlineData(720, 576, true, "576i")]
+ [InlineData(256, 144, false, "144p")]
+ [InlineData(256, 144, true, "144i")]
+ [InlineData(426, 240, false, "240p")]
+ [InlineData(426, 240, true, "240i")]
+ [InlineData(640, 360, false, "360p")]
+ [InlineData(640, 360, true, "360i")]
+ [InlineData(854, 480, false, "480p")]
+ [InlineData(854, 480, true, "480i")]
[InlineData(960, 540, false, "540p")]
[InlineData(960, 540, true, "540i")]
+ [InlineData(1024, 576, false, "576p")]
+ [InlineData(1024, 576, true, "576i")]
[InlineData(1280, 720, false, "720p")]
[InlineData(1280, 720, true, "720i")]
- [InlineData(1920, 1080, false, "1080p")]
- [InlineData(1920, 1080, true, "1080i")]
+ [InlineData(2560, 1080, false, "1080p")]
+ [InlineData(2560, 1080, true, "1080i")]
[InlineData(4096, 3072, false, "4K")]
[InlineData(8192, 6144, false, "8K")]
- [InlineData(512, 384, false, "480p")]
- [InlineData(576, 336, false, "480p")]
- [InlineData(624, 352, false, "480p")]
- [InlineData(640, 352, false, "480p")]
- [InlineData(704, 396, false, "480p")]
- [InlineData(720, 404, false, "480p")]
+ [InlineData(512, 384, false, "384p")]
+ [InlineData(576, 336, false, "360p")]
+ [InlineData(576, 336, true, "360i")]
+ [InlineData(624, 352, false, "360p")]
+ [InlineData(640, 352, false, "360p")]
+ [InlineData(640, 480, false, "480p")]
+ [InlineData(704, 396, false, "404p")]
+ [InlineData(720, 404, false, "404p")]
[InlineData(720, 480, false, "480p")]
+ [InlineData(720, 576, false, "576p")]
[InlineData(768, 576, false, "576p")]
+ [InlineData(960, 544, false, "540p")]
+ [InlineData(960, 544, true, "540i")]
[InlineData(960, 720, false, "720p")]
[InlineData(1280, 528, false, "720p")]
[InlineData(1280, 532, false, "720p")]
@@ -140,6 +151,11 @@ namespace Jellyfin.Model.Tests.Entities
[InlineData(1280, 696, false, "720p")]
[InlineData(1280, 716, false, "720p")]
[InlineData(1280, 718, false, "720p")]
+ [InlineData(1920, 1080, false, "1080p")]
+ [InlineData(1440, 1070, false, "1080p")]
+ [InlineData(1440, 1072, false, "1080p")]
+ [InlineData(1440, 1080, false, "1080p")]
+ [InlineData(1440, 1440, false, "1080p")]
[InlineData(1912, 792, false, "1080p")]
[InlineData(1916, 1076, false, "1080p")]
[InlineData(1918, 1080, false, "1080p")]
@@ -153,14 +169,16 @@ namespace Jellyfin.Model.Tests.Entities
[InlineData(1920, 960, false, "1080p")]
[InlineData(1920, 1024, false, "1080p")]
[InlineData(1920, 1040, false, "1080p")]
+ [InlineData(1920, 1070, false, "1080p")]
[InlineData(1920, 1072, false, "1080p")]
- [InlineData(1440, 1072, false, "1080p")]
- [InlineData(1440, 1080, false, "1080p")]
+ [InlineData(1920, 1440, false, "1080p")]
[InlineData(3840, 1600, false, "4K")]
[InlineData(3840, 1606, false, "4K")]
[InlineData(3840, 1608, false, "4K")]
[InlineData(3840, 2160, false, "4K")]
+ [InlineData(4090, 3070, false, "4K")]
[InlineData(7680, 4320, false, "8K")]
+ [InlineData(8190, 6140, false, "8K")]
public void GetResolutionText_Valid(int? width, int? height, bool interlaced, string expected)
{
var mediaStream = new MediaStream()
diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
index d2304d0d0..fbcaa66f4 100644
--- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
+++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
@@ -7,12 +7,15 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
- <PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
+ <PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
</ItemGroup>
<ItemGroup>
@@ -28,7 +31,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-AndroidTVExoPlayer.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-AndroidTVExoPlayer.json
new file mode 100644
index 000000000..3d3968268
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-AndroidTVExoPlayer.json
@@ -0,0 +1,216 @@
+{
+ "Name": "Jellyfin AndroidTV-ExoPlayer",
+ "EnableAlbumArtInDidl": false,
+ "EnableSingleAlbumArtLimit": false,
+ "EnableSingleSubtitleLimit": false,
+ "SupportedMediaTypes": "Audio,Photo,Video",
+ "MaxAlbumArtWidth": 0,
+ "MaxAlbumArtHeight": 0,
+ "MaxStreamingBitrate": 120000000,
+ "MaxStaticBitrate": 100000000,
+ "MusicStreamingTranscodingBitrate": 192000,
+ "TimelineOffsetSeconds": 0,
+ "RequiresPlainVideoItems": false,
+ "RequiresPlainFolders": false,
+ "EnableMSMediaReceiverRegistrar": false,
+ "IgnoreTranscodeByteRangeRequests": false,
+ "DirectPlayProfiles": [
+ {
+ "Container": "m4v,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,mp4,webm",
+ "AudioCodec": "aac,mp3,mp2,aac_latm,alac,ac3,eac3,dca,dts,mlp,truehd,pcm_alaw,pcm_mulaw",
+ "VideoCodec": "h264,hevc,vp8,vp9,mpeg,mpeg2video",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "aac,mp3,mp2,aac_latm,alac,ac3,eac3,dca,dts,mlp,truehd,pcm_alaw,pcm_mulaw,,pa,flac,wav,wma,ogg,oga,webma,ape,opus",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "jpg,jpeg,png,gif,web",
+ "Type": "Photo",
+ "$type": "DirectPlayProfile"
+ }
+ ],
+ "CodecProfiles": [
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "EqualsAny",
+ "Property": "VideoProfile",
+ "Value": "high|main|baseline|constrained baseline",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoLevel",
+ "Value": "51",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "Codec": "h264",
+ "$type": "CodecProfile"
+ },
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "RefFrames",
+ "Value": "12",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "ApplyConditions": [
+ {
+ "Condition": "GreaterThanEqual",
+ "Property": "Width",
+ "Value": "1200",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "Codec": "h264",
+ "$type": "CodecProfile"
+ },
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "RefFrames",
+ "Value": "4",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "ApplyConditions": [
+ {
+ "Condition": "GreaterThanEqual",
+ "Property": "Width",
+ "Value": "1900",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "Codec": "h264",
+ "$type": "CodecProfile"
+ },
+ {
+ "Type": "VideoAudio",
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "AudioChannels",
+ "Value": "6",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "CodecProfile"
+ }
+ ],
+ "TranscodingProfiles": [
+ {
+ "Container": "ts",
+ "Type": "Video",
+ "VideoCodec": "h264",
+ "AudioCodec": "aac,mp3",
+ "Protocol": "hls",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mp3",
+ "Type": "Audio",
+ "AudioCodec": "mp3",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ }
+ ],
+ "SubtitleProfiles": [
+ {
+ "Format": "srt",
+ "Method": "Embed",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "srt",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "subrip",
+ "Method": "Embed",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "subrip",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "ass",
+ "Method": "Encode",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "ssa",
+ "Method": "Encode",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "pgs",
+ "Method": "Encode",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "pgssub",
+ "Method": "Encode",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "dvdsub",
+ "Method": "Encode",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "vtt",
+ "Method": "Embed",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "sub",
+ "Method": "Embed",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "idx",
+ "Method": "Embed",
+ "$type": "SubtitleProfile"
+ }
+ ],
+ "$type": "DeviceProfile"
+}
diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json
new file mode 100644
index 000000000..53637b793
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen3-stereo.json
@@ -0,0 +1,526 @@
+{
+ "Name": "Jellyfin Tizen 3 Stereo",
+ "EnableAlbumArtInDidl": false,
+ "EnableSingleAlbumArtLimit": false,
+ "EnableSingleSubtitleLimit": false,
+ "SupportedMediaTypes": "Audio,Photo,Video",
+ "MaxAlbumArtWidth": 0,
+ "MaxAlbumArtHeight": 0,
+ "MaxStreamingBitrate": 120000000,
+ "MaxStaticBitrate": 100000000,
+ "MusicStreamingTranscodingBitrate": 384000,
+ "TimelineOffsetSeconds": 0,
+ "RequiresPlainVideoItems": false,
+ "RequiresPlainFolders": false,
+ "EnableMSMediaReceiverRegistrar": false,
+ "IgnoreTranscodeByteRangeRequests": false,
+ "DirectPlayProfiles": [
+ {
+ "Container": "webm",
+ "AudioCodec": "vorbis,opus",
+ "VideoCodec": "vp8,vp9",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mp4,m4v",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mkv",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "m2ts",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,vc1,mpeg2video",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "wmv",
+ "AudioCodec": "wma",
+ "VideoCodec": "wmv,vc1",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "ts,mpegts",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,hevc,vc1,mpeg2video",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "asf",
+ "AudioCodec": "wma",
+ "VideoCodec": "wmv,vc1",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "avi",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mpg,mpeg,flv,3gp,mts,trp,vob,vro",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mov",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "opus",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "webm",
+ "AudioCodec": "opus",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mp3",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "m4a",
+ "AudioCodec": "aac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "m4b",
+ "AudioCodec": "aac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "flac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "webma",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "webm",
+ "AudioCodec": "webma",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "wma",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "wav",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "ogg",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ }
+ ],
+ "TranscodingProfiles": [
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "AudioCodec": "aac",
+ "Protocol": "hls",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 1,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": true,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "AudioCodec": "aac",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mp3",
+ "Type": "Audio",
+ "AudioCodec": "mp3",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "opus",
+ "Type": "Audio",
+ "AudioCodec": "opus",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "wav",
+ "Type": "Audio",
+ "AudioCodec": "wav",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "opus",
+ "Type": "Audio",
+ "AudioCodec": "opus",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mp3",
+ "Type": "Audio",
+ "AudioCodec": "mp3",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "AudioCodec": "aac",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "wav",
+ "Type": "Audio",
+ "AudioCodec": "wav",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mkv",
+ "Type": "Video",
+ "VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "Protocol": "",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": true,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "1920",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "ts",
+ "Type": "Video",
+ "VideoCodec": "h264,hevc",
+ "AudioCodec": "aac,mp3,ac3,eac3,opus",
+ "Protocol": "hls",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 1,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "1920",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "webm",
+ "Type": "Video",
+ "VideoCodec": "vp8,vp9,vpx",
+ "AudioCodec": "vorbis,opus",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "2",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "1920",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mp4",
+ "Type": "Video",
+ "VideoCodec": "h264",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,dca,dts,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "1920",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ }
+ ],
+ "CodecProfiles": [
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "NotEquals",
+ "Property": "IsAnamorphic",
+ "Value": "true",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "EqualsAny",
+ "Property": "VideoProfile",
+ "Value": "high|main|baseline|constrained baseline|high 10",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoLevel",
+ "Value": "52",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "20000000",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "Codec": "h264",
+ "$type": "CodecProfile"
+ },
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "NotEquals",
+ "Property": "IsAnamorphic",
+ "Value": "true",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "EqualsAny",
+ "Property": "VideoProfile",
+ "Value": "main|main 10",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoLevel",
+ "Value": "183",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "20000000",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "Codec": "hevc",
+ "$type": "CodecProfile"
+ },
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "20000000",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "CodecProfile"
+ }
+ ],
+ "ResponseProfiles": [
+ {
+ "Container": "m4v",
+ "Type": "Video",
+ "MimeType": "video/mp4",
+ "$type": "ResponseProfile"
+ }
+ ],
+ "SubtitleProfiles": [
+ {
+ "Format": "vtt",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "ass",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "ssa",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ }
+ ],
+ "$type": "DeviceProfile"
+}
diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json
new file mode 100644
index 000000000..d3ef22c25
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Tizen4-4K-5.1.json
@@ -0,0 +1,499 @@
+{
+ "Name": "Jellyfin Tizen 4 4K 5.1",
+ "EnableAlbumArtInDidl": false,
+ "EnableSingleAlbumArtLimit": false,
+ "EnableSingleSubtitleLimit": false,
+ "SupportedMediaTypes": "Audio,Photo,Video",
+ "MaxAlbumArtWidth": 0,
+ "MaxAlbumArtHeight": 0,
+ "MaxStreamingBitrate": 120000000,
+ "MaxStaticBitrate": 100000000,
+ "MusicStreamingTranscodingBitrate": 384000,
+ "TimelineOffsetSeconds": 0,
+ "RequiresPlainVideoItems": false,
+ "RequiresPlainFolders": false,
+ "EnableMSMediaReceiverRegistrar": false,
+ "IgnoreTranscodeByteRangeRequests": false,
+ "DirectPlayProfiles": [
+ {
+ "Container": "webm",
+ "AudioCodec": "vorbis,opus",
+ "VideoCodec": "vp8,vp9",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mp4,m4v",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mkv",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "m2ts",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,vc1,mpeg2video",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "wmv",
+ "AudioCodec": "wma",
+ "VideoCodec": "wmv,vc1",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "ts,mpegts",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,hevc,vc1,mpeg2video",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "asf",
+ "AudioCodec": "wma",
+ "VideoCodec": "wmv,vc1",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "avi",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264,hevc",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mpg,mpeg,flv,3gp,mts,trp,vob,vro",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mov",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "VideoCodec": "h264",
+ "Type": "Video",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "opus",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "webm",
+ "AudioCodec": "opus",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "mp3",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "m4a",
+ "AudioCodec": "aac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "m4b",
+ "AudioCodec": "aac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "flac",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "webma",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "webm",
+ "AudioCodec": "webma",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "wma",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "wav",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ },
+ {
+ "Container": "ogg",
+ "Type": "Audio",
+ "$type": "DirectPlayProfile"
+ }
+ ],
+ "TranscodingProfiles": [
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "AudioCodec": "aac",
+ "Protocol": "hls",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 1,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": true,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "AudioCodec": "aac",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mp3",
+ "Type": "Audio",
+ "AudioCodec": "mp3",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "opus",
+ "Type": "Audio",
+ "AudioCodec": "opus",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "wav",
+ "Type": "Audio",
+ "AudioCodec": "wav",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "opus",
+ "Type": "Audio",
+ "AudioCodec": "opus",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mp3",
+ "Type": "Audio",
+ "AudioCodec": "mp3",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "aac",
+ "Type": "Audio",
+ "AudioCodec": "aac",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "wav",
+ "Type": "Audio",
+ "AudioCodec": "wav",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mkv",
+ "Type": "Video",
+ "VideoCodec": "h264,hevc,mpeg2video,vc1,msmpeg4v2,vp8,vp9",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "Protocol": "",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": true,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "3840",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "ts",
+ "Type": "Video",
+ "VideoCodec": "h264,hevc",
+ "AudioCodec": "aac,mp3,ac3,eac3,opus",
+ "Protocol": "hls",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 1,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "3840",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "webm",
+ "Type": "Video",
+ "VideoCodec": "vp8,vp9,vpx",
+ "AudioCodec": "vorbis,opus",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Streaming",
+ "EnableSubtitlesInManifest": false,
+ "MaxAudioChannels": "6",
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "3840",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ },
+ {
+ "Container": "mp4",
+ "Type": "Video",
+ "VideoCodec": "h264",
+ "AudioCodec": "aac,mp3,ac3,eac3,mp2,pcm_s16le,pcm_s24le,aac_latm,opus,flac,vorbis",
+ "Protocol": "http",
+ "EstimateContentLength": false,
+ "EnableMpegtsM2TsMode": false,
+ "TranscodeSeekInfo": "Auto",
+ "CopyTimestamps": false,
+ "Context": "Static",
+ "EnableSubtitlesInManifest": false,
+ "MinSegments": 0,
+ "SegmentLength": 0,
+ "BreakOnNonKeyFrames": false,
+ "Conditions": [
+ {
+ "Condition": "LessThanEqual",
+ "Property": "Width",
+ "Value": "3840",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "$type": "TranscodingProfile"
+ }
+ ],
+ "CodecProfiles": [
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "NotEquals",
+ "Property": "IsAnamorphic",
+ "Value": "true",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "EqualsAny",
+ "Property": "VideoProfile",
+ "Value": "high|main|baseline|constrained baseline|high 10",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoLevel",
+ "Value": "52",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "Codec": "h264",
+ "$type": "CodecProfile"
+ },
+ {
+ "Type": "Video",
+ "Conditions": [
+ {
+ "Condition": "NotEquals",
+ "Property": "IsAnamorphic",
+ "Value": "true",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "EqualsAny",
+ "Property": "VideoProfile",
+ "Value": "main|main 10",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ },
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoLevel",
+ "Value": "183",
+ "IsRequired": false,
+ "$type": "ProfileCondition"
+ }
+ ],
+ "Codec": "hevc",
+ "$type": "CodecProfile"
+ }
+ ],
+ "ResponseProfiles": [
+ {
+ "Container": "m4v",
+ "Type": "Video",
+ "MimeType": "video/mp4",
+ "$type": "ResponseProfile"
+ }
+ ],
+ "SubtitleProfiles": [
+ {
+ "Format": "vtt",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "ass",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ },
+ {
+ "Format": "ssa",
+ "Method": "External",
+ "$type": "SubtitleProfile"
+ }
+ ],
+ "$type": "DeviceProfile"
+}
diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-dts-srt-2600k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-dts-srt-2600k.json
new file mode 100644
index 000000000..224365df6
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-dts-srt-2600k.json
@@ -0,0 +1,70 @@
+{
+ "Id": "a766d122b58e45d9492d17af77748bf5",
+ "Path": "/Media/MyVideo-720p.mp4",
+ "Container": "mov,mp4,m4a,3gp,3g2,mj2",
+ "Size": 835317696,
+ "Name": "MyVideo-720p",
+ "ETag": "579a34c6d5dfb21d81539a51220b6a23",
+ "RunTimeTicks": 25801230336,
+ "SupportsTranscoding": true,
+ "SupportsDirectStream": true,
+ "SupportsDirectPlay": true,
+ "SupportsProbing": true,
+ "MediaStreams": [
+ {
+ "Codec": "h264",
+ "CodecTag": "avc1",
+ "Language": "eng",
+ "TimeBase": "1/11988",
+ "VideoRange": "SDR",
+ "DisplayTitle": "720p H264 SDR",
+ "NalLengthSize": "0",
+ "BitRate": 2032876,
+ "BitDepth": 8,
+ "RefFrames": 1,
+ "IsDefault": true,
+ "Height": 720,
+ "Width": 1280,
+ "AverageFrameRate": 23.976,
+ "RealFrameRate": 23.976,
+ "Profile": "High",
+ "Type": 1,
+ "AspectRatio": "16:9",
+ "PixelFormat": "yuv420p",
+ "Level": 41
+ },
+ {
+ "Codec": "dts",
+ "Language": "eng",
+ "TimeBase": "1/48000",
+ "DisplayTitle": "En - DTS - 5.1 - Default",
+ "ChannelLayout": "5.1",
+ "BitRate": 384000,
+ "Channels": 6,
+ "SampleRate": 48000,
+ "IsDefault": true,
+ "Index": 1,
+ "Score": 202
+ },
+ {
+ "Codec": "srt",
+ "Language": "eng",
+ "TimeBase": "1/1000000",
+ "localizedUndefined": "Undefined",
+ "localizedDefault": "Default",
+ "localizedForced": "Forced",
+ "DisplayTitle": "En - Default",
+ "BitRate": 92,
+ "IsDefault": true,
+ "Type": 2,
+ "Index": 2,
+ "Score": 6421,
+ "IsExternal": true,
+ "IsTextSubtitleStream": true,
+ "SupportsExternalStream": true
+ }
+ ],
+ "Bitrate": 2590008,
+ "DefaultAudioStreamIndex": 1,
+ "DefaultSubtitleStreamIndex": 2
+}
diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-hevc-truehd-srt-15200k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-hevc-truehd-srt-15200k.json
new file mode 100644
index 000000000..a5393966f
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-hevc-truehd-srt-15200k.json
@@ -0,0 +1,74 @@
+{
+ "Id": "f6eab7118618ab26e61e495a1853481a",
+ "Path": "/Media/MyVideo-WEBDL-2160p.mp4",
+ "Container": "mov,mp4,m4a,3gp,3g2,mj2",
+ "Size": 6521110016,
+ "Name": "MyVideo WEBDL-2160p",
+ "ETag": "a2fb84b618ba2467fe377543f879e9bf",
+ "RunTimeTicks": 34318510080,
+ "SupportsTranscoding": true,
+ "SupportsDirectStream": true,
+ "SupportsDirectPlay": true,
+ "SupportsProbing": true,
+ "MediaStreams": [
+ {
+ "Codec": "hevc",
+ "CodecTag": "hev1",
+ "Language": "eng",
+ "ColorSpace": "bt2020nc",
+ "ColorTransfer": "smpte2084",
+ "ColorPrimaries": "bt2020",
+ "TimeBase": "1/16000",
+ "VideoRange": "HDR",
+ "DisplayTitle": "4K HEVC HDR",
+ "BitRate": 14715079,
+ "BitDepth": 8,
+ "RefFrames": 1,
+ "IsDefault": true,
+ "Height": 2160,
+ "Width": 3840,
+ "AverageFrameRate": 23.976,
+ "RealFrameRate": 23.976,
+ "Profile": "Main 10",
+ "Type": 1,
+ "AspectRatio": "16:9",
+ "PixelFormat": "yuv420p10le",
+ "Level": 150
+ },
+ {
+ "Codec": "truehd",
+ "CodecTag": "AC-3",
+ "Language": "eng",
+ "TimeBase": "1/48000",
+ "DisplayTitle": "TRUEHD - 7.1",
+ "ChannelLayout": "7.1",
+ "BitRate": 384000,
+ "Channels": 8,
+ "SampleRate": 48000,
+ "IsDefault": true,
+ "Index": 1,
+ "Score": 203
+ },
+ {
+ "Codec": "srt",
+ "Language": "eng",
+ "TimeBase": "1/1000000",
+ "localizedUndefined": "Undefined",
+ "localizedDefault": "Default",
+ "localizedForced": "Forced",
+ "DisplayTitle": "En - Default",
+ "BitRate": 92,
+ "IsDefault": true,
+ "Type": 2,
+ "Index": 2,
+ "Score": 6421,
+ "IsExternal": true,
+ "IsTextSubtitleStream": true,
+ "SupportsExternalStream": true,
+ "Path": "/Media/MyVideo-WEBDL-2160p.default.eng.srt"
+ }
+ ],
+ "Bitrate": 15201382,
+ "DefaultAudioStreamIndex": 1,
+ "DefaultSubtitleStreamIndex": 2
+}
diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-no-streams.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-no-streams.json
new file mode 100644
index 000000000..86713e255
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-no-streams.json
@@ -0,0 +1,17 @@
+{
+ "Id": "f6eab7118618ab26e61e495a1853481a",
+ "Path": "/Media/MyVideo-WEBDL-2160p.mp4",
+ "Container": "mov,mp4,m4a,3gp,3g2,mj2",
+ "Size": 6521110016,
+ "Name": "MyVideo WEBDL-2160p",
+ "ETag": "a2fb84b618ba2467fe377543f879e9bf",
+ "RunTimeTicks": 34318510080,
+ "SupportsTranscoding": true,
+ "SupportsDirectStream": true,
+ "SupportsDirectPlay": true,
+ "SupportsProbing": true,
+ "MediaStreams": [],
+ "Bitrate": 15201382,
+ "DefaultAudioStreamIndex": null,
+ "DefaultSubtitleStreamIndex": null
+}
diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
index ea86906e7..da0e9f5b1 100644
--- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
+++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
@@ -12,10 +12,13 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
@@ -30,7 +33,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
index 1e7fedb36..68059f980 100644
--- a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
+++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
@@ -1,4 +1,4 @@
-using Emby.Naming.Common;
+using Emby.Naming.Common;
using Emby.Naming.TV;
using Xunit;
@@ -9,6 +9,7 @@ namespace Jellyfin.Naming.Tests.TV
private readonly NamingOptions _namingOptions = new NamingOptions();
[Theory]
+ [InlineData("Season 21/One Piece 1001", 1001)]
[InlineData("Watchmen (2019)/Watchmen 1x03 [WEBDL-720p][EAC3 5.1][h264][-TBS] - She Was Killed by Space Junk.mkv", 3)]
[InlineData("The Daily Show/The Daily Show 25x22 - [WEBDL-720p][AAC 2.0][x264] Noah Baumbach-TBS.mkv", 22)]
[InlineData("Castle Rock 2x01 Que el rio siga su curso [WEB-DL HULU 1080p h264 Dual DD5.1 Subs].mkv", 1)]
diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
index 9a9a57be4..79f2366b8 100644
--- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
@@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Linq;
using Emby.Naming.Common;
using Emby.Naming.Video;
-using MediaBrowser.Model.IO;
using Xunit;
namespace Jellyfin.Naming.Tests.Video
diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs
index b76187842..cc9cfdd7d 100644
--- a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs
@@ -3,7 +3,6 @@ using System.Linq;
using Emby.Naming.Common;
using Emby.Naming.Video;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
using Xunit;
namespace Jellyfin.Naming.Tests.Video
diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
index e15f59e5a..8ec0262bd 100644
--- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
+++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
@@ -12,12 +12,15 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
- <PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
- <PackageReference Include="Moq" Version="4.17.2" />
+ <PackageReference Include="FsCheck.Xunit" Version="2.16.5" />
+ <PackageReference Include="Moq" Version="4.18.2" />
</ItemGroup>
<!-- Code Analyzers-->
@@ -27,7 +30,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
index 6b9397437..166bc0513 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
@@ -103,10 +103,7 @@ namespace Jellyfin.Networking.Tests
"[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)
{
- if (settings == null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
+ ArgumentNullException.ThrowIfNull(settings);
var conf = new NetworkConfiguration()
{
@@ -155,20 +152,11 @@ namespace Jellyfin.Networking.Tests
[InlineData("127.0.0.1", "127.0.0.1/8", "[127.0.0.1/32]")]
public void UnionCheck(string settings, string compare, string result)
{
- if (settings == null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
+ ArgumentNullException.ThrowIfNull(settings);
- if (compare == null)
- {
- throw new ArgumentNullException(nameof(compare));
- }
+ ArgumentNullException.ThrowIfNull(compare);
- if (result == null)
- {
- throw new ArgumentNullException(nameof(result));
- }
+ ArgumentNullException.ThrowIfNull(result);
var conf = new NetworkConfiguration()
{
@@ -264,20 +252,11 @@ namespace Jellyfin.Networking.Tests
public void TestCollectionEquality(string source, string dest, string result)
{
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
+ ArgumentNullException.ThrowIfNull(source);
- if (dest == null)
- {
- throw new ArgumentNullException(nameof(dest));
- }
+ ArgumentNullException.ThrowIfNull(dest);
- if (result == null)
- {
- throw new ArgumentNullException(nameof(result));
- }
+ ArgumentNullException.ThrowIfNull(result);
var conf = new NetworkConfiguration()
{
@@ -331,20 +310,11 @@ namespace Jellyfin.Networking.Tests
[InlineData("", "", false, "eth16")]
public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result)
{
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
+ ArgumentNullException.ThrowIfNull(source);
- if (bindAddresses == null)
- {
- throw new ArgumentNullException(nameof(bindAddresses));
- }
+ ArgumentNullException.ThrowIfNull(bindAddresses);
- if (result == null)
- {
- throw new ArgumentNullException(nameof(result));
- }
+ ArgumentNullException.ThrowIfNull(result);
var conf = new NetworkConfiguration()
{
@@ -393,7 +363,7 @@ namespace Jellyfin.Networking.Tests
// 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")]
- // User on external network, no binding - so result is the 1st external which is overriden.
+ // 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 assumed to be internal, no binding - so result is the 1st internal.
@@ -403,15 +373,9 @@ namespace Jellyfin.Networking.Tests
[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)
{
- if (lan == null)
- {
- throw new ArgumentNullException(nameof(lan));
- }
+ ArgumentNullException.ThrowIfNull(lan);
- if (bindAddresses == null)
- {
- throw new ArgumentNullException(nameof(bindAddresses));
- }
+ ArgumentNullException.ThrowIfNull(bindAddresses);
var conf = new NetworkConfiguration()
{
diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
index 9d6923d05..194229737 100644
--- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
+++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
@@ -13,10 +13,10 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@@ -33,7 +33,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs
index c0931dbcf..08b343cd8 100644
--- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs
+++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs
@@ -44,7 +44,7 @@ namespace Jellyfin.Providers.Tests.Manager
ValidateImages_Test(ImageType.Primary, 0, true, 0, false, 0);
}
- private static TheoryData<ImageType, int> GetImageTypesWithCount()
+ public static TheoryData<ImageType, int> GetImageTypesWithCount()
{
var theoryTypes = new TheoryData<ImageType, int>
{
diff --git a/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs
index b74b331b7..28b2e1d8f 100644
--- a/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs
+++ b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs
@@ -132,7 +132,7 @@ namespace Jellyfin.Providers.Tests.Manager
Assert.True(TestMergeBaseItemData<Audio, SongInfo>(propName, oldValue, Array.Empty<string>(), null, true, out _));
}
- private static TheoryData<string, object, object> MergeBaseItemData_SimpleField_ReplacesAppropriately_TestData()
+ public static TheoryData<string, object, object> MergeBaseItemData_SimpleField_ReplacesAppropriately_TestData()
=> new()
{
{ "IndexNumber", 1, 2 },
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/AudioResolverTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/AudioResolverTests.cs
index aec523882..33a9aca31 100644
--- a/tests/Jellyfin.Providers.Tests/MediaInfo/AudioResolverTests.cs
+++ b/tests/Jellyfin.Providers.Tests/MediaInfo/AudioResolverTests.cs
@@ -13,6 +13,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.MediaInfo;
+using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
@@ -43,6 +44,9 @@ public class AudioResolverTests
MediaStreams = new List<MediaStream>
{
new()
+ {
+ Type = MediaStreamType.Audio
+ }
}
}));
@@ -52,7 +56,7 @@ public class AudioResolverTests
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MediaInfoResolverTests.MetadataDirectoryRegex)))
.Returns(true);
- _audioResolver = new AudioResolver(localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
+ _audioResolver = new AudioResolver(Mock.Of<ILogger<AudioResolver>>(), localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
}
[Theory]
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs
index 98b4a6ccf..57674bb7f 100644
--- a/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs
+++ b/tests/Jellyfin.Providers.Tests/MediaInfo/MediaInfoResolverTests.cs
@@ -18,6 +18,7 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Providers.MediaInfo;
+using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
@@ -70,7 +71,7 @@ public class MediaInfoResolverTests
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MetadataDirectoryRegex)))
.Returns(true);
- _subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
+ _subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
}
[Fact]
@@ -201,14 +202,14 @@ public class MediaInfoResolverTests
var mediaEncoder = Mock.Of<IMediaEncoder>(MockBehavior.Strict);
var fileSystem = Mock.Of<IFileSystem>();
- var subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder, fileSystem, new NamingOptions());
+ var subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder, fileSystem, new NamingOptions());
var streams = await subtitleResolver.GetExternalStreamsAsync(video, 0, directoryService.Object, false, CancellationToken.None);
Assert.Empty(streams);
}
- private static TheoryData<string, MediaStream[], MediaStream[]> GetExternalStreams_MergeMetadata_HandlesOverridesCorrectly_Data()
+ public static TheoryData<string, MediaStream[], MediaStream[]> GetExternalStreams_MergeMetadata_HandlesOverridesCorrectly_Data()
{
var data = new TheoryData<string, MediaStream[], MediaStream[]>();
@@ -306,7 +307,7 @@ public class MediaInfoResolverTests
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MetadataDirectoryRegex)))
.Returns(true);
- var subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
+ var subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
var directoryService = GetDirectoryServiceForExternalFile(file);
var streams = await subtitleResolver.GetExternalStreamsAsync(video, 0, directoryService, false, CancellationToken.None);
@@ -359,7 +360,10 @@ public class MediaInfoResolverTests
var mediaStreams = new List<MediaStream>();
for (int i = 0; i < streamCount; i++)
{
- mediaStreams.Add(new());
+ mediaStreams.Add(new()
+ {
+ Type = MediaStreamType.Subtitle
+ });
}
return mediaStreams;
@@ -378,7 +382,7 @@ public class MediaInfoResolverTests
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MetadataDirectoryRegex)))
.Returns(true);
- var subtitleResolver = new SubtitleResolver(_localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
+ var subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), _localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
int startIndex = 1;
var streams = await subtitleResolver.GetExternalStreamsAsync(video, startIndex, directoryService.Object, false, CancellationToken.None);
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs
index 0e6457ce3..0c1c269a4 100644
--- a/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs
+++ b/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs
@@ -13,6 +13,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.MediaInfo;
+using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
@@ -43,6 +44,9 @@ public class SubtitleResolverTests
MediaStreams = new List<MediaStream>
{
new()
+ {
+ Type = MediaStreamType.Subtitle
+ }
}
}));
@@ -52,7 +56,7 @@ public class SubtitleResolverTests
fileSystem.Setup(fs => fs.DirectoryExists(It.IsRegex(MediaInfoResolverTests.MetadataDirectoryRegex)))
.Returns(true);
- _subtitleResolver = new SubtitleResolver(localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
+ _subtitleResolver = new SubtitleResolver(Mock.Of<ILogger<SubtitleResolver>>(), localizationManager, mediaEncoder.Object, fileSystem.Object, new NamingOptions());
}
[Theory]
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs
index 7e88cdb20..6b2a05241 100644
--- a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs
+++ b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs
@@ -19,7 +19,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo
{
public class VideoImageProviderTests
{
- private static TheoryData<Video> GetImage_UnsupportedInput_ReturnsNoImage_TestData()
+ public static TheoryData<Video> GetImage_UnsupportedInput_ReturnsNoImage_TestData()
{
return new()
{
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
index 55920c928..918802d77 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
+++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
@@ -21,10 +21,13 @@
<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
@@ -36,7 +39,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/MediaStreamSelectorTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/MediaStreamSelectorTests.cs
index d59f2f4e5..538010f6c 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Library/MediaStreamSelectorTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Library/MediaStreamSelectorTests.cs
@@ -16,15 +16,39 @@ public class MediaStreamSelectorTests
}
[Theory]
- [InlineData(true)]
- [InlineData(false)]
- public void GetDefaultAudioStreamIndex_WithoutDefault_NotNull(bool preferDefaultTrack)
+ [InlineData(new string[0], false, 1)]
+ [InlineData(new string[0], true, 1)]
+ [InlineData(new[] { "eng" }, false, 2)]
+ [InlineData(new[] { "eng" }, true, 1)]
+ [InlineData(new[] { "eng", "fre" }, false, 2)]
+ [InlineData(new[] { "fre", "eng" }, false, 1)]
+ [InlineData(new[] { "eng", "fre" }, true, 1)]
+ public void GetDefaultAudioStreamIndex_PreferredLanguage_SelectsCorrect(string[] preferredLanguages, bool preferDefaultTrack, int expectedIndex)
{
- var streams = new[]
+ var streams = new MediaStream[]
{
- new MediaStream()
+ new()
+ {
+ Index = 0,
+ Type = MediaStreamType.Video,
+ IsDefault = true
+ },
+ new()
+ {
+ Index = 1,
+ Type = MediaStreamType.Audio,
+ Language = "fre",
+ IsDefault = true
+ },
+ new()
+ {
+ Index = 2,
+ Type = MediaStreamType.Audio,
+ Language = "eng",
+ IsDefault = false
+ }
};
- Assert.NotNull(MediaStreamSelector.GetDefaultAudioStreamIndex(streams, Array.Empty<string>(), preferDefaultTrack));
+ Assert.Equal(expectedIndex, MediaStreamSelector.GetDefaultAudioStreamIndex(streams, preferredLanguages, preferDefaultTrack));
}
}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs
index 09aec82b0..f107b1ef9 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs
@@ -85,6 +85,17 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
EpisodeTitle = "The VCR Illumination"
});
+ data.Add(
+ "Lorem ipsum dolor sit amet: consect 2018_12_06_21_06_00",
+ new TimerInfo
+ {
+ Name = "Lorem ipsum dolor sit amet: consect",
+ IsProgramSeries = true,
+ StartDate = new DateTime(2018, 12, 6, 21, 6, 0, DateTimeKind.Local),
+ OriginalAirDate = new DateTime(2018, 12, 6),
+ EpisodeTitle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor"
+ });
+
return data;
}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs
index 3b3e38bd1..e1d2bb2d5 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs
@@ -18,7 +18,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect
}
/// <summary>
- /// /token reponse.
+ /// /token response.
/// </summary>
[Fact]
public void Deserialize_Token_Response_Live_Success()
diff --git a/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
index 28d832ef8..c32d89ea5 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
@@ -50,7 +50,10 @@ namespace Jellyfin.Server.Implementations.Tests.QuickConnect
[Fact]
public void IsEnabled_QuickConnectUnavailable_False()
- => Assert.False(_quickConnectManager.IsEnabled);
+ {
+ _config.QuickConnectAvailable = false;
+ Assert.False(_quickConnectManager.IsEnabled);
+ }
[Theory]
[InlineData("", "DeviceId", "Client", "1.0.0")]
@@ -69,19 +72,31 @@ namespace Jellyfin.Server.Implementations.Tests.QuickConnect
[Fact]
public void TryConnect_QuickConnectUnavailable_ThrowsAuthenticationException()
- => Assert.Throws<AuthenticationException>(() => _quickConnectManager.TryConnect(_quickConnectAuthInfo));
+ {
+ _config.QuickConnectAvailable = false;
+ Assert.Throws<AuthenticationException>(() => _quickConnectManager.TryConnect(_quickConnectAuthInfo));
+ }
[Fact]
public void CheckRequestStatus_QuickConnectUnavailable_ThrowsAuthenticationException()
- => Assert.Throws<AuthenticationException>(() => _quickConnectManager.CheckRequestStatus(string.Empty));
+ {
+ _config.QuickConnectAvailable = false;
+ Assert.Throws<AuthenticationException>(() => _quickConnectManager.CheckRequestStatus(string.Empty));
+ }
[Fact]
public void AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
- => Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
+ {
+ _config.QuickConnectAvailable = false;
+ Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
+ }
[Fact]
public void GetAuthorizedRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
- => Assert.Throws<AuthenticationException>(() => _quickConnectManager.GetAuthorizedRequest(string.Empty));
+ {
+ _config.QuickConnectAvailable = false;
+ Assert.Throws<AuthenticationException>(() => _quickConnectManager.GetAuthorizedRequest(string.Empty));
+ }
[Fact]
public void IsEnabled_QuickConnectAvailable_True()
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs
new file mode 100644
index 000000000..18588bd67
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/IndexNumberComparerTests.cs
@@ -0,0 +1,49 @@
+using System;
+using Emby.Server.Implementations.Sorting;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Sorting;
+using Xunit;
+
+namespace Jellyfin.Server.Implementations.Tests.Sorting;
+
+public class IndexNumberComparerTests
+{
+ private readonly IBaseItemComparer _cmp = new IndexNumberComparer();
+
+ public static TheoryData<BaseItem?, BaseItem?> Compare_GivenNull_ThrowsArgumentNullException_TestData()
+ => new()
+ {
+ { null, new Audio() },
+ { new Audio(), null }
+ };
+
+ [Theory]
+ [MemberData(nameof(Compare_GivenNull_ThrowsArgumentNullException_TestData))]
+ public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem? x, BaseItem? y)
+ {
+ Assert.Throws<ArgumentNullException>(() => _cmp.Compare(x, y));
+ }
+
+ [Theory]
+ [InlineData(null, null, 0)]
+ [InlineData(0, null, 1)]
+ [InlineData(null, 0, -1)]
+ [InlineData(1, 1, 0)]
+ [InlineData(0, 1, -1)]
+ [InlineData(1, 0, 1)]
+ public void Compare_ValidIndices_SortsExpected(int? index1, int? index2, int expected)
+ {
+ BaseItem x = new Audio
+ {
+ IndexNumber = index1
+ };
+ BaseItem y = new Audio
+ {
+ IndexNumber = index2
+ };
+
+ Assert.Equal(expected, _cmp.Compare(x, y));
+ Assert.Equal(-expected, _cmp.Compare(y, x));
+ }
+}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs
new file mode 100644
index 000000000..261092e01
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs
@@ -0,0 +1,49 @@
+using System;
+using Emby.Server.Implementations.Sorting;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Sorting;
+using Xunit;
+
+namespace Jellyfin.Server.Implementations.Tests.Sorting;
+
+public class ParentIndexNumberComparerTests
+{
+ private readonly IBaseItemComparer _cmp = new ParentIndexNumberComparer();
+
+ public static TheoryData<BaseItem?, BaseItem?> Compare_GivenNull_ThrowsArgumentNullException_TestData()
+ => new()
+ {
+ { null, new Audio() },
+ { new Audio(), null }
+ };
+
+ [Theory]
+ [MemberData(nameof(Compare_GivenNull_ThrowsArgumentNullException_TestData))]
+ public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem? x, BaseItem? y)
+ {
+ Assert.Throws<ArgumentNullException>(() => _cmp.Compare(x, y));
+ }
+
+ [Theory]
+ [InlineData(null, null, 0)]
+ [InlineData(0, null, 1)]
+ [InlineData(null, 0, -1)]
+ [InlineData(1, 1, 0)]
+ [InlineData(0, 1, -1)]
+ [InlineData(1, 0, 1)]
+ public void Compare_ValidIndices_SortsExpected(int? parentIndex1, int? parentIndex2, int expected)
+ {
+ BaseItem x = new Audio
+ {
+ ParentIndexNumber = parentIndex1
+ };
+ BaseItem y = new Audio
+ {
+ ParentIndexNumber = parentIndex2
+ };
+
+ Assert.Equal(expected, _cmp.Compare(x, y));
+ Assert.Equal(-expected, _cmp.Compare(y, x));
+ }
+}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json
index b766e668e..fa8fbd8d2 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json
+++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json
@@ -253,7 +253,7 @@
"versions": [
{
"version": "5.0.0.0",
- "changelog": "Updated to use NextPVR API v5, no longer compatable with API v4.\n",
+ "changelog": "Updated to use NextPVR API v5, no longer compatible with API v4.\n",
"targetAbi": "10.7.0.0",
"sourceUrl": "https://repo.jellyfin.org/releases/plugin/nextpvr/nextpvr_5.0.0.0.zip",
"checksum": "d70f694d14bf9462ba2b2ebe110068d3",
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs
index 0afb6f88d..52df1cd60 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs
@@ -83,6 +83,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
var res = await response.Content.ReadAsStreamAsync();
var data = await JsonSerializer.DeserializeAsync<ConfigurationPageInfo[]>(res, _jsonOpions);
+ Assert.NotNull(data);
Assert.Empty(data);
}
}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs
index e72dacfe0..0dd22644a 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs
@@ -62,7 +62,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
using var contentStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var user = await JsonSerializer.DeserializeAsync<StartupUserDto>(contentStream, _jsonOptions).ConfigureAwait(false);
- Assert.NotEmpty(user!.Name);
+ Assert.NotNull(user);
+ Assert.NotNull(user.Name);
+ Assert.NotEmpty(user.Name);
Assert.Null(user.Password);
}
@@ -87,7 +89,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
var contentStream = await getResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
var newUser = await JsonSerializer.DeserializeAsync<StartupUserDto>(contentStream, _jsonOptions).ConfigureAwait(false);
- Assert.Equal(user.Name, newUser!.Name);
+ Assert.NotNull(newUser);
+ Assert.Equal(user.Name, newUser.Name);
+ Assert.NotNull(newUser.Password);
Assert.NotEmpty(newUser.Password);
Assert.NotEqual(user.Password, newUser.Password);
}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs
index 9d34c39a2..2b825a93a 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs
@@ -46,6 +46,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
var users = await JsonSerializer.DeserializeAsync<UserDto[]>(
await response.Content.ReadAsStreamAsync().ConfigureAwait(false), _jsonOpions).ConfigureAwait(false);
// User are hidden by default
+ Assert.NotNull(users);
Assert.Empty(users);
}
@@ -60,6 +61,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var users = await JsonSerializer.DeserializeAsync<UserDto[]>(
await response.Content.ReadAsStreamAsync().ConfigureAwait(false), _jsonOpions).ConfigureAwait(false);
+ Assert.NotNull(users);
Assert.Single(users);
Assert.False(users![0].HasConfiguredPassword);
}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
index 55101ce10d..659737392 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
+++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
@@ -9,14 +9,17 @@
<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="6.0.3" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="Xunit.Priority" Version="1.1.6" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
- <PackageReference Include="Moq" Version="4.17.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
</ItemGroup>
<ItemGroup>
@@ -33,7 +36,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
index adaf624a9..48c49bf84 100644
--- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
@@ -11,7 +11,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Extensions.Logging;
-using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
namespace Jellyfin.Server.Integration.Tests
{
diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
index f5d60d2d3..b2653b28b 100644
--- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
+++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
@@ -10,13 +10,16 @@
<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="6.0.3" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
- <PackageReference Include="Moq" Version="4.17.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
</ItemGroup>
<!-- Code Analyzers -->
@@ -26,7 +29,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
index 7689d1da3..f03448eed 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
@@ -13,10 +13,13 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
- <PackageReference Include="Moq" Version="4.17.2" />
- <PackageReference Include="xunit" Version="2.4.1" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
+ <PackageReference Include="Moq" Version="4.18.2" />
+ <PackageReference Include="xunit" Version="2.4.2" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
@@ -27,7 +30,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs
index 7c9952030..988abce81 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Jellyfin.Data.Entities;