mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-16 22:39:29 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c7d3a2be2 | |||
| 0a30872781 | |||
| 7eed1ca466 | |||
| b6cc64fd51 | |||
| c8bfaffb42 | |||
| bf163251dd | |||
| c0b5734b71 | |||
| 2944d9887e | |||
| 57925151fa |
@@ -21,6 +21,7 @@ jobs:
|
||||
Test_Project_Path: SystemExtensions.Tests\SystemExtensions.NetStandard.Tests.csproj
|
||||
DI_Test_Project_Path: SystemExtensions.DependencyInjection.Tests\SystemExtensions.NetStandard.DependencyInjection.Tests.csproj
|
||||
Source_Project_Path: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
|
||||
Core_Project_Path: SystemExtensions.NetCore\SystemExtensions.NetCore.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
@@ -32,7 +33,7 @@ jobs:
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.202'
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.1
|
||||
@@ -45,6 +46,9 @@ jobs:
|
||||
- name: Build SystemExtensions.NetStandard project
|
||||
run: dotnet build SystemExtensions.NetStandard -c $env:Configuration
|
||||
|
||||
- name: Build SystemExtensions.NetCore project
|
||||
run: dotnet build SystemExtensions.NetCore -c $env:Configuration
|
||||
|
||||
- name: Build SystemExtensions.NetStandard.DependencyInjection project
|
||||
run: dotnet build SystemExtensions.NetStandard.DependencyInjection -c $env:Configuration
|
||||
|
||||
@@ -57,6 +61,12 @@ jobs:
|
||||
PROJECT_FILE_PATH: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
|
||||
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
|
||||
- name: Push SystemExtensions.NetCore nuget package
|
||||
uses: brandedoutcast/publish-nuget@v2.5.5
|
||||
with:
|
||||
PROJECT_FILE_PATH: SystemExtensions.NetCore\SystemExtensions.NetCore.csproj
|
||||
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
|
||||
- name: Push SystemExtensions.NetStandard.DependencyInjection nuget package
|
||||
uses: brandedoutcast/publish-nuget@v2.5.5
|
||||
with:
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.202'
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.1
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.Core.Extensions;
|
||||
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
public static T ThrowIfNull<T>([ValidatedNotNull] this T obj, [CallerArgumentExpression("obj")] string? paramName = null)
|
||||
where T : class
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(paramName);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
sealed class ValidatedNotNullAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<Version>1.0.1</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the System namespace</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+17
@@ -104,6 +104,23 @@ namespace System.Extensions
|
||||
return serviceManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a <see cref="ILoggerFactory"/> with a <see cref="CVLoggerProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceManager"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceManager RegisterCVLoggerFactory(this IServiceManager serviceManager)
|
||||
{
|
||||
serviceManager.RegisterScoped<ILoggerFactory, LoggerFactory>(sp =>
|
||||
{
|
||||
LoggerFactory loggerFactory = new();
|
||||
loggerFactory.AddProvider(new CVLoggerProvider(sp.GetService<ILogsWriter>()));
|
||||
return loggerFactory;
|
||||
});
|
||||
|
||||
return serviceManager;
|
||||
}
|
||||
|
||||
public static IServiceManager RegisterLoggerFactory(this IServiceManager serviceManager, Func<Slim.IServiceProvider, ILoggerFactory> loggerFactory)
|
||||
{
|
||||
serviceManager.ThrowIfNull(nameof(serviceManager));
|
||||
|
||||
+5
-4
@@ -6,9 +6,10 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Version>1.1.2</Version>
|
||||
<Version>1.1.7</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the Slim Dependency Injection engine</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -20,9 +21,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<PackageReference Include="Slim" Version="1.5.1" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Slim" Version="1.6.0" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -3,9 +3,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Encryption;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensions.NetStandard.Security.Encryption;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
using System.Rng;
|
||||
using System.Security.Rng;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Security.Hashing;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Rfc2898DeriveBytesPasswordHashingServiceTests
|
||||
{
|
||||
private const int TooShortHashLength = 31;
|
||||
private const int DesiredHashLength = 32;
|
||||
private const int Iterations = 10000;
|
||||
private const int TooLittleIterations = 1000;
|
||||
|
||||
private readonly Rfc2898DeriveBytesPasswordHashingService rfc2898DeriveBytesPasswordHashingService = new();
|
||||
|
||||
private byte[] tooShortSaltBytes;
|
||||
private string tooShortSaltString;
|
||||
private byte[] incorrectSaltBytes;
|
||||
private string incorrectSaltString;
|
||||
private byte[] saltBytes;
|
||||
private string saltString;
|
||||
private byte[] passwordBytes;
|
||||
private string passwordString;
|
||||
private byte[] incorrectPasswordBytes;
|
||||
private string incorrectPasswordString;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
this.tooShortSaltBytes = new byte[16];
|
||||
this.tooShortSaltString = Convert.ToBase64String(this.tooShortSaltBytes);
|
||||
this.saltBytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
|
||||
this.incorrectSaltBytes = new byte[32];
|
||||
this.incorrectSaltString = Convert.ToBase64String(this.incorrectSaltBytes);
|
||||
this.saltString = Convert.ToBase64String(this.saltBytes);
|
||||
this.passwordBytes = new byte[] { 5, 1, 2, 34, 35, 123, 4, 23, 1, 235, 32, 234 };
|
||||
this.passwordString = Convert.ToBase64String(this.passwordBytes);
|
||||
this.incorrectPasswordBytes = new byte[] { 14, 123, 23, 4, 2, 1, 23, 25 };
|
||||
this.incorrectPasswordString = Convert.ToBase64String(this.incorrectPasswordBytes);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PasswordNull_HashBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(null, this.saltBytes, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void PasswordNull_HashString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(null, this.saltString, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_HashBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, null, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_HashString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, null, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashLengthTooSmall_HashBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, TooShortHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashLengthTooSmall_HashString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, TooShortHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_HashBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_HashString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooShortSalt_HashBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.tooShortSaltBytes, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooShortSalt_HashString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.tooShortSaltString, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void PasswordNull_VerifyBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(null, this.incorrectPasswordBytes, this.saltBytes, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void PasswordNull_VerifyString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(null, this.incorrectPasswordString, this.saltString, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashNull_VerifyBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordBytes, null, this.saltBytes, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashNull_VerifyString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordString, null, this.saltString, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_VerifyBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordBytes, this.incorrectPasswordBytes, null, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_VerifyString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordString, this.incorrectPasswordString, null, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_VerifyBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordBytes, this.incorrectPasswordBytes, this.saltBytes, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_VerifyString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordString, this.incorrectPasswordString, this.saltString, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task HashBytes_ReturnsHashedBytes()
|
||||
{
|
||||
var hashedBytes = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, DesiredHashLength, Iterations);
|
||||
|
||||
hashedBytes.Should().NotBeNull();
|
||||
hashedBytes.Should().HaveCount(DesiredHashLength);
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task HashString_ReturnsHashedString()
|
||||
{
|
||||
var hashedString = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, DesiredHashLength, Iterations);
|
||||
|
||||
hashedString.Should().NotBeNull();
|
||||
var hashedBytes = Convert.FromBase64String(hashedString);
|
||||
hashedBytes.Should().HaveCount(DesiredHashLength);
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyBytes_CorrectPassword_ReturnsTrue()
|
||||
{
|
||||
var hashedBytes = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedBytes, this.passwordBytes, this.saltBytes, Iterations);
|
||||
|
||||
result.Should().BeTrue();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyString_CorrectPassword_ReturnsTrue()
|
||||
{
|
||||
var hashedString = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedString, this.passwordString, this.saltString, Iterations);
|
||||
|
||||
result.Should().BeTrue();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyBytes_IncorrectPassword_ReturnsFalse()
|
||||
{
|
||||
var hashedBytes = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedBytes, this.incorrectPasswordBytes, this.saltBytes, Iterations);
|
||||
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyString_IncorrectPassword_ReturnsFalse()
|
||||
{
|
||||
var hashedString = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedString, this.incorrectPasswordString, this.saltString, Iterations);
|
||||
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyBytes_IncorrectSalt_ReturnsFalse()
|
||||
{
|
||||
var hashedBytes = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedBytes, this.passwordBytes, this.incorrectSaltBytes, Iterations);
|
||||
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyString_IncorrectSalt_ReturnsFalse()
|
||||
{
|
||||
var hashedString = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedString, this.passwordString, this.incorrectSaltString, Iterations);
|
||||
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyBytes_IncorrectIterations_ReturnsFalse()
|
||||
{
|
||||
var hashedBytes = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedBytes, this.passwordBytes, this.saltBytes, Iterations + 1);
|
||||
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task VerifyString_IncorrectIterations_ReturnsFalse()
|
||||
{
|
||||
var hashedString = await this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, DesiredHashLength, Iterations);
|
||||
|
||||
var result = await this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(hashedString, this.passwordString, this.saltString, Iterations + 1);
|
||||
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Encryption;
|
||||
using System.Security.Encryption;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Hashing;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensions.NetStandard.Security.Hashing;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensions.NetStandard.Security.Utilities;
|
||||
using System.Security.Utilities;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Encryption
|
||||
namespace System.Security.Encryption
|
||||
{
|
||||
public sealed class AesEncrypter : ISymmetricEncrypter
|
||||
{
|
||||
@@ -77,16 +76,16 @@ namespace SystemExtensions.NetStandard.Security.Encryption
|
||||
|
||||
public async Task<Stream> Encrypt(string key, string iv, Stream value)
|
||||
{
|
||||
if (value is null) throw new ArgumentNullException(nameof(value));
|
||||
|
||||
return await EncryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await EncryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value)
|
||||
{
|
||||
if (value is null) throw new ArgumentNullException(nameof(value));
|
||||
|
||||
return await EncryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await EncryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Stream GetEncryptionStream(string key, string iv, Stream outStream)
|
||||
@@ -112,9 +111,9 @@ namespace SystemExtensions.NetStandard.Security.Encryption
|
||||
private static byte[] StreamToBytes(Stream value)
|
||||
{
|
||||
value.Position = 0;
|
||||
byte[] buffer = new byte[1024];
|
||||
var buffer = new byte[1024];
|
||||
using var ms = new MemoryStream();
|
||||
int read = -1;
|
||||
var read = -1;
|
||||
do
|
||||
{
|
||||
read = value.Read(buffer, 0, buffer.Length);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Encryption
|
||||
namespace System.Security.Encryption
|
||||
{
|
||||
public interface ISymmetricEncrypter
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Encryption
|
||||
namespace System.Security.Encryption
|
||||
{
|
||||
public sealed class SecureString
|
||||
{
|
||||
@@ -47,20 +47,33 @@ namespace System.Encryption
|
||||
public static implicit operator SecureString(string s) => new(s);
|
||||
public static SecureString operator +(SecureString ss1, SecureString ss2)
|
||||
{
|
||||
if (ss1 is null) throw new ArgumentNullException(nameof(ss1));
|
||||
if (ss2 is null) throw new ArgumentNullException(nameof(ss2));
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
if (ss2 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss2));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + ss2.Value);
|
||||
}
|
||||
public static SecureString operator +(SecureString ss1, string s2)
|
||||
{
|
||||
if (ss1 is null) throw new ArgumentNullException(nameof(ss1));
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + s2);
|
||||
}
|
||||
public static SecureString operator +(SecureString ss1, char c)
|
||||
{
|
||||
if (ss1 is null) throw new ArgumentNullException(nameof(ss1));
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + c);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Hashing
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
public interface IHashingService
|
||||
{
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
public interface IPasswordHashingService
|
||||
{
|
||||
/// <summary>
|
||||
/// Hash provided raw password and return the hashed value.
|
||||
/// </summary>
|
||||
/// <param name="raw">Base64 encoded password.</param>
|
||||
/// <param name="salt">Base64 encoded salt to be used for hashing.</param>
|
||||
/// <param name="length">Length of the resulting hash.</param>
|
||||
/// <param name="iterations">Number of hashing iterations to be performed.</param>
|
||||
/// <remarks>
|
||||
/// The length of the hash will vary due to the base64 encoding of the resulting hash.
|
||||
/// </remarks>
|
||||
/// <returns>Base64 encoded hashed password.</returns>
|
||||
Task<string> Hash(string raw, string salt, int length, int iterations);
|
||||
/// <summary>
|
||||
/// Hash provided raw password and return the hashed value.
|
||||
/// </summary>
|
||||
/// <param name="raw">Password to be hashed.</param>
|
||||
/// <param name="salt">Salt to be used for hashing.</param>
|
||||
/// <param name="length">Length of the resulting hash.</param>
|
||||
/// <param name="iterations">Number of hashing iterations to be performed.</param>
|
||||
/// <returns>Hashed password.</returns>
|
||||
Task<byte[]> Hash(byte[] raw, byte[] salt, int length, int iterations);
|
||||
/// <summary>
|
||||
/// Verify provided password against a hashed password.
|
||||
/// </summary>
|
||||
/// <param name="hash">Base64 encoding of the previously hashed password.</param>
|
||||
/// <param name="password">Base64 encoding of the password to be verified.</param>
|
||||
/// <param name="salt">Salt used to hash the previous password.</param>
|
||||
/// <param name="iterations">Number of iterations used to hash the previous password.</param>
|
||||
/// <returns>Returns true if password matches the previously hashed password. Otherwise returns false.</returns>
|
||||
Task<bool> VerifyPassword(string hash, string password, string salt, int iterations);
|
||||
/// <summary>
|
||||
/// Verify provided password against a hashed password.
|
||||
/// </summary>
|
||||
/// <param name="hash">Previously hashed password.</param>
|
||||
/// <param name="password">Password to be verified.</param>
|
||||
/// <param name="salt">Salt used to hash the previous password.</param>
|
||||
/// <param name="iterations">Number of iterations used to hash the previous password.</param>
|
||||
/// <returns>Returns true if password matches the previously hashed password. Otherwise returns false.</returns>
|
||||
Task<bool> VerifyPassword(byte[] hash, byte[] password, byte[] salt, int iterations);
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
public sealed class Rfc2898DeriveBytesPasswordHashingService : IPasswordHashingService
|
||||
{
|
||||
private const int MinimumIterations = 10000;
|
||||
private const int MinimumHashLength = 32;
|
||||
|
||||
public Rfc2898DeriveBytesPasswordHashingService()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<string> Hash(string raw, string salt, int length, int iterations)
|
||||
{
|
||||
this.ValidateHashArguments(raw, salt, length, iterations);
|
||||
|
||||
var rawBytes = Convert.FromBase64String(raw);
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
var hashBytes = await this.HashInternal(rawBytes, saltBytes, length, iterations);
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
public Task<byte[]> Hash(byte[] raw, byte[] salt, int length, int iterations)
|
||||
{
|
||||
this.ValidateHashArguments(raw, salt, length, iterations);
|
||||
|
||||
return this.HashInternal(raw, salt, length, iterations);
|
||||
}
|
||||
public Task<bool> VerifyPassword(string hash, string password, string salt, int iterations)
|
||||
{
|
||||
this.ValidateVerifyArguments(hash, password, salt, iterations);
|
||||
var hashBytes = Convert.FromBase64String(hash);
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
var passwordBytes = Convert.FromBase64String(password);
|
||||
return this.VerifyPasswordInternal(hashBytes, passwordBytes, saltBytes, iterations);
|
||||
}
|
||||
public Task<bool> VerifyPassword(byte[] hash, byte[] password, byte[] salt, int iterations)
|
||||
{
|
||||
this.ValidateVerifyArguments(hash, password, salt, iterations);
|
||||
return this.VerifyPasswordInternal(hash, password, salt, iterations);
|
||||
}
|
||||
|
||||
private void ValidateHashArguments(object raw, object salt, int length, int iterations)
|
||||
{
|
||||
_ = raw ?? throw new ArgumentNullException(nameof(raw));
|
||||
_ = salt ?? throw new ArgumentNullException(nameof(salt));
|
||||
|
||||
if (iterations < MinimumIterations)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to perform secure hash. Iteration count must be over {MinimumIterations}");
|
||||
}
|
||||
|
||||
if (length < MinimumHashLength)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to perform secure hash. Hash length must be over {MinimumHashLength}");
|
||||
}
|
||||
}
|
||||
private void ValidateVerifyArguments(object hash, object password, object salt, int iterations)
|
||||
{
|
||||
_ = hash ?? throw new ArgumentNullException(nameof(hash));
|
||||
_ = salt ?? throw new ArgumentNullException(nameof(salt));
|
||||
_ = password ?? throw new ArgumentNullException(nameof(password));
|
||||
|
||||
if (iterations < MinimumIterations)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to verify hash. Iteration count must be over {MinimumIterations}");
|
||||
}
|
||||
}
|
||||
private Task<byte[]> HashInternal(byte[] raw, byte[] salt, int length, int iterations)
|
||||
{
|
||||
using var pbkdf2 = new Rfc2898DeriveBytes(raw, salt, iterations);
|
||||
var hash = pbkdf2.GetBytes(length);
|
||||
return Task.FromResult(hash);
|
||||
}
|
||||
private Task<bool> VerifyPasswordInternal(byte[] hash, byte[] password, byte[] salt, int iterations)
|
||||
{
|
||||
using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
|
||||
var hashToVerify = pbkdf2.GetBytes(hash.Length);
|
||||
var lengthToVerify = Math.Max(hash.Length, hashToVerify.Length);
|
||||
var match = true;
|
||||
if (lengthToVerify <= 0)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
for(var i = 0; i < lengthToVerify; i++)
|
||||
{
|
||||
if (i < hash.Length && i < hashToVerify.Length)
|
||||
{
|
||||
if (hashToVerify[i].Equals(hash[i]) is false)
|
||||
{
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(match && hash.Length.Equals(hashToVerify.Length));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Hashing
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
public sealed class Sha256HashingService : IHashingService
|
||||
{
|
||||
@@ -27,9 +26,9 @@ namespace SystemExtensions.NetStandard.Security.Hashing
|
||||
private static byte[] StreamToBytes(Stream value)
|
||||
{
|
||||
value.Position = 0;
|
||||
byte[] buffer = new byte[1024];
|
||||
var buffer = new byte[1024];
|
||||
using var ms = new MemoryStream();
|
||||
int read = -1;
|
||||
var read = -1;
|
||||
do
|
||||
{
|
||||
read = value.Read(buffer, 0, buffer.Length);
|
||||
@@ -51,7 +50,10 @@ namespace SystemExtensions.NetStandard.Security.Hashing
|
||||
}
|
||||
private static async Task<Stream> HashInternal(Stream raw)
|
||||
{
|
||||
if (raw is null) throw new ArgumentNullException(nameof(raw));
|
||||
if (raw is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(raw));
|
||||
}
|
||||
|
||||
using var sha256 = SHA256.Create();
|
||||
return await Task.Run(() => new MemoryStream(sha256.ComputeHash(raw)));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace System.Rng
|
||||
namespace System.Security.Rng
|
||||
{
|
||||
public sealed class CryptoRngProvider : ICryptoRngProvider, IDisposable
|
||||
{
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
namespace System.Rng
|
||||
namespace System.Security.Rng
|
||||
{
|
||||
public interface ICryptoRngProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Populate provided array of bytes with cryptographically secure random bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">Array of bytes to be populated.</param>
|
||||
public void GetBytes(byte[] data);
|
||||
/// <summary>
|
||||
/// Return an array of cryptographically secure random bytes.
|
||||
/// </summary>
|
||||
/// <param name="byteCount">Length of the returned array.</param>
|
||||
/// <returns>Array containing cryptographically secure random values.</returns>
|
||||
public byte[] GetBytes(int byteCount);
|
||||
/// <summary>
|
||||
/// Populate provided array of bytes with cryptographically secure random non-zero bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">Array of bytes to be populated.</param>
|
||||
public void GetNonZeroBytes(byte[] data);
|
||||
/// <summary>
|
||||
/// Return an array of cryptographically secure random non-zero bytes.
|
||||
/// </summary>
|
||||
/// <param name="byteCount">Length of the returned array.</param>
|
||||
/// <returns>Array containing cryptographically secure random non-zero values.</returns>
|
||||
public byte[] GetNonZeroBytes(int byteCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
<Version>1.1.1</Version>
|
||||
<Version>1.2.3</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Security extensions for the System namespace</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Utilities
|
||||
namespace System.Security.Utilities
|
||||
{
|
||||
internal sealed class NotClosingCryptoStream : CryptoStream
|
||||
{
|
||||
@@ -13,7 +13,9 @@ namespace SystemExtensions.NetStandard.Security.Utilities
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.HasFlushedFinalBlock)
|
||||
{
|
||||
this.FlushFinalBlock();
|
||||
}
|
||||
|
||||
base.Dispose(false);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace System.Collections.Generic
|
||||
public void Add(T value)
|
||||
{
|
||||
count++;
|
||||
AVLNode<T> newItem = new AVLNode<T>(value);
|
||||
var newItem = new AVLNode<T>(value);
|
||||
if (root == null)
|
||||
{
|
||||
root = newItem;
|
||||
@@ -77,7 +77,7 @@ namespace System.Collections.Generic
|
||||
/// <returns>True if the value is in the tree.</returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
AVLNode<T> node = Find(value, root);
|
||||
var node = Find(value, root);
|
||||
if (node == null)
|
||||
{
|
||||
return false;
|
||||
@@ -105,12 +105,12 @@ namespace System.Collections.Generic
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
Queue<AVLNode<T>> queue = new Queue<AVLNode<T>>();
|
||||
var queue = new Queue<AVLNode<T>>();
|
||||
queue.Enqueue(root);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
AVLNode<T> currentNode = queue.Dequeue();
|
||||
var currentNode = queue.Dequeue();
|
||||
if (currentNode.Left != null)
|
||||
{
|
||||
queue.Enqueue(currentNode.Left);
|
||||
@@ -134,11 +134,11 @@ namespace System.Collections.Generic
|
||||
/// <param name="arrayIndex">Starting index of the provided array.</param>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
Queue<AVLNode<T>> queue = new Queue<AVLNode<T>>();
|
||||
var queue = new Queue<AVLNode<T>>();
|
||||
queue.Enqueue(root);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
AVLNode<T> currentNode = queue.Dequeue();
|
||||
var currentNode = queue.Dequeue();
|
||||
array[arrayIndex++] = currentNode.Value;
|
||||
if (currentNode.Left != null)
|
||||
{
|
||||
@@ -164,7 +164,7 @@ namespace System.Collections.Generic
|
||||
/// <returns>Array containing the values contained in the tree.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
T[] array = new T[count];
|
||||
var array = new T[count];
|
||||
CopyTo(array, 0);
|
||||
return array;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ namespace System.Collections.Generic
|
||||
}
|
||||
private AVLNode<T> BalanceTree(AVLNode<T> current)
|
||||
{
|
||||
int b_factor = BalanceFactor(current);
|
||||
var b_factor = BalanceFactor(current);
|
||||
if (b_factor > 1)
|
||||
{
|
||||
if (BalanceFactor(current.Left) > 0)
|
||||
@@ -299,7 +299,9 @@ namespace System.Collections.Generic
|
||||
return current;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Find(target, current.Left);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -308,7 +310,9 @@ namespace System.Collections.Generic
|
||||
return current;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Find(target, current.Right);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -318,46 +322,46 @@ namespace System.Collections.Generic
|
||||
}
|
||||
private int GetHeight(AVLNode<T> current)
|
||||
{
|
||||
int height = 0;
|
||||
var height = 0;
|
||||
if (current != null)
|
||||
{
|
||||
int l = GetHeight(current.Left);
|
||||
int r = GetHeight(current.Right);
|
||||
int m = Max(l, r);
|
||||
var l = GetHeight(current.Left);
|
||||
var r = GetHeight(current.Right);
|
||||
var m = Max(l, r);
|
||||
height = m + 1;
|
||||
}
|
||||
return height;
|
||||
}
|
||||
private int BalanceFactor(AVLNode<T> current)
|
||||
{
|
||||
int l = GetHeight(current.Left);
|
||||
int r = GetHeight(current.Right);
|
||||
int b_factor = l - r;
|
||||
var l = GetHeight(current.Left);
|
||||
var r = GetHeight(current.Right);
|
||||
var b_factor = l - r;
|
||||
return b_factor;
|
||||
}
|
||||
private AVLNode<T> RotateRR(AVLNode<T> parent)
|
||||
{
|
||||
AVLNode<T> pivot = parent.Right;
|
||||
var pivot = parent.Right;
|
||||
parent.Right = pivot.Left;
|
||||
pivot.Left = parent;
|
||||
return pivot;
|
||||
}
|
||||
private AVLNode<T> RotateLL(AVLNode<T> parent)
|
||||
{
|
||||
AVLNode<T> pivot = parent.Left;
|
||||
var pivot = parent.Left;
|
||||
parent.Left = pivot.Right;
|
||||
pivot.Right = parent;
|
||||
return pivot;
|
||||
}
|
||||
private AVLNode<T> RotateLR(AVLNode<T> parent)
|
||||
{
|
||||
AVLNode<T> pivot = parent.Left;
|
||||
var pivot = parent.Left;
|
||||
parent.Left = RotateRR(pivot);
|
||||
return RotateLL(parent);
|
||||
}
|
||||
private AVLNode<T> RotateRL(AVLNode<T> parent)
|
||||
{
|
||||
AVLNode<T> pivot = parent.Right;
|
||||
var pivot = parent.Right;
|
||||
parent.Right = RotateLL(pivot);
|
||||
return RotateRR(parent);
|
||||
}
|
||||
@@ -367,12 +371,12 @@ namespace System.Collections.Generic
|
||||
}
|
||||
private IEnumerator<T> GetEnumerator(AVLNode<T> rootNode)
|
||||
{
|
||||
Queue<AVLNode<T>> queue = new Queue<AVLNode<T>>();
|
||||
var queue = new Queue<AVLNode<T>>();
|
||||
queue.Enqueue(rootNode);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
AVLNode<T> currentNode = queue.Dequeue();
|
||||
var currentNode = queue.Dequeue();
|
||||
yield return currentNode.Value;
|
||||
if (currentNode.Left != null)
|
||||
{
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
Capacity = 2 * Capacity;
|
||||
}
|
||||
int position = ++count;
|
||||
var position = ++count;
|
||||
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position /= 2)
|
||||
{
|
||||
items[position] = items[position / 2];
|
||||
@@ -105,7 +105,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
throw new IndexOutOfRangeException("Heap is empty!");
|
||||
}
|
||||
T min = items[1];
|
||||
var min = items[1];
|
||||
items[1] = items[count--];
|
||||
BubbleDown(1);
|
||||
return min;
|
||||
@@ -120,7 +120,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
throw new IndexOutOfRangeException("Heap is empty!");
|
||||
}
|
||||
T min = items[1];
|
||||
var min = items[1];
|
||||
return min;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -129,7 +129,7 @@ namespace System.Collections.Generic
|
||||
/// <returns>Array with values sorted as in heap</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
T[] newArray = new T[count];
|
||||
var newArray = new T[count];
|
||||
Array.Copy(items, 1, newArray, 0, count);
|
||||
return newArray;
|
||||
}
|
||||
@@ -168,7 +168,7 @@ namespace System.Collections.Generic
|
||||
/// <returns>Enumerator that iterates over the heap.</returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
yield return items[i + 1];
|
||||
}
|
||||
@@ -181,7 +181,7 @@ namespace System.Collections.Generic
|
||||
/// <param name="index">Index of element to bubble</param>
|
||||
private void BubbleDown(int index)
|
||||
{
|
||||
T temp = items[index];
|
||||
var temp = items[index];
|
||||
int childIndex;
|
||||
for (; 2 * index <= count; index = childIndex)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
/// <param name="value">Value to be added.</param>
|
||||
public void Add(T value)
|
||||
{
|
||||
FibonacciNode<T> node = new FibonacciNode<T>
|
||||
var node = new FibonacciNode<T>
|
||||
{
|
||||
Value = value,
|
||||
Marked = false,
|
||||
@@ -77,7 +77,7 @@
|
||||
/// <returns>Minimum value.</returns>
|
||||
public T Remove()
|
||||
{
|
||||
FibonacciNode<T> currentRoot = root;
|
||||
var currentRoot = root;
|
||||
if (currentRoot != null)
|
||||
{
|
||||
root = RemoveMinimum(root);
|
||||
@@ -96,7 +96,7 @@
|
||||
/// <param name="value">New value to be assigned to the node.</param>
|
||||
public void DecreaseKey(T oldValue, T value)
|
||||
{
|
||||
FibonacciNode<T> node = Find(root, oldValue);
|
||||
var node = Find(root, oldValue);
|
||||
root = DecreaseKey(root, node, value);
|
||||
}
|
||||
/// <summary>
|
||||
@@ -129,7 +129,7 @@
|
||||
{
|
||||
return null;
|
||||
}
|
||||
T[] array = new T[count];
|
||||
var array = new T[count];
|
||||
if (count == 1)
|
||||
{
|
||||
array[0] = root.Value;
|
||||
@@ -137,7 +137,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = 0;
|
||||
var index = 0;
|
||||
RecursiveFillArray(root, ref array, ref index);
|
||||
return array;
|
||||
}
|
||||
@@ -160,7 +160,7 @@
|
||||
/// <param name="index">Index of the next unintialized element in the array.</param>
|
||||
private void RecursiveFillArray(FibonacciNode<T> currentNode, ref T[] array, ref int index)
|
||||
{
|
||||
FibonacciNode<T> oldNode = currentNode;
|
||||
var oldNode = currentNode;
|
||||
do
|
||||
{
|
||||
array[index] = currentNode.Value;
|
||||
@@ -178,12 +178,12 @@
|
||||
/// <param name="currentNode">Current node in the iteration.</param>
|
||||
private IEnumerator<T> GetEnumerator(FibonacciNode<T> currentNode)
|
||||
{
|
||||
Queue<FibonacciNode<T>> queue = new Queue<FibonacciNode<T>>();
|
||||
var queue = new Queue<FibonacciNode<T>>();
|
||||
queue.Enqueue(currentNode);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
currentNode = queue.Dequeue();
|
||||
FibonacciNode<T> oldNode = currentNode;
|
||||
var oldNode = currentNode;
|
||||
do
|
||||
{
|
||||
yield return currentNode.Value;
|
||||
@@ -204,7 +204,7 @@
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
FibonacciNode<T> current = node;
|
||||
var current = node;
|
||||
do
|
||||
{
|
||||
Remove(current.Child);
|
||||
@@ -234,12 +234,12 @@
|
||||
}
|
||||
if (node1.Value.CompareTo(node2.Value) > 0)
|
||||
{
|
||||
FibonacciNode<T> temp = node1;
|
||||
var temp = node1;
|
||||
node1 = node2;
|
||||
node2 = temp;
|
||||
}
|
||||
FibonacciNode<T> node1Next = node1.Next;
|
||||
FibonacciNode<T> node2Prev = node2.Previous;
|
||||
var node1Next = node1.Next;
|
||||
var node2Prev = node2.Previous;
|
||||
node1.Next = node2;
|
||||
node2.Previous = node1;
|
||||
node1Next.Previous = node2Prev;
|
||||
@@ -268,7 +268,7 @@
|
||||
{
|
||||
return;
|
||||
}
|
||||
FibonacciNode<T> current = node;
|
||||
var current = node;
|
||||
do
|
||||
{
|
||||
current.Marked = false;
|
||||
@@ -299,12 +299,12 @@
|
||||
return node;
|
||||
}
|
||||
|
||||
FibonacciNode<T>[] trees = new FibonacciNode<T>[64];
|
||||
var trees = new FibonacciNode<T>[64];
|
||||
while (true)
|
||||
{
|
||||
if (trees[node.Degree] != null)
|
||||
{
|
||||
FibonacciNode<T> t = trees[node.Degree];
|
||||
var t = trees[node.Degree];
|
||||
if (t == node)
|
||||
{
|
||||
break;
|
||||
@@ -344,8 +344,8 @@
|
||||
}
|
||||
node = node.Next;
|
||||
}
|
||||
FibonacciNode<T> min = node;
|
||||
FibonacciNode<T> start = node;
|
||||
var min = node;
|
||||
var start = node;
|
||||
do
|
||||
{
|
||||
if (node.Value.CompareTo(min.Value) < 0)
|
||||
@@ -397,7 +397,7 @@
|
||||
if (node.Value.CompareTo(node.Parent.Value) < 0)
|
||||
{
|
||||
root = Cut(root, node);
|
||||
FibonacciNode<T> parent = node.Parent;
|
||||
var parent = node.Parent;
|
||||
node.Parent = null;
|
||||
while (parent != null && parent.Marked)
|
||||
{
|
||||
@@ -429,7 +429,7 @@
|
||||
/// <returns></returns>
|
||||
private FibonacciNode<T> Find(FibonacciNode<T> root, T value)
|
||||
{
|
||||
FibonacciNode<T> node = root;
|
||||
var node = root;
|
||||
if (node == null)
|
||||
{
|
||||
return null;
|
||||
@@ -440,7 +440,7 @@
|
||||
{
|
||||
return node;
|
||||
}
|
||||
FibonacciNode<T> ret = Find(node.Child, value);
|
||||
var ret = Find(node.Child, value);
|
||||
if (ret != null)
|
||||
{
|
||||
return ret;
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
random = new Random();
|
||||
head = new NodeSet<T>(default, maxLevel);
|
||||
end = head;
|
||||
for (int i = 0; i <= maxLevel; i++)
|
||||
for (var i = 0; i <= maxLevel; i++)
|
||||
{
|
||||
head.Next[i] = end;
|
||||
}
|
||||
@@ -64,8 +64,8 @@
|
||||
/// <param name="item">Item to be added.</param>
|
||||
public void Add(T item)
|
||||
{
|
||||
NodeSet<T> curNode = head;
|
||||
int newLevel = 0;
|
||||
var curNode = head;
|
||||
var newLevel = 0;
|
||||
while (random.Next(0, 2) > 0 && newLevel < maxLevel)
|
||||
{
|
||||
newLevel++;
|
||||
@@ -74,7 +74,7 @@
|
||||
{
|
||||
level = newLevel;
|
||||
}
|
||||
NodeSet<T> newNode = new NodeSet<T>(item, newLevel);
|
||||
var newNode = new NodeSet<T>(item, newLevel);
|
||||
for (var i = 0; i <= newLevel; i++)
|
||||
{
|
||||
if (i > curNode.Level)
|
||||
@@ -97,8 +97,8 @@
|
||||
/// <returns>True if removal was successful.</returns>
|
||||
public bool Remove(T item)
|
||||
{
|
||||
bool removed = false;
|
||||
NodeSet<T> curNode = head;
|
||||
var removed = false;
|
||||
var curNode = head;
|
||||
for (var i = 0; i <= maxLevel; i++)
|
||||
{
|
||||
if (i > curNode.Level)
|
||||
@@ -134,7 +134,7 @@
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
for (int i = 0; i < maxLevel; i++)
|
||||
for (var i = 0; i < maxLevel; i++)
|
||||
{
|
||||
head.Next[i] = end;
|
||||
}
|
||||
@@ -160,7 +160,7 @@
|
||||
/// <param name="arrayIndex">Index to start insertion in the array.</param>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
NodeSet<T> node = head.Next[0];
|
||||
var node = head.Next[0];
|
||||
while (node != end)
|
||||
{
|
||||
array[arrayIndex] = node.Key;
|
||||
@@ -174,9 +174,9 @@
|
||||
/// <returns>Array filled with elements from the collection.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
T[] array = new T[count];
|
||||
int index = 0;
|
||||
NodeSet<T> curNode = head.Next[0];
|
||||
var array = new T[count];
|
||||
var index = 0;
|
||||
var curNode = head.Next[0];
|
||||
while (curNode != end)
|
||||
{
|
||||
array[index] = curNode.Key;
|
||||
@@ -191,7 +191,7 @@
|
||||
/// <returns></returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
NodeSet<T> curNode = head.Next[0];
|
||||
var curNode = head.Next[0];
|
||||
while (curNode != end)
|
||||
{
|
||||
yield return curNode.Key;
|
||||
@@ -206,9 +206,9 @@
|
||||
}
|
||||
private NodeSet<T> Find(T key)
|
||||
{
|
||||
NodeSet<T> curNode = head;
|
||||
var curNode = head;
|
||||
|
||||
for (int i = level; i >= 0; i--)
|
||||
for (var i = level; i >= 0; i--)
|
||||
{
|
||||
while (curNode.Next[i] != end)
|
||||
{
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
{
|
||||
if (root != null)
|
||||
{
|
||||
T[] array = new T[count];
|
||||
int index = 0;
|
||||
var array = new T[count];
|
||||
var index = 0;
|
||||
ToArray(root, ref array, ref index);
|
||||
return array;
|
||||
}
|
||||
@@ -221,7 +221,7 @@
|
||||
{
|
||||
if (node.Key.CompareTo(key) < 0)
|
||||
{
|
||||
Node<T> found = Find(node.Left, key);
|
||||
var found = Find(node.Left, key);
|
||||
if (found == null)
|
||||
{
|
||||
found = Find(node.Right, key);
|
||||
@@ -230,7 +230,7 @@
|
||||
}
|
||||
else if (node.Key.CompareTo(key) > 0)
|
||||
{
|
||||
Node<T> found = Find(node.Right, key);
|
||||
var found = Find(node.Right, key);
|
||||
if (found == null)
|
||||
{
|
||||
found = Find(node.Left, key);
|
||||
@@ -255,7 +255,7 @@
|
||||
}
|
||||
private IEnumerator<T> GetEnumerator(Node<T> currentNode)
|
||||
{
|
||||
Queue<Node<T>> queue = new Queue<Node<T>>();
|
||||
var queue = new Queue<Node<T>>();
|
||||
queue.Enqueue(currentNode);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
|
||||
@@ -6,10 +6,13 @@ namespace System.Extensions
|
||||
{
|
||||
public static byte[] ReadAllBytes(this Stream stream)
|
||||
{
|
||||
if (stream is null) throw new ArgumentNullException(nameof(stream));
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
var buffer = new byte[256];
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
int read;
|
||||
while ((read = stream.Read(buffer, 0, 256)) > 0)
|
||||
|
||||
@@ -22,7 +22,10 @@ namespace System.Extensions
|
||||
|
||||
public static ICollection<T> ClearAnd<T>(this ICollection<T> collection)
|
||||
{
|
||||
if (collection is null) throw new ArgumentNullException(nameof(collection));
|
||||
if (collection is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
collection.Clear();
|
||||
return collection;
|
||||
@@ -30,10 +33,17 @@ namespace System.Extensions
|
||||
|
||||
public static ICollection<T> AddRange<T>(this ICollection<T> collection, IEnumerable<T> values)
|
||||
{
|
||||
if (collection is null) throw new ArgumentNullException(nameof(collection));
|
||||
if (values is null) throw new ArgumentNullException(nameof(values));
|
||||
if (collection is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
foreach(var item in values)
|
||||
if (values is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(values));
|
||||
}
|
||||
|
||||
foreach (var item in values)
|
||||
{
|
||||
collection.Add(item);
|
||||
}
|
||||
@@ -43,8 +53,15 @@ namespace System.Extensions
|
||||
|
||||
public static int IndexOfWhere<T>(this ICollection<T> collection, Func<T, bool> selector)
|
||||
{
|
||||
if (collection is null) throw new ArgumentNullException(nameof(collection));
|
||||
if (selector is null) throw new ArgumentNullException(nameof(selector));
|
||||
if (collection is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
if (selector is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(selector));
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
foreach (var item in collection)
|
||||
|
||||
@@ -7,7 +7,10 @@ namespace System.Extensions
|
||||
public static T Deserialize<T>(this string serialized)
|
||||
where T : class
|
||||
{
|
||||
if (serialized.IsNullOrWhiteSpace()) throw new ArgumentException("Provided serialized string cannot be null or whitespace", nameof(serialized));
|
||||
if (serialized.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new ArgumentException("Provided serialized string cannot be null or whitespace", nameof(serialized));
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<T>(serialized);
|
||||
}
|
||||
@@ -15,7 +18,10 @@ namespace System.Extensions
|
||||
public static string Serialize<T>(this T obj)
|
||||
where T : class
|
||||
{
|
||||
if (obj is null) throw new ArgumentNullException(nameof(obj));
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(obj);
|
||||
}
|
||||
@@ -37,7 +43,10 @@ namespace System.Extensions
|
||||
|
||||
public static T ThrowIfNull<T>([ValidatedNotNull] this T obj, string name) where T : class
|
||||
{
|
||||
if (obj is null) throw new ArgumentNullException(name);
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(name);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,15 @@
|
||||
}
|
||||
public Optional<T> Do(Action<T> onSome, Action onNone)
|
||||
{
|
||||
if (onSome is null) throw new ArgumentNullException(nameof(onSome));
|
||||
if (onNone is null) throw new ArgumentNullException(nameof(onNone));
|
||||
if (onSome is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSome));
|
||||
}
|
||||
|
||||
if (onNone is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onNone));
|
||||
}
|
||||
|
||||
if (this is Some)
|
||||
{
|
||||
@@ -67,8 +74,15 @@
|
||||
}
|
||||
public Optional<V> Switch<V>(Func<T, V> onSome, Func<V> onNone)
|
||||
{
|
||||
if (onSome is null) throw new ArgumentNullException($"{nameof(onSome)}");
|
||||
if (onNone is null) throw new ArgumentNullException($"{nameof(onNone)}");
|
||||
if (onSome is null)
|
||||
{
|
||||
throw new ArgumentNullException($"{nameof(onSome)}");
|
||||
}
|
||||
|
||||
if (onNone is null)
|
||||
{
|
||||
throw new ArgumentNullException($"{nameof(onNone)}");
|
||||
}
|
||||
|
||||
if (this is Some)
|
||||
{
|
||||
|
||||
@@ -43,9 +43,15 @@
|
||||
}
|
||||
public Result<TSuccess, TFailure> Do(Action onSuccess, Action onFailure)
|
||||
{
|
||||
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess)
|
||||
{
|
||||
@@ -71,9 +77,15 @@
|
||||
}
|
||||
public Result<TSuccess, TFailure> Do(Action<TSuccess> onSuccess, Action<TFailure> onFailure)
|
||||
{
|
||||
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
@@ -99,9 +111,15 @@
|
||||
}
|
||||
public T Switch<T>(Func<TSuccess, T> onSuccess, Func<TFailure, T> onFailure)
|
||||
{
|
||||
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
@@ -127,9 +145,15 @@
|
||||
}
|
||||
public Result<V, K> Switch<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
|
||||
{
|
||||
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
|
||||
@@ -7,8 +7,15 @@ namespace System.Extensions
|
||||
{
|
||||
public static void DoWhileReading(this Stream stream, Action<int, byte[]> action, int bufferLength = 256)
|
||||
{
|
||||
if (stream is null) throw new ArgumentNullException(nameof(stream));
|
||||
if (action is null) throw new ArgumentNullException(nameof(action));
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if (action is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
var buffer = new byte[bufferLength];
|
||||
var read = stream.Read(buffer, 0, bufferLength);
|
||||
@@ -21,7 +28,10 @@ namespace System.Extensions
|
||||
|
||||
public static byte[] ReadBytes(this Stream stream, int count)
|
||||
{
|
||||
if (stream is null) throw new ArgumentNullException(nameof(stream));
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
var buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
@@ -30,9 +40,15 @@ namespace System.Extensions
|
||||
|
||||
public static Stream Rewind(this Stream stream)
|
||||
{
|
||||
if (stream is null) throw new ArgumentNullException(nameof(stream));
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if (!stream.CanSeek) throw new InvalidOperationException("Stream doesn't support rewinding");
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
throw new InvalidOperationException("Stream doesn't support rewinding");
|
||||
}
|
||||
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return stream;
|
||||
@@ -41,17 +57,19 @@ namespace System.Extensions
|
||||
public static string ReadUntil(this StreamReader sr, string delim)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
bool found = false;
|
||||
var found = false;
|
||||
|
||||
while (!found && !sr.EndOfStream)
|
||||
{
|
||||
for (int i = 0; i < delim.Length; i++)
|
||||
for (var i = 0; i < delim.Length; i++)
|
||||
{
|
||||
char c = (char)sr.Read();
|
||||
var c = (char)sr.Read();
|
||||
sb.Append(c);
|
||||
|
||||
if (c != delim[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == delim.Length - 1)
|
||||
{
|
||||
|
||||
@@ -44,13 +44,17 @@ namespace System.Extensions
|
||||
public static async Task RunPeriodicAsync(this Action onTick, TimeSpan dueTime, TimeSpan interval, CancellationToken token)
|
||||
{
|
||||
if (dueTime > TimeSpan.Zero)
|
||||
{
|
||||
await Task.Delay(dueTime, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
onTick?.Invoke();
|
||||
if (interval > TimeSpan.Zero)
|
||||
{
|
||||
await Task.Delay(interval, token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +99,7 @@ namespace System.Extensions
|
||||
var oldContext = SynchronizationContext.Current;
|
||||
var synch = new ExclusiveSynchronizationContext();
|
||||
SynchronizationContext.SetSynchronizationContext(synch);
|
||||
T ret = default(T);
|
||||
var ret = default(T);
|
||||
synch.Post(async _ =>
|
||||
{
|
||||
try
|
||||
|
||||
@@ -46,7 +46,10 @@ namespace System.Extensions
|
||||
|
||||
public TResult Finally(Action act)
|
||||
{
|
||||
if (act is null) throw new ArgumentNullException(nameof(act));
|
||||
if (act is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(act));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
<Version>1.3.1</Version>
|
||||
<Version>1.3.2</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the System namespace</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace System.Threading
|
||||
threadpool = new List<WorkerThread>();
|
||||
tasks = new PriorityQueue<QueueEntry>();
|
||||
maxThreads = System.Environment.ProcessorCount;
|
||||
for (int i = 0; i < maxThreads; i++)
|
||||
for (var i = 0; i < maxThreads; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread();
|
||||
}
|
||||
@@ -194,7 +194,7 @@ namespace System.Threading
|
||||
threadpool = new List<WorkerThread>();
|
||||
tasks = new PriorityQueue<QueueEntry>();
|
||||
this.maxThreads = Math.Max(maxThreads, 1);
|
||||
for (int i = 0; i < maxThreads; i++)
|
||||
for (var i = 0; i < maxThreads; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread();
|
||||
}
|
||||
@@ -216,23 +216,23 @@ namespace System.Threading
|
||||
{
|
||||
threadpool = new List<WorkerThread>();
|
||||
tasks = new PriorityQueue<QueueEntry>();
|
||||
for (int i = 0; i < lowest; i++)
|
||||
for (var i = 0; i < lowest; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.Lowest);
|
||||
}
|
||||
for (int i = 0; i < belowNormal; i++)
|
||||
for (var i = 0; i < belowNormal; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.BelowNormal);
|
||||
}
|
||||
for (int i = 0; i < normal; i++)
|
||||
for (var i = 0; i < normal; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.Normal);
|
||||
}
|
||||
for (int i = 0; i < aboveNormal; i++)
|
||||
for (var i = 0; i < aboveNormal; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.AboveNormal);
|
||||
}
|
||||
for (int i = 0; i < highest; i++)
|
||||
for (var i = 0; i < highest; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.Highest);
|
||||
}
|
||||
@@ -247,7 +247,11 @@ namespace System.Threading
|
||||
/// <param name="taskPriority">Priority of task. Affects its position into the queue.</param>
|
||||
public void QueueUserWorkItem(WaitCallback waitCallback, object callbackState, TaskPriority taskPriority)
|
||||
{
|
||||
while (!Monitor.TryEnter(tasksLock)) ;
|
||||
while (!Monitor.TryEnter(tasksLock))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
tasks.Enqueue(new QueueEntry(taskPriority, waitCallback, callbackState));
|
||||
Monitor.Exit(tasksLock);
|
||||
}
|
||||
@@ -307,7 +311,11 @@ namespace System.Threading
|
||||
|
||||
thisWorkerThread.Working = true;
|
||||
QueueEntry task = null;
|
||||
while (!Monitor.TryEnter(tasksLock)) ;
|
||||
while (!Monitor.TryEnter(tasksLock))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (tasks.Count > 0)
|
||||
{
|
||||
task = tasks.Dequeue();
|
||||
@@ -316,7 +324,7 @@ namespace System.Threading
|
||||
if (task != null)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + " - Running task!");
|
||||
WaitCallback waitCallback = task.WaitCallback;
|
||||
var waitCallback = task.WaitCallback;
|
||||
waitCallback.Invoke(task.Object);
|
||||
}
|
||||
thisWorkerThread.Working = false;
|
||||
@@ -328,7 +336,7 @@ namespace System.Threading
|
||||
/// </summary>
|
||||
private void ObserverLoop()
|
||||
{
|
||||
Statistics statistics = new Statistics();
|
||||
var statistics = new Statistics();
|
||||
while (true)
|
||||
{
|
||||
//Observer operates on a 100ms loop. Due to the low priority of the thread itself, this loop will almost always take
|
||||
@@ -346,7 +354,7 @@ namespace System.Threading
|
||||
//This part of code updates the statistics of the threadpool.
|
||||
if (statistics.Initialized)
|
||||
{
|
||||
double loopDuration = (DateTime.Now - statistics.LastUpdate).TotalMilliseconds;
|
||||
var loopDuration = (DateTime.Now - statistics.LastUpdate).TotalMilliseconds;
|
||||
if (statistics.LoopFrequency == 0)
|
||||
{
|
||||
statistics.LoopFrequency = loopDuration;
|
||||
@@ -387,7 +395,7 @@ namespace System.Threading
|
||||
if (tasks.Count > 0)
|
||||
{
|
||||
//If there are tasks pending, find a thread with priority under Normal and upgrade its priority.
|
||||
Thread t = FindThreadWithLowPriority();
|
||||
var t = FindThreadWithLowPriority();
|
||||
if (t != null)
|
||||
{
|
||||
UpgradeThreadPriority(t);
|
||||
@@ -396,7 +404,7 @@ namespace System.Threading
|
||||
else
|
||||
{
|
||||
//If there are no tasks pending, find a thread with priority above Lowest and downgrade its priority.
|
||||
Thread t = FindThreadWithAcceptablePriority();
|
||||
var t = FindThreadWithAcceptablePriority();
|
||||
if (t != null)
|
||||
{
|
||||
DowngradeThreadPriority(t);
|
||||
@@ -423,7 +431,7 @@ namespace System.Threading
|
||||
//If thread is currently working, notify it to close.
|
||||
//Else, abort the thread.
|
||||
//Reset counter to 0.
|
||||
WorkerThread worker = threadpool[threadpool.Count - 1];
|
||||
var worker = threadpool[threadpool.Count - 1];
|
||||
if (worker.Working)
|
||||
{
|
||||
worker.Running = false;
|
||||
@@ -444,7 +452,7 @@ namespace System.Threading
|
||||
/// <returns>Thread with low priority.</returns>
|
||||
private Thread FindThreadWithLowPriority()
|
||||
{
|
||||
foreach (WorkerThread t in threadpool)
|
||||
foreach (var t in threadpool)
|
||||
{
|
||||
if (t.Thread.Priority == ThreadPriority.Lowest || t.Thread.Priority == ThreadPriority.BelowNormal)
|
||||
{
|
||||
@@ -459,7 +467,7 @@ namespace System.Threading
|
||||
/// <returns>Thread with BelowNormal or Normal priority.</returns>
|
||||
private Thread FindThreadWithAcceptablePriority()
|
||||
{
|
||||
foreach (WorkerThread t in threadpool)
|
||||
foreach (var t in threadpool)
|
||||
{
|
||||
if (t.Thread.Priority == ThreadPriority.Normal || t.Thread.Priority == ThreadPriority.BelowNormal)
|
||||
{
|
||||
@@ -538,7 +546,7 @@ namespace System.Threading
|
||||
this.observerCancellationTokenSource.Cancel();
|
||||
this.observer.Join();
|
||||
}
|
||||
foreach (WorkerThread worker in threadpool)
|
||||
foreach (var worker in threadpool)
|
||||
{
|
||||
worker.CancellationTokenSource.Cancel();
|
||||
worker.Thread.Join();
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace System.Collections.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i * 20 - (50 + i));
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ContainsTest()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void RemoveTest()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ClearTest()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
}
|
||||
@@ -82,24 +82,24 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void CopyToTest()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
}
|
||||
|
||||
int[] array = new int[100];
|
||||
var array = new int[100];
|
||||
avlTree.CopyTo(array, 0);
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void GetEnumeratorTest()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
}
|
||||
int count = 0;
|
||||
foreach(int value in avlTree)
|
||||
var count = 0;
|
||||
foreach(var value in avlTree)
|
||||
{
|
||||
count++;
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
@@ -114,34 +114,34 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ToArrayTest()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
}
|
||||
|
||||
int[] array = avlTree.ToArray();
|
||||
var array = avlTree.ToArray();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void Serialize()
|
||||
{
|
||||
AVLTree<int> avlTree2 = new AVLTree<int>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
var avlTree2 = new AVLTree<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
}
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
string s = string.Empty;
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, avlTree);
|
||||
stream.Position = 0;
|
||||
avlTree2 = (AVLTree<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
IEnumerator<int> avlTreeEnum = avlTree.GetEnumerator();
|
||||
IEnumerator<int> avlTree2Enum = avlTree2.GetEnumerator();
|
||||
var avlTreeEnum = avlTree.GetEnumerator();
|
||||
var avlTree2Enum = avlTree2.GetEnumerator();
|
||||
|
||||
for(int i = 0; i < 100; i++)
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
if(avlTreeEnum.Current != avlTree2Enum.Current)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace System.Collections.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
binaryHeap.Add(i * 20 - (50 + i));
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace System.Collections.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
int tries = binaryHeap.Count;
|
||||
var tries = binaryHeap.Count;
|
||||
while (binaryHeap.Count > 0)
|
||||
{
|
||||
if (tries == 0)
|
||||
@@ -72,7 +72,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void MinMaxTest()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ClearTest()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
}
|
||||
@@ -99,12 +99,12 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ClearTest2()
|
||||
{
|
||||
for (int i = 100; i < 200; i++)
|
||||
for (var i = 100; i < 200; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
}
|
||||
binaryHeap.Clear(false);
|
||||
int[] array = binaryHeap.ToArray();
|
||||
var array = binaryHeap.ToArray();
|
||||
if (binaryHeap.Count > 0 || binaryHeap.Capacity == 10)
|
||||
{
|
||||
Assert.Fail();
|
||||
@@ -133,11 +133,11 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ToArrayTest()
|
||||
{
|
||||
for(int i = 0; i < 1000; i++)
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
}
|
||||
int[] array = binaryHeap.ToArray();
|
||||
var array = binaryHeap.ToArray();
|
||||
if(array.Length != binaryHeap.Count)
|
||||
{
|
||||
Assert.Fail();
|
||||
@@ -151,12 +151,12 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void GetEnumeratorTest()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
}
|
||||
int count = 0;
|
||||
foreach(int value in binaryHeap)
|
||||
var count = 0;
|
||||
foreach(var value in binaryHeap)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
count++;
|
||||
@@ -173,22 +173,22 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void Serialize()
|
||||
{
|
||||
BinaryHeap<int> binaryHeap2 = new BinaryHeap<int>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
var binaryHeap2 = new BinaryHeap<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
}
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
string s = string.Empty;
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream()) {
|
||||
serializer.Serialize(stream, binaryHeap);
|
||||
stream.Position = 0;
|
||||
binaryHeap2 = (BinaryHeap<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
IEnumerator<int> binaryHeapEnum = binaryHeap.GetEnumerator();
|
||||
IEnumerator<int> binaryHeapEnum2 = binaryHeap2.GetEnumerator();
|
||||
var binaryHeapEnum = binaryHeap.GetEnumerator();
|
||||
var binaryHeapEnum2 = binaryHeap2.GetEnumerator();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
if (binaryHeapEnum.Current != binaryHeapEnum2.Current)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void InsertTest()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
}
|
||||
@@ -31,21 +31,21 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void MergeTest()
|
||||
{
|
||||
FibonacciHeap<int> fibonacciHeap1 = new FibonacciHeap<int>();
|
||||
FibonacciHeap<int> fibonacciHeap2 = new FibonacciHeap<int>();
|
||||
var fibonacciHeap1 = new FibonacciHeap<int>();
|
||||
var fibonacciHeap2 = new FibonacciHeap<int>();
|
||||
|
||||
for(int i = 0; i < 100; i++)
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
fibonacciHeap1.Add(i);
|
||||
}
|
||||
|
||||
for(int i = 100; i < 300; i++)
|
||||
for(var i = 100; i < 300; i++)
|
||||
{
|
||||
fibonacciHeap2.Add(i);
|
||||
}
|
||||
|
||||
fibonacciHeap1.Merge(fibonacciHeap2);
|
||||
for(int i = 1; i < 300; i++)
|
||||
for(var i = 1; i < 300; i++)
|
||||
{
|
||||
if (!fibonacciHeap1.Contains(i))
|
||||
{
|
||||
@@ -70,11 +70,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
}
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
if (fibonacciHeap.Remove() != i)
|
||||
{
|
||||
@@ -104,7 +104,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ContainsTest()
|
||||
{
|
||||
for(int i = 0; i < 10000; i++)
|
||||
for(var i = 0; i < 10000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
}
|
||||
@@ -117,7 +117,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ClearTest()
|
||||
{
|
||||
for(int i = 0; i < 10000; i++)
|
||||
for(var i = 0; i < 10000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
}
|
||||
@@ -132,14 +132,14 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ToArrayTest()
|
||||
{
|
||||
for(int i = 999; i >= 0; i--)
|
||||
for(var i = 999; i >= 0; i--)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
}
|
||||
fibonacciHeap.Remove();
|
||||
int[] arr = fibonacciHeap.ToArray();
|
||||
var arr = fibonacciHeap.ToArray();
|
||||
|
||||
for(int i = 1; i < 512; i++)
|
||||
for(var i = 1; i < 512; i++)
|
||||
{
|
||||
if(arr[i - 1] != i)
|
||||
{
|
||||
@@ -151,14 +151,14 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void GetEnumeratorTest()
|
||||
{
|
||||
for (int i = 999; i >= 0; i--)
|
||||
for (var i = 999; i >= 0; i--)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
var count = 0;
|
||||
|
||||
foreach(int value in fibonacciHeap)
|
||||
foreach(var value in fibonacciHeap)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
count++;
|
||||
@@ -175,23 +175,23 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void Serialize()
|
||||
{
|
||||
FibonacciHeap<int> fibonacciHeap2 = new FibonacciHeap<int>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
var fibonacciHeap2 = new FibonacciHeap<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
}
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
string s = string.Empty;
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, fibonacciHeap);
|
||||
stream.Position = 0;
|
||||
fibonacciHeap2 = (FibonacciHeap<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
IEnumerator<int> enum1 = fibonacciHeap.GetEnumerator();
|
||||
IEnumerator<int> enum2 = fibonacciHeap2.GetEnumerator();
|
||||
var enum1 = fibonacciHeap.GetEnumerator();
|
||||
var enum2 = fibonacciHeap2.GetEnumerator();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
if (enum1.Current != enum2.Current)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void EnqueueTest()
|
||||
{
|
||||
for(int i = 0; i < 100; i++)
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
priorityQueue.Enqueue(i);
|
||||
}
|
||||
@@ -42,11 +42,11 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void DequeueTest()
|
||||
{
|
||||
for(int i = 0; i < 100; i++)
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
priorityQueue.Enqueue(i);
|
||||
}
|
||||
for(int i = 0; i < 100; i++)
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
if(i != priorityQueue.Dequeue())
|
||||
{
|
||||
@@ -81,23 +81,23 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void Serialize()
|
||||
{
|
||||
PriorityQueue<int> priorityQueue2 = new PriorityQueue<int>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
var priorityQueue2 = new PriorityQueue<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
priorityQueue.Enqueue(i);
|
||||
}
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
string s = string.Empty;
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, priorityQueue);
|
||||
stream.Position = 0;
|
||||
priorityQueue2 = (PriorityQueue<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
IEnumerator<int> enum1 = priorityQueue.GetEnumerator();
|
||||
IEnumerator<int> enum2 = priorityQueue2.GetEnumerator();
|
||||
var enum1 = priorityQueue.GetEnumerator();
|
||||
var enum2 = priorityQueue2.GetEnumerator();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
if (enum1.Current != enum2.Current)
|
||||
{
|
||||
|
||||
@@ -12,19 +12,19 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void SkipListTest()
|
||||
{
|
||||
SkipList<int> skipList = new SkipList<int>();
|
||||
var skipList = new SkipList<int>();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void SkipListTest2()
|
||||
{
|
||||
SkipList<int> skipList = new SkipList<int>(30);
|
||||
var skipList = new SkipList<int>(30);
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void AddTest()
|
||||
{
|
||||
for(int i = 0; i < 200; i++)
|
||||
for(var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ClearTest()
|
||||
{
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
@@ -47,7 +47,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ContainsTest()
|
||||
{
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
@@ -61,13 +61,13 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void CopyToTest()
|
||||
{
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
int[] array = new int[skipList.Count];
|
||||
var array = new int[skipList.Count];
|
||||
skipList.CopyTo(array, 0);
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
if(array[i] != i)
|
||||
{
|
||||
@@ -79,13 +79,13 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ToArrayTest()
|
||||
{
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
int[] array = skipList.ToArray();
|
||||
var array = skipList.ToArray();
|
||||
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
if(array[i] != i)
|
||||
{
|
||||
@@ -97,12 +97,12 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void GetEnumeratorTest()
|
||||
{
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
|
||||
foreach(int i in skipList)
|
||||
foreach(var i in skipList)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(i);
|
||||
}
|
||||
@@ -111,7 +111,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void RemoveTest()
|
||||
{
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
@@ -126,23 +126,23 @@ namespace System.Collections.Tests
|
||||
[Ignore("Binary serialization is obsolete and should not be used anymore")]
|
||||
public void Serialize()
|
||||
{
|
||||
SkipList<int> skipList2 = new SkipList<int>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
var skipList2 = new SkipList<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
}
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
string s = string.Empty;
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, skipList);
|
||||
stream.Position = 0;
|
||||
skipList2 = (SkipList<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
IEnumerator<int> enum1 = skipList.GetEnumerator();
|
||||
IEnumerator<int> enum2 = skipList2.GetEnumerator();
|
||||
var enum1 = skipList.GetEnumerator();
|
||||
var enum2 = skipList2.GetEnumerator();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
if (enum1.Current != enum2.Current)
|
||||
{
|
||||
|
||||
@@ -18,8 +18,8 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void InsertTest()
|
||||
{
|
||||
Random random = new Random();
|
||||
for(int i = 0; i < 1000; i++)
|
||||
var random = new Random();
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
treap.Add(random.Next(0, 5000));
|
||||
}
|
||||
@@ -41,8 +41,8 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ClearTest()
|
||||
{
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 100; i++)
|
||||
var random = new Random();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
treap.Add(random.Next(0, 5000));
|
||||
}
|
||||
@@ -71,12 +71,12 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ToArrayTest()
|
||||
{
|
||||
for(int i = 0; i < 1000; i++)
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
treap.Add(i);
|
||||
}
|
||||
int[] arr = treap.ToArray();
|
||||
for(int i = 0; i < 1000; i++)
|
||||
var arr = treap.ToArray();
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
if(arr[i] != i)
|
||||
{
|
||||
@@ -88,13 +88,13 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void GetEnumeratorTest()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
treap.Add(i);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
foreach(int value in treap)
|
||||
var count = 0;
|
||||
foreach(var value in treap)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
count++;
|
||||
@@ -112,23 +112,23 @@ namespace System.Collections.Tests
|
||||
[Ignore("Binary serialization is obsolete and should not be used anymore")]
|
||||
public void Serialize()
|
||||
{
|
||||
Treap<int> treap2 = new Treap<int>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
var treap2 = new Treap<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
treap.Add(i);
|
||||
}
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
string s = string.Empty;
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, treap);
|
||||
stream.Position = 0;
|
||||
treap2 = (Treap<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
IEnumerator<int> enum1 = treap.GetEnumerator();
|
||||
IEnumerator<int> enum2 = treap2.GetEnumerator();
|
||||
var enum1 = treap.GetEnumerator();
|
||||
var enum2 = treap2.GetEnumerator();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
if (enum1.Current != enum2.Current)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace System.Extensions.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class ObjectExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ThrowIfNull_NetCore_ThrowsWithCorrectName()
|
||||
{
|
||||
object obj = null;
|
||||
try
|
||||
{
|
||||
System.Core.Extensions.ObjectExtensions.ThrowIfNull(obj);
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
ex.ParamName.Should().Be("obj");
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail("Null object should throw");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ThrowIfNull_NetStandard_ThrowsWithCorrectName()
|
||||
{
|
||||
object obj = null;
|
||||
try
|
||||
{
|
||||
ObjectExtensions.ThrowIfNull(obj, nameof(obj));
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
ex.ParamName.Should().Be("obj");
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail("Null object should throw");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Http;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
@@ -9,7 +7,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensionsTests.Utils;
|
||||
|
||||
namespace SystemExtensionsTests.Http
|
||||
namespace System.Http.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpClientTests
|
||||
@@ -32,7 +30,7 @@ namespace SystemExtensionsTests.Http
|
||||
[TestMethod]
|
||||
public async Task HttpClientEmitsCorrectMessages()
|
||||
{
|
||||
int messagesEmitted = 0;
|
||||
var messagesEmitted = 0;
|
||||
this.httpClient.EventEmitted += (sender, message) =>
|
||||
{
|
||||
messagesEmitted++;
|
||||
@@ -309,7 +307,7 @@ namespace SystemExtensionsTests.Http
|
||||
this.handler.ResponseResolverAsync = async (request) =>
|
||||
{
|
||||
request.RequestUri.Should().Be(expectedUri);
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace System.Structures.BitStructures.Tests
|
||||
[DataRow(int.MaxValue, int.MinValue)]
|
||||
public void TestLowHigh(int low, int high)
|
||||
{
|
||||
Int64BitStruct int64 = new Int64BitStruct(low, high);
|
||||
var int64 = new Int64BitStruct(low, high);
|
||||
Int32BitStruct lowStruct = low;
|
||||
Int32BitStruct highStruct = high;
|
||||
Assert.IsTrue(int64.Low == lowStruct);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
@@ -18,6 +18,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SystemExtensions.NetCore\SystemExtensions.NetCore.csproj" />
|
||||
<ProjectReference Include="..\SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace System.Threading.Tests
|
||||
Thread.Sleep(100);
|
||||
try
|
||||
{
|
||||
int x = threadPool.NumberOfThreads;
|
||||
var x = threadPool.NumberOfThreads;
|
||||
Assert.Fail();
|
||||
}
|
||||
catch(Exception e)
|
||||
@@ -63,17 +63,17 @@ namespace System.Threading.Tests
|
||||
{
|
||||
threadPool.Dispose();
|
||||
threadPool = new PriorityThreadPool();
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
threadPool.QueueUserWorkItem(o =>
|
||||
{
|
||||
for (int x = 0; x < 100; x++)
|
||||
for (var x = 0; x < 100; x++)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.ManagedThreadId + " - " + x);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("=====================================");
|
||||
System.Diagnostics.Debug.WriteLine("Current threads in threadpool: " + threadPool.NumberOfThreads);
|
||||
@@ -98,11 +98,11 @@ namespace System.Threading.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
threadPool.QueueUserWorkItem(o =>
|
||||
{
|
||||
for (int x = 0; x < 100; x++)
|
||||
for (var x = 0; x < 100; x++)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.ManagedThreadId + " - " + x);
|
||||
}
|
||||
@@ -126,11 +126,11 @@ namespace System.Threading.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
threadPool.QueueUserWorkItem(o =>
|
||||
{
|
||||
for (int x = 0; x < 100; x++)
|
||||
for (var x = 0; x < 100; x++)
|
||||
{
|
||||
switch (Thread.CurrentThread.Priority)
|
||||
{
|
||||
@@ -153,7 +153,7 @@ namespace System.Threading.Tests
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
for (int i = 0; i < 50; i++)
|
||||
for (var i = 0; i < 50; i++)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("=====================================");
|
||||
System.Diagnostics.Debug.WriteLine("Current threads in threadpool: " + threadPool.NumberOfThreads);
|
||||
@@ -168,9 +168,9 @@ namespace System.Threading.Tests
|
||||
{
|
||||
threadPool.Dispose();
|
||||
threadPool = new PriorityThreadPool();
|
||||
for (int i = 0; i < 1000; i++)
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
TaskPriority taskPriority = TaskPriority.Lowest;
|
||||
var taskPriority = TaskPriority.Lowest;
|
||||
if(i % 10 == 0)
|
||||
{
|
||||
taskPriority = TaskPriority.Highest;
|
||||
|
||||
+21
-4
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31005.135
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31815.197
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard", "SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj", "{4CE9E55C-6016-4631-B8D4-4D763DD05F23}"
|
||||
EndProject
|
||||
@@ -14,9 +14,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandar
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.DependencyInjection.Tests", "SystemExtensions.DependencyInjection.Tests\SystemExtensions.NetStandard.DependencyInjection.Tests.csproj", "{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions.NetStandard.Security", "SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj", "{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.Security", "SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj", "{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions.NetStandard.Security.Tests", "SystemExtensions.NetStandard.Security.Tests\SystemExtensions.NetStandard.Security.Tests.csproj", "{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.Security.Tests", "SystemExtensions.NetStandard.Security.Tests\SystemExtensions.NetStandard.Security.Tests.csproj", "{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions.NetCore", "SystemExtensions.NetCore\SystemExtensions.NetCore.csproj", "{9E6EBBF0-671B-4941-A72B-2CA60C882038}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{BBA334F6-779A-4A45-8BF3-EA321D0D12CF}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{52962B0C-BB5F-4211-A70C-801D0A73CACC}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\cd.yaml = .github\workflows\cd.yaml
|
||||
.github\workflows\ci.yaml = .github\workflows\ci.yaml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -48,10 +58,17 @@ Global
|
||||
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9E6EBBF0-671B-4941-A72B-2CA60C882038}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E6EBBF0-671B-4941-A72B-2CA60C882038}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9E6EBBF0-671B-4941-A72B-2CA60C882038}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9E6EBBF0-671B-4941-A72B-2CA60C882038}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{52962B0C-BB5F-4211-A70C-801D0A73CACC} = {BBA334F6-779A-4A45-8BF3-EA321D0D12CF}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BFA90E90-BD97-40AD-B19E-C723E504369A}
|
||||
EndGlobalSection
|
||||
|
||||
Reference in New Issue
Block a user