mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-26 20:16:33 +00:00
Merge remote-tracking branch 'upstream/master' into schedules-direct
This commit is contained in:
@@ -136,7 +136,7 @@ namespace Jellyfin.Api.Tests.Auth
|
||||
_jellyfinAuthServiceMock.Setup(
|
||||
a => a.Authenticate(
|
||||
It.IsAny<HttpRequest>()))
|
||||
.Returns(authorizationInfo);
|
||||
.Returns(Task.FromResult(authorizationInfo));
|
||||
|
||||
return authorizationInfo;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using AutoFixture;
|
||||
using AutoFixture.AutoMoq;
|
||||
using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
|
||||
using Jellyfin.Api.Constants;
|
||||
using Jellyfin.Server.Implementations.Security;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -49,5 +50,61 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy
|
||||
await _sut.HandleAsync(context);
|
||||
Assert.True(context.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetParts_ValidAuthHeader_Success_Data))]
|
||||
public void GetParts_ValidAuthHeader_Success(string input, Dictionary<string, string> parts)
|
||||
{
|
||||
var dict = AuthorizationContext.GetParts(input);
|
||||
foreach (var (key, value) in parts)
|
||||
{
|
||||
Assert.Equal(dict[key], value);
|
||||
}
|
||||
}
|
||||
|
||||
private static TheoryData<string, Dictionary<string, string>> GetParts_ValidAuthHeader_Success_Data()
|
||||
{
|
||||
var data = new TheoryData<string, Dictionary<string, string>>();
|
||||
|
||||
data.Add(
|
||||
"x=\"123,123\",y=\"123\"",
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{ "x", "123,123" },
|
||||
{ "y", "123" }
|
||||
});
|
||||
|
||||
data.Add(
|
||||
"x=\"123,123\", y=\"123\",z=\"'hi'\"",
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{ "x", "123,123" },
|
||||
{ "y", "123" },
|
||||
{ "z", "'hi'" }
|
||||
});
|
||||
|
||||
data.Add(
|
||||
"x=\"ab\"",
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{ "x", "ab" }
|
||||
});
|
||||
|
||||
data.Add(
|
||||
"param=Hörbücher",
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{ "param", "Hörbücher" }
|
||||
});
|
||||
|
||||
data.Add(
|
||||
"param=%22%Hörbücher",
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{ "param", "\"%Hörbücher" }
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
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
|
||||
@@ -26,33 +18,28 @@ namespace Jellyfin.Api.Tests.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetSegmentLengths_Success_TestData()
|
||||
public static TheoryData<long, int, double[]> GetSegmentLengths_Success_TestData()
|
||||
{
|
||||
yield return new object[] { 0, 6, Array.Empty<double>() };
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<long, int, double[]>();
|
||||
data.Add(0, 6, Array.Empty<double>());
|
||||
data.Add(
|
||||
TimeSpan.FromSeconds(3).Ticks,
|
||||
6,
|
||||
new double[] { 3 }
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
new double[] { 3 });
|
||||
data.Add(
|
||||
TimeSpan.FromSeconds(6).Ticks,
|
||||
6,
|
||||
new double[] { 6 }
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
new double[] { 6 });
|
||||
data.Add(
|
||||
TimeSpan.FromSeconds(3.3333333).Ticks,
|
||||
6,
|
||||
new double[] { 3.3333333 }
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
new double[] { 3.3333333 });
|
||||
data.Add(
|
||||
TimeSpan.FromSeconds(9.3333333).Ticks,
|
||||
6,
|
||||
new double[] { 6, 3.3333333 }
|
||||
};
|
||||
new double[] { 6, 3.3333333 });
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,16 @@ namespace Jellyfin.Api.Tests.Helpers
|
||||
Assert.Equal(expected, RequestHelpers.GetOrderBy(sortBy, requestedSortOrder));
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetOrderBy_Success_TestData()
|
||||
public static TheoryData<IReadOnlyList<string>, IReadOnlyList<SortOrder>, (string, SortOrder)[]> GetOrderBy_Success_TestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<IReadOnlyList<string>, IReadOnlyList<SortOrder>, (string, SortOrder)[]>();
|
||||
|
||||
data.Add(
|
||||
Array.Empty<string>(),
|
||||
Array.Empty<SortOrder>(),
|
||||
Array.Empty<(string, SortOrder)>()
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
Array.Empty<(string, SortOrder)>());
|
||||
|
||||
data.Add(
|
||||
new string[]
|
||||
{
|
||||
"IsFavoriteOrLiked",
|
||||
@@ -35,10 +35,9 @@ namespace Jellyfin.Api.Tests.Helpers
|
||||
{
|
||||
("IsFavoriteOrLiked", SortOrder.Ascending),
|
||||
("Random", SortOrder.Ascending),
|
||||
}
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
});
|
||||
|
||||
data.Add(
|
||||
new string[]
|
||||
{
|
||||
"SortName",
|
||||
@@ -52,8 +51,9 @@ namespace Jellyfin.Api.Tests.Helpers
|
||||
{
|
||||
("SortName", SortOrder.Descending),
|
||||
("ProductionYear", SortOrder.Descending),
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -15,7 +15,7 @@
|
||||
<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.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
|
||||
@@ -19,18 +19,16 @@ namespace Jellyfin.Common.Tests.Cryptography
|
||||
Assert.Throws<ArgumentException>(() => new PasswordHash(string.Empty, Array.Empty<byte>()));
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> Parse_Valid_TestData()
|
||||
public static TheoryData<string, PasswordHash> Parse_Valid_TestData()
|
||||
{
|
||||
var data = new TheoryData<string, PasswordHash>();
|
||||
// Id
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2",
|
||||
new PasswordHash("PBKDF2", Array.Empty<byte>())
|
||||
};
|
||||
new PasswordHash("PBKDF2", Array.Empty<byte>()));
|
||||
|
||||
// Id + parameter
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2$iterations=1000",
|
||||
new PasswordHash(
|
||||
"PBKDF2",
|
||||
@@ -39,12 +37,10 @@ namespace Jellyfin.Common.Tests.Cryptography
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "iterations", "1000" },
|
||||
})
|
||||
};
|
||||
}));
|
||||
|
||||
// Id + parameters
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2$iterations=1000,m=120",
|
||||
new PasswordHash(
|
||||
"PBKDF2",
|
||||
@@ -54,34 +50,28 @@ namespace Jellyfin.Common.Tests.Cryptography
|
||||
{
|
||||
{ "iterations", "1000" },
|
||||
{ "m", "120" }
|
||||
})
|
||||
};
|
||||
}));
|
||||
|
||||
// Id + hash
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D",
|
||||
new PasswordHash(
|
||||
"PBKDF2",
|
||||
Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"),
|
||||
Array.Empty<byte>(),
|
||||
new Dictionary<string, string>())
|
||||
};
|
||||
new Dictionary<string, string>()));
|
||||
|
||||
// Id + salt + hash
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D",
|
||||
new PasswordHash(
|
||||
"PBKDF2",
|
||||
Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"),
|
||||
Convert.FromHexString("69F420"),
|
||||
new Dictionary<string, string>())
|
||||
};
|
||||
new Dictionary<string, string>()));
|
||||
|
||||
// Id + parameter + hash
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D",
|
||||
new PasswordHash(
|
||||
"PBKDF2",
|
||||
@@ -90,12 +80,9 @@ namespace Jellyfin.Common.Tests.Cryptography
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "iterations", "1000" }
|
||||
})
|
||||
};
|
||||
|
||||
}));
|
||||
// Id + parameters + hash
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2$iterations=1000,m=120$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D",
|
||||
new PasswordHash(
|
||||
"PBKDF2",
|
||||
@@ -105,12 +92,9 @@ namespace Jellyfin.Common.Tests.Cryptography
|
||||
{
|
||||
{ "iterations", "1000" },
|
||||
{ "m", "120" }
|
||||
})
|
||||
};
|
||||
|
||||
}));
|
||||
// Id + parameters + salt + hash
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"$PBKDF2$iterations=1000,m=120$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D",
|
||||
new PasswordHash(
|
||||
"PBKDF2",
|
||||
@@ -120,8 +104,8 @@ namespace Jellyfin.Common.Tests.Cryptography
|
||||
{
|
||||
{ "iterations", "1000" },
|
||||
{ "m", "120" }
|
||||
})
|
||||
};
|
||||
}));
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -16,7 +16,7 @@
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.1" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -6,10 +6,17 @@ namespace Jellyfin.Extensions.Tests
|
||||
{
|
||||
public static class CopyToExtensionsTests
|
||||
{
|
||||
public static IEnumerable<object[]> CopyTo_Valid_Correct_TestData()
|
||||
public static TheoryData<IReadOnlyList<int>, IList<int>, int, IList<int>> CopyTo_Valid_Correct_TestData()
|
||||
{
|
||||
yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 0, new[] { 0, 1, 2, 3, 4, 5 } };
|
||||
yield return new object[] { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 2, new[] { 5, 4, 0, 1, 2, 0 } };
|
||||
var data = new TheoryData<IReadOnlyList<int>, IList<int>, int, IList<int>>();
|
||||
|
||||
data.Add(
|
||||
new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 0, new[] { 0, 1, 2, 3, 4, 5 });
|
||||
|
||||
data.Add(
|
||||
new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 2, new[] { 5, 4, 0, 1, 2, 0 } );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -20,13 +27,26 @@ namespace Jellyfin.Extensions.Tests
|
||||
Assert.Equal(expected, destination);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData()
|
||||
public static TheoryData<IReadOnlyList<int>, IList<int>, int> CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData()
|
||||
{
|
||||
yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, -1 };
|
||||
yield return new object[] { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 6 };
|
||||
yield return new object[] { new[] { 0, 1, 2 }, Array.Empty<int>(), 0 };
|
||||
yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0 }, 0 };
|
||||
yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 1 };
|
||||
var data = new TheoryData<IReadOnlyList<int>, IList<int>, int>();
|
||||
|
||||
data.Add(
|
||||
new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, -1 );
|
||||
|
||||
data.Add(
|
||||
new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 6 );
|
||||
|
||||
data.Add(
|
||||
new[] { 0, 1, 2 }, Array.Empty<int>(), 0 );
|
||||
|
||||
data.Add(
|
||||
new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0 }, 0 );
|
||||
|
||||
data.Add(
|
||||
new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 1 );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -17,7 +17,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.1" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using FsCheck;
|
||||
using FsCheck.Xunit;
|
||||
|
||||
@@ -14,5 +14,28 @@ namespace Jellyfin.Extensions.Tests
|
||||
{
|
||||
Assert.Equal(count, str.AsSpan().Count(needle));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", 'q', "")]
|
||||
[InlineData("Banana split", ' ', "Banana")]
|
||||
[InlineData("Banana split", 'q', "Banana split")]
|
||||
[InlineData("Banana split 2", ' ', "Banana")]
|
||||
public void LeftPart_ValidArgsCharNeedle_Correct(string str, char needle, string expectedResult)
|
||||
{
|
||||
var result = str.AsSpan().LeftPart(needle).ToString();
|
||||
Assert.Equal(expectedResult, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", 'q', "")]
|
||||
[InlineData("Banana split", ' ', "split")]
|
||||
[InlineData("Banana split", 'q', "Banana split")]
|
||||
[InlineData("Banana split.", '.', "")]
|
||||
[InlineData("Banana split 2", ' ', "2")]
|
||||
public void RightPart_ValidArgsCharNeedle_Correct(string str, char needle, string expectedResult)
|
||||
{
|
||||
var result = str.AsSpan().RightPart(needle).ToString();
|
||||
Assert.Equal(expectedResult, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.MediaEncoding.Encoder;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
@@ -34,23 +32,21 @@ namespace Jellyfin.MediaEncoding.Tests
|
||||
Assert.Equal(valid, _encoderValidator.ValidateVersionInternal(versionOutput));
|
||||
}
|
||||
|
||||
private class GetFFmpegVersionTestData : IEnumerable<object?[]>
|
||||
private class GetFFmpegVersionTestData : TheoryData<string, Version?>
|
||||
{
|
||||
public IEnumerator<object?[]> GetEnumerator()
|
||||
public GetFFmpegVersionTestData()
|
||||
{
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV44Output, new Version(4, 4) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV432Output, new Version(4, 3, 2) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV431Output, new Version(4, 3, 1) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV43Output, new Version(4, 3) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV421Output, new Version(4, 2, 1) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV414Output, new Version(4, 1, 4) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegV404Output, new Version(4, 0, 4) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput2, new Version(4, 0) };
|
||||
yield return new object?[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput, null };
|
||||
Add(EncoderValidatorTestsData.FFmpegV44Output, new Version(4, 4));
|
||||
Add(EncoderValidatorTestsData.FFmpegV432Output, new Version(4, 3, 2));
|
||||
Add(EncoderValidatorTestsData.FFmpegV431Output, new Version(4, 3, 1));
|
||||
Add(EncoderValidatorTestsData.FFmpegV43Output, new Version(4, 3));
|
||||
Add(EncoderValidatorTestsData.FFmpegV421Output, new Version(4, 2, 1));
|
||||
Add(EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2));
|
||||
Add(EncoderValidatorTestsData.FFmpegV414Output, new Version(4, 1, 4));
|
||||
Add(EncoderValidatorTestsData.FFmpegV404Output, new Version(4, 0, 4));
|
||||
Add(EncoderValidatorTestsData.FFmpegGitUnknownOutput2, new Version(4, 0));
|
||||
Add(EncoderValidatorTestsData.FFmpegGitUnknownOutput, null);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Extensions.Json;
|
||||
using MediaBrowser.MediaEncoding.Probing;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.MediaEncoding.Tests
|
||||
@@ -14,7 +15,7 @@ namespace Jellyfin.MediaEncoding.Tests
|
||||
public async Task Test(string fileName)
|
||||
{
|
||||
var path = Path.Join("Test Data", fileName);
|
||||
await using (var stream = File.OpenRead(path))
|
||||
await using (var stream = AsyncFile.OpenRead(path))
|
||||
{
|
||||
var res = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.Options).ConfigureAwait(false);
|
||||
Assert.NotNull(res);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -18,10 +18,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<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="coverlet.collector" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
|
||||
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);
|
||||
Assert.Equal(DateTime.Parse("2021-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AdjustToUniversal), res.PremiereDate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -85,11 +85,44 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
|
||||
Assert.Equal("City to City", res.Album);
|
||||
Assert.Equal(1978, res.ProductionYear);
|
||||
Assert.True(res.PremiereDate.HasValue);
|
||||
Assert.Equal(DateTime.Parse("1978-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate);
|
||||
Assert.Equal(DateTime.Parse("1978-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AdjustToUniversal), res.PremiereDate);
|
||||
Assert.Contains("Electronic", res.Genres);
|
||||
Assert.Contains("Ambient", res.Genres);
|
||||
Assert.Contains("Pop", res.Genres);
|
||||
Assert.Contains("Jazz", res.Genres);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetMediaInfo_Music_Success()
|
||||
{
|
||||
var bytes = File.ReadAllBytes("Test Data/Probing/music_metadata.json");
|
||||
var internalMediaInfoResult = JsonSerializer.Deserialize<InternalMediaInfoResult>(bytes, _jsonOptions);
|
||||
MediaInfo res = _probeResultNormalizer.GetMediaInfo(internalMediaInfoResult, null, true, "Test Data/Probing/music.flac", MediaProtocol.File);
|
||||
|
||||
Assert.Equal("UP NO MORE", res.Name);
|
||||
Assert.Single(res.Artists);
|
||||
Assert.Equal("TWICE", res.Artists[0]);
|
||||
Assert.Equal("Eyes wide open", res.Album);
|
||||
Assert.Equal(2020, res.ProductionYear);
|
||||
Assert.True(res.PremiereDate.HasValue);
|
||||
Assert.Equal(DateTime.Parse("2020-10-26T00:00Z", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AdjustToUniversal), res.PremiereDate);
|
||||
Assert.Equal(22, res.People.Length);
|
||||
Assert.Equal("Krysta Youngs", res.People[0].Name);
|
||||
Assert.Equal(PersonType.Composer, res.People[0].Type);
|
||||
Assert.Equal("Julia Ross", res.People[1].Name);
|
||||
Assert.Equal(PersonType.Composer, res.People[1].Type);
|
||||
Assert.Equal("Yiwoomin", res.People[2].Name);
|
||||
Assert.Equal(PersonType.Composer, res.People[2].Type);
|
||||
Assert.Equal("Ji-hyo Park", res.People[3].Name);
|
||||
Assert.Equal(PersonType.Lyricist, res.People[3].Type);
|
||||
Assert.Equal("Yiwoomin", res.People[4].Name);
|
||||
Assert.Equal(PersonType.Actor, res.People[4].Type);
|
||||
Assert.Equal("Electric Piano", res.People[4].Role);
|
||||
Assert.Equal(4, res.Genres.Length);
|
||||
Assert.Contains("Electronic", res.Genres);
|
||||
Assert.Contains("Trance", res.Genres);
|
||||
Assert.Contains("Dance", res.Genres);
|
||||
Assert.Contains("Jazz", res.Genres);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,5 +31,27 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
Assert.Equal("Very good, Lieutenant.", trackEvent2.Text);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_EmptyNewlineBetweenText_Success()
|
||||
{
|
||||
using (var stream = File.OpenRead("Test Data/example2.srt"))
|
||||
{
|
||||
var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None);
|
||||
Assert.Equal(2, parsed.TrackEvents.Count);
|
||||
|
||||
var trackEvent1 = parsed.TrackEvents[0];
|
||||
Assert.Equal("311", trackEvent1.Id);
|
||||
Assert.Equal(TimeSpan.Parse("00:16:46.465", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks);
|
||||
Assert.Equal(TimeSpan.Parse("00:16:49.009", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks);
|
||||
Assert.Equal("Una vez que la gente se entere" + Environment.NewLine + Environment.NewLine + "de que ustedes están aquí,", trackEvent1.Text);
|
||||
|
||||
var trackEvent2 = parsed.TrackEvents[1];
|
||||
Assert.Equal("312", trackEvent2.Id);
|
||||
Assert.Equal(TimeSpan.Parse("00:16:49.092", CultureInfo.InvariantCulture).Ticks, trackEvent2.StartPositionTicks);
|
||||
Assert.Equal(TimeSpan.Parse("00:16:51.470", CultureInfo.InvariantCulture).Ticks, trackEvent2.EndPositionTicks);
|
||||
Assert.Equal("este lugar se convertirá" + Environment.NewLine + Environment.NewLine + "en un maldito zoológico.", trackEvent2.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> Parse_MultipleDialogues_TestData()
|
||||
public static TheoryData<string, IReadOnlyList<SubtitleTrackEvent>> Parse_MultipleDialogues_TestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<string, IReadOnlyList<SubtitleTrackEvent>>();
|
||||
|
||||
data.Add(
|
||||
@"[Events]
|
||||
Format: Layer, Start, End, Text
|
||||
Dialogue: ,0:00:01.18,0:00:01.85,dialogue1
|
||||
@@ -65,8 +66,9 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
StartPositionTicks = 31800000,
|
||||
EndPositionTicks = 38500000
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoFixture;
|
||||
using AutoFixture.AutoMoq;
|
||||
using MediaBrowser.MediaEncoding.Subtitles;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.MediaEncoding.Subtitles.Tests
|
||||
{
|
||||
public class SubtitleEncoderTests
|
||||
{
|
||||
internal static TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo> GetReadableFile_Valid_TestData()
|
||||
{
|
||||
var data = new TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo>();
|
||||
|
||||
data.Add(
|
||||
new MediaSourceInfo()
|
||||
{
|
||||
Protocol = MediaProtocol.File
|
||||
},
|
||||
new MediaStream()
|
||||
{
|
||||
Path = "/media/sub.ass",
|
||||
IsExternal = true
|
||||
},
|
||||
new SubtitleEncoder.SubtitleInfo("/media/sub.ass", MediaProtocol.File, "ass", true));
|
||||
|
||||
data.Add(
|
||||
new MediaSourceInfo()
|
||||
{
|
||||
Protocol = MediaProtocol.File
|
||||
},
|
||||
new MediaStream()
|
||||
{
|
||||
Path = "/media/sub.ssa",
|
||||
IsExternal = true
|
||||
},
|
||||
new SubtitleEncoder.SubtitleInfo("/media/sub.ssa", MediaProtocol.File, "ssa", true));
|
||||
|
||||
data.Add(
|
||||
new MediaSourceInfo()
|
||||
{
|
||||
Protocol = MediaProtocol.File
|
||||
},
|
||||
new MediaStream()
|
||||
{
|
||||
Path = "/media/sub.srt",
|
||||
IsExternal = true
|
||||
},
|
||||
new SubtitleEncoder.SubtitleInfo("/media/sub.srt", MediaProtocol.File, "srt", true));
|
||||
|
||||
data.Add(
|
||||
new MediaSourceInfo()
|
||||
{
|
||||
Protocol = MediaProtocol.Http
|
||||
},
|
||||
new MediaStream()
|
||||
{
|
||||
Path = "/media/sub.ass",
|
||||
IsExternal = true
|
||||
},
|
||||
new SubtitleEncoder.SubtitleInfo("/media/sub.ass", MediaProtocol.File, "ass", true));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetReadableFile_Valid_TestData))]
|
||||
internal async Task GetReadableFile_Valid_Success(MediaSourceInfo mediaSource, MediaStream subtitleStream, SubtitleEncoder.SubtitleInfo subtitleInfo)
|
||||
{
|
||||
var fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
|
||||
var subtitleEncoder = fixture.Create<SubtitleEncoder>();
|
||||
var result = await subtitleEncoder.GetReadableFile(mediaSource, subtitleStream, CancellationToken.None).ConfigureAwait(false);
|
||||
Assert.Equal(subtitleInfo.Path, result.Path);
|
||||
Assert.Equal(subtitleInfo.Protocol, result.Protocol);
|
||||
Assert.Equal(subtitleInfo.Format, result.Format);
|
||||
Assert.Equal(subtitleInfo.IsExternal, result.IsExternal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
{
|
||||
"streams": [
|
||||
{
|
||||
"index": 0,
|
||||
"codec_name": "flac",
|
||||
"codec_long_name": "FLAC (Free Lossless Audio Codec)",
|
||||
"codec_type": "audio",
|
||||
"codec_tag_string": "[0][0][0][0]",
|
||||
"codec_tag": "0x0000",
|
||||
"sample_fmt": "s16",
|
||||
"sample_rate": "44100",
|
||||
"channels": 2,
|
||||
"channel_layout": "stereo",
|
||||
"bits_per_sample": 0,
|
||||
"r_frame_rate": "0/0",
|
||||
"avg_frame_rate": "0/0",
|
||||
"time_base": "1/44100",
|
||||
"start_pts": 0,
|
||||
"start_time": "0.000000",
|
||||
"duration_ts": 9447984,
|
||||
"duration": "214.240000",
|
||||
"bits_per_raw_sample": "16",
|
||||
"disposition": {
|
||||
"default": 0,
|
||||
"dub": 0,
|
||||
"original": 0,
|
||||
"comment": 0,
|
||||
"lyrics": 0,
|
||||
"karaoke": 0,
|
||||
"forced": 0,
|
||||
"hearing_impaired": 0,
|
||||
"visual_impaired": 0,
|
||||
"clean_effects": 0,
|
||||
"attached_pic": 0,
|
||||
"timed_thumbnails": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"codec_name": "mjpeg",
|
||||
"codec_long_name": "Motion JPEG",
|
||||
"profile": "Baseline",
|
||||
"codec_type": "video",
|
||||
"codec_tag_string": "[0][0][0][0]",
|
||||
"codec_tag": "0x0000",
|
||||
"width": 500,
|
||||
"height": 500,
|
||||
"coded_width": 500,
|
||||
"coded_height": 500,
|
||||
"closed_captions": 0,
|
||||
"has_b_frames": 0,
|
||||
"sample_aspect_ratio": "1:1",
|
||||
"display_aspect_ratio": "1:1",
|
||||
"pix_fmt": "yuvj420p",
|
||||
"level": -99,
|
||||
"color_range": "pc",
|
||||
"color_space": "bt470bg",
|
||||
"chroma_location": "center",
|
||||
"refs": 1,
|
||||
"r_frame_rate": "90000/1",
|
||||
"avg_frame_rate": "0/0",
|
||||
"time_base": "1/90000",
|
||||
"start_pts": 0,
|
||||
"start_time": "0.000000",
|
||||
"duration_ts": 19281600,
|
||||
"duration": "214.240000",
|
||||
"bits_per_raw_sample": "8",
|
||||
"disposition": {
|
||||
"default": 0,
|
||||
"dub": 0,
|
||||
"original": 0,
|
||||
"comment": 0,
|
||||
"lyrics": 0,
|
||||
"karaoke": 0,
|
||||
"forced": 0,
|
||||
"hearing_impaired": 0,
|
||||
"visual_impaired": 0,
|
||||
"clean_effects": 0,
|
||||
"attached_pic": 1,
|
||||
"timed_thumbnails": 0
|
||||
},
|
||||
"tags": {
|
||||
"comment": "Cover (front)"
|
||||
}
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"filename": "03 UP NO MORE.flac",
|
||||
"nb_streams": 2,
|
||||
"nb_programs": 0,
|
||||
"format_name": "flac",
|
||||
"format_long_name": "raw FLAC",
|
||||
"start_time": "0.000000",
|
||||
"duration": "214.240000",
|
||||
"size": "28714641",
|
||||
"bit_rate": "1072242",
|
||||
"probe_score": 100,
|
||||
"tags": {
|
||||
"MUSICBRAINZ_RELEASEGROUPID": "aa05ff10-8589-4c9c-a0d4-6b024f4e4556",
|
||||
"ORIGINALDATE": "2020-10-26",
|
||||
"ORIGINALYEAR": "2020",
|
||||
"RELEASETYPE": "album",
|
||||
"MUSICBRAINZ_ALBUMID": "222e6610-75c9-400e-8dc3-bb61f9fc5ca7",
|
||||
"SCRIPT": "Latn",
|
||||
"ALBUM": "Eyes wide open",
|
||||
"RELEASECOUNTRY": "JP",
|
||||
"BARCODE": "190295105280",
|
||||
"LABEL": "JYP Entertainment",
|
||||
"RELEASESTATUS": "official",
|
||||
"DATE": "2020-10-26",
|
||||
"MUSICBRAINZ_ALBUMARTISTID": "8da127cc-c432-418f-b356-ef36210d82ac",
|
||||
"album_artist": "TWICE",
|
||||
"ALBUMARTISTSORT": "TWICE",
|
||||
"TOTALDISCS": "1",
|
||||
"TOTALTRACKS": "13",
|
||||
"MEDIA": "Digital Media",
|
||||
"disc": "1",
|
||||
"MUSICBRAINZ_TRACKID": "7d1a1044-b564-480d-9df3-22f9656fdb97",
|
||||
"TITLE": "UP NO MORE",
|
||||
"ISRC": "US5TA2000136",
|
||||
"PERFORMER": "Yiwoomin (electric piano);Yiwoomin (synthesizer);Yiwoomin (bass);Yiwoomin (guitar);TWICE;Tzu-yu Chou (vocals);Momo Hirai (vocals);Na-yeon Im (vocals);Da-hyun Kim (vocals);Sana Minatozaki (vocals);Mina Myoui (vocals);Ji-hyo Park (vocals);Chae-young Son (vocals);Jeong-yeon Yoo (vocals);Perrie (background vocals)",
|
||||
"MIXER": "Bong Won Shin",
|
||||
"ARRANGER": "Krysta Youngs;Julia Ross;Yiwoomin",
|
||||
"MUSICBRAINZ_WORKID": "02b37083-0337-4721-9f17-bf31971043e8",
|
||||
"LANGUAGE": "kor;eng",
|
||||
"WORK": "Up No More",
|
||||
"COMPOSER": "Krysta Youngs;Julia Ross;Yiwoomin",
|
||||
"COMPOSERSORT": "Krysta Youngs;Ross, Julia;Yiwoomin",
|
||||
"LYRICIST": "Ji-hyo Park",
|
||||
"MUSICBRAINZ_ARTISTID": "8da127cc-c432-418f-b356-ef36210d82ac",
|
||||
"ARTIST": "TWICE",
|
||||
"ARTISTSORT": "TWICE",
|
||||
"ARTISTS": "TWICE",
|
||||
"MUSICBRAINZ_RELEASETRACKID": "ad49b840-da9e-4e7c-924b-29fdee187052",
|
||||
"track": "3",
|
||||
"GENRE": "Electronic;Trance;Dance;Jazz",
|
||||
"WEBSITE": "http://twice.jype.com/;http://www.twicejapan.com/",
|
||||
"ACOUSTID_ID": "aae2e972-108c-4d0c-8e31-9d078283e3dc",
|
||||
"MOOD": "Not acoustic;Not aggressive;Electronic;Happy;Party;Not relaxed;Not sad",
|
||||
"TRACKTOTAL": "13",
|
||||
"DISCTOTAL": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
11
tests/Jellyfin.MediaEncoding.Tests/Test Data/example2.srt
Normal file
11
tests/Jellyfin.MediaEncoding.Tests/Test Data/example2.srt
Normal file
@@ -0,0 +1,11 @@
|
||||
311
|
||||
00:16:46,465 --> 00:16:49,009
|
||||
Una vez que la gente se entere
|
||||
|
||||
de que ustedes están aquí,
|
||||
|
||||
312
|
||||
00:16:49,092 --> 00:16:51,470
|
||||
este lugar se convertirá
|
||||
|
||||
en un maldito zoológico.
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using Xunit;
|
||||
|
||||
@@ -6,12 +5,11 @@ namespace Jellyfin.Model.Tests.Entities
|
||||
{
|
||||
public class MediaStreamTests
|
||||
{
|
||||
public static IEnumerable<object[]> Get_DisplayTitle_TestData()
|
||||
public static TheoryData<MediaStream, string> Get_DisplayTitle_TestData()
|
||||
{
|
||||
return new List<object[]>
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
var data = new TheoryData<MediaStream, string>();
|
||||
|
||||
data.Add(
|
||||
new MediaStream
|
||||
{
|
||||
Type = MediaStreamType.Subtitle,
|
||||
@@ -21,61 +19,57 @@ namespace Jellyfin.Model.Tests.Entities
|
||||
IsDefault = false,
|
||||
Codec = "ASS"
|
||||
},
|
||||
"English - Und - ASS"
|
||||
},
|
||||
new object[]
|
||||
"English - Und - ASS");
|
||||
|
||||
data.Add(
|
||||
new MediaStream
|
||||
{
|
||||
new MediaStream
|
||||
{
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = "English",
|
||||
Language = string.Empty,
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
Codec = string.Empty
|
||||
},
|
||||
"English - Und"
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = "English",
|
||||
Language = string.Empty,
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
Codec = string.Empty
|
||||
},
|
||||
new object[]
|
||||
"English - Und");
|
||||
|
||||
data.Add(
|
||||
new MediaStream
|
||||
{
|
||||
new MediaStream
|
||||
{
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = "English",
|
||||
Language = "EN",
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
Codec = string.Empty
|
||||
},
|
||||
"English"
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = "English",
|
||||
Language = "EN",
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
Codec = string.Empty
|
||||
},
|
||||
new object[]
|
||||
"English");
|
||||
|
||||
data.Add(
|
||||
new MediaStream
|
||||
{
|
||||
new MediaStream
|
||||
{
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = "English",
|
||||
Language = "EN",
|
||||
IsForced = true,
|
||||
IsDefault = true,
|
||||
Codec = "SRT"
|
||||
},
|
||||
"English - Default - Forced - SRT"
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = "English",
|
||||
Language = "EN",
|
||||
IsForced = true,
|
||||
IsDefault = true,
|
||||
Codec = "SRT"
|
||||
},
|
||||
new object[]
|
||||
"English - Default - Forced - SRT");
|
||||
|
||||
data.Add(
|
||||
new MediaStream
|
||||
{
|
||||
new MediaStream
|
||||
{
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = null,
|
||||
Language = null,
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
Codec = null
|
||||
},
|
||||
"Und"
|
||||
}
|
||||
};
|
||||
Type = MediaStreamType.Subtitle,
|
||||
Title = null,
|
||||
Language = null,
|
||||
IsForced = false,
|
||||
IsDefault = false,
|
||||
Codec = null
|
||||
},
|
||||
"Und");
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -11,7 +11,7 @@
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.1" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Code Analyzers -->
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using Emby.Naming.AudioBook;
|
||||
using Emby.Naming.Common;
|
||||
using Xunit;
|
||||
@@ -9,29 +8,29 @@ namespace Jellyfin.Naming.Tests.AudioBook
|
||||
{
|
||||
private readonly NamingOptions _namingOptions = new NamingOptions();
|
||||
|
||||
public static IEnumerable<object[]> Resolve_ValidFileNameTestData()
|
||||
public static TheoryData<AudioBookFileInfo> Resolve_ValidFileNameTestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<AudioBookFileInfo>();
|
||||
|
||||
data.Add(
|
||||
new AudioBookFileInfo(
|
||||
@"/server/AudioBooks/Larry Potter/Larry Potter.mp3",
|
||||
"mp3")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
"mp3"));
|
||||
|
||||
data.Add(
|
||||
new AudioBookFileInfo(
|
||||
@"/server/AudioBooks/Berry Potter/Chapter 1 .ogg",
|
||||
"ogg",
|
||||
chapterNumber: 1)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
chapterNumber: 1));
|
||||
|
||||
data.Add(
|
||||
new AudioBookFileInfo(
|
||||
@"/server/AudioBooks/Nerry Potter/Part 3 - Chapter 2.mp3",
|
||||
"mp3",
|
||||
chapterNumber: 2,
|
||||
partNumber: 3)
|
||||
};
|
||||
partNumber: 3));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -18,30 +18,31 @@ namespace Jellyfin.Naming.Tests.Video
|
||||
[Fact]
|
||||
public void TestKodiExtras()
|
||||
{
|
||||
Test("trailer.mp4", ExtraType.Trailer, _videoOptions);
|
||||
Test("300-trailer.mp4", ExtraType.Trailer, _videoOptions);
|
||||
Test("trailer.mp4", ExtraType.Trailer);
|
||||
Test("300-trailer.mp4", ExtraType.Trailer);
|
||||
|
||||
Test("theme.mp3", ExtraType.ThemeSong, _videoOptions);
|
||||
Test("theme.mp3", ExtraType.ThemeSong);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestExpandedExtras()
|
||||
{
|
||||
Test("trailer.mp4", ExtraType.Trailer, _videoOptions);
|
||||
Test("trailer.mp3", null, _videoOptions);
|
||||
Test("300-trailer.mp4", ExtraType.Trailer, _videoOptions);
|
||||
Test("trailer.mp4", ExtraType.Trailer);
|
||||
Test("trailer.mp3", null);
|
||||
Test("300-trailer.mp4", ExtraType.Trailer);
|
||||
Test("stuff trailerthings.mkv", null);
|
||||
|
||||
Test("theme.mp3", ExtraType.ThemeSong, _videoOptions);
|
||||
Test("theme.mkv", null, _videoOptions);
|
||||
Test("theme.mp3", ExtraType.ThemeSong);
|
||||
Test("theme.mkv", null);
|
||||
|
||||
Test("300-scene.mp4", ExtraType.Scene, _videoOptions);
|
||||
Test("300-scene2.mp4", ExtraType.Scene, _videoOptions);
|
||||
Test("300-clip.mp4", ExtraType.Clip, _videoOptions);
|
||||
Test("300-scene.mp4", ExtraType.Scene);
|
||||
Test("300-scene2.mp4", ExtraType.Scene);
|
||||
Test("300-clip.mp4", ExtraType.Clip);
|
||||
|
||||
Test("300-deleted.mp4", ExtraType.DeletedScene, _videoOptions);
|
||||
Test("300-deletedscene.mp4", ExtraType.DeletedScene, _videoOptions);
|
||||
Test("300-interview.mp4", ExtraType.Interview, _videoOptions);
|
||||
Test("300-behindthescenes.mp4", ExtraType.BehindTheScenes, _videoOptions);
|
||||
Test("300-deleted.mp4", ExtraType.DeletedScene);
|
||||
Test("300-deletedscene.mp4", ExtraType.DeletedScene);
|
||||
Test("300-interview.mp4", ExtraType.Interview);
|
||||
Test("300-behindthescenes.mp4", ExtraType.BehindTheScenes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -55,9 +56,9 @@ namespace Jellyfin.Naming.Tests.Video
|
||||
[InlineData(ExtraType.Unknown, "extras")]
|
||||
public void TestDirectories(ExtraType type, string dirName)
|
||||
{
|
||||
Test(dirName + "/300.mp4", type, _videoOptions);
|
||||
Test("300/" + dirName + "/something.mkv", type, _videoOptions);
|
||||
Test("/data/something/Movies/300/" + dirName + "/whoknows.mp4", type, _videoOptions);
|
||||
Test(dirName + "/300.mp4", type);
|
||||
Test("300/" + dirName + "/something.mkv", type);
|
||||
Test("/data/something/Movies/300/" + dirName + "/whoknows.mp4", type);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -66,32 +67,25 @@ namespace Jellyfin.Naming.Tests.Video
|
||||
[InlineData("The Big Short")]
|
||||
public void TestNonExtraDirectories(string dirName)
|
||||
{
|
||||
Test(dirName + "/300.mp4", null, _videoOptions);
|
||||
Test("300/" + dirName + "/something.mkv", null, _videoOptions);
|
||||
Test("/data/something/Movies/300/" + dirName + "/whoknows.mp4", null, _videoOptions);
|
||||
Test("/data/something/Movies/" + dirName + "/" + dirName + ".mp4", null, _videoOptions);
|
||||
Test(dirName + "/300.mp4", null);
|
||||
Test("300/" + dirName + "/something.mkv", null);
|
||||
Test("/data/something/Movies/300/" + dirName + "/whoknows.mp4", null);
|
||||
Test("/data/something/Movies/" + dirName + "/" + dirName + ".mp4", null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSample()
|
||||
{
|
||||
Test("300-sample.mp4", ExtraType.Sample, _videoOptions);
|
||||
Test("300-sample.mp4", ExtraType.Sample);
|
||||
}
|
||||
|
||||
private void Test(string input, ExtraType? expectedType, NamingOptions videoOptions)
|
||||
private void Test(string input, ExtraType? expectedType)
|
||||
{
|
||||
var parser = GetExtraTypeParser(videoOptions);
|
||||
var parser = GetExtraTypeParser(_videoOptions);
|
||||
|
||||
var extraType = parser.GetExtraInfo(input).ExtraType;
|
||||
|
||||
if (expectedType == null)
|
||||
{
|
||||
Assert.Null(extraType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(expectedType, extraType);
|
||||
}
|
||||
Assert.Equal(expectedType, extraType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Emby.Naming.Common;
|
||||
using Emby.Naming.Video;
|
||||
@@ -11,148 +10,134 @@ namespace Jellyfin.Naming.Tests.Video
|
||||
{
|
||||
private static NamingOptions _namingOptions = new NamingOptions();
|
||||
|
||||
public static IEnumerable<object[]> ResolveFile_ValidFileNameTestData()
|
||||
public static TheoryData<VideoFileInfo> ResolveFile_ValidFileNameTestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<VideoFileInfo>();
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/7 Psychos.mkv/7 Psychos.mkv",
|
||||
container: "mkv",
|
||||
name: "7 Psychos")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
name: "7 Psychos"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/3 days to kill (2005)/3 days to kill (2005).mkv",
|
||||
container: "mkv",
|
||||
name: "3 days to kill",
|
||||
year: 2005)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
year: 2005));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/American Psycho/American.Psycho.mkv",
|
||||
container: "mkv",
|
||||
name: "American.Psycho")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
name: "American.Psycho"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/brave (2007)/brave (2006).3d.sbs.mkv",
|
||||
container: "mkv",
|
||||
name: "brave",
|
||||
year: 2006,
|
||||
is3D: true,
|
||||
format3D: "sbs")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
format3D: "sbs"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/300 (2007)/300 (2006).3d1.sbas.mkv",
|
||||
container: "mkv",
|
||||
name: "300",
|
||||
year: 2006)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
year: 2006));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/300 (2007)/300 (2006).3d.sbs.mkv",
|
||||
container: "mkv",
|
||||
name: "300",
|
||||
year: 2006,
|
||||
is3D: true,
|
||||
format3D: "sbs")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
format3D: "sbs"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/brave (2007)/brave (2006)-trailer.bluray.disc",
|
||||
container: "disc",
|
||||
name: "brave",
|
||||
year: 2006,
|
||||
isStub: true,
|
||||
stubType: "bluray")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
stubType: "bluray"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/300 (2007)/300 (2006)-trailer.bluray.disc",
|
||||
container: "disc",
|
||||
name: "300",
|
||||
year: 2006,
|
||||
isStub: true,
|
||||
stubType: "bluray")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
stubType: "bluray"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/Brave (2007)/Brave (2006).bluray.disc",
|
||||
container: "disc",
|
||||
name: "Brave",
|
||||
year: 2006,
|
||||
isStub: true,
|
||||
stubType: "bluray")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
stubType: "bluray"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/300 (2007)/300 (2006).bluray.disc",
|
||||
container: "disc",
|
||||
name: "300",
|
||||
year: 2006,
|
||||
isStub: true,
|
||||
stubType: "bluray")
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
stubType: "bluray"));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/300 (2007)/300 (2006)-trailer.mkv",
|
||||
container: "mkv",
|
||||
name: "300",
|
||||
year: 2006,
|
||||
extraType: ExtraType.Trailer)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
extraType: ExtraType.Trailer));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/Brave (2007)/Brave (2006)-trailer.mkv",
|
||||
container: "mkv",
|
||||
name: "Brave",
|
||||
year: 2006,
|
||||
extraType: ExtraType.Trailer)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
extraType: ExtraType.Trailer));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/300 (2007)/300 (2006).mkv",
|
||||
container: "mkv",
|
||||
name: "300",
|
||||
year: 2006)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
year: 2006));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/Bad Boys (1995)/Bad Boys (1995).mkv",
|
||||
container: "mkv",
|
||||
name: "Bad Boys",
|
||||
year: 1995)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
year: 1995));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/Brave (2007)/Brave (2006).mkv",
|
||||
container: "mkv",
|
||||
name: "Brave",
|
||||
year: 2006)
|
||||
};
|
||||
yield return new object[]
|
||||
{
|
||||
year: 2006));
|
||||
|
||||
data.Add(
|
||||
new VideoFileInfo(
|
||||
path: @"/server/Movies/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF/Rain Man 1988 REMASTERED 1080p BluRay x264 AAC - JEFF.mp4",
|
||||
container: "mp4",
|
||||
name: "Rain Man",
|
||||
year: 1988)
|
||||
};
|
||||
year: 1988));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -16,7 +16,7 @@
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.1" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.3" />
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Jellyfin.Networking.Tests
|
||||
CallBase = true
|
||||
};
|
||||
configManager.Setup(x => x.GetConfiguration(It.IsAny<string>())).Returns(conf);
|
||||
return (IConfigurationManager)configManager.Object;
|
||||
return configManager.Object;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma warning disable CA1002 // Do not expose generic lists
|
||||
#pragma warning disable CA1002 // Do not expose generic lists
|
||||
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Model.Entities;
|
||||
@@ -11,11 +11,12 @@ namespace Jellyfin.Providers.Tests.MediaInfo
|
||||
{
|
||||
public class SubtitleResolverTests
|
||||
{
|
||||
public static IEnumerable<object[]> AddExternalSubtitleStreams_GivenMixedFilenames_ReturnsValidSubtitles_TestData()
|
||||
public static TheoryData<List<MediaStream>, string, int, string[], MediaStream[]> AddExternalSubtitleStreams_GivenMixedFilenames_ReturnsValidSubtitles_TestData()
|
||||
{
|
||||
var data = new TheoryData<List<MediaStream>, string, int, string[], MediaStream[]>();
|
||||
|
||||
var index = 0;
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
new List<MediaStream>(),
|
||||
"/video/My.Video.mkv",
|
||||
index,
|
||||
@@ -52,8 +53,9 @@ namespace Jellyfin.Providers.Tests.MediaInfo
|
||||
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),
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -32,10 +32,11 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
_sqliteItemRepository = _fixture.Create<SqliteItemRepository>();
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ItemImageInfoFromValueString_Valid_TestData()
|
||||
public static TheoryData<string, ItemImageInfo> ItemImageInfoFromValueString_Valid_TestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<string, ItemImageInfo>();
|
||||
|
||||
data.Add(
|
||||
"/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Primary*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN",
|
||||
new ItemImageInfo
|
||||
{
|
||||
@@ -45,41 +46,33 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
Width = 1920,
|
||||
Height = 1080,
|
||||
BlurHash = "WjQbtJtSO8nhNZ%L_Io#R*oaS6o}-;adXAoIn7j[%hW9s:WGw[nN"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0*Primary*0*0",
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg",
|
||||
Type = ImageType.Primary,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0*Primary",
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg",
|
||||
Type = ImageType.Primary,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0*Primary*600",
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = "https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg",
|
||||
Type = ImageType.Primary,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"%MetadataPath%/library/68/68578562b96c80a7ebd530848801f645/poster.jpg*637264380567586027*Primary*600*336",
|
||||
new ItemImageInfo
|
||||
{
|
||||
@@ -88,8 +81,9 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
DateModified = new DateTime(637264380567586027, DateTimeKind.Utc),
|
||||
Width = 600,
|
||||
Height = 336
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -117,10 +111,10 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
Assert.Null(_sqliteItemRepository.ItemImageInfoFromValueString(value));
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> DeserializeImages_Valid_TestData()
|
||||
public static TheoryData<string, ItemImageInfo[]> DeserializeImages_Valid_TestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<string, ItemImageInfo[]>();
|
||||
data.Add(
|
||||
"/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Primary*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN",
|
||||
new ItemImageInfo[]
|
||||
{
|
||||
@@ -133,11 +127,9 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
Height = 1080,
|
||||
BlurHash = "WjQbtJtSO8nhNZ%L_Io#R*oaS6o}-;adXAoIn7j[%hW9s:WGw[nN"
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/poster.jpg*637261226720645297*Primary*0*0|%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/logo.png*637261226720805297*Logo*0*0|%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/landscape.jpg*637261226721285297*Thumb*0*0|%MetadataPath%/library/2a/2a27372f1e9bc757b1db99721bbeae1e/backdrop.jpg*637261226721685297*Backdrop*0*0",
|
||||
new ItemImageInfo[]
|
||||
{
|
||||
@@ -165,20 +157,19 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
Type = ImageType.Backdrop,
|
||||
DateModified = new DateTime(637261226721685297, DateTimeKind.Utc),
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> DeserializeImages_ValidAndInvalid_TestData()
|
||||
public static TheoryData<string, ItemImageInfo[]> DeserializeImages_ValidAndInvalid_TestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<string, ItemImageInfo[]>();
|
||||
data.Add(
|
||||
string.Empty,
|
||||
Array.Empty<ItemImageInfo>()
|
||||
};
|
||||
Array.Empty<ItemImageInfo>());
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"/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[]
|
||||
{
|
||||
@@ -191,14 +182,13 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
Height = 1080,
|
||||
BlurHash = "WjQbtJtSO8nhNZ%L_Io#R*oaS6o}-;adXAoIn7j[%hW9s:WGw[nN"
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"|",
|
||||
Array.Empty<ItemImageInfo>()
|
||||
};
|
||||
Array.Empty<ItemImageInfo>());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -242,30 +232,27 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
Assert.Equal(expected, _sqliteItemRepository.SerializeImages(value));
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> DeserializeProviderIds_Valid_TestData()
|
||||
public static TheoryData<string, Dictionary<string, string>> DeserializeProviderIds_Valid_TestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<string, Dictionary<string, string>>();
|
||||
|
||||
data.Add(
|
||||
"Imdb=tt0119567",
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "Imdb", "tt0119567" },
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"Imdb=tt0119567|Tmdb=330|TmdbCollection=328",
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
{ "Imdb", "tt0119567" },
|
||||
{ "Tmdb", "330" },
|
||||
{ "TmdbCollection", "328" },
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"MusicBrainzAlbum=9d363e43-f24f-4b39-bc5a-7ef305c677c7|MusicBrainzReleaseGroup=63eba062-847c-3b73-8b0f-6baf27bba6fa|AudioDbArtist=111352|AudioDbAlbum=2116560|MusicBrainzAlbumArtist=20244d07-534f-4eff-b4d4-930878889970",
|
||||
new Dictionary<string, string>()
|
||||
{
|
||||
@@ -274,8 +261,9 @@ namespace Jellyfin.Server.Implementations.Tests.Data
|
||||
{ "AudioDbArtist", "111352" },
|
||||
{ "AudioDbAlbum", "2116560" },
|
||||
{ "MusicBrainzAlbumArtist", "20244d07-534f-4eff-b4d4-930878889970" },
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
<RootNamespace>Jellyfin.Server.Implementations.Tests</RootNamespace>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Emby.Server.Implementations.LiveTv.EmbyTV;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using Xunit;
|
||||
@@ -8,43 +7,36 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
{
|
||||
public static class RecordingHelperTests
|
||||
{
|
||||
public static IEnumerable<object[]> GetRecordingName_Success_TestData()
|
||||
public static TheoryData<string, TimerInfo> GetRecordingName_Success_TestData()
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
var data = new TheoryData<string, TimerInfo>();
|
||||
|
||||
data.Add(
|
||||
"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[]
|
||||
{
|
||||
data.Add(
|
||||
"The Incredibles (2004)",
|
||||
new TimerInfo
|
||||
{
|
||||
Name = "The Incredibles",
|
||||
IsMovie = true,
|
||||
ProductionYear = 2004
|
||||
}
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
});
|
||||
data.Add(
|
||||
"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[]
|
||||
{
|
||||
});
|
||||
data.Add(
|
||||
"The Big Bang Theory S12E10",
|
||||
new TimerInfo
|
||||
{
|
||||
@@ -52,11 +44,8 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
IsProgramSeries = true,
|
||||
SeasonNumber = 12,
|
||||
EpisodeNumber = 10
|
||||
}
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
});
|
||||
data.Add(
|
||||
"The Big Bang Theory S12E10 The VCR Illumination",
|
||||
new TimerInfo
|
||||
{
|
||||
@@ -65,22 +54,17 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
SeasonNumber = 12,
|
||||
EpisodeNumber = 10,
|
||||
EpisodeTitle = "The VCR Illumination"
|
||||
}
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
});
|
||||
data.Add(
|
||||
"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[]
|
||||
{
|
||||
data.Add(
|
||||
"The Big Bang Theory 2018-12-06 - The VCR Illumination",
|
||||
new TimerInfo
|
||||
{
|
||||
@@ -88,11 +72,9 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
IsProgramSeries = true,
|
||||
OriginalAirDate = new DateTime(2018, 12, 6),
|
||||
EpisodeTitle = "The VCR Illumination"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
data.Add(
|
||||
"The Big Bang Theory 2018_12_06_21_06_00 - The VCR Illumination",
|
||||
new TimerInfo
|
||||
{
|
||||
@@ -101,8 +83,9 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
IsProgramSeries = true,
|
||||
OriginalAirDate = new DateTime(2018, 12, 6),
|
||||
EpisodeTitle = "The VCR Illumination"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AutoFixture;
|
||||
using AutoFixture.AutoMoq;
|
||||
using Emby.Server.Implementations.QuickConnect;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
namespace Jellyfin.Server.Implementations.Tests.QuickConnect
|
||||
{
|
||||
public class QuickConnectManagerTests
|
||||
{
|
||||
private static readonly AuthorizationInfo _quickConnectAuthInfo = new AuthorizationInfo
|
||||
{
|
||||
Device = "Device",
|
||||
DeviceId = "DeviceId",
|
||||
Client = "Client",
|
||||
Version = "1.0.0"
|
||||
};
|
||||
|
||||
private readonly Fixture _fixture;
|
||||
private readonly ServerConfiguration _config;
|
||||
private readonly QuickConnectManager _quickConnectManager;
|
||||
@@ -27,6 +38,12 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
{
|
||||
ConfigureMembers = true
|
||||
}).Inject(configManager.Object);
|
||||
|
||||
// User object contains circular references.
|
||||
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
|
||||
.ForEach(b => _fixture.Behaviors.Remove(b));
|
||||
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
|
||||
|
||||
_quickConnectManager = _fixture.Create<QuickConnectManager>();
|
||||
}
|
||||
|
||||
@@ -36,7 +53,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
|
||||
[Fact]
|
||||
public void TryConnect_QuickConnectUnavailable_ThrowsAuthenticationException()
|
||||
=> Assert.Throws<AuthenticationException>(_quickConnectManager.TryConnect);
|
||||
=> Assert.Throws<AuthenticationException>(() => _quickConnectManager.TryConnect(_quickConnectAuthInfo));
|
||||
|
||||
[Fact]
|
||||
public void CheckRequestStatus_QuickConnectUnavailable_ThrowsAuthenticationException()
|
||||
@@ -44,7 +61,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
|
||||
[Fact]
|
||||
public void AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
|
||||
=> Assert.Throws<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
|
||||
=> Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
|
||||
|
||||
[Fact]
|
||||
public void IsEnabled_QuickConnectAvailable_True()
|
||||
@@ -57,17 +74,17 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||
public void CheckRequestStatus_QuickConnectAvailable_Success()
|
||||
{
|
||||
_config.QuickConnectAvailable = true;
|
||||
var res1 = _quickConnectManager.TryConnect();
|
||||
var res1 = _quickConnectManager.TryConnect(_quickConnectAuthInfo);
|
||||
var res2 = _quickConnectManager.CheckRequestStatus(res1.Secret);
|
||||
Assert.Equal(res1, res2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AuthorizeRequest_QuickConnectAvailable_Success()
|
||||
public async Task AuthorizeRequest_QuickConnectAvailable_Success()
|
||||
{
|
||||
_config.QuickConnectAvailable = true;
|
||||
var res = _quickConnectManager.TryConnect();
|
||||
Assert.True(_quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code));
|
||||
var res = _quickConnectManager.TryConnect(_quickConnectAuthInfo);
|
||||
Assert.True(await _quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Emby.Server.Implementations.Sorting;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
@@ -13,7 +11,7 @@ namespace Jellyfin.Server.Implementations.Tests.Sorting
|
||||
{
|
||||
[Theory]
|
||||
[ClassData(typeof(EpisodeBadData))]
|
||||
public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem x, BaseItem y)
|
||||
public void Compare_GivenNull_ThrowsArgumentNullException(BaseItem? x, BaseItem? y)
|
||||
{
|
||||
var cmp = new AiredEpisodeOrderComparer();
|
||||
Assert.Throws<ArgumentNullException>(() => cmp.Compare(x, y));
|
||||
@@ -29,152 +27,138 @@ namespace Jellyfin.Server.Implementations.Tests.Sorting
|
||||
Assert.Equal(-expected, cmp.Compare(y, x));
|
||||
}
|
||||
|
||||
private class EpisodeBadData : IEnumerable<object?[]>
|
||||
private class EpisodeBadData : TheoryData<BaseItem?, BaseItem?>
|
||||
{
|
||||
public IEnumerator<object?[]> GetEnumerator()
|
||||
public EpisodeBadData()
|
||||
{
|
||||
yield return new object?[] { null, new Episode() };
|
||||
yield return new object?[] { new Episode(), null };
|
||||
Add(null, new Episode());
|
||||
Add(new Episode(), null);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
|
||||
private class EpisodeTestData : IEnumerable<object?[]>
|
||||
private class EpisodeTestData : TheoryData<BaseItem, BaseItem, int>
|
||||
{
|
||||
public IEnumerator<object?[]> GetEnumerator()
|
||||
public EpisodeTestData()
|
||||
{
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Movie(),
|
||||
new Movie(),
|
||||
0
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
0);
|
||||
|
||||
Add(
|
||||
new Movie(),
|
||||
new Episode(),
|
||||
1
|
||||
};
|
||||
1);
|
||||
|
||||
// Good cases
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Episode(),
|
||||
new Episode(),
|
||||
0
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
0);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
0
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
0);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
1
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 2, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
1
|
||||
};
|
||||
1);
|
||||
|
||||
// Good Specials
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
|
||||
0
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
0);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 2 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
|
||||
1
|
||||
};
|
||||
1);
|
||||
|
||||
// Specials to Episodes
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
|
||||
1
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 2 },
|
||||
1
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
|
||||
1
|
||||
};
|
||||
1);
|
||||
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
|
||||
1
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1 },
|
||||
1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 2 },
|
||||
1
|
||||
};
|
||||
1);
|
||||
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsAfterSeasonNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
1
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 3, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsAfterSeasonNumber = 1 },
|
||||
1
|
||||
};
|
||||
1);
|
||||
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 3, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsAfterSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
|
||||
1
|
||||
};
|
||||
1);
|
||||
|
||||
yield return new object?[]
|
||||
{
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1 },
|
||||
1
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 2 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
|
||||
1
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
|
||||
0
|
||||
};
|
||||
yield return new object?[]
|
||||
{
|
||||
0);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 3 },
|
||||
new Episode { ParentIndexNumber = 0, IndexNumber = 1, AirsBeforeSeasonNumber = 1, AirsBeforeEpisodeNumber = 2 },
|
||||
1
|
||||
};
|
||||
}
|
||||
1);
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
// Premiere Date
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) },
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) },
|
||||
0);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 11, 0, 0, 0) },
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) },
|
||||
-1);
|
||||
|
||||
Add(
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 12, 0, 0, 0) },
|
||||
new Episode { ParentIndexNumber = 1, IndexNumber = 1, PremiereDate = new DateTime(2021, 09, 11, 0, 0, 0) },
|
||||
1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -6,7 +6,9 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoFixture;
|
||||
using AutoFixture.AutoMoq;
|
||||
using Emby.Server.Implementations.Archiving;
|
||||
using Emby.Server.Implementations.Updates;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Updates;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
@@ -40,7 +42,9 @@ namespace Jellyfin.Server.Implementations.Tests.Updates
|
||||
_fixture.Customize(new AutoMoqCustomization
|
||||
{
|
||||
ConfigureMembers = true
|
||||
}).Inject(http);
|
||||
});
|
||||
_fixture.Inject(http);
|
||||
_fixture.Inject<IZipClient>(new ZipClient());
|
||||
_installationManager = _fixture.Create<InstallationManager>();
|
||||
}
|
||||
|
||||
@@ -78,5 +82,32 @@ namespace Jellyfin.Server.Implementations.Tests.Updates
|
||||
packages = _installationManager.FilterPackages(packages, id: new Guid("a4df60c5-6ab4-412a-8f79-2cab93fb2bc5")).ToArray();
|
||||
Assert.Single(packages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InstallPackage_InvalidChecksum_ThrowsInvalidDataException()
|
||||
{
|
||||
var packageInfo = new InstallationInfo()
|
||||
{
|
||||
Name = "Test",
|
||||
SourceUrl = "https://repo.jellyfin.org/releases/plugin/empty/empty.zip",
|
||||
Checksum = "InvalidChecksum"
|
||||
};
|
||||
|
||||
await Assert.ThrowsAsync<InvalidDataException>(() => _installationManager.InstallPackage(packageInfo, CancellationToken.None)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InstallPackage_Valid_Success()
|
||||
{
|
||||
var packageInfo = new InstallationInfo()
|
||||
{
|
||||
Name = "Test",
|
||||
SourceUrl = "https://repo.jellyfin.org/releases/plugin/empty/empty.zip",
|
||||
Checksum = "11b5b2f1a9ebc4f66d6ef19018543361"
|
||||
};
|
||||
|
||||
var ex = await Record.ExceptionAsync(() => _installationManager.InstallPackage(packageInfo, CancellationToken.None)).ConfigureAwait(false);
|
||||
Assert.Null(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Jellyfin.Server.Integration.Tests
|
||||
[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%3D1", "a=1")]
|
||||
[InlineData("a%3Db%26a%3Dc", "a=b")]
|
||||
public async Task Ensure_Decoding_Of_Urls_Is_Working(string sourceUrl, string unencodedUrl)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -9,7 +9,7 @@
|
||||
<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.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
@@ -10,7 +10,7 @@
|
||||
<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.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Jellyfin.Networking.Configuration;
|
||||
using Jellyfin.Networking.Manager;
|
||||
using Jellyfin.Server.Extensions;
|
||||
|
||||
@@ -12,9 +12,6 @@ namespace Jellyfin.Server.Tests
|
||||
{
|
||||
[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>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -11,7 +11,6 @@ using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using MediaBrowser.Model.System;
|
||||
using MediaBrowser.Providers.Plugins.Tmdb.Movies;
|
||||
using MediaBrowser.XbmcMetadata.Parsers;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
Reference in New Issue
Block a user