repo creation with initial code after cloning public repo

This commit is contained in:
2026-02-19 07:36:25 -05:00
commit 460884fea3
2860 changed files with 650825 additions and 0 deletions
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using Xunit;
namespace Jellyfin.Extensions.Tests
{
public static class CopyToExtensionsTests
{
public static TheoryData<IReadOnlyList<int>, IList<int>, int, IList<int>> CopyTo_Valid_Correct_TestData()
{
var data = new TheoryData<IReadOnlyList<int>, IList<int>, int, IList<int>>
{
{ new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 0, new[] { 0, 1, 2, 3, 4, 5 } },
{ new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 2, new[] { 5, 4, 0, 1, 2, 0 } }
};
return data;
}
[Theory]
[MemberData(nameof(CopyTo_Valid_Correct_TestData))]
public static void CopyTo_Valid_Correct(IReadOnlyList<int> source, IList<int> destination, int index, IList<int> expected)
{
source.CopyTo(destination, index);
Assert.Equal(expected, destination);
}
public static TheoryData<IReadOnlyList<int>, IList<int>, int> CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData()
{
var data = new TheoryData<IReadOnlyList<int>, IList<int>, int>
{
{ new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, -1 },
{ new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 6 },
{ new[] { 0, 1, 2 }, Array.Empty<int>(), 0 },
{ new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0 }, 0 },
{ new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 1 }
};
return data;
}
[Theory]
[MemberData(nameof(CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData))]
public static void CopyTo_Invalid_ThrowsArgumentOutOfRangeException(IReadOnlyList<int> source, IList<int> destination, int index)
{
Assert.Throws<ArgumentOutOfRangeException>(() => source.CopyTo(destination, index));
}
}
}
@@ -0,0 +1,23 @@
using System.IO;
using Xunit;
namespace Jellyfin.Extensions.Tests;
public static class FileHelperTests
{
[Fact]
public static void CreateEmpty_Valid_Correct()
{
var path = Path.Join(Path.GetTempPath(), Path.GetRandomFileName());
var fileInfo = new FileInfo(path);
Assert.False(fileInfo.Exists);
FileHelper.CreateEmpty(path);
fileInfo.Refresh();
Assert.True(fileInfo.Exists);
File.Delete(path);
}
}
@@ -0,0 +1,23 @@
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading;
using Xunit;
namespace Jellyfin.Extensions.Tests;
public static class FormattingStreamWriterTests
{
[Fact]
public static void Shuffle_Valid_Correct()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE", false);
using (var ms = new MemoryStream())
using (var txt = new FormattingStreamWriter(ms, CultureInfo.InvariantCulture))
{
txt.Write("{0}", 3.14159);
txt.Close();
Assert.Equal("3.14159", Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FsCheck.Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../MediaBrowser.Model/MediaBrowser.Model.csproj" />
<ProjectReference Include="../../src/Jellyfin.Extensions/Jellyfin.Extensions.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,45 @@
using System.Text.Json;
using FsCheck;
using FsCheck.Fluent;
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();
}
}
@@ -0,0 +1,37 @@
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonBoolStringTests
{
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions()
{
Converters =
{
new JsonBoolStringConverter()
}
};
[Theory]
[InlineData(@"{ ""Value"": ""true"" }", true)]
[InlineData(@"{ ""Value"": ""false"" }", false)]
public void Deserialize_String_Valid_Success(string input, bool output)
{
var s = JsonSerializer.Deserialize<TestStruct>(input, _jsonOptions);
Assert.Equal(s.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);
}
private readonly record struct TestStruct(bool Value);
}
}
@@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Tests.Json.Models;
using MediaBrowser.Model.Session;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonCommaDelimitedCollectionTests
{
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions()
{
Converters =
{
new JsonStringEnumConverter()
}
};
[Fact]
public void Deserialize_String_Null_Success()
{
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": null }", _jsonOptions);
Assert.Null(value?.Value);
}
[Fact]
public void Deserialize_Empty_Success()
{
var desiredValue = new GenericBodyArrayModel<string>
{
Value = Array.Empty<string>()
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": """" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_EmptyList_Success()
{
var desiredValue = new GenericBodyListModel<string>
{
Value = []
};
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<GenericBodyListModel<string>>(@"{ ""Value"": """" }", _jsonOptions));
}
[Fact]
public void Deserialize_EmptyIReadOnlyList_Success()
{
var desiredValue = new GenericBodyIReadOnlyListModel<string>
{
Value = []
};
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": """" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_String_Valid_Success()
{
var desiredValue = new GenericBodyArrayModel<string>
{
Value = ["a", "b", "c"]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_StringList_Valid_Success()
{
var desiredValue = new GenericBodyListModel<string>
{
Value = ["a", "b", "c"]
};
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<GenericBodyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions));
}
[Fact]
public void Deserialize_String_Space_Valid_Success()
{
var desiredValue = new GenericBodyArrayModel<string>
{
Value = ["a", "b", "c"]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_Valid_Success()
{
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_EmptyEntry_Success()
{
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_Invalid_Success()
{
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAValidCommand,MoveDown"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_Space_Valid_Success()
{
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_String_Array_Valid_Success()
{
var desiredValue = new GenericBodyArrayModel<string>
{
Value = ["a", "b", "c"]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_Array_Valid_Success()
{
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown]
};
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Serialize_GenericCommandType_ReadOnlyArray_Valid_Success()
{
var valueToSerialize = new GenericBodyIReadOnlyCollectionModel<GeneralCommandType>
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }.AsReadOnly()
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyCollectionModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
[Fact]
public void Serialize_GenericCommandType_ImmutableArrayArray_Valid_Success()
{
var valueToSerialize = new GenericBodyIReadOnlyCollectionModel<GeneralCommandType>
{
Value = ImmutableArray.Create(new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown })
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyCollectionModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
[Fact]
public void Serialize_GenericCommandType_List_Valid_Success()
{
var valueToSerialize = new GenericBodyIReadOnlyListModel<GeneralCommandType>
{
Value = new List<GeneralCommandType> { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
}
}
@@ -0,0 +1,104 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Tests.Json.Models;
using MediaBrowser.Model.Session;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonCommaDelimitedIReadOnlyListTests
{
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions()
{
Converters =
{
new JsonStringEnumConverter()
}
};
[Fact]
public void Deserialize_String_Valid_Success()
{
var desiredValue = new GenericBodyIReadOnlyListModel<string>
{
Value = new[] { "a", "b", "c" }
};
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_String_Space_Valid_Success()
{
var desiredValue = new GenericBodyIReadOnlyListModel<string>
{
Value = new[] { "a", "b", "c" }
};
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_Valid_Success()
{
var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
};
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_Space_Valid_Success()
{
var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
};
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_String_Array_Valid_Success()
{
var desiredValue = new GenericBodyIReadOnlyListModel<string>
{
Value = new[] { "a", "b", "c" }
};
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Deserialize_GenericCommandType_Array_Valid_Success()
{
var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
};
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
[Fact]
public void Serialize_GenericCommandType_IReadOnlyList_Valid_Success()
{
var valueToSerialize = new GenericBodyIReadOnlyListModel<GeneralCommandType>
{
Value = new List<GeneralCommandType> { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
}
}
@@ -0,0 +1,112 @@
using System.Text.Json;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters;
public class JsonDefaultStringEnumConverterTests
{
private readonly JsonSerializerOptions _jsonOptions = new() { Converters = { new JsonDefaultStringEnumConverterFactory() } };
/// <summary>
/// Test to ensure that `null` and empty string are deserialized to the default value.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum_Direct(string input, MediaStreamProtocol output)
{
var value = JsonSerializer.Deserialize<MediaStreamProtocol>(input, _jsonOptions);
Assert.Equal(output, value);
}
/// <summary>
/// Test to ensure that `null` and empty string are deserialized to the default value.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData(null, MediaStreamProtocol.http)]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum(string? input, MediaStreamProtocol output)
{
input ??= "null";
var json = $"{{ \"EnumValue\": {input} }}";
var value = JsonSerializer.Deserialize<TestClass>(json, _jsonOptions);
Assert.NotNull(value);
Assert.Equal(output, value.EnumValue);
}
/// <summary>
/// Test to ensure that empty string is deserialized to the default value,
/// and `null` is deserialized to `null`.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData(null, null)]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum_Nullable(string? input, MediaStreamProtocol? output)
{
input ??= "null";
var json = $"{{ \"EnumValue\": {input} }}";
var value = JsonSerializer.Deserialize<NullTestClass>(json, _jsonOptions);
Assert.NotNull(value);
Assert.Equal(output, value.EnumValue);
}
/// <summary>
/// Ensures that the roundtrip serialization & deserialization is successful.
/// </summary>
/// <param name="input">Input enum.</param>
/// <param name="output">Output enum.</param>
[Theory]
[InlineData(MediaStreamProtocol.http, MediaStreamProtocol.http)]
[InlineData(MediaStreamProtocol.hls, MediaStreamProtocol.hls)]
public void Enum_RoundTrip(MediaStreamProtocol input, MediaStreamProtocol output)
{
var inputObj = new TestClass { EnumValue = input };
var outputObj = JsonSerializer.Deserialize<TestClass>(JsonSerializer.Serialize(inputObj, _jsonOptions), _jsonOptions);
Assert.NotNull(outputObj);
Assert.Equal(output, outputObj.EnumValue);
}
/// <summary>
/// Ensures that the roundtrip serialization & deserialization is successful, including null.
/// </summary>
/// <param name="input">Input enum.</param>
/// <param name="output">Output enum.</param>
[Theory]
[InlineData(MediaStreamProtocol.http, MediaStreamProtocol.http)]
[InlineData(MediaStreamProtocol.hls, MediaStreamProtocol.hls)]
[InlineData(null, null)]
public void Enum_RoundTrip_Nullable(MediaStreamProtocol? input, MediaStreamProtocol? output)
{
var inputObj = new NullTestClass { EnumValue = input };
var outputObj = JsonSerializer.Deserialize<NullTestClass>(JsonSerializer.Serialize(inputObj, _jsonOptions), _jsonOptions);
Assert.NotNull(outputObj);
Assert.Equal(output, outputObj.EnumValue);
}
private sealed class TestClass
{
public MediaStreamProtocol EnumValue { get; set; }
}
private sealed class NullTestClass
{
public MediaStreamProtocol? EnumValue { get; set; }
}
}
@@ -0,0 +1,28 @@
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using MediaBrowser.Model.Session;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters;
public class JsonFlagEnumTests
{
private readonly JsonSerializerOptions _jsonOptions = new()
{
Converters =
{
new JsonFlagEnumConverter<TranscodeReason>()
}
};
[Theory]
[InlineData(TranscodeReason.AudioIsExternal | TranscodeReason.ContainerNotSupported, "[\"ContainerNotSupported\",\"AudioIsExternal\"]")]
[InlineData(TranscodeReason.AudioIsExternal | TranscodeReason.ContainerNotSupported | TranscodeReason.VideoBitDepthNotSupported, "[\"ContainerNotSupported\",\"AudioIsExternal\",\"VideoBitDepthNotSupported\"]")]
[InlineData((TranscodeReason)0, "[]")]
public void Serialize_Transcode_Reason(TranscodeReason transcodeReason, string output)
{
var result = JsonSerializer.Serialize(transcodeReason, _jsonOptions);
Assert.Equal(output, result);
}
}
@@ -0,0 +1,68 @@
using System;
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonGuidConverterTests
{
private readonly JsonSerializerOptions _options;
public JsonGuidConverterTests()
{
_options = new JsonSerializerOptions();
_options.Converters.Add(new JsonGuidConverter());
}
[Fact]
public void Deserialize_Valid_Success()
{
Guid value = JsonSerializer.Deserialize<Guid>(@"""a852a27afe324084ae66db579ee3ee18""", _options);
Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value);
}
[Fact]
public void Deserialize_ValidDashed_Success()
{
Guid value = JsonSerializer.Deserialize<Guid>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options);
Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value);
}
[Fact]
public void Roundtrip_Valid_Success()
{
Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18");
string value = JsonSerializer.Serialize(guid, _options);
Assert.Equal(guid, JsonSerializer.Deserialize<Guid>(value, _options));
}
[Fact]
public void Deserialize_Null_EmptyGuid()
{
Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid>("null", _options));
}
[Fact]
public void Serialize_EmptyGuid_EmptyGuid()
{
Assert.Equal($"\"{Guid.Empty:N}\"", JsonSerializer.Serialize(Guid.Empty, _options));
}
[Fact]
public void Serialize_Valid_NoDash_Success()
{
var guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
Assert.Equal($"\"{guid:N}\"", str);
}
[Fact]
public void Serialize_Nullable_Success()
{
Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
Assert.Equal($"\"{guid:N}\"", str);
}
}
}
@@ -0,0 +1,80 @@
using System;
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonNullableGuidConverterTests
{
private readonly JsonSerializerOptions _options;
public JsonNullableGuidConverterTests()
{
_options = new JsonSerializerOptions();
_options.Converters.Add(new JsonNullableGuidConverter());
}
[Fact]
public void Deserialize_Valid_Success()
{
Guid? value = JsonSerializer.Deserialize<Guid?>(@"""a852a27afe324084ae66db579ee3ee18""", _options);
Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value);
}
[Fact]
public void Deserialize_ValidDashed_Success()
{
Guid? value = JsonSerializer.Deserialize<Guid?>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options);
Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value);
}
[Fact]
public void Roundtrip_Valid_Success()
{
Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18");
string value = JsonSerializer.Serialize(guid, _options);
Assert.Equal(guid, JsonSerializer.Deserialize<Guid?>(value, _options));
}
[Fact]
public void Deserialize_Null_Null()
{
Assert.Null(JsonSerializer.Deserialize<Guid?>("null", _options));
}
[Fact]
public void Deserialize_EmptyGuid_EmptyGuid()
{
Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid?>(@"""00000000-0000-0000-0000-000000000000""", _options));
}
[Fact]
public void Serialize_EmptyGuid_Null()
{
Assert.Equal("null", JsonSerializer.Serialize((Guid?)Guid.Empty, _options));
}
[Fact]
public void Serialize_Null_Null()
{
Assert.Equal("null", JsonSerializer.Serialize((Guid?)null, _options));
}
[Fact]
public void Serialize_Valid_NoDash_Success()
{
var guid = (Guid?)new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
Assert.Equal($"\"{guid:N}\"", str);
}
[Fact]
public void Serialize_Nullable_Success()
{
Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
Assert.Equal($"\"{guid:N}\"", str);
}
}
}
@@ -0,0 +1,38 @@
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonStringConverterTests
{
private readonly JsonSerializerOptions _jsonSerializerOptions = new()
{
Converters =
{
new JsonStringConverter()
}
};
[Theory]
[InlineData("\"test\"", "test")]
[InlineData("123", "123")]
[InlineData("123.45", "123.45")]
[InlineData("true", "true")]
[InlineData("false", "false")]
public void Deserialize_String_Valid_Success(string input, string output)
{
var deserialized = JsonSerializer.Deserialize<string>(input, _jsonSerializerOptions);
Assert.Equal(deserialized, output);
}
[Fact]
public void Deserialize_Int32asInt32_Valid_Success()
{
const string? input = "123";
const int output = 123;
var deserialized = JsonSerializer.Deserialize<int>(input, _jsonSerializerOptions);
Assert.Equal(output, deserialized);
}
}
}
@@ -0,0 +1,36 @@
using System;
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
namespace Jellyfin.Extensions.Tests.Json.Converters
{
public class JsonVersionConverterTests
{
private readonly JsonSerializerOptions _options;
public JsonVersionConverterTests()
{
_options = new JsonSerializerOptions();
_options.Converters.Add(new JsonVersionConverter());
}
[Fact]
public void Deserialize_Version_Success()
{
var input = "\"1.025.222\"";
var output = new Version(1, 25, 222);
var deserializedInput = JsonSerializer.Deserialize<Version>(input, _options);
Assert.Equal(output, deserializedInput);
}
[Fact]
public void Serialize_Version_Success()
{
var input = new Version(1, 09, 59);
var output = "\"1.9.59\"";
var serializedInput = JsonSerializer.Serialize(input, _options);
Assert.Equal(output, serializedInput);
}
}
}
@@ -0,0 +1,20 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Json.Converters;
namespace Jellyfin.Extensions.Tests.Json.Models
{
/// <summary>
/// The generic body model.
/// </summary>
/// <typeparam name="T">The value type.</typeparam>
public sealed class GenericBodyArrayModel<T>
{
/// <summary>
/// Gets or sets the value.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1819:Properties should not return arrays", MessageId = "Value", Justification = "Imported from ServiceStack")]
[JsonConverter(typeof(JsonCommaDelimitedCollectionConverterFactory))]
public T[] Value { get; set; } = default!;
}
}
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Json.Converters;
namespace Jellyfin.Extensions.Tests.Json.Models
{
/// <summary>
/// The generic body <c>IReadOnlyCollection</c> model.
/// </summary>
/// <typeparam name="T">The value type.</typeparam>
public sealed class GenericBodyIReadOnlyCollectionModel<T>
{
/// <summary>
/// Gets or sets the value.
/// </summary>
[JsonConverter(typeof(JsonCommaDelimitedCollectionConverterFactory))]
public IReadOnlyCollection<T> Value { get; set; } = default!;
}
}
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Json.Converters;
namespace Jellyfin.Extensions.Tests.Json.Models
{
/// <summary>
/// The generic body <c>IReadOnlyList</c> model.
/// </summary>
/// <typeparam name="T">The value type.</typeparam>
public sealed class GenericBodyIReadOnlyListModel<T>
{
/// <summary>
/// Gets or sets the value.
/// </summary>
[JsonConverter(typeof(JsonCommaDelimitedCollectionConverterFactory))]
public IReadOnlyList<T> Value { get; set; } = default!;
}
}
@@ -0,0 +1,22 @@
#pragma warning disable CA1002 // Do not expose generic lists
#pragma warning disable CA2227 // Collection properties should be read only
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Json.Converters;
namespace Jellyfin.Extensions.Tests.Json.Models
{
/// <summary>
/// The generic body <c>List</c> model.
/// </summary>
/// <typeparam name="T">The value type.</typeparam>
public sealed class GenericBodyListModel<T>
{
/// <summary>
/// Gets or sets the value.
/// </summary>
[JsonConverter(typeof(JsonCommaDelimitedCollectionConverterFactory))]
public List<T> Value { get; set; } = default!;
}
}
@@ -0,0 +1,19 @@
using System;
using Xunit;
namespace Jellyfin.Extensions.Tests
{
public static class ShuffleExtensionsTests
{
[Fact]
public static void Shuffle_Valid_Correct()
{
byte[] original = new byte[1 << 6];
Random.Shared.NextBytes(original);
byte[] shuffled = (byte[])original.Clone();
shuffled.Shuffle();
Assert.NotEqual(original, shuffled);
}
}
}
@@ -0,0 +1,79 @@
using System;
using Xunit;
namespace Jellyfin.Extensions.Tests
{
public class StringExtensionsTests
{
[Theory]
[InlineData("", "")] // Identity edge-case (no diacritics)
[InlineData("Indiana Jones", "Indiana Jones")] // Identity (no diacritics)
[InlineData("a\ud800b", "ab")] // Invalid UTF-16 char stripping
[InlineData("åäö", "aao")] // Issue #7484
[InlineData("Jön", "Jon")] // Issue #7484
[InlineData("Jönssonligan", "Jonssonligan")] // Issue #7484
[InlineData("Kieślowski", "Kieslowski")] // Issue #7450
[InlineData("Cidadão Kane", "Cidadao Kane")] // Issue #7560
[InlineData("운명처럼 널 사랑해", "운명처럼 널 사랑해")] // Issue #6393 (Korean language support)
[InlineData("애타는 로맨스", "애타는 로맨스")] // Issue #6393
[InlineData("Le cœur a ses raisons", "Le coeur a ses raisons")] // Issue #8893
[InlineData("Béla Tarr", "Bela Tarr")] // Issue #8893
public void RemoveDiacritics_ValidInput_Corrects(string input, string expectedResult)
{
string result = input.RemoveDiacritics();
Assert.Equal(expectedResult, result);
}
[Theory]
[InlineData("", false)] // Identity edge-case (no diacritics)
[InlineData("Indiana Jones", false)] // Identity (no diacritics)
[InlineData("a\ud800b", true)] // Invalid UTF-16 char stripping
[InlineData("åäö", true)] // Issue #7484
[InlineData("Jön", true)] // Issue #7484
[InlineData("Jönssonligan", true)] // Issue #7484
[InlineData("Kieślowski", true)] // Issue #7450
[InlineData("Cidadão Kane", true)] // Issue #7560
[InlineData("운명처럼 널 사랑해", false)] // Issue #6393 (Korean language support)
[InlineData("애타는 로맨스", false)] // Issue #6393
[InlineData("Le cœur a ses raisons", true)] // Issue #8893
[InlineData("Béla Tarr", true)] // Issue #8893
public void HasDiacritics_ValidInput_Corrects(string input, bool expectedResult)
{
bool result = input.HasDiacritics();
Assert.Equal(expectedResult, result);
}
[Theory]
[InlineData("", '_', 0)]
[InlineData("___", '_', 3)]
[InlineData("test\x00", '\x00', 1)]
[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));
}
[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);
}
}
}
@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]
@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Jellyfin.Extensions.Tests")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("Jellyfin.Extensions.Tests")]
[assembly: System.Reflection.AssemblyTitleAttribute("Jellyfin.Extensions.Tests")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.
@@ -0,0 +1 @@
a9cd9f1b54cb0c14d8cfa5b8178fecf508c852c97b2e4a7c895ddcc7cc974ad2
@@ -0,0 +1,27 @@
is_global = true
build_property.TargetFramework = net10.0
build_property.TargetFramework = net10.0
build_property.TargetFrameworkIdentifier = .NETCoreApp
build_property.TargetFrameworkIdentifier = .NETCoreApp
build_property.TargetFrameworkVersion = v10.0
build_property.TargetFrameworkVersion = v10.0
build_property.TargetPlatformMinVersion =
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = Jellyfin.Extensions.Tests
build_property.ProjectDir = /srv/common_drive/Projects/pgsql-jellyfin/tests/Jellyfin.Extensions.Tests/
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 10.0
build_property.EnableCodeStyleSeverity =
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/home/wjones/.nuget/packages/</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/home/wjones/.nuget/packages/</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="/home/wjones/.nuget/packages/" />
</ItemGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.runner.visualstudio/2.8.2/build/net6.0/xunit.runner.visualstudio.props" Condition="Exists('$(NuGetPackageRoot)xunit.runner.visualstudio/2.8.2/build/net6.0/xunit.runner.visualstudio.props')" />
<Import Project="$(NuGetPackageRoot)xunit.core/2.9.3/build/xunit.core.props" Condition="Exists('$(NuGetPackageRoot)xunit.core/2.9.3/build/xunit.core.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost/18.0.1/build/net8.0/Microsoft.TestPlatform.TestHost.props" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost/18.0.1/build/net8.0/Microsoft.TestPlatform.TestHost.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage/18.0.1/build/netstandard2.0/Microsoft.CodeCoverage.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage/18.0.1/build/netstandard2.0/Microsoft.CodeCoverage.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk/18.0.1/build/net8.0/Microsoft.NET.Test.Sdk.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk/18.0.1/build/net8.0/Microsoft.NET.Test.Sdk.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore/10.0.3/buildTransitive/net10.0/Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore/10.0.3/buildTransitive/net10.0/Microsoft.EntityFrameworkCore.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.bannedapianalyzers/4.14.0/buildTransitive/Microsoft.CodeAnalysis.BannedApiAnalyzers.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.bannedapianalyzers/4.14.0/buildTransitive/Microsoft.CodeAnalysis.BannedApiAnalyzers.props')" />
</ImportGroup>
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Pkgxunit_analyzers Condition=" '$(Pkgxunit_analyzers)' == '' ">/home/wjones/.nuget/packages/xunit.analyzers/1.18.0</Pkgxunit_analyzers>
<PkgStyleCop_Analyzers_Unstable Condition=" '$(PkgStyleCop_Analyzers_Unstable)' == '' ">/home/wjones/.nuget/packages/stylecop.analyzers.unstable/1.2.0.556</PkgStyleCop_Analyzers_Unstable>
<PkgSmartAnalyzers_MultithreadingAnalyzer Condition=" '$(PkgSmartAnalyzers_MultithreadingAnalyzer)' == '' ">/home/wjones/.nuget/packages/smartanalyzers.multithreadinganalyzer/1.1.31</PkgSmartAnalyzers_MultithreadingAnalyzer>
<PkgSerilogAnalyzer Condition=" '$(PkgSerilogAnalyzer)' == '' ">/home/wjones/.nuget/packages/seriloganalyzer/0.15.0</PkgSerilogAnalyzer>
<PkgMicrosoft_CodeAnalysis_BannedApiAnalyzers Condition=" '$(PkgMicrosoft_CodeAnalysis_BannedApiAnalyzers)' == '' ">/home/wjones/.nuget/packages/microsoft.codeanalysis.bannedapianalyzers/4.14.0</PkgMicrosoft_CodeAnalysis_BannedApiAnalyzers>
</PropertyGroup>
</Project>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.core/2.9.3/build/xunit.core.targets" Condition="Exists('$(NuGetPackageRoot)xunit.core/2.9.3/build/xunit.core.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost/18.0.1/build/net8.0/Microsoft.TestPlatform.TestHost.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost/18.0.1/build/net8.0/Microsoft.TestPlatform.TestHost.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage/18.0.1/build/netstandard2.0/Microsoft.CodeCoverage.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage/18.0.1/build/netstandard2.0/Microsoft.CodeCoverage.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk/18.0.1/build/net8.0/Microsoft.NET.Test.Sdk.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk/18.0.1/build/net8.0/Microsoft.NET.Test.Sdk.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options/10.0.3/buildTransitive/net8.0/Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options/10.0.3/buildTransitive/net8.0/Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/10.0.3/buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions/10.0.3/buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.bannedapianalyzers/4.14.0/buildTransitive/Microsoft.CodeAnalysis.BannedApiAnalyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.bannedapianalyzers/4.14.0/buildTransitive/Microsoft.CodeAnalysis.BannedApiAnalyzers.targets')" />
<Import Project="$(NuGetPackageRoot)coverlet.collector/8.0.0/build/net8.0/coverlet.collector.targets" Condition="Exists('$(NuGetPackageRoot)coverlet.collector/8.0.0/build/net8.0/coverlet.collector.targets')" />
</ImportGroup>
</Project>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,50 @@
{
"version": 2,
"dgSpecHash": "0dsNVQWWNB8=",
"success": true,
"projectFilePath": "/srv/common_drive/Projects/pgsql-jellyfin/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj",
"expectedPackageFiles": [
"/home/wjones/.nuget/packages/coverlet.collector/8.0.0/coverlet.collector.8.0.0.nupkg.sha512",
"/home/wjones/.nuget/packages/diacritics/4.1.4/diacritics.4.1.4.nupkg.sha512",
"/home/wjones/.nuget/packages/fscheck/3.3.2/fscheck.3.3.2.nupkg.sha512",
"/home/wjones/.nuget/packages/fscheck.xunit/3.3.2/fscheck.xunit.3.3.2.nupkg.sha512",
"/home/wjones/.nuget/packages/fsharp.core/5.0.2/fsharp.core.5.0.2.nupkg.sha512",
"/home/wjones/.nuget/packages/icu4n/60.1.0-alpha.356/icu4n.60.1.0-alpha.356.nupkg.sha512",
"/home/wjones/.nuget/packages/icu4n.transliterator/60.1.0-alpha.356/icu4n.transliterator.60.1.0-alpha.356.nupkg.sha512",
"/home/wjones/.nuget/packages/j2n/2.0.0/j2n.2.0.0.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.codeanalysis.bannedapianalyzers/4.14.0/microsoft.codeanalysis.bannedapianalyzers.4.14.0.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.codecoverage/18.0.1/microsoft.codecoverage.18.0.1.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.entityframeworkcore/10.0.3/microsoft.entityframeworkcore.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.entityframeworkcore.abstractions/10.0.3/microsoft.entityframeworkcore.abstractions.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.entityframeworkcore.analyzers/10.0.3/microsoft.entityframeworkcore.analyzers.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.entityframeworkcore.relational/10.0.3/microsoft.entityframeworkcore.relational.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.caching.abstractions/10.0.3/microsoft.extensions.caching.abstractions.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.caching.memory/10.0.3/microsoft.extensions.caching.memory.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.configuration.abstractions/10.0.3/microsoft.extensions.configuration.abstractions.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.dependencyinjection/10.0.3/microsoft.extensions.dependencyinjection.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.dependencyinjection.abstractions/10.0.3/microsoft.extensions.dependencyinjection.abstractions.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.logging/10.0.3/microsoft.extensions.logging.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.logging.abstractions/10.0.3/microsoft.extensions.logging.abstractions.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.options/10.0.3/microsoft.extensions.options.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.extensions.primitives/10.0.3/microsoft.extensions.primitives.10.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.net.test.sdk/18.0.1/microsoft.net.test.sdk.18.0.1.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.testplatform.objectmodel/18.0.1/microsoft.testplatform.objectmodel.18.0.1.nupkg.sha512",
"/home/wjones/.nuget/packages/microsoft.testplatform.testhost/18.0.1/microsoft.testplatform.testhost.18.0.1.nupkg.sha512",
"/home/wjones/.nuget/packages/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/polly/8.6.5/polly.8.6.5.nupkg.sha512",
"/home/wjones/.nuget/packages/polly.core/8.6.5/polly.core.8.6.5.nupkg.sha512",
"/home/wjones/.nuget/packages/seriloganalyzer/0.15.0/seriloganalyzer.0.15.0.nupkg.sha512",
"/home/wjones/.nuget/packages/smartanalyzers.multithreadinganalyzer/1.1.31/smartanalyzers.multithreadinganalyzer.1.1.31.nupkg.sha512",
"/home/wjones/.nuget/packages/stylecop.analyzers/1.2.0-beta.556/stylecop.analyzers.1.2.0-beta.556.nupkg.sha512",
"/home/wjones/.nuget/packages/stylecop.analyzers.unstable/1.2.0.556/stylecop.analyzers.unstable.1.2.0.556.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit/2.9.3/xunit.2.9.3.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit.abstractions/2.0.3/xunit.abstractions.2.0.3.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit.analyzers/1.18.0/xunit.analyzers.1.18.0.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit.assert/2.9.3/xunit.assert.2.9.3.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit.core/2.9.3/xunit.core.2.9.3.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit.extensibility.core/2.9.3/xunit.extensibility.core.2.9.3.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit.extensibility.execution/2.9.3/xunit.extensibility.execution.2.9.3.nupkg.sha512",
"/home/wjones/.nuget/packages/xunit.runner.visualstudio/2.8.2/xunit.runner.visualstudio.2.8.2.nupkg.sha512"
],
"logs": []
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
17714532033100000
@@ -0,0 +1 @@
17715044195400000