Merge branch 'master' into providermanager-cleanup

This commit is contained in:
Claus Vium
2022-10-07 09:57:16 +02:00
committed by GitHub
470 changed files with 6148 additions and 9078 deletions

View File

@@ -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>>();

View File

@@ -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.406" 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>

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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.406" 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>

View File

@@ -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.406" 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>

View File

@@ -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.406" 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>

View File

@@ -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.406" 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>

View File

@@ -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);
}
}
}

View File

@@ -5,6 +5,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)]

View File

@@ -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.406" 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>

View File

@@ -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[]>
{

View File

@@ -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.406" 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>

View File

@@ -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.406" 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>

View File

@@ -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);

View File

@@ -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];

View File

@@ -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];

View File

@@ -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];

View File

@@ -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>();

View File

@@ -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": [

View File

@@ -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

View File

@@ -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)

View File

@@ -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>())

View File

@@ -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()

View File

@@ -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.406" 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>

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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.406" 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>

View File

@@ -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)]

View File

@@ -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

View File

@@ -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

View File

@@ -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.406" 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>

View File

@@ -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()
{

View File

@@ -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.406" 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>

View File

@@ -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>
{

View File

@@ -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 },

View File

@@ -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]

View File

@@ -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);

View File

@@ -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]

View File

@@ -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()
{

View File

@@ -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.406" 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>

View File

@@ -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));
}
}

View File

@@ -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;
}

View File

@@ -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()

View File

@@ -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()

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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",

View File

@@ -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);
}
}

View File

@@ -34,8 +34,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
var client = _factory.CreateClient();
client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
using var getResponse = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode);
using var response = await client.GetAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
@@ -45,8 +45,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
var client = _factory.CreateClient();
client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
using var getResponse = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode);
using var response = await client.DeleteAsync("/Dlna/Profiles/" + NonExistentProfile).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
@@ -61,8 +61,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
Name = "ThisProfileDoesNotExist"
};
using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NotFound, getResponse.StatusCode);
using var response = await client.PostAsJsonAsync("/Dlna/Profiles/" + NonExistentProfile, deviceProfile, _jsonOptions).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
@@ -77,8 +77,8 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
Name = "ThisProfileIsNew"
};
using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode);
using var response = await client.PostAsJsonAsync("/Dlna/Profiles", deviceProfile, _jsonOptions).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
}
[Fact]
@@ -115,20 +115,46 @@ namespace Jellyfin.Server.Integration.Tests.Controllers
Id = _newDeviceProfileId
};
using var getResponse = await client.PostAsJsonAsync("/Dlna/Profiles", updatedProfile, _jsonOptions).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode);
using var postResponse = await client.PostAsJsonAsync("/Dlna/Profiles/" + _newDeviceProfileId, updatedProfile, _jsonOptions).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode);
// Verify that the profile got updated
using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType);
Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet);
var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>(
await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
_jsonOptions).ConfigureAwait(false);
Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsNew", StringComparison.Ordinal)));
var newProfile = profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal));
Assert.NotNull(newProfile);
_newDeviceProfileId = newProfile!.Id;
}
[Fact]
[Priority(4)]
[Priority(5)]
public async Task DeleteProfile_Valid_NoContent()
{
var client = _factory.CreateClient();
client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
using var getResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId).ConfigureAwait(false);
Console.WriteLine(await getResponse.Content.ReadAsStringAsync().ConfigureAwait(false));
Assert.Equal(HttpStatusCode.NoContent, getResponse.StatusCode);
using var deleteResponse = await client.DeleteAsync("/Dlna/Profiles/" + _newDeviceProfileId).ConfigureAwait(false);
Assert.Equal(HttpStatusCode.NoContent, deleteResponse.StatusCode);
// Verify that the profile got deleted
using var response = await client.GetAsync("/Dlna/ProfileInfos").ConfigureAwait(false);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType);
Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet);
var profiles = await JsonSerializer.DeserializeAsync<DeviceProfileInfo[]>(
await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
_jsonOptions).ConfigureAwait(false);
Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal)));
}
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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.406" 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>

View File

@@ -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
{

View File

@@ -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.406" 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>

View File

@@ -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.406" 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>

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Jellyfin.Data.Entities;