aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDavid Ullmer <davidullmer@outlook.de>2021-08-10 14:03:21 +0200
committerDavid Ullmer <davidullmer@outlook.de>2021-08-10 14:03:21 +0200
commit45e0f7893ba8f53827983109557447d2c0c8adcf (patch)
tree05ba6fec826a6bcf4cdb17aa1ccfa6939358052c /tests
parentb5880c26808a6d7f183acb3f7977b42e13ccbf8a (diff)
parent854bb79ae8b1e7004c731939e54e52ef937abe47 (diff)
Merge remote-tracking branch 'upstream/master' into localization-test
Diffstat (limited to 'tests')
-rw-r--r--tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs58
-rw-r--r--tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj9
-rw-r--r--tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj8
-rw-r--r--tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs34
-rw-r--r--tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj7
-rw-r--r--tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj7
-rw-r--r--tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs (renamed from tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs)9
-rw-r--r--tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs (renamed from tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs)3
-rw-r--r--tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj35
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs45
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs (renamed from tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs)6
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs (renamed from tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs)6
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs (renamed from tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs)4
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs (renamed from tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs)3
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs (renamed from tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs)4
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs (renamed from tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs)21
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs (renamed from tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs)6
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs (renamed from tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs)6
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs (renamed from tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs)6
-rw-r--r--tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs (renamed from tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs)3
-rw-r--r--tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs18
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs7
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj7
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs25
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_video_metadata.json111
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json (renamed from tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/some_matadata.json)0
-rw-r--r--tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs76
-rw-r--r--tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs14
-rw-r--r--tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj8
-rw-r--r--tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj7
-rw-r--r--tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs3
-rw-r--r--tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs3
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs2
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs6
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs7
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs9
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs208
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/StubTests.cs3
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs242
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs38
-rw-r--r--tests/Jellyfin.Networking.Tests/IPHostTests.cs53
-rw-r--r--tests/Jellyfin.Networking.Tests/IPNetAddressTests.cs49
-rw-r--r--tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj8
-rw-r--r--tests/Jellyfin.Networking.Tests/NetworkParseTests.cs60
-rw-r--r--tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj34
-rw-r--r--tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs96
-rw-r--r--tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs (renamed from tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs)3
-rw-r--r--tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs27
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs49
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs6
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj8
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs47
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs115
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs73
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/discover.json1
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/lineup.json1
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/192.168.1.182/discover.json (renamed from tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/discover.json)0
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/192.168.1.182/lineup.json (renamed from tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/lineup.json)0
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs31
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/BaseJellyfinTestController.cs14
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/EncoderController.cs53
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs61
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs48
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj9
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs5
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs32
-rw-r--r--tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj9
-rw-r--r--tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs31
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj7
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs8
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs2
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs2
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs4
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs4
78 files changed, 1566 insertions, 466 deletions
diff --git a/tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs b/tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs
new file mode 100644
index 0000000000..1170838156
--- /dev/null
+++ b/tests/Jellyfin.Api.Tests/Controllers/DynamicHlsControllerTests.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using AutoFixture;
+using AutoFixture.AutoMoq;
+using Jellyfin.Api.Controllers;
+using Jellyfin.Api.Helpers;
+using Jellyfin.Api.Models.StreamingDtos;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaEncoding;
+using Moq;
+using Xunit;
+
+namespace Jellyfin.Api.Tests.Controllers
+{
+ public class DynamicHlsControllerTests
+ {
+ [Theory]
+ [MemberData(nameof(GetSegmentLengths_Success_TestData))]
+ public void GetSegmentLengths_Success(long runtimeTicks, int segmentlength, double[] expected)
+ {
+ var res = DynamicHlsController.GetSegmentLengthsInternal(runtimeTicks, segmentlength);
+ Assert.Equal(expected.Length, res.Length);
+ for (int i = 0; i < expected.Length; i++)
+ {
+ Assert.Equal(expected[i], res[i]);
+ }
+ }
+
+ public static IEnumerable<object[]> GetSegmentLengths_Success_TestData()
+ {
+ yield return new object[] { 0, 6, Array.Empty<double>() };
+ yield return new object[]
+ {
+ TimeSpan.FromSeconds(3).Ticks,
+ 6,
+ new double[] { 3 }
+ };
+ yield return new object[]
+ {
+ TimeSpan.FromSeconds(6).Ticks,
+ 6,
+ new double[] { 6 }
+ };
+ yield return new object[]
+ {
+ TimeSpan.FromSeconds(3.3333333).Ticks,
+ 6,
+ new double[] { 3.3333333 }
+ };
+ yield return new object[]
+ {
+ TimeSpan.FromSeconds(9.3333333).Ticks,
+ 6,
+ new double[] { 6, 3.3333333 }
+ };
+ }
+ }
+}
diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
index 397b863b70..4edd843841 100644
--- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
+++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
@@ -8,9 +8,6 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
@@ -18,12 +15,12 @@
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
- <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.5" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.8" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="Moq" Version="4.16.1" />
</ItemGroup>
diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
index 8018b29663..e4350c3369 100644
--- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
+++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
@@ -8,17 +8,15 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
</ItemGroup>
<!-- Code Analyzers -->
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs
deleted file mode 100644
index 9ded01f2b1..0000000000
--- a/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.Text.Json;
-using MediaBrowser.Common.Json.Converters;
-using Xunit;
-
-namespace Jellyfin.Common.Tests.Json
-{
- public static class JsonBoolNumberTests
- {
- [Theory]
- [InlineData("1", true)]
- [InlineData("0", false)]
- [InlineData("2", true)]
- [InlineData("true", true)]
- [InlineData("false", false)]
- public static void Deserialize_Number_Valid_Success(string input, bool? output)
- {
- var options = new JsonSerializerOptions();
- options.Converters.Add(new JsonBoolNumberConverter());
- var value = JsonSerializer.Deserialize<bool>(input, options);
- Assert.Equal(value, output);
- }
-
- [Theory]
- [InlineData(true, "true")]
- [InlineData(false, "false")]
- public static void Serialize_Bool_Success(bool input, string output)
- {
- var options = new JsonSerializerOptions();
- options.Converters.Add(new JsonBoolNumberConverter());
- var value = JsonSerializer.Serialize(input, options);
- Assert.Equal(value, output);
- }
- }
-} \ No newline at end of file
diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
index ad16276989..5b269a4b20 100644
--- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
+++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
@@ -8,18 +8,15 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<!-- Code Analyzers -->
diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
index f7c21f0721..713f6423c9 100644
--- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
+++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
@@ -3,18 +3,15 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<!-- Code Analyzers -->
diff --git a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs b/tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs
index 0adf098c33..7730841a1c 100644
--- a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs
@@ -1,11 +1,10 @@
using System;
using System.Linq;
-using MediaBrowser.Controller.Sorting;
using Xunit;
-namespace Jellyfin.Controller.Tests
+namespace Jellyfin.Extensions.Tests
{
- public class AlphanumComparatorTests
+ public class AlphanumericComparatorTests
{
// InlineData is pre-sorted
[Theory]
@@ -20,10 +19,10 @@ namespace Jellyfin.Controller.Tests
[InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567892")]
[InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891a")]
[InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891b")]
- public void AlphanumComparatorTest(params string?[] strings)
+ public void AlphanumericComparatorTest(params string?[] strings)
{
var copy = strings.Reverse().ToArray();
- Array.Sort(copy, new AlphanumComparator());
+ Array.Sort(copy, new AlphanumericComparator());
Assert.True(strings.SequenceEqual(copy));
}
}
diff --git a/tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs
index 9903409fa6..6fdca46944 100644
--- a/tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs
@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
-using MediaBrowser.Common.Extensions;
using Xunit;
-namespace Jellyfin.Common.Tests.Extensions
+namespace Jellyfin.Extensions.Tests
{
public static class CopyToExtensionsTests
{
diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
new file mode 100644
index 0000000000..9272d5eef9
--- /dev/null
+++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
@@ -0,0 +1,35 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net5.0</TargetFramework>
+ <IsPackable>false</IsPackable>
+ <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
+ <PackageReference Include="xunit" Version="2.4.1" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ <PackageReference Include="coverlet.collector" Version="3.1.0">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ <PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
+ </ItemGroup>
+
+ <!-- Code Analyzers -->
+ <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="../../MediaBrowser.Model/MediaBrowser.Model.csproj" />
+ <ProjectReference Include="../../src/Jellyfin.Extensions/Jellyfin.Extensions.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs
new file mode 100644
index 0000000000..d0e3e94568
--- /dev/null
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs
@@ -0,0 +1,45 @@
+using System.Globalization;
+using System.Text.Json;
+using FsCheck;
+using FsCheck.Xunit;
+using Jellyfin.Extensions.Json.Converters;
+using Xunit;
+
+namespace Jellyfin.Extensions.Tests.Json.Converters
+{
+ public class JsonBoolNumberTests
+ {
+ private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions()
+ {
+ Converters =
+ {
+ new JsonBoolNumberConverter()
+ }
+ };
+
+ [Theory]
+ [InlineData("1", true)]
+ [InlineData("0", false)]
+ [InlineData("2", true)]
+ [InlineData("true", true)]
+ [InlineData("false", false)]
+ public void Deserialize_Number_Valid_Success(string input, bool? output)
+ {
+ var value = JsonSerializer.Deserialize<bool>(input, _jsonOptions);
+ Assert.Equal(value, output);
+ }
+
+ [Theory]
+ [InlineData(true, "true")]
+ [InlineData(false, "false")]
+ public void Serialize_Bool_Success(bool input, string output)
+ {
+ var value = JsonSerializer.Serialize(input, _jsonOptions);
+ Assert.Equal(value, output);
+ }
+
+ [Property]
+ public Property Deserialize_NonZeroInt_True(NonZeroInt input)
+ => JsonSerializer.Deserialize<bool>(input.ToString(), _jsonOptions).ToProperty();
+ }
+}
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs
index ca300401da..f2ca2ff081 100644
--- a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs
@@ -1,11 +1,11 @@
-using System;
+using System;
using System.Text.Json;
using System.Text.Json.Serialization;
-using Jellyfin.Common.Tests.Models;
+using Jellyfin.Extensions.Tests.Json.Models;
using MediaBrowser.Model.Session;
using Xunit;
-namespace Jellyfin.Common.Tests.Json
+namespace Jellyfin.Extensions.Tests.Json.Converters
{
public static class JsonCommaDelimitedArrayTests
{
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs
index 34ad9bac79..92886dcd28 100644
--- a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs
@@ -1,10 +1,10 @@
-using System.Text.Json;
+using System.Text.Json;
using System.Text.Json.Serialization;
-using Jellyfin.Common.Tests.Models;
+using Jellyfin.Extensions.Tests.Json.Models;
using MediaBrowser.Model.Session;
using Xunit;
-namespace Jellyfin.Common.Tests.Json
+namespace Jellyfin.Extensions.Tests.Json.Converters
{
public static class JsonCommaDelimitedIReadOnlyListTests
{
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs
index dbfad3c2ff..8465d465ab 100644
--- a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs
@@ -1,9 +1,9 @@
using System;
using System.Text.Json;
-using MediaBrowser.Common.Json.Converters;
+using Jellyfin.Extensions.Json.Converters;
using Xunit;
-namespace Jellyfin.Common.Tests.Json
+namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonGuidConverterTests
{
diff --git a/tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs
index 955d296cc8..af9227de27 100644
--- a/tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs
@@ -1,9 +1,10 @@
using System.Text.Json;
using System.Text.Json.Serialization;
+using Jellyfin.Extensions.Json.Converters;
using MediaBrowser.Model.Entities;
using Xunit;
-namespace Jellyfin.Model.Tests.Entities
+namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonLowerCaseConverterTests
{
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs
index cb3b66c4c5..b0dbc09e4f 100644
--- a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs
@@ -1,9 +1,9 @@
using System;
using System.Text.Json;
-using MediaBrowser.Common.Json.Converters;
+using Jellyfin.Extensions.Json.Converters;
using Xunit;
-namespace Jellyfin.Common.Tests.Json
+namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonNullableGuidConverterTests
{
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs
index fd77694b30..655e070742 100644
--- a/tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs
@@ -1,19 +1,18 @@
-using System.Text.Json;
-using MediaBrowser.Common.Json.Converters;
+using System.Text.Json;
+using Jellyfin.Extensions.Json.Converters;
using Xunit;
-namespace Jellyfin.Common.Tests.Json
+namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonStringConverterTests
{
- private readonly JsonSerializerOptions _jsonSerializerOptions
- = new ()
+ private readonly JsonSerializerOptions _jsonSerializerOptions = new ()
+ {
+ Converters =
{
- Converters =
- {
- new JsonStringConverter()
- }
- };
+ new JsonStringConverter()
+ }
+ };
[Theory]
[InlineData("\"test\"", "test")]
@@ -36,4 +35,4 @@ namespace Jellyfin.Common.Tests.Json
Assert.Equal(deserialized, output);
}
}
-} \ No newline at end of file
+}
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs
index f2cefdbf8e..5fbac7eab0 100644
--- a/tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs
@@ -1,9 +1,9 @@
-using System;
+using System;
using System.Text.Json;
-using MediaBrowser.Common.Json.Converters;
+using Jellyfin.Extensions.Json.Converters;
using Xunit;
-namespace Jellyfin.Common.Tests.Json
+namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonVersionConverterTests
{
diff --git a/tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs
index 276e1bfbe2..ef135278fd 100644
--- a/tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs
@@ -1,8 +1,8 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
-using MediaBrowser.Common.Json.Converters;
+using Jellyfin.Extensions.Json.Converters;
-namespace Jellyfin.Common.Tests.Models
+namespace Jellyfin.Extensions.Tests.Json.Models
{
/// <summary>
/// The generic body model.
diff --git a/tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs
index 627454b25f..8e7b5a35b4 100644
--- a/tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs
+++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs
@@ -1,8 +1,8 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Text.Json.Serialization;
-using MediaBrowser.Common.Json.Converters;
+using Jellyfin.Extensions.Json.Converters;
-namespace Jellyfin.Common.Tests.Models
+namespace Jellyfin.Extensions.Tests.Json.Models
{
/// <summary>
/// The generic body <c>IReadOnlyList</c> model.
diff --git a/tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs
index cbdbcf112c..c72216d94b 100644
--- a/tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs
+++ b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs
@@ -1,8 +1,7 @@
using System;
-using MediaBrowser.Common.Extensions;
using Xunit;
-namespace Jellyfin.Common.Tests.Extensions
+namespace Jellyfin.Extensions.Tests
{
public static class ShuffleExtensionsTests
{
diff --git a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs
new file mode 100644
index 0000000000..d1aa2e4764
--- /dev/null
+++ b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs
@@ -0,0 +1,18 @@
+using System;
+using Xunit;
+
+namespace Jellyfin.Extensions.Tests
+{
+ public class StringExtensionsTests
+ {
+ [Theory]
+ [InlineData("", '_', 0)]
+ [InlineData("___", '_', 3)]
+ [InlineData("test\x00", '\x00', 1)]
+ [InlineData("Imdb=tt0119567|Tmdb=330|TmdbCollection=328", '|', 2)]
+ public void ReadOnlySpan_Count_Success(string str, char needle, int count)
+ {
+ Assert.Equal(count, str.AsSpan().Count(needle));
+ }
+ }
+}
diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs
index 415682e855..2955104a27 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs
@@ -1,7 +1,7 @@
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
-using MediaBrowser.Common.Json;
+using Jellyfin.Extensions.Json;
using MediaBrowser.MediaEncoding.Probing;
using Xunit;
@@ -14,9 +14,10 @@ namespace Jellyfin.MediaEncoding.Tests
public async Task Test(string fileName)
{
var path = Path.Join("Test Data", fileName);
- using (var stream = File.OpenRead(path))
+ await using (var stream = File.OpenRead(path))
{
- await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.Options).ConfigureAwait(false);
+ var res = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.Options).ConfigureAwait(false);
+ Assert.NotNull(res);
}
}
}
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
index 8321d02552..a6a948e2b7 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
+++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
@@ -8,9 +8,6 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
@@ -21,10 +18,10 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<!-- Code Analyzers -->
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
index 69e2aa4372..d8089eea2d 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
@@ -1,6 +1,8 @@
+using System;
+using System.Globalization;
using System.IO;
using System.Text.Json;
-using MediaBrowser.Common.Json;
+using Jellyfin.Extensions.Json;
using MediaBrowser.MediaEncoding.Probing;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
@@ -17,9 +19,9 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
[Fact]
public void GetMediaInfo_MetaData_Success()
{
- var bytes = File.ReadAllBytes("Test Data/Probing/some_matadata.json");
+ var bytes = File.ReadAllBytes("Test Data/Probing/video_metadata.json");
var internalMediaInfoResult = JsonSerializer.Deserialize<InternalMediaInfoResult>(bytes, _jsonOptions);
- MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, VideoType.VideoFile, false, "Test Data/Probing/some_matadata.mkv", MediaProtocol.File);
+ MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, VideoType.VideoFile, false, "Test Data/Probing/video_metadata.mkv", MediaProtocol.File);
Assert.Single(res.MediaStreams);
@@ -52,5 +54,22 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
Assert.Empty(res.Chapters);
Assert.Equal("Just color bars", res.Overview);
}
+
+ [Fact]
+ public void GetMediaInfo_MusicVideo_Success()
+ {
+ var bytes = File.ReadAllBytes("Test Data/Probing/music_video_metadata.json");
+ var internalMediaInfoResult = JsonSerializer.Deserialize<InternalMediaInfoResult>(bytes, _jsonOptions);
+ MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, VideoType.VideoFile, false, "Test Data/Probing/music_video.mkv", MediaProtocol.File);
+
+ Assert.Equal("The Title", res.Name);
+ Assert.Equal("Title, The", res.ForcedSortName);
+ Assert.Single(res.Artists);
+ Assert.Equal("The Artist", res.Artists[0]);
+ Assert.Equal("Album", res.Album);
+ Assert.Equal(2021, res.ProductionYear);
+ Assert.True(res.PremiereDate.HasValue);
+ Assert.Equal(DateTime.Parse("2021-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate);
+ }
}
}
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_video_metadata.json b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_video_metadata.json
new file mode 100644
index 0000000000..97d6600a4a
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/music_video_metadata.json
@@ -0,0 +1,111 @@
+{
+ "streams": [
+ {
+ "index": 0,
+ "codec_name": "h264",
+ "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
+ "profile": "High",
+ "codec_type": "video",
+ "codec_time_base": "1001/48000",
+ "codec_tag_string": "[0][0][0][0]",
+ "codec_tag": "0x0000",
+ "width": 1920,
+ "height": 1080,
+ "coded_width": 1920,
+ "coded_height": 1088,
+ "closed_captions": 0,
+ "has_b_frames": 0,
+ "sample_aspect_ratio": "1:1",
+ "display_aspect_ratio": "16:9",
+ "pix_fmt": "yuv420p",
+ "level": 42,
+ "chroma_location": "left",
+ "field_order": "progressive",
+ "refs": 1,
+ "is_avc": "true",
+ "nal_length_size": "4",
+ "r_frame_rate": "24000/1001",
+ "avg_frame_rate": "24000/1001",
+ "time_base": "1/1000",
+ "start_pts": 0,
+ "start_time": "0.000000",
+ "bits_per_raw_sample": "8",
+ "disposition": {
+ "default": 1,
+ "dub": 0,
+ "original": 0,
+ "comment": 0,
+ "lyrics": 0,
+ "karaoke": 0,
+ "forced": 0,
+ "hearing_impaired": 0,
+ "visual_impaired": 0,
+ "clean_effects": 0,
+ "attached_pic": 0,
+ "timed_thumbnails": 0
+ },
+ "tags": {
+ "language": "eng"
+ }
+ },
+ {
+ "index": 1,
+ "codec_name": "aac",
+ "codec_long_name": "AAC (Advanced Audio Coding)",
+ "profile": "LC",
+ "codec_type": "audio",
+ "codec_time_base": "1/48000",
+ "codec_tag_string": "[0][0][0][0]",
+ "codec_tag": "0x0000",
+ "sample_fmt": "fltp",
+ "sample_rate": "48000",
+ "channels": 2,
+ "channel_layout": "stereo",
+ "bits_per_sample": 0,
+ "r_frame_rate": "0/0",
+ "avg_frame_rate": "0/0",
+ "time_base": "1/1000",
+ "start_pts": 0,
+ "start_time": "0.000000",
+ "disposition": {
+ "default": 1,
+ "dub": 0,
+ "original": 0,
+ "comment": 0,
+ "lyrics": 0,
+ "karaoke": 0,
+ "forced": 0,
+ "hearing_impaired": 0,
+ "visual_impaired": 0,
+ "clean_effects": 0,
+ "attached_pic": 0,
+ "timed_thumbnails": 0
+ },
+ "tags": {
+ "language": "eng"
+ }
+ }
+ ],
+ "chapters": [
+ ],
+ "format": {
+ "filename": "music_video.mkv",
+ "nb_streams": 2,
+ "nb_programs": 0,
+ "format_name": "matroska,webm",
+ "format_long_name": "Matroska / WebM",
+ "start_time": "0.000000",
+ "duration": "180.000000",
+ "size": "500000000",
+ "bit_rate": "22222222",
+ "probe_score": 100,
+ "tags": {
+ "TITLE-eng": "The Title",
+ "TITLESORT": "Title, The",
+ "ARTIST": "The Artist",
+ "ARTISTSORT": "Artist, The",
+ "ALBUM": "Album",
+ "DATE_RELEASED": "2021-01-01"
+ }
+ }
+}
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/some_matadata.json b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
index 720fc5c8fa..720fc5c8fa 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/some_matadata.json
+++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/Probing/video_metadata.json
diff --git a/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
new file mode 100644
index 0000000000..e2274e19ee
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Entities/MediaStreamTests.cs
@@ -0,0 +1,76 @@
+using MediaBrowser.Model.Entities;
+using Xunit;
+
+namespace Jellyfin.Model.Tests.Entities
+{
+ public class MediaStreamTests
+ {
+ [Theory]
+ [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(960, 540, false, "540p")]
+ [InlineData(960, 540, true, "540i")]
+ [InlineData(1280, 720, false, "720p")]
+ [InlineData(1280, 720, true, "720i")]
+ [InlineData(1920, 1080, false, "1080p")]
+ [InlineData(1920, 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(720, 480, false, "480p")]
+ [InlineData(768, 576, false, "576p")]
+ [InlineData(960, 720, false, "720p")]
+ [InlineData(1280, 528, false, "720p")]
+ [InlineData(1280, 532, false, "720p")]
+ [InlineData(1280, 534, false, "720p")]
+ [InlineData(1280, 536, false, "720p")]
+ [InlineData(1280, 544, false, "720p")]
+ [InlineData(1280, 690, false, "720p")]
+ [InlineData(1280, 694, false, "720p")]
+ [InlineData(1280, 696, false, "720p")]
+ [InlineData(1280, 716, false, "720p")]
+ [InlineData(1280, 718, false, "720p")]
+ [InlineData(1912, 792, false, "1080p")]
+ [InlineData(1916, 1076, false, "1080p")]
+ [InlineData(1918, 1080, false, "1080p")]
+ [InlineData(1920, 796, false, "1080p")]
+ [InlineData(1920, 800, false, "1080p")]
+ [InlineData(1920, 802, false, "1080p")]
+ [InlineData(1920, 804, false, "1080p")]
+ [InlineData(1920, 808, false, "1080p")]
+ [InlineData(1920, 816, false, "1080p")]
+ [InlineData(1920, 856, false, "1080p")]
+ [InlineData(1920, 960, false, "1080p")]
+ [InlineData(1920, 1024, false, "1080p")]
+ [InlineData(1920, 1040, false, "1080p")]
+ [InlineData(1920, 1072, false, "1080p")]
+ [InlineData(1440, 1072, false, "1080p")]
+ [InlineData(1440, 1080, false, "1080p")]
+ [InlineData(3840, 1600, false, "4K")]
+ [InlineData(3840, 1606, false, "4K")]
+ [InlineData(3840, 1608, false, "4K")]
+ [InlineData(3840, 2160, false, "4K")]
+ [InlineData(7680, 4320, false, "8K")]
+ public void GetResolutionText_Valid(int? width, int? height, bool interlaced, string expected)
+ {
+ var mediaStream = new MediaStream()
+ {
+ Width = width,
+ Height = height,
+ IsInterlaced = interlaced
+ };
+
+ Assert.Equal(expected, mediaStream.GetResolutionText());
+ }
+ }
+}
diff --git a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs
index 5864a05094..0a4e060df6 100644
--- a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs
+++ b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs
@@ -1,3 +1,6 @@
+using System;
+using FsCheck;
+using FsCheck.Xunit;
using MediaBrowser.Model.Extensions;
using Xunit;
@@ -10,9 +13,20 @@ namespace Jellyfin.Model.Tests.Extensions
[InlineData("banana", "Banana")]
[InlineData("Banana", "Banana")]
[InlineData("ä", "Ä")]
+ [InlineData("\027", "\027")]
public void StringHelper_ValidArgs_Success(string input, string expectedResult)
{
Assert.Equal(expectedResult, StringHelper.FirstToUpper(input));
}
+
+ [Property]
+ public Property FirstToUpper_RandomArg_Correct(NonEmptyString input)
+ {
+ var result = StringHelper.FirstToUpper(input.Item);
+
+ // We check IsLower instead of IsUpper because both return false for non-letters
+ return (!char.IsLower(result[0])).Label("First char is uppercase")
+ .And(input.Item.Length == 1 || result[1..].Equals(input.Item[1..], StringComparison.Ordinal)).Label("Remaining chars are unmodified");
+ }
}
}
diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
index c5b51ef766..06ff22c7e0 100644
--- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
+++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
@@ -3,17 +3,15 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
</ItemGroup>
<!-- Code Analyzers -->
diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
index ebb134fc3c..510c8f60a3 100644
--- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
+++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
@@ -8,17 +8,14 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<ItemGroup>
diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
index 921c2b1f57..2873f61613 100644
--- a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
+++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
@@ -70,7 +70,8 @@ namespace Jellyfin.Naming.Tests.TV
[InlineData("Log Horizon 2/[HorribleSubs] Log Horizon 2 - 03 [720p].mkv", 3)] // digit in series name
[InlineData("Season 1/seriesname 05.mkv", 5)] // no hyphen between series name and episode number
[InlineData("[BBT-RMX] Ranma ½ - 154 [50AC421A].mkv", 154)] // hyphens in the pre-name info, triple digit episode number
- // TODO: [InlineData("Case Closed (1996-2007)/Case Closed - 317.mkv", 317)] // triple digit episode number
+ [InlineData("Season 2/Episode 21 - 94 Meetings.mp4", 21)] // Title starts with a number
+ // [InlineData("Case Closed (1996-2007)/Case Closed - 317.mkv", 317)] // triple digit episode number
// TODO: [InlineData("Season 2/16 12 Some Title.avi", 16)]
// TODO: [InlineData("/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv/The.Legend.of.Condor.Heroes.2017.E07.V2.web-dl.1080p.h264.aac-hdctv.mkv", 7)]
// TODO: [InlineData("Season 4/Uchuu.Senkan.Yamato.2199.E03.avi", 3)]
diff --git a/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs
index 89579c0376..6d49ac832d 100644
--- a/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs
+++ b/tests/Jellyfin.Naming.Tests/TV/SimpleEpisodeTests.cs
@@ -21,7 +21,8 @@ namespace Jellyfin.Naming.Tests.TV
[InlineData("[Baz-Bar]Foo - [1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)]
[InlineData(@"/Foo/The.Series.Name.S01E04.WEBRip.x264-Baz[Bar]/the.series.name.s01e04.webrip.x264-Baz[Bar].mkv", "The.Series.Name", 1, 4)]
[InlineData(@"Love.Death.and.Robots.S01.1080p.NF.WEB-DL.DDP5.1.x264-NTG/Love.Death.and.Robots.S01E01.Sonnies.Edge.1080p.NF.WEB-DL.DDP5.1.x264-NTG.mkv", "Love.Death.and.Robots", 1, 1)]
- // TODO: [InlineData("[Baz-Bar]Foo - 01 - 12[1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)]
+ [InlineData("[YuiSubs] Tensura Nikki - Tensei Shitara Slime Datta Ken/[YuiSubs] Tensura Nikki - Tensei Shitara Slime Datta Ken - 12 (NVENC H.265 1080p).mkv", "Tensura Nikki - Tensei Shitara Slime Datta Ken", null, 12)]
+ [InlineData("[Baz-Bar]Foo - 01 - 12[1080p][Multiple Subtitle]/[Baz-Bar] Foo - 05 [1080p][Multiple Subtitle].mkv", "Foo", null, 5)]
// TODO: [InlineData("E:\\Anime\\Yahari Ore no Seishun Love Comedy wa Machigatteiru\\Yahari Ore no Seishun Love Comedy wa Machigatteiru. Zoku\\Oregairu Zoku 11 - Hayama Hayato Always Renconds to Everyone's Expectations..mkv", "Yahari Ore no Seishun Love Comedy wa Machigatteiru", null, 11)]
// TODO: [InlineData(@"/Library/Series/The Grand Tour (2016)/Season 1/S01E01 The Holy Trinity.mkv", "The Grand Tour", 1, 1)]
public void TestSimple(string path, string seriesName, int? seasonNumber, int? episodeNumber)
diff --git a/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs
index 950899d7e7..b1141df479 100644
--- a/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/CleanDateTimeTests.cs
@@ -58,7 +58,7 @@ namespace Jellyfin.Naming.Tests.Video
{
input = Path.GetFileName(input);
- var result = new VideoResolver(_namingOptions).CleanDateTime(input);
+ var result = VideoResolver.CleanDateTime(input, _namingOptions);
Assert.Equal(expectedName, result.Name, true);
Assert.Equal(expectedYear, result.Year);
diff --git a/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs
index a720bdadeb..fb050cf5a7 100644
--- a/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs
@@ -7,7 +7,7 @@ namespace Jellyfin.Naming.Tests.Video
{
public sealed class CleanStringTests
{
- private readonly VideoResolver _videoResolver = new VideoResolver(new NamingOptions());
+ private readonly NamingOptions _namingOptions = new NamingOptions();
[Theory]
[InlineData("Super movie 480p.mp4", "Super movie")]
@@ -26,7 +26,7 @@ namespace Jellyfin.Naming.Tests.Video
// FIXME: [InlineData("After The Sunset - [0004].mkv", "After The Sunset")]
public void CleanStringTest_NeedsCleaning_Success(string input, string expectedName)
{
- Assert.True(_videoResolver.TryCleanString(input, out ReadOnlySpan<char> newName));
+ Assert.True(VideoResolver.TryCleanString(input, _namingOptions, out ReadOnlySpan<char> newName));
// TODO: compare spans when XUnit supports it
Assert.Equal(expectedName, newName.ToString());
}
@@ -41,7 +41,7 @@ namespace Jellyfin.Naming.Tests.Video
[InlineData("Run lola run (lola rennt) (2009).mp4")]
public void CleanStringTest_DoesntNeedCleaning_False(string? input)
{
- Assert.False(_videoResolver.TryCleanString(input, out ReadOnlySpan<char> newName));
+ Assert.False(VideoResolver.TryCleanString(input, _namingOptions, out ReadOnlySpan<char> newName));
Assert.True(newName.IsEmpty);
}
}
diff --git a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs
index 2f173b0ce0..f872f94f8e 100644
--- a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs
@@ -104,13 +104,6 @@ namespace Jellyfin.Naming.Tests.Video
Assert.Equal(rule, res.Rule);
}
- [Fact]
- public void TestFlagsParser()
- {
- var flags = new FlagParser(_videoOptions).GetFlags(string.Empty);
- Assert.Empty(flags);
- }
-
private ExtraResolver GetExtraTypeParser(NamingOptions videoOptions)
{
return new ExtraResolver(videoOptions);
diff --git a/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs b/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs
index 69de96a47a..1762b91b9d 100644
--- a/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/Format3DTests.cs
@@ -22,8 +22,7 @@ namespace Jellyfin.Naming.Tests.Video
[Fact]
public void Test3DName()
{
- var result =
- new VideoResolver(_namingOptions).ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.3d.hsbs.mkv");
+ var result = VideoResolver.ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.3d.hsbs.mkv", _namingOptions);
Assert.Equal("hsbs", result?.Format3D);
Assert.Equal("Oblivion", result?.Name);
@@ -58,15 +57,13 @@ namespace Jellyfin.Naming.Tests.Video
private void Test(string input, bool is3D, string? format3D)
{
- var parser = new Format3DParser(_namingOptions);
-
- var result = parser.Parse(input);
+ var result = Format3DParser.Parse(input, _namingOptions);
Assert.Equal(is3D, result.Is3D);
if (format3D == null)
{
- Assert.Null(result.Format3D);
+ Assert.Null(result?.Format3D);
}
else
{
diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
index 6e803593e8..d02f8ae924 100644
--- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
@@ -9,7 +9,7 @@ namespace Jellyfin.Naming.Tests.Video
{
public class MultiVersionTests
{
- private readonly VideoListResolver _videoListResolver = new VideoListResolver(new NamingOptions());
+ private readonly NamingOptions _namingOptions = new NamingOptions();
[Fact]
public void TestMultiEdition1()
@@ -22,11 +22,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/X-Men Days of Future Past/X-Men Days of Future Past [hsbs].mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Single(result[0].Extras);
@@ -43,11 +45,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/X-Men Days of Future Past/X-Men Days of Future Past [banana].mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Single(result[0].Extras);
@@ -63,11 +67,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/The Phantom of the Opera (1925)/The Phantom of the Opera (1925) - 1929 version.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Single(result[0].AlternateVersions);
@@ -87,11 +93,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/M/Movie 7.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(7, result.Count);
Assert.Empty(result[0].Extras);
@@ -113,11 +121,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Movie/Movie-8.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Empty(result[0].Extras);
@@ -140,11 +150,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Mo/Movie 9.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(9, result.Count);
Assert.Empty(result[0].Extras);
@@ -163,11 +175,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Movie/Movie 5.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(5, result.Count);
Assert.Empty(result[0].Extras);
@@ -188,11 +202,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Iron Man/Iron Man (2011).mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(5, result.Count);
Assert.Empty(result[0].Extras);
@@ -214,11 +230,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Iron Man/Iron Man[test].mkv",
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Empty(result[0].Extras);
@@ -243,11 +261,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Iron Man/Iron Man [test].mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Empty(result[0].Extras);
@@ -266,11 +286,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Iron Man/Iron Man - C (2007).mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(2, result.Count);
}
@@ -289,11 +311,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Iron Man/Iron Man_3d.hsbs.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(7, result.Count);
Assert.Empty(result[0].Extras);
@@ -314,11 +338,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Iron Man/Iron Man (2011).mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(5, result.Count);
Assert.Empty(result[0].Extras);
@@ -334,11 +360,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/Blade Runner (1982)/Blade Runner (1982) [EE by ADM] [480p HEVC AAC,AAC,AAC].mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Empty(result[0].Extras);
@@ -354,11 +382,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) [2160p] Blu-ray.x265.AAC.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Empty(result[0].Extras);
@@ -374,11 +404,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/John Wick - Kapitel 3 (2019) [imdbid=tt6146586]/John Wick - Kapitel 3 (2019) [imdbid=tt6146586] - Version 2.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
Assert.Empty(result[0].Extras);
@@ -394,11 +426,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/movies/John Wick - Chapter 3 (2019)/John Wick - Chapter 3 (2019) [Version 2.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(2, result.Count);
}
@@ -406,7 +440,7 @@ namespace Jellyfin.Naming.Tests.Video
[Fact]
public void TestEmptyList()
{
- var result = _videoListResolver.Resolve(new List<FileSystemMetadata>()).ToList();
+ var result = VideoListResolver.Resolve(new List<FileSystemMetadata>(), _namingOptions).ToList();
Assert.Empty(result);
}
diff --git a/tests/Jellyfin.Naming.Tests/Video/StubTests.cs b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs
index 6e759c6d6b..1d50df7a60 100644
--- a/tests/Jellyfin.Naming.Tests/Video/StubTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs
@@ -29,8 +29,7 @@ namespace Jellyfin.Naming.Tests.Video
[Fact]
public void TestStubName()
{
- var result =
- new VideoResolver(_namingOptions).ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.dvd.disc");
+ var result = VideoResolver.ResolveFile(@"C:/Users/media/Desktop/Video Test/Movies/Oblivion/Oblivion.dvd.disc", _namingOptions);
Assert.Equal("Oblivion", result?.Name);
}
diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs
index 08af766699..9e0776c3cd 100644
--- a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs
@@ -9,7 +9,7 @@ namespace Jellyfin.Naming.Tests.Video
{
public class VideoListResolverTests
{
- private readonly VideoListResolver _videoListResolver = new VideoListResolver(new NamingOptions());
+ private readonly NamingOptions _namingOptions = new NamingOptions();
[Fact]
public void TestStackAndExtras()
@@ -40,11 +40,13 @@ namespace Jellyfin.Naming.Tests.Video
"WillyWonka-trailer.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(5, result.Count);
var batman = result.FirstOrDefault(x => string.Equals(x.Name, "Batman", StringComparison.Ordinal));
@@ -67,11 +69,13 @@ namespace Jellyfin.Naming.Tests.Video
"300.nfo"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -85,11 +89,13 @@ namespace Jellyfin.Naming.Tests.Video
"300 trailer.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -103,11 +109,13 @@ namespace Jellyfin.Naming.Tests.Video
"X-Men Days of Future Past-trailer.mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -122,11 +130,13 @@ namespace Jellyfin.Naming.Tests.Video
"X-Men Days of Future Past-trailer2.mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -140,11 +150,13 @@ namespace Jellyfin.Naming.Tests.Video
"Looper.2012.bluray.720p.x264.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -162,11 +174,13 @@ namespace Jellyfin.Naming.Tests.Video
"My video 5.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(5, result.Count);
}
@@ -180,11 +194,13 @@ namespace Jellyfin.Naming.Tests.Video
@"M:/Movies (DVD)/Movies (Musical)/Sound of Music (1965)/Sound of Music Disc 2"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = true,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = true,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -199,11 +215,13 @@ namespace Jellyfin.Naming.Tests.Video
@"My movie #2.mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = true,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = true,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(2, result.Count);
}
@@ -218,11 +236,13 @@ namespace Jellyfin.Naming.Tests.Video
@"No (2012) part1-trailer.mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -237,11 +257,13 @@ namespace Jellyfin.Naming.Tests.Video
@"No (2012)-trailer.mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -257,11 +279,13 @@ namespace Jellyfin.Naming.Tests.Video
@"trailer.mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -277,11 +301,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/MCFAMILY-PC/Private3$/Heterosexual/Breast In Class 2 Counterfeit Racks (2011)/Breast In Class 2 Disc 2 cd2.avi"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(2, result.Count);
}
@@ -294,11 +320,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/nas-markrobbo78/Videos/INDEX HTPC/Movies/Watched/3 - ACTION/Argo (2012)/movie.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -311,11 +339,13 @@ namespace Jellyfin.Naming.Tests.Video
@"The Colony.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -329,11 +359,13 @@ namespace Jellyfin.Naming.Tests.Video
@"Four Sisters and a Wedding - B.avi"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -347,11 +379,13 @@ namespace Jellyfin.Naming.Tests.Video
@"Four Rooms - A.mp4"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(2, result.Count);
}
@@ -365,11 +399,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/Server/Despicable Me/movie-trailer.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
@@ -385,11 +421,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/Server/Despicable Me/Baywatch (2017) - Trailer.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Equal(4, result.Count);
}
@@ -403,11 +441,13 @@ namespace Jellyfin.Naming.Tests.Video
@"/Movies/Despicable Me/trailers/trailer.mkv"
};
- var result = _videoListResolver.Resolve(files.Select(i => new FileSystemMetadata
- {
- IsDirectory = false,
- FullName = i
- }).ToList()).ToList();
+ var result = VideoListResolver.Resolve(
+ files.Select(i => new FileSystemMetadata
+ {
+ IsDirectory = false,
+ FullName = i
+ }).ToList(),
+ _namingOptions).ToList();
Assert.Single(result);
}
diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs
index 9bbbe29709..ac5a7a21e6 100644
--- a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs
@@ -9,7 +9,7 @@ namespace Jellyfin.Naming.Tests.Video
{
public class VideoResolverTests
{
- private readonly VideoResolver _videoResolver = new VideoResolver(new NamingOptions());
+ private static NamingOptions _namingOptions = new NamingOptions();
public static IEnumerable<object[]> ResolveFile_ValidFileNameTestData()
{
@@ -148,7 +148,7 @@ namespace Jellyfin.Naming.Tests.Video
yield return new object[]
{
new VideoFileInfo(
- path: @"/server/Movies/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - Ozlem/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - Ozlem.mp4",
+ path: @"/server/Movies/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF.mp4",
container: "mp4",
name: "Rain Man",
year: 1988)
@@ -159,27 +159,27 @@ namespace Jellyfin.Naming.Tests.Video
[MemberData(nameof(ResolveFile_ValidFileNameTestData))]
public void ResolveFile_ValidFileName_Success(VideoFileInfo expectedResult)
{
- var result = _videoResolver.ResolveFile(expectedResult.Path);
+ var result = VideoResolver.ResolveFile(expectedResult.Path, _namingOptions);
Assert.NotNull(result);
- Assert.Equal(result?.Path, expectedResult.Path);
- Assert.Equal(result?.Container, expectedResult.Container);
- Assert.Equal(result?.Name, expectedResult.Name);
- Assert.Equal(result?.Year, expectedResult.Year);
- Assert.Equal(result?.ExtraType, expectedResult.ExtraType);
- Assert.Equal(result?.Format3D, expectedResult.Format3D);
- Assert.Equal(result?.Is3D, expectedResult.Is3D);
- Assert.Equal(result?.IsStub, expectedResult.IsStub);
- Assert.Equal(result?.StubType, expectedResult.StubType);
- Assert.Equal(result?.IsDirectory, expectedResult.IsDirectory);
- Assert.Equal(result?.FileNameWithoutExtension, expectedResult.FileNameWithoutExtension);
- Assert.Equal(result?.ToString(), expectedResult.ToString());
+ Assert.Equal(result!.Path, expectedResult.Path);
+ Assert.Equal(result.Container, expectedResult.Container);
+ Assert.Equal(result.Name, expectedResult.Name);
+ Assert.Equal(result.Year, expectedResult.Year);
+ Assert.Equal(result.ExtraType, expectedResult.ExtraType);
+ Assert.Equal(result.Format3D, expectedResult.Format3D);
+ Assert.Equal(result.Is3D, expectedResult.Is3D);
+ Assert.Equal(result.IsStub, expectedResult.IsStub);
+ Assert.Equal(result.StubType, expectedResult.StubType);
+ Assert.Equal(result.IsDirectory, expectedResult.IsDirectory);
+ Assert.Equal(result.FileNameWithoutExtension.ToString(), expectedResult.FileNameWithoutExtension.ToString());
+ Assert.Equal(result.ToString(), expectedResult.ToString());
}
[Fact]
public void ResolveFile_EmptyPath()
{
- var result = _videoResolver.ResolveFile(string.Empty);
+ var result = VideoResolver.ResolveFile(string.Empty, _namingOptions);
Assert.Null(result);
}
@@ -194,12 +194,16 @@ namespace Jellyfin.Naming.Tests.Video
string.Empty
};
- var results = paths.Select(path => _videoResolver.ResolveDirectory(path)).ToList();
+ var results = paths.Select(path => VideoResolver.ResolveDirectory(path, _namingOptions)).ToList();
Assert.Equal(3, results.Count);
Assert.NotNull(results[0]);
Assert.NotNull(results[1]);
Assert.Null(results[2]);
+ foreach (var result in results)
+ {
+ Assert.Null(result?.Container);
+ }
}
}
}
diff --git a/tests/Jellyfin.Networking.Tests/IPHostTests.cs b/tests/Jellyfin.Networking.Tests/IPHostTests.cs
new file mode 100644
index 0000000000..ec3a1300c8
--- /dev/null
+++ b/tests/Jellyfin.Networking.Tests/IPHostTests.cs
@@ -0,0 +1,53 @@
+using FsCheck;
+using FsCheck.Xunit;
+using MediaBrowser.Common.Net;
+using Xunit;
+
+namespace Jellyfin.Networking.Tests
+{
+ public static class IPHostTests
+ {
+ /// <summary>
+ /// Checks IP address formats.
+ /// </summary>
+ /// <param name="address">IP Address.</param>
+ [Theory]
+ [InlineData("127.0.0.1")]
+ [InlineData("127.0.0.1:123")]
+ [InlineData("localhost")]
+ [InlineData("localhost:1345")]
+ [InlineData("www.google.co.uk")]
+ [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")]
+ [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")]
+ [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]:124")]
+ [InlineData("fe80::7add:12ff:febb:c67b%16")]
+ [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")]
+ [InlineData("fe80::7add:12ff:febb:c67b%16:123")]
+ [InlineData("[fe80::7add:12ff:febb:c67b%16]")]
+ [InlineData("192.168.1.2/255.255.255.0")]
+ [InlineData("192.168.1.2/24")]
+ public static void TryParse_ValidHostStrings_True(string address)
+ => Assert.True(IPHost.TryParse(address, out _));
+
+ [Property]
+ public static Property TryParse_IPv4Address_True(IPv4Address address)
+ => IPHost.TryParse(address.Item.ToString(), out _).ToProperty();
+
+ [Property]
+ public static Property TryParse_IPv6Address_True(IPv6Address address)
+ => IPHost.TryParse(address.Item.ToString(), out _).ToProperty();
+
+ /// <summary>
+ /// All should be invalid address strings.
+ /// </summary>
+ /// <param name="address">Invalid address strings.</param>
+ [Theory]
+ [InlineData("256.128.0.0.0.1")]
+ [InlineData("127.0.0.1#")]
+ [InlineData("localhost!")]
+ [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")]
+ [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")]
+ public static void TryParse_InvalidAddressString_False(string address)
+ => Assert.False(IPHost.TryParse(address, out _));
+ }
+}
diff --git a/tests/Jellyfin.Networking.Tests/IPNetAddressTests.cs b/tests/Jellyfin.Networking.Tests/IPNetAddressTests.cs
new file mode 100644
index 0000000000..aa2dbc57a2
--- /dev/null
+++ b/tests/Jellyfin.Networking.Tests/IPNetAddressTests.cs
@@ -0,0 +1,49 @@
+using FsCheck;
+using FsCheck.Xunit;
+using MediaBrowser.Common.Net;
+using Xunit;
+
+namespace Jellyfin.Networking.Tests
+{
+ public static class IPNetAddressTests
+ {
+ /// <summary>
+ /// Checks IP address formats.
+ /// </summary>
+ /// <param name="address">IP Address.</param>
+ [Theory]
+ [InlineData("127.0.0.1")]
+ [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")]
+ [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")]
+ [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")]
+ [InlineData("fe80::7add:12ff:febb:c67b%16")]
+ [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")]
+ [InlineData("fe80::7add:12ff:febb:c67b%16:123")]
+ [InlineData("[fe80::7add:12ff:febb:c67b%16]")]
+ [InlineData("192.168.1.2/255.255.255.0")]
+ [InlineData("192.168.1.2/24")]
+ public static void TryParse_ValidIPStrings_True(string address)
+ => Assert.True(IPNetAddress.TryParse(address, out _));
+
+ [Property]
+ public static Property TryParse_IPv4Address_True(IPv4Address address)
+ => IPNetAddress.TryParse(address.Item.ToString(), out _).ToProperty();
+
+ [Property]
+ public static Property TryParse_IPv6Address_True(IPv6Address address)
+ => IPNetAddress.TryParse(address.Item.ToString(), out _).ToProperty();
+
+ /// <summary>
+ /// All should be invalid address strings.
+ /// </summary>
+ /// <param name="address">Invalid address strings.</param>
+ [Theory]
+ [InlineData("256.128.0.0.0.1")]
+ [InlineData("127.0.0.1#")]
+ [InlineData("localhost!")]
+ [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")]
+ [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")]
+ public static void TryParse_InvalidAddressString_False(string address)
+ => Assert.False(IPNetAddress.TryParse(address, out _));
+ }
+}
diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
index d5268facc9..2c6e2e5f66 100644
--- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
+++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
@@ -8,17 +8,15 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="FsCheck.Xunit" Version="2.15.3" />
<PackageReference Include="Moq" Version="4.16.1" />
</ItemGroup>
diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
index 671b8598de..97c14d463b 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
@@ -57,66 +57,6 @@ namespace Jellyfin.Networking.Tests
}
/// <summary>
- /// Checks IP address formats.
- /// </summary>
- /// <param name="address">IP Address.</param>
- [Theory]
- [InlineData("127.0.0.1")]
- [InlineData("127.0.0.1:123")]
- [InlineData("localhost")]
- [InlineData("localhost:1345")]
- [InlineData("www.google.co.uk")]
- [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")]
- [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")]
- [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]:124")]
- [InlineData("fe80::7add:12ff:febb:c67b%16")]
- [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")]
- [InlineData("fe80::7add:12ff:febb:c67b%16:123")]
- [InlineData("[fe80::7add:12ff:febb:c67b%16]")]
- [InlineData("192.168.1.2/255.255.255.0")]
- [InlineData("192.168.1.2/24")]
- public void ValidHostStrings(string address)
- {
- Assert.True(IPHost.TryParse(address, out _));
- }
-
- /// <summary>
- /// Checks IP address formats.
- /// </summary>
- /// <param name="address">IP Address.</param>
- [Theory]
- [InlineData("127.0.0.1")]
- [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")]
- [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")]
- [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")]
- [InlineData("fe80::7add:12ff:febb:c67b%16")]
- [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")]
- [InlineData("fe80::7add:12ff:febb:c67b%16:123")]
- [InlineData("[fe80::7add:12ff:febb:c67b%16]")]
- [InlineData("192.168.1.2/255.255.255.0")]
- [InlineData("192.168.1.2/24")]
- public void ValidIPStrings(string address)
- {
- Assert.True(IPNetAddress.TryParse(address, out _));
- }
-
- /// <summary>
- /// All should be invalid address strings.
- /// </summary>
- /// <param name="address">Invalid address strings.</param>
- [Theory]
- [InlineData("256.128.0.0.0.1")]
- [InlineData("127.0.0.1#")]
- [InlineData("localhost!")]
- [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")]
- [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")]
- public void InvalidAddressString(string address)
- {
- Assert.False(IPNetAddress.TryParse(address, out _));
- Assert.False(IPHost.TryParse(address, out _));
- }
-
- /// <summary>
/// Test collection parsing.
/// </summary>
/// <param name="settings">Collection to parse.</param>
diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
new file mode 100644
index 0000000000..195fc8801d
--- /dev/null
+++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
@@ -0,0 +1,34 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net5.0</TargetFramework>
+ <IsPackable>false</IsPackable>
+ <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
+ <PackageReference Include="Moq" Version="4.16.1" />
+ <PackageReference Include="xunit" Version="2.4.1" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ <PackageReference Include="coverlet.collector" Version="3.1.0">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ </ItemGroup>
+
+ <!-- Code Analyzers -->
+ <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="../../MediaBrowser.Providers/MediaBrowser.Providers.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs
new file mode 100644
index 0000000000..b160e676e4
--- /dev/null
+++ b/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs
@@ -0,0 +1,96 @@
+#pragma warning disable CA1002 // Do not expose generic lists
+
+using System.Collections.Generic;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Globalization;
+using MediaBrowser.Providers.MediaInfo;
+using Moq;
+using Xunit;
+
+namespace Jellyfin.Providers.Tests.MediaInfo
+{
+ public class SubtitleResolverTests
+ {
+ public static IEnumerable<object[]> AddExternalSubtitleStreams_GivenMixedFilenames_ReturnsValidSubtitles_TestData()
+ {
+ var index = 0;
+ yield return new object[]
+ {
+ new List<MediaStream>(),
+ "/video/My.Video.mkv",
+ index,
+ new[]
+ {
+ "/video/My.Video.mp3",
+ "/video/My.Video.png",
+ "/video/My.Video.srt",
+ "/video/My.Video.txt",
+ "/video/My.Video.vtt",
+ "/video/My.Video.ass",
+ "/video/My.Video.sub",
+ "/video/My.Video.ssa",
+ "/video/My.Video.smi",
+ "/video/My.Video.sami",
+ "/video/My.Video.en.srt",
+ "/video/My.Video.default.en.srt",
+ "/video/My.Video.default.forced.en.srt",
+ "/video/My.Video.en.default.forced.srt",
+ "/video/My.Video.With.Additional.Garbage.en.srt",
+ "/video/My.Video With Additional Garbage.srt"
+ },
+ new[]
+ {
+ CreateMediaStream("/video/My.Video.srt", "srt", null, index++),
+ CreateMediaStream("/video/My.Video.vtt", "vtt", null, index++),
+ CreateMediaStream("/video/My.Video.ass", "ass", null, index++),
+ CreateMediaStream("/video/My.Video.sub", "sub", null, index++),
+ CreateMediaStream("/video/My.Video.ssa", "ssa", null, index++),
+ CreateMediaStream("/video/My.Video.smi", "smi", null, index++),
+ CreateMediaStream("/video/My.Video.sami", "sami", null, index++),
+ CreateMediaStream("/video/My.Video.en.srt", "srt", "en", index++),
+ CreateMediaStream("/video/My.Video.default.en.srt", "srt", "en", index++, isDefault: true),
+ CreateMediaStream("/video/My.Video.default.forced.en.srt", "srt", "en", index++, isForced: true, isDefault: true),
+ CreateMediaStream("/video/My.Video.en.default.forced.srt", "srt", "en", index++, isForced: true, isDefault: true),
+ CreateMediaStream("/video/My.Video.With.Additional.Garbage.en.srt", "srt", "en", index),
+ }
+ };
+ }
+
+ [Theory]
+ [MemberData(nameof(AddExternalSubtitleStreams_GivenMixedFilenames_ReturnsValidSubtitles_TestData))]
+ public void AddExternalSubtitleStreams_GivenMixedFilenames_ReturnsValidSubtitles(List<MediaStream> streams, string videoPath, int startIndex, string[] files, MediaStream[] expectedResult)
+ {
+ new SubtitleResolver(Mock.Of<ILocalizationManager>()).AddExternalSubtitleStreams(streams, videoPath, startIndex, files);
+
+ Assert.Equal(expectedResult.Length, streams.Count);
+ for (var i = 0; i < expectedResult.Length; i++)
+ {
+ var expected = expectedResult[i];
+ var actual = streams[i];
+
+ Assert.Equal(expected.Index, actual.Index);
+ Assert.Equal(expected.Type, actual.Type);
+ Assert.Equal(expected.IsExternal, actual.IsExternal);
+ Assert.Equal(expected.Path, actual.Path);
+ Assert.Equal(expected.IsDefault, actual.IsDefault);
+ Assert.Equal(expected.IsForced, actual.IsForced);
+ Assert.Equal(expected.Language, actual.Language);
+ }
+ }
+
+ private static MediaStream CreateMediaStream(string path, string codec, string? language, int index, bool isForced = false, bool isDefault = false)
+ {
+ return new ()
+ {
+ Index = index,
+ Codec = codec,
+ Type = MediaStreamType.Subtitle,
+ IsExternal = true,
+ Path = path,
+ IsDefault = isDefault,
+ IsForced = isForced,
+ Language = language
+ };
+ }
+ }
+}
diff --git a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs
index efe8063a07..25900bc09e 100644
--- a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs
+++ b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs
@@ -1,10 +1,9 @@
using System.Text.Json;
using System.Text.Json.Serialization;
-using MediaBrowser.Common.Json.Converters;
using MediaBrowser.Providers.Plugins.Omdb;
using Xunit;
-namespace Jellyfin.Common.Tests.Json
+namespace Jellyfin.Providers.Tests.Omdb
{
public class JsonOmdbConverterTests
{
diff --git a/tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs b/tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs
new file mode 100644
index 0000000000..f6a7c676f4
--- /dev/null
+++ b/tests/Jellyfin.Providers.Tests/Tmdb/TmdbUtilsTests.cs
@@ -0,0 +1,27 @@
+using MediaBrowser.Providers.Plugins.Tmdb;
+using Xunit;
+
+namespace Jellyfin.Providers.Tests.Tmdb
+{
+ public static class TmdbUtilsTests
+ {
+ [Theory]
+ [InlineData("de", "de")]
+ [InlineData("En", "En")]
+ [InlineData("de-de", "de-DE")]
+ [InlineData("en-US", "en-US")]
+ [InlineData("de-CH", "de")]
+ public static void NormalizeLanguage_Valid_Success(string input, string expected)
+ {
+ Assert.Equal(expected, TmdbUtils.NormalizeLanguage(input));
+ }
+
+ [Theory]
+ [InlineData(null, null)]
+ [InlineData("", "")]
+ public static void NormalizeLanguage_Invalid_Equal(string? input, string? expected)
+ {
+ Assert.Equal(expected, TmdbUtils.NormalizeLanguage(input!));
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs
index 71f8c51818..f312933fbf 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs
@@ -166,6 +166,38 @@ namespace Jellyfin.Server.Implementations.Tests.Data
};
}
+ public static IEnumerable<object[]> DeserializeImages_ValidAndInvalid_TestData()
+ {
+ yield return new object[]
+ {
+ string.Empty,
+ Array.Empty<ItemImageInfo>()
+ };
+
+ yield return new object[]
+ {
+ "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Primary*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN|test|1234||ss",
+ new ItemImageInfo[]
+ {
+ new ()
+ {
+ Path = "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg",
+ Type = ImageType.Primary,
+ DateModified = new DateTime(637452096478512963, DateTimeKind.Utc),
+ Width = 1920,
+ Height = 1080,
+ BlurHash = "WjQbtJtSO8nhNZ%L_Io#R*oaS6o}-;adXAoIn7j[%hW9s:WGw[nN"
+ }
+ }
+ };
+
+ yield return new object[]
+ {
+ "|",
+ Array.Empty<ItemImageInfo>()
+ };
+ }
+
[Theory]
[MemberData(nameof(DeserializeImages_Valid_TestData))]
public void DeserializeImages_Valid_Success(string value, ItemImageInfo[] expected)
@@ -184,6 +216,23 @@ namespace Jellyfin.Server.Implementations.Tests.Data
}
[Theory]
+ [MemberData(nameof(DeserializeImages_ValidAndInvalid_TestData))]
+ public void DeserializeImages_ValidAndInvalid_Success(string value, ItemImageInfo[] expected)
+ {
+ var result = _sqliteItemRepository.DeserializeImages(value);
+ Assert.Equal(expected.Length, result.Length);
+ for (int i = 0; i < expected.Length; i++)
+ {
+ Assert.Equal(expected[i].Path, result[i].Path);
+ Assert.Equal(expected[i].Type, result[i].Type);
+ Assert.Equal(expected[i].DateModified, result[i].DateModified);
+ Assert.Equal(expected[i].Width, result[i].Width);
+ Assert.Equal(expected[i].Height, result[i].Height);
+ Assert.Equal(expected[i].BlurHash, result[i].BlurHash);
+ }
+ }
+
+ [Theory]
[MemberData(nameof(DeserializeImages_Valid_TestData))]
public void SerializeImages_Valid_Success(string expected, ItemImageInfo[] value)
{
diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs
index 30e6542f94..d991f55748 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs
@@ -1,10 +1,10 @@
+using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using AutoFixture;
using AutoFixture.AutoMoq;
using Emby.Server.Implementations.IO;
-using MediaBrowser.Model.System;
using Xunit;
namespace Jellyfin.Server.Implementations.Tests.IO
@@ -31,7 +31,7 @@ namespace Jellyfin.Server.Implementations.Tests.IO
{
var generatedPath = _sut.MakeAbsolutePath(folderPath, filePath);
- if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows)
+ if (OperatingSystem.IsWindows())
{
var expectedWindowsPath = expectedAbsolutePath.Replace('/', '\\');
Assert.Equal(expectedWindowsPath, generatedPath.Split(':')[1]);
@@ -55,7 +55,7 @@ namespace Jellyfin.Server.Implementations.Tests.IO
[SkippableFact]
public void GetFileInfo_DanglingSymlink_ExistsFalse()
{
- Skip.If(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
+ Skip.If(OperatingSystem.IsWindows());
string testFileDir = Path.Combine(Path.GetTempPath(), "jellyfin-test-data");
string testFileName = Path.Combine(testFileDir, Path.GetRandomFileName() + "-danglingsym.link");
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
index 27713d58a3..387f259ce3 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
+++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
@@ -8,9 +8,6 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
<RootNamespace>Jellyfin.Server.Implementations.Tests</RootNamespace>
</PropertyGroup>
@@ -24,12 +21,12 @@
<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<!-- Code Analyzers -->
@@ -42,6 +39,7 @@
<ItemGroup>
<ProjectReference Include="..\..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" />
<ProjectReference Include="..\..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
+ <ProjectReference Include="..\Jellyfin.Server.Integration.Tests\Jellyfin.Server.Integration.Tests.csproj" />
</ItemGroup>
</Project>
diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs
index 8847239d90..c859d11c69 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Net.Http;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using AutoFixture;
@@ -15,8 +16,6 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
{
public class HdHomerunHostTests
{
- private const string TestIp = "http://192.168.1.182";
-
private readonly Fixture _fixture;
private readonly HdHomerunHost _hdHomerunHost;
@@ -30,7 +29,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
{
return Task.FromResult(new HttpResponseMessage()
{
- Content = new StreamContent(File.OpenRead("Test Data/LiveTv/" + m.RequestUri?.Segments[^1]))
+ Content = new StreamContent(File.OpenRead(Path.Combine("Test Data/LiveTv", m.RequestUri!.Host, m.RequestUri.Segments[^1])))
});
});
@@ -50,7 +49,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
{
var host = new TunerHostInfo()
{
- Url = TestIp
+ Url = "192.168.1.182"
};
var modelInfo = await _hdHomerunHost.GetModelInfo(host, true, CancellationToken.None).ConfigureAwait(false);
@@ -66,6 +65,26 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
}
[Fact]
+ public async Task GetModelInfo_Legacy_Success()
+ {
+ var host = new TunerHostInfo()
+ {
+ Url = "10.10.10.100"
+ };
+
+ var modelInfo = await _hdHomerunHost.GetModelInfo(host, true, CancellationToken.None).ConfigureAwait(false);
+ Assert.Equal("HDHomeRun DUAL", modelInfo.FriendlyName);
+ Assert.Equal("HDHR3-US", modelInfo.ModelNumber);
+ Assert.Equal("hdhomerun3_atsc", modelInfo.FirmwareName);
+ Assert.Equal("20200225", modelInfo.FirmwareVersion);
+ Assert.Equal("10xxxxx5", modelInfo.DeviceID);
+ Assert.Null(modelInfo.DeviceAuth);
+ Assert.Equal(2, modelInfo.TunerCount);
+ Assert.Equal("http://10.10.10.100:80", modelInfo.BaseURL);
+ Assert.Null(modelInfo.LineupURL);
+ }
+
+ [Fact]
public async Task GetModelInfo_EmptyUrl_ArgumentException()
{
var host = new TunerHostInfo()
@@ -81,7 +100,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
{
var host = new TunerHostInfo()
{
- Url = TestIp
+ Url = "192.168.1.182"
};
var channels = await _hdHomerunHost.GetLineup(host, CancellationToken.None).ConfigureAwait(false);
@@ -94,11 +113,23 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
}
[Fact]
+ public async Task GetLineup_Legacy_Success()
+ {
+ var host = new TunerHostInfo()
+ {
+ Url = "10.10.10.100"
+ };
+
+ // Placeholder json is invalid, just need to make sure we can reach it
+ await Assert.ThrowsAsync<JsonException>(() => _hdHomerunHost.GetLineup(host, CancellationToken.None));
+ }
+
+ [Fact]
public async Task GetLineup_ImportFavoritesOnly_Success()
{
var host = new TunerHostInfo()
{
- Url = TestIp,
+ Url = "192.168.1.182",
ImportFavoritesOnly = true
};
@@ -114,9 +145,9 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
[Fact]
public async Task TryGetTunerHostInfo_Valid_Success()
{
- var host = await _hdHomerunHost.TryGetTunerHostInfo(TestIp, CancellationToken.None).ConfigureAwait(false);
+ var host = await _hdHomerunHost.TryGetTunerHostInfo("192.168.1.182", CancellationToken.None).ConfigureAwait(false);
Assert.Equal(_hdHomerunHost.Type, host.Type);
- Assert.Equal(TestIp, host.Url);
+ Assert.Equal("192.168.1.182", host.Url);
Assert.Equal("HDHomeRun PRIME", host.FriendlyName);
Assert.Equal("FFFFFFFF", host.DeviceId);
Assert.Equal(3, host.TunerCount);
diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs
new file mode 100644
index 0000000000..e8b93b437b
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/RecordingHelperTests.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using Emby.Server.Implementations.LiveTv.EmbyTV;
+using MediaBrowser.Controller.LiveTv;
+using Xunit;
+
+namespace Jellyfin.Server.Implementations.Tests.LiveTv
+{
+ public static class RecordingHelperTests
+ {
+ public static IEnumerable<object[]> GetRecordingName_Success_TestData()
+ {
+ yield return new object[]
+ {
+ "The Incredibles 2020_04_20_21_06_00",
+ new TimerInfo
+ {
+ Name = "The Incredibles",
+ StartDate = new DateTime(2020, 4, 20, 21, 6, 0, DateTimeKind.Local),
+ IsMovie = true
+ }
+ };
+
+ yield return new object[]
+ {
+ "The Incredibles (2004)",
+ new TimerInfo
+ {
+ Name = "The Incredibles",
+ IsMovie = true,
+ ProductionYear = 2004
+ }
+ };
+
+ yield return new object[]
+ {
+ "The Big Bang Theory 2020_04_20_21_06_00",
+ new TimerInfo
+ {
+ Name = "The Big Bang Theory",
+ StartDate = new DateTime(2020, 4, 20, 21, 6, 0, DateTimeKind.Local),
+ IsProgramSeries = true,
+ }
+ };
+
+ yield return new object[]
+ {
+ "The Big Bang Theory S12E10",
+ new TimerInfo
+ {
+ Name = "The Big Bang Theory",
+ IsProgramSeries = true,
+ SeasonNumber = 12,
+ EpisodeNumber = 10
+ }
+ };
+
+ yield return new object[]
+ {
+ "The Big Bang Theory S12E10 The VCR Illumination",
+ new TimerInfo
+ {
+ Name = "The Big Bang Theory",
+ IsProgramSeries = true,
+ SeasonNumber = 12,
+ EpisodeNumber = 10,
+ EpisodeTitle = "The VCR Illumination"
+ }
+ };
+
+ yield return new object[]
+ {
+ "The Big Bang Theory 2018-12-06",
+ new TimerInfo
+ {
+ Name = "The Big Bang Theory",
+ IsProgramSeries = true,
+ OriginalAirDate = new DateTime(2018, 12, 6)
+ }
+ };
+
+ yield return new object[]
+ {
+ "The Big Bang Theory 2018-12-06 - The VCR Illumination",
+ new TimerInfo
+ {
+ Name = "The Big Bang Theory",
+ IsProgramSeries = true,
+ OriginalAirDate = new DateTime(2018, 12, 6),
+ EpisodeTitle = "The VCR Illumination"
+ }
+ };
+
+ yield return new object[]
+ {
+ "The Big Bang Theory 2018_12_06_21_06_00 - The VCR Illumination",
+ new TimerInfo
+ {
+ Name = "The Big Bang Theory",
+ StartDate = new DateTime(2018, 12, 6, 21, 6, 0, DateTimeKind.Local),
+ IsProgramSeries = true,
+ OriginalAirDate = new DateTime(2018, 12, 6),
+ EpisodeTitle = "The VCR Illumination"
+ }
+ };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetRecordingName_Success_TestData))]
+ public static void GetRecordingName_Success(string expected, TimerInfo timerInfo)
+ {
+ Assert.Equal(expected, RecordingHelper.GetRecordingName(timerInfo));
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
new file mode 100644
index 0000000000..365acfa341
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/QuickConnect/QuickConnectManagerTests.cs
@@ -0,0 +1,73 @@
+using System;
+using AutoFixture;
+using AutoFixture.AutoMoq;
+using Emby.Server.Implementations.QuickConnect;
+using MediaBrowser.Controller.Authentication;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Configuration;
+using Moq;
+using Xunit;
+
+namespace Jellyfin.Server.Implementations.Tests.LiveTv
+{
+ public class QuickConnectManagerTests
+ {
+ private readonly Fixture _fixture;
+ private readonly ServerConfiguration _config;
+ private readonly QuickConnectManager _quickConnectManager;
+
+ public QuickConnectManagerTests()
+ {
+ _config = new ServerConfiguration();
+ var configManager = new Mock<IServerConfigurationManager>();
+ configManager.Setup(x => x.Configuration).Returns(_config);
+
+ _fixture = new Fixture();
+ _fixture.Customize(new AutoMoqCustomization
+ {
+ ConfigureMembers = true
+ }).Inject(configManager.Object);
+ _quickConnectManager = _fixture.Create<QuickConnectManager>();
+ }
+
+ [Fact]
+ public void IsEnabled_QuickConnectUnavailable_False()
+ => Assert.False(_quickConnectManager.IsEnabled);
+
+ [Fact]
+ public void TryConnect_QuickConnectUnavailable_ThrowsAuthenticationException()
+ => Assert.Throws<AuthenticationException>(_quickConnectManager.TryConnect);
+
+ [Fact]
+ public void CheckRequestStatus_QuickConnectUnavailable_ThrowsAuthenticationException()
+ => Assert.Throws<AuthenticationException>(() => _quickConnectManager.CheckRequestStatus(string.Empty));
+
+ [Fact]
+ public void AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
+ => Assert.Throws<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
+
+ [Fact]
+ public void IsEnabled_QuickConnectAvailable_True()
+ {
+ _config.QuickConnectAvailable = true;
+ Assert.True(_quickConnectManager.IsEnabled);
+ }
+
+ [Fact]
+ public void CheckRequestStatus_QuickConnectAvailable_Success()
+ {
+ _config.QuickConnectAvailable = true;
+ var res1 = _quickConnectManager.TryConnect();
+ var res2 = _quickConnectManager.CheckRequestStatus(res1.Secret);
+ Assert.Equal(res1, res2);
+ }
+
+ [Fact]
+ public void AuthorizeRequest_QuickConnectAvailable_Success()
+ {
+ _config.QuickConnectAvailable = true;
+ var res = _quickConnectManager.TryConnect();
+ Assert.True(_quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code));
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/discover.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/discover.json
new file mode 100644
index 0000000000..a4ad4ed444
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/discover.json
@@ -0,0 +1 @@
+{"FriendlyName":"HDHomeRun DUAL","ModelNumber":"HDHR3-US","Legacy":1,"FirmwareName":"hdhomerun3_atsc","FirmwareVersion":"20200225","DeviceID":"10xxxxx5","TunerCount":2,"BaseURL":"http://10.10.10.100:80"}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/lineup.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/lineup.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/10.10.10.100/lineup.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/discover.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/192.168.1.182/discover.json
index 851f17bb26..851f17bb26 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/discover.json
+++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/192.168.1.182/discover.json
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/lineup.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/192.168.1.182/lineup.json
index 4cb5ebc8ec..4cb5ebc8ec 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/lineup.json
+++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/LiveTv/192.168.1.182/lineup.json
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs
index 4fa64d8a22..70acbfc40e 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs
@@ -1,5 +1,6 @@
-using System.Collections.Generic;
+using System;
using System.IO;
+using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
@@ -46,12 +47,36 @@ namespace Jellyfin.Server.Implementations.Tests.Updates
[Fact]
public async Task GetPackages_Valid_Success()
{
- IList<PackageInfo> packages = await _installationManager.GetPackages(
+ PackageInfo[] packages = await _installationManager.GetPackages(
"Jellyfin Stable",
"https://repo.jellyfin.org/releases/plugin/manifest-stable.json",
false);
- Assert.Equal(25, packages.Count);
+ Assert.Equal(25, packages.Length);
+ }
+
+ [Fact]
+ public async Task FilterPackages_NameOnly_Success()
+ {
+ PackageInfo[] packages = await _installationManager.GetPackages(
+ "Jellyfin Stable",
+ "https://repo.jellyfin.org/releases/plugin/manifest-stable.json",
+ false);
+
+ packages = _installationManager.FilterPackages(packages, "Anime").ToArray();
+ Assert.Single(packages);
+ }
+
+ [Fact]
+ public async Task FilterPackages_GuidOnly_Success()
+ {
+ PackageInfo[] packages = await _installationManager.GetPackages(
+ "Jellyfin Stable",
+ "https://repo.jellyfin.org/releases/plugin/manifest-stable.json",
+ false);
+
+ packages = _installationManager.FilterPackages(packages, id: new Guid("a4df60c5-6ab4-412a-8f79-2cab93fb2bc5")).ToArray();
+ Assert.Single(packages);
}
}
}
diff --git a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs
index ea6838682a..4ea05397dd 100644
--- a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs
@@ -7,7 +7,7 @@ using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Models.StartupDtos;
using Jellyfin.Api.Models.UserDtos;
-using MediaBrowser.Common.Json;
+using Jellyfin.Extensions.Json;
using Xunit;
namespace Jellyfin.Server.Integration.Tests
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/BaseJellyfinTestController.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/BaseJellyfinTestController.cs
new file mode 100644
index 0000000000..9db8689a78
--- /dev/null
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/BaseJellyfinTestController.cs
@@ -0,0 +1,14 @@
+using Jellyfin.Api;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Jellyfin.Server.Integration.Tests.Controllers
+{
+ /// <summary>
+ /// Base controller for testing infrastructure.
+ /// Automatically ignored in generated openapi spec.
+ /// </summary>
+ [ApiExplorerSettings(IgnoreApi = true)]
+ public class BaseJellyfinTestController : BaseJellyfinApiController
+ {
+ }
+}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs
index f5411dcb8d..8273653637 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs
@@ -5,7 +5,7 @@ using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Models;
-using MediaBrowser.Common.Json;
+using Jellyfin.Extensions.Json;
using Xunit;
namespace Jellyfin.Server.Integration.Tests.Controllers
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/EncoderController.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/EncoderController.cs
new file mode 100644
index 0000000000..1a720c2f62
--- /dev/null
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/EncoderController.cs
@@ -0,0 +1,53 @@
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Jellyfin.Server.Integration.Tests.Controllers
+{
+ /// <summary>
+ /// Controller for testing the encoded url.
+ /// </summary>
+ public class EncoderController : BaseJellyfinTestController
+ {
+ /// <summary>
+ /// Tests the url decoding.
+ /// </summary>
+ /// <param name="params">Parameters to echo back in the response.</param>
+ /// <returns>An <see cref="OkResult"/>.</returns>
+ /// <response code="200">Information retrieved.</response>
+ [HttpGet("UrlDecode")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ public ContentResult TestUrlDecoding([FromQuery] Dictionary<string, string>? @params = null)
+ {
+ return new ContentResult()
+ {
+ Content = (@params != null && @params.Count > 0)
+ ? string.Join("&", @params.Select(x => x.Key + "=" + x.Value))
+ : string.Empty,
+ ContentType = "text/plain; charset=utf-8",
+ StatusCode = 200
+ };
+ }
+
+ /// <summary>
+ /// Tests the url decoding.
+ /// </summary>
+ /// <param name="params">Parameters to echo back in the response.</param>
+ /// <returns>An <see cref="OkResult"/>.</returns>
+ /// <response code="200">Information retrieved.</response>
+ [HttpGet("UrlArrayDecode")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ public ContentResult TestUrlArrayDecoding([FromQuery] Dictionary<string, string[]>? @params = null)
+ {
+ return new ContentResult()
+ {
+ Content = (@params != null && @params.Count > 0)
+ ? string.Join("&", @params.Select(x => x.Key + "=" + string.Join(',', x.Value)))
+ : string.Empty,
+ ContentType = "text/plain; charset=utf-8",
+ StatusCode = 200
+ };
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs
new file mode 100644
index 0000000000..34d26680ad
--- /dev/null
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs
@@ -0,0 +1,61 @@
+using System.Globalization;
+using System.Net;
+using System.Net.Mime;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Jellyfin.Server.Integration.Tests.Controllers
+{
+ public sealed class MediaInfoControllerTests : IClassFixture<JellyfinApplicationFactory>
+ {
+ private readonly JellyfinApplicationFactory _factory;
+ private static string? _accessToken;
+
+ public MediaInfoControllerTests(JellyfinApplicationFactory factory)
+ {
+ _factory = factory;
+ }
+
+ [Fact]
+ public async Task BitrateTest_Default_Ok()
+ {
+ var client = _factory.CreateClient();
+ client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
+
+ var response = await client.GetAsync("Playback/BitrateTest").ConfigureAwait(false);
+
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType);
+ Assert.NotNull(response.Content.Headers.ContentLength);
+ }
+
+ [Theory]
+ [InlineData(102400)]
+ public async Task BitrateTest_WithValidParam_Ok(int size)
+ {
+ var client = _factory.CreateClient();
+ client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
+
+ var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
+
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType);
+ Assert.NotNull(response.Content.Headers.ContentLength);
+ Assert.InRange(response.Content.Headers.ContentLength!.Value, size, long.MaxValue);
+ }
+
+ [Theory]
+ [InlineData(0)] // Zero
+ [InlineData(-102400)] // Negative value
+ [InlineData(1000000000)] // Too large
+ public async Task BitrateTest_InvalidValue_BadRequest(int size)
+ {
+ var client = _factory.CreateClient();
+ client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client).ConfigureAwait(false));
+
+ var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
+
+ Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs
index 169a5a6c52..9c0fc72f65 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs
@@ -6,7 +6,7 @@ using System.Net.Mime;
using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Models.StartupDtos;
-using MediaBrowser.Common.Json;
+using Jellyfin.Extensions.Json;
using Xunit;
using Xunit.Priority;
diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs
index 6584490de5..8866ab53cd 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs
@@ -8,7 +8,7 @@ using System.Net.Mime;
using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Models.UserDtos;
-using MediaBrowser.Common.Json;
+using Jellyfin.Extensions.Json;
using MediaBrowser.Model.Dto;
using Xunit;
using Xunit.Priority;
diff --git a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs
new file mode 100644
index 0000000000..732b4f050d
--- /dev/null
+++ b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs
@@ -0,0 +1,48 @@
+using System.Net;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Jellyfin.Server.Integration.Tests
+{
+ /// <summary>
+ /// Defines the test for encoded querystrings in the url.
+ /// </summary>
+ public class EncodedQueryStringTest : IClassFixture<JellyfinApplicationFactory>
+ {
+ private readonly JellyfinApplicationFactory _factory;
+
+ public EncodedQueryStringTest(JellyfinApplicationFactory factory)
+ {
+ _factory = factory;
+ }
+
+ [Theory]
+ [InlineData("a=1&b=2&c=3", "a=1&b=2&c=3")] // won't be processed as there is more than 1.
+ [InlineData("a=1", "a=1")] // won't be processed as it has a value
+ [InlineData("a%3D1%26b%3D2%26c%3D3", "a=1&b=2&c=3")] // will be processed.
+ [InlineData("a=b&a=c", "a=b")]
+ [InlineData("a%3Db%26a%3Dc", "a=b")]
+ public async Task Ensure_Decoding_Of_Urls_Is_Working(string sourceUrl, string unencodedUrl)
+ {
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("Encoder/UrlDecode?" + sourceUrl).ConfigureAwait(false);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ string reply = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ Assert.Equal(unencodedUrl, reply);
+ }
+
+ [Theory]
+ [InlineData("a=b&a=c", "a=b,c")]
+ [InlineData("a%3Db%26a%3Dc", "a=b,c")]
+ public async Task Ensure_Array_Decoding_Of_Urls_Is_Working(string sourceUrl, string unencodedUrl)
+ {
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("Encoder/UrlArrayDecode?" + sourceUrl).ConfigureAwait(false);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ string reply = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ Assert.Equal(unencodedUrl, reply);
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
index 938385a2ad..cf42153393 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
+++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
@@ -2,9 +2,6 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
@@ -12,13 +9,13 @@
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
- <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.5" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.8" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="Xunit.Priority" Version="1.1.6" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="Moq" Version="4.16.0" />
</ItemGroup>
diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
index d9ec81a271..976e19d468 100644
--- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
@@ -44,10 +44,7 @@ namespace Jellyfin.Server.Integration.Tests
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
// Specify the startup command line options
- var commandLineOpts = new StartupOptions
- {
- NoWebClient = true
- };
+ var commandLineOpts = new StartupOptions();
// Use a temporary directory for the application paths
var webHostPathRoot = Path.Combine(_testPathRoot, "test-host-" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));
diff --git a/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs
new file mode 100644
index 0000000000..8c49a2e2b5
--- /dev/null
+++ b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs
@@ -0,0 +1,32 @@
+using System.Net;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace Jellyfin.Server.Integration.Tests.Middleware
+{
+ public sealed class RobotsRedirectionMiddlewareTests : IClassFixture<JellyfinApplicationFactory>
+ {
+ private readonly JellyfinApplicationFactory _factory;
+
+ public RobotsRedirectionMiddlewareTests(JellyfinApplicationFactory factory)
+ {
+ _factory = factory;
+ }
+
+ [Fact]
+ public async Task RobotsDotTxtRedirects()
+ {
+ var client = _factory.CreateClient(
+ new WebApplicationFactoryClientOptions()
+ {
+ AllowAutoRedirect = false
+ });
+
+ var response = await client.GetAsync("robots.txt").ConfigureAwait(false);
+
+ Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
+ Assert.Equal("web/robots.txt", response.Headers.Location?.ToString());
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
index 72e40ebcb5..2f95f5c01c 100644
--- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
+++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
@@ -3,9 +3,6 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
@@ -13,12 +10,12 @@
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
- <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.5" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.8" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="Moq" Version="4.16.0" />
</ItemGroup>
diff --git a/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs b/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs
new file mode 100644
index 0000000000..419afb2dc4
--- /dev/null
+++ b/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Linq;
+using Jellyfin.Server.Middleware;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
+using Microsoft.Extensions.Primitives;
+using Xunit;
+
+namespace Jellyfin.Server.Tests
+{
+ public static class UrlDecodeQueryFeatureTests
+ {
+ [Theory]
+ [InlineData("e0a72cb2a2c7", "e0a72cb2a2c7")] // isn't encoded
+ [InlineData("random+test", "random test")] // encoded
+ [InlineData("random%20test", "random test")] // encoded
+ [InlineData("++", " ")] // encoded
+ public static void EmptyValueTest(string query, string key)
+ {
+ var dict = new Dictionary<string, StringValues>
+ {
+ { query, StringValues.Empty }
+ };
+ var test = new UrlDecodeQueryFeature(new QueryFeature(new QueryCollection(dict)));
+ Assert.Single(test.Query);
+ var (k, v) = test.Query.First();
+ Assert.Equal(key, k);
+ Assert.Empty(v);
+ }
+ }
+}
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
index 4132205c3f..78837bba67 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
@@ -3,9 +3,6 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
- <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
- <Nullable>enable</Nullable>
- <AnalysisMode>AllEnabledByDefault</AnalysisMode>
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
@@ -16,11 +13,11 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.0.3" />
+ <PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<!-- Code Analyzers -->
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs
index 357d61c0bc..8019e0ab39 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Location/MovieNfoLocationTests.cs
@@ -1,8 +1,8 @@
-using System.Linq;
+using System;
+using System.Linq;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.System;
using MediaBrowser.XbmcMetadata.Savers;
using Xunit;
@@ -28,7 +28,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Location
var path2 = "/media/movies/Avengers Endgame/movie.nfo";
// uses ContainingFolderPath which uses Operating system specific paths
- if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows)
+ if (OperatingSystem.IsWindows())
{
movie.Path = movie.Path.Replace('/', '\\');
path1 = path1.Replace('/', '\\');
@@ -49,7 +49,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Location
var path2 = "/media/movies/Avengers Endgame/VIDEO_TS/VIDEO_TS.nfo";
// uses ContainingFolderPath which uses Operating system specific paths
- if (MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows)
+ if (OperatingSystem.IsWindows())
{
movie.Path = movie.Path.Replace('/', '\\');
path1 = path1.Replace('/', '\\');
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs
index 9ad093a2b9..3e726f23d9 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs
@@ -14,8 +14,6 @@ using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
-#pragma warning disable CA5369
-
namespace Jellyfin.XbmcMetadata.Tests.Parsers
{
public class EpisodeNfoProviderTests
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs
index 30a48857a4..cbcce73eb6 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs
@@ -59,7 +59,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers
_localImageFileMetadata = new FileSystemMetadata()
{
Exists = true,
- FullName = MediaBrowser.Common.System.OperatingSystem.Id == OperatingSystemId.Windows ?
+ FullName = OperatingSystem.IsWindows() ?
"C:\\media\\movies\\Justice League (2017).jpg"
: "/media/movies/Justice League (2017).jpg"
};
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs
index 2129f34222..eea8cb50a7 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicAlbumNfoProviderTests.cs
@@ -1,6 +1,4 @@
-#pragma warning disable CA5369
-
-using System;
+using System;
using System.Threading;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities.Audio;
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs
index 0e61fa2a19..31110dbd7d 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeasonNfoProviderTests.cs
@@ -1,6 +1,4 @@
-#pragma warning disable CA5369
-
-using System;
+using System;
using System.Linq;
using System.Threading;
using MediaBrowser.Common.Configuration;