Compare commits

...

48 Commits

Author SHA1 Message Date
Alexandru Macocian c0b5734b71 Add extensions to simplify CVLoggerFactory usage 2021-11-01 16:18:10 +01:00
Alexandru Macocian 2944d9887e Update dependencies 2021-10-02 07:45:42 +02:00
amacocian 57925151fa Update dependencies (#10)
Fix code style
2021-09-16 13:56:05 +02:00
amacocian d20e5bd308 Fix CV extension (#9) 2021-08-18 16:34:54 +02:00
amacocian c9d1ba8773 Merge pull request #8 from AlexMacocian/alexmacocian/extend-cryptorngprovider
Extend CryptoRngProvider api
2021-07-15 16:33:28 +03:00
Alexandru Macocian ce3cac9fa2 Extend CryptoRngProvider api 2021-07-15 16:32:40 +03:00
amacocian a2d23ed716 Merge pull request #7 from AlexMacocian/alexmacocian/rngprovider-securestring
Implementation of SecureString and CryptoRngProvider
2021-07-15 16:19:32 +03:00
Alexandru Macocian 7660893087 Remove UTs expecting exception 2021-07-15 16:15:17 +03:00
Alexandru Macocian 68ec8f983d Implementation of SecureString and CryptoRngProvider 2021-07-15 16:11:05 +03:00
amacocian 1711dd2ec2 Merge pull request #6 from AlexMacocian/alexmacocian/serialization-extensions
Serialize and Deserialize extensions
2021-07-15 12:46:48 +03:00
Alexandru Macocian 3b67e45e64 Bump version 2021-07-15 12:41:47 +03:00
Alexandru Macocian 22fa8eccf7 Serialize and Deserialize extensions 2021-07-15 12:41:18 +03:00
amacocian 9609b2912c Merge pull request #5 from AlexMacocian/alexmacocian/security-package
SystemExtensions Security
2021-07-14 12:22:53 +03:00
Alexandru Macocian a2e99cb263 SystemExtensions Security 2021-07-14 12:17:31 +03:00
amacocian f9088a5aef Merge pull request #4 from AlexMacocian/alexmacocian/move-logger-resolver
Move logger resolver to System.Logging
2021-07-10 13:06:35 +03:00
Alexandru Macocian d67ee95916 Fix UTs 2021-07-10 13:02:54 +03:00
Alexandru Macocian 8bfb8f1757 Move logger resolver to System.Logging
Nit fixes
2021-07-10 13:01:47 +03:00
amacocian a6572a1d15 Merge pull request #3 from AlexMacocian/alexmacocian/move-di-config-namespace
Move configuration namespace to system
2021-07-10 11:29:20 +03:00
Alexandru Macocian 646b6dc253 Move configuration namespace to system 2021-07-10 11:24:37 +03:00
amacocian 0b2a76143b Merge pull request #2 from AlexMacocian/alexmacocian/di-extensions
Dependency Injection extensions
2021-07-10 11:15:48 +03:00
Alexandru Macocian 019d7e240d Stop CD pipeline from running on PR 2021-07-10 11:04:31 +03:00
Alexandru Macocian 7a764a5929 Dependency Injection extensions 2021-07-10 10:59:27 +03:00
amacocian 5aaa0d318a Merge pull request #1 from AlexMacocian/alexmacocian/add-pipelines
Added CI&CD pipelines
2021-06-02 13:04:46 +02:00
Alexandru Macocian 5767ccfd70 Fix misnaming in CI pipeline
Disable CD pipeline for PRs
2021-06-02 13:02:01 +02:00
Alexandru Macocian 16a9208e07 Added CI&CD pipelines
Changed test project to .net5
Changed ThreadPool to use CancellationTokens
2021-06-02 12:58:04 +02:00
Alexandru Macocian 3038661f6d Mockable http client implementation. 2021-05-13 13:55:17 +02:00
Alexandru Macocian 035e58248e Updated to 1.1.4 2021-04-23 10:52:13 +02:00
Alexandru Macocian 0d418ac9bf Merge branch 'master' of https://github.com/AlexMacocian/SystemExtensions 2021-04-23 10:49:50 +02:00
Alexandru Macocian 0288b385a0 String IsNullOrWhiteSpace and IsNullOrEmpty extensions. 2021-04-23 10:49:41 +02:00
Alexandru Macocian 5d442580c3 Add linq extension Do 2021-04-03 14:44:17 +02:00
Alexandru Macocian ee341af2c3 Read until extension. 2021-04-01 14:43:18 +02:00
Alexandru Macocian 8d1355ecbc Include repository 2021-04-01 12:49:44 +02:00
Alexandru Macocian c04b6ba906 Include author name 2021-04-01 12:49:04 +02:00
Alexandru Macocian 9a7125fbb0 Added various extensions.
Added coding style helpers.
Unit tests.
2021-04-01 12:38:26 +02:00
Alexandru Macocian 66b766326b Use license file from repo 2021-03-26 12:00:53 +01:00
Alexandru Macocian c8a98a0494 Merge 2021-03-26 11:59:12 +01:00
Alexandru Macocian f39e8cf89e Port to netstandard.
Nit fixes.
Fixed e2e tests.
Added MIT license.
2021-03-26 11:58:07 +01:00
Alexandru Macocian 0b5e93f9ea Changed package id 2020-07-27 11:21:22 +02:00
Alexandru Macocian 8fd22b3644 Restructured project to new project style
Targeted netstandard 2.0
Built nuget package
2020-07-27 11:18:56 +02:00
amacocian f6069bd3aa Bit field structures. 2019-12-09 10:44:16 +01:00
amacocian 89159e6cba Merge branch 'master' of https://github.com/AlexMacocian/SystemExtensions 2019-09-16 08:41:45 +03:00
amacocian a608b1ac95 changed proj details 2019-09-16 08:41:33 +03:00
amacocian 2ebd821bbd Cleaned code and upgraded framework to 4.7.2. 2019-07-19 11:10:34 +03:00
amacocian f0a5d509ea Implemented another way to get current process filename 2019-07-15 10:47:09 +03:00
amacocian 9003157a0f Changed elevateprocess way of getting the filename 2019-07-15 10:42:45 +03:00
amacocian 47c1e67f38 Implemented basic application functionality and security. 2019-07-15 10:36:50 +03:00
amacocian 5cb4b3a512 Removed a mistake in code 2019-07-11 09:49:00 +03:00
amacocian e8c9e682ed Marked class as sealed 2019-07-11 09:46:22 +03:00
98 changed files with 5362 additions and 863 deletions
+70
View File
@@ -0,0 +1,70 @@
name: SystemExtensions CD Pipeline
on:
push:
branches:
- master
jobs:
build:
environment: Default
strategy:
matrix:
targetplatform: [x64]
runs-on: windows-latest
env:
Configuration: Release
Solution_Path: SystemExtensions.sln
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
Actions_Allow_Unsecure_Commands: true
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Install .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.202'
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.1
- name: Restore project
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
env:
RuntimeIdentifier: win-${{ matrix.targetplatform }}
- name: Build SystemExtensions.NetStandard project
run: dotnet build SystemExtensions.NetStandard -c $env:Configuration
- name: Build SystemExtensions.NetStandard.DependencyInjection project
run: dotnet build SystemExtensions.NetStandard.DependencyInjection -c $env:Configuration
- name: Build SystemExtensions.NetStandard.Security project
run: dotnet build SystemExtensions.NetStandard.Security -c $env:Configuration
- name: Push SystemExtensions.NetStandard nuget package
uses: brandedoutcast/publish-nuget@v2.5.5
with:
PROJECT_FILE_PATH: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
- name: Push SystemExtensions.NetStandard.DependencyInjection nuget package
uses: brandedoutcast/publish-nuget@v2.5.5
with:
PROJECT_FILE_PATH: SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
- name: Push SystemExtensions.NetStandard.Security nuget package
uses: brandedoutcast/publish-nuget@v2.5.5
with:
PROJECT_FILE_PATH: SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
+56
View File
@@ -0,0 +1,56 @@
name: SystemExtensions CI Pipeline
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
strategy:
matrix:
targetplatform: [x64]
runs-on: windows-latest
env:
Solution_Path: SystemExtensions.sln
Test_Project_Path: SystemExtensions.Tests\SystemExtensions.NetStandard.Tests.csproj
DI_Test_Project_Path: SystemExtensions.DependencyInjection.Tests\SystemExtensions.NetStandard.DependencyInjection.Tests.csproj
Sec_Test_Project_Path: SystemExtensions.NetStandard.Security.Tests\SystemExtensions.NetStandard.Security.Tests.csproj
Source_Project_Path: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
Actions_Allow_Unsecure_Commands: true
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Install .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.202'
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.1
- name: Execute Unit Tests
run: dotnet test $env:Test_Project_Path
- name: Execute DI Unit Tests
run: dotnet test $env:DI_Test_Project_Path
- name: Execute Security Unit Tests
run: dotnet test $env:Sec_Test_Project_Path
- name: Restore Project
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
env:
Configuration: Debug
RuntimeIdentifier: win-${{ matrix.targetplatform }}
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Macocian Alexandru Victor
Copyright (c) 2021 Macocian Alexandru Victor
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,26 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class DefaultOptionsManagerTests
{
private readonly DefaultOptionsManager optionsManager = new();
[TestMethod]
public void GetOptions_ReturnsDefault()
{
var options = this.optionsManager.GetOptions<string>();
options.Should().BeNull();
}
[TestMethod]
public void UpdateOptions_Succeeds()
{
this.optionsManager.UpdateOptions(string.Empty);
}
}
}
@@ -0,0 +1,6 @@
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
public sealed class DummyOptions
{
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class LiveOptionsResolverTests
{
private readonly LiveOptionsResolver liveOptionsResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestMethod]
public void CanResolve_ILiveOptions_ReturnsTrue()
{
var type = typeof(ILiveOptions<string>);
var canResolve = this.liveOptionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(LiveOptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.liveOptionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_ILiveOptions_ReturnsILiveOptions()
{
this.SetupServiceProvider();
var liveOptions = this.liveOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(ILiveOptions<string>));
liveOptions.Should().BeAssignableTo<ILiveOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.liveOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.optionsManagerMock.Object);
}
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class LiveUpdateableOptionsResolverTests
{
private readonly LiveUpdateableOptionsResolver liveUpdateableOptionsResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestMethod]
public void CanResolve_ILiveUpdateableOptions_ReturnsTrue()
{
var type = typeof(ILiveUpdateableOptions<string>);
var canResolve = this.liveUpdateableOptionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(LiveOptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.liveUpdateableOptionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_ILiveUpdateableOptions_ReturnsILiveUpdateableOptions()
{
this.SetupServiceProvider();
var liveOptions = this.liveUpdateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(ILiveUpdateableOptions<string>));
liveOptions.Should().BeAssignableTo<ILiveUpdateableOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.liveUpdateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.optionsManagerMock.Object);
}
}
}
@@ -0,0 +1,44 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class LiveUpdateableOptionsWrapperTests
{
private LiveUpdateableOptionsWrapper<string> optionsWrapper;
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestInitialize]
public void TestInitialize()
{
this.optionsWrapper = new LiveUpdateableOptionsWrapper<string>(this.optionsManagerMock.Object);
}
[TestMethod]
public void GetValue_ReturnsValue()
{
this.optionsManagerMock
.Setup(u => u.GetOptions<string>())
.Returns("hello");
var value = this.optionsWrapper.Value;
value.Should().Be("hello");
}
[TestMethod]
public void UpdateOption_CallsOptionsManager()
{
this.optionsManagerMock
.Setup(u => u.UpdateOptions<string>(It.IsAny<string>()))
.Verifiable();
this.optionsWrapper.UpdateOption();
this.optionsManagerMock.Verify();
}
}
}
@@ -0,0 +1,72 @@
using FluentAssertions;
using Microsoft.Extensions.Options;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class OptionsResolverTests
{
private readonly OptionsResolver optionsResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<IOptionsManager> optionsManagerMock = new();
public Mock<IOptionsManager> OptionsManagerMock => optionsManagerMock;
[TestMethod]
public void CanResolve_ILiveOptions_ReturnsTrue()
{
var type = typeof(IOptions<string>);
var canResolve = this.optionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(OptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.optionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_IOptions_ReturnsIOptions()
{
this.SetupServiceProvider();
var liveOptions = this.optionsResolver.Resolve(this.serviceProviderMock.Object, typeof(IOptions<string>));
liveOptions.Should().BeAssignableTo<IOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.optionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.OptionsManagerMock.Object);
}
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class UpdateableOptionsResolverTests
{
private readonly UpdateableOptionsResolver updateableOptionsResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestMethod]
public void CanResolve_ILiveOptions_ReturnsTrue()
{
var type = typeof(IUpdateableOptions<string>);
var canResolve = this.updateableOptionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(UpdateableOptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.updateableOptionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_IUpdateableOptions_ReturnsIUpdateableOptions()
{
this.SetupServiceProvider();
var liveOptions = this.updateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(IUpdateableOptions<string>));
liveOptions.Should().BeAssignableTo<IUpdateableOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.updateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.optionsManagerMock.Object);
}
}
}
@@ -0,0 +1,48 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Configuration;
using System.Extensions.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class UpdateableOptionsWrapperTests
{
private const string Value = "hello";
private UpdateableOptionsWrapper<string> optionsWrapper;
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestInitialize]
public void TestInitialize()
{
this.optionsWrapper = new UpdateableOptionsWrapper<string>(optionsManagerMock.Object, Value);
}
[TestMethod]
public void GetValue_ReturnsValue()
{
this.optionsManagerMock
.Setup(u => u.GetOptions<string>())
.Throws<Exception>();
var value = this.optionsWrapper.Value;
value.Should().Be(Value);
}
[TestMethod]
public void UpdateOption_CallsOptionsManager()
{
this.optionsManagerMock
.Setup(u => u.UpdateOptions<string>(It.IsAny<string>()))
.Verifiable();
this.optionsWrapper.UpdateOption();
this.optionsManagerMock.Verify();
}
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Http;
using System.Net.Http;
namespace SystemExtensions.DependencyInjection.Tests.Http
{
[TestClass]
public class HttpClientResolverTests
{
private readonly HttpClientResolver httpClientResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
[TestMethod]
public void CanResolve_IHttpClient_ReturnsTrue()
{
var type = typeof(IHttpClient<>);
var canResolve = this.httpClientResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(HttpClient), typeof(object), typeof(string), typeof(HttpClientResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.httpClientResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_TypedClient_ReturnsIHttpClient()
{
var client = this.httpClientResolver.Resolve(this.serviceProviderMock.Object, typeof(IHttpClient<string>));
client.Should().BeAssignableTo<IHttpClient<string>>();
}
[TestMethod]
public void Resolve_NonGenericType_Throws()
{
Action action = new(() =>
{
this.httpClientResolver.Resolve(this.serviceProviderMock.Object, typeof(IHttpClient<>));
});
action.Should().Throw<Exception>();
}
[TestMethod]
public void Resolve_RandomType_Throws()
{
Action action = new(() =>
{
this.httpClientResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
}
}
@@ -0,0 +1,43 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class CVLoggerProviderTests
{
private readonly Mock<ILogsWriter> logsWriterMock = new();
private CVLoggerProvider cVLoggerProvider;
[TestInitialize]
public void TestInitialize()
{
this.cVLoggerProvider = new CVLoggerProvider(this.logsWriterMock.Object);
}
[TestMethod]
public void CreateLogger_CreatesNewLogger()
{
var logger = this.cVLoggerProvider.CreateLogger(string.Empty);
logger.Should().NotBeNull();
}
[TestMethod]
public void LogEntry_CallsLogWriter()
{
this.cVLoggerProvider.LogEntry(new Log());
this.logsWriterMock.Verify();
}
private void SetupLogsWriter()
{
this.logsWriterMock
.Setup(u => u.WriteLog(It.IsAny<Log>()))
.Verifiable();
}
}
}
@@ -0,0 +1,76 @@
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class CVLoggerTests
{
private readonly Mock<ICVLoggerProvider> cvLoggerProviderMock = new();
private CVLogger cVLogger;
[TestInitialize]
public void TestInitialize()
{
this.cVLogger = new CVLogger(string.Empty, this.cvLoggerProviderMock.Object);
}
[TestMethod]
public void BeginScope_ReturnsNull()
{
var scope = this.cVLogger.BeginScope(string.Empty);
scope.Should().BeNull();
}
[TestMethod]
[DataRow(LogLevel.Debug)]
[DataRow(LogLevel.Trace)]
[DataRow(LogLevel.Information)]
[DataRow(LogLevel.Warning)]
[DataRow(LogLevel.Error)]
[DataRow(LogLevel.Critical)]
public void IsEnabled_OnAllLogLevels_ReturnsTrue(LogLevel logLevel)
{
var enabled = this.cVLogger.IsEnabled(logLevel);
enabled.Should().BeTrue();
}
[TestMethod]
public void Log_CallsFormatter()
{
var called = false;
Func<string, Exception, string> messageFormatter = new((state, exception) =>
{
called = true;
return string.Empty;
});
this.cVLogger.Log(LogLevel.Debug, new EventId(), "Some message", new Exception(), messageFormatter);
called.Should().BeTrue();
}
[TestMethod]
public void Log_CallsLogsProvider()
{
this.SetupLoggerProvider();
this.cVLogger.Log(LogLevel.Debug, new EventId(), "Some message", new Exception(), new Func<string, Exception, string>((s, e) => string.Empty));
this.cvLoggerProviderMock.Verify();
}
private void SetupLoggerProvider()
{
this.cvLoggerProviderMock
.Setup(u => u.LogEntry(It.IsAny<Log>()))
.Verifiable();
}
}
}
@@ -0,0 +1,30 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class DebugLogsWriterTests
{
private readonly DebugLogsWriter logsWriter = new();
[TestMethod]
public void WriteLog_Succeeds()
{
this.logsWriter.WriteLog(new Log());
}
[TestMethod]
public void WriteNullLog_Throws()
{
Action action = new(() =>
{
this.logsWriter.WriteLog(null);
});
action.Should().Throw<Exception>();
}
}
}
@@ -0,0 +1,108 @@
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class LoggerResolverTests
{
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<ILoggerFactory> loggerFactoryMock = new();
private readonly Mock<ILogger> loggerMock = new();
private readonly LoggerResolver loggerResolver = new();
[TestMethod]
public void CanResolve_ILogger_ReturnsTrue()
{
var type = typeof(ILogger);
var canResolve = this.loggerResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_GenericILogger_ReturnsTrue()
{
var type = typeof(ILogger<string>);
var canResolve = this.loggerResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(CVLogger), typeof(object), typeof(string), typeof(LoggerResolverTests), typeof(int) };
foreach(var type in types)
{
var canResolve = this.loggerResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_ILogger_ReturnsILogger()
{
this.SetupIServiceProvider();
var logger = this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(ILogger));
logger.Should().BeAssignableTo<ILogger>();
}
[TestMethod]
public void Resolve_TypedILogger_ReturnsTypedILogger()
{
this.SetupIServiceProvider();
var logger = this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(ILogger<string>));
logger.Should().BeAssignableTo<ILogger<string>>();
}
[TestMethod]
public void Resolve_RandomType_Throws()
{
this.SetupIServiceProvider();
Action action = new(() =>
{
this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
[TestMethod]
public void Resolve_NonTypedGeneric_Throws()
{
this.SetupIServiceProvider();
Action action = new(() =>
{
this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(ILogger<>));
});
action.Should().Throw<Exception>();
}
private void SetupIServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<ILoggerFactory>())
.Returns(this.loggerFactoryMock.Object);
this.loggerFactoryMock
.Setup(u => u.CreateLogger(It.IsAny<string>()))
.Returns(this.loggerMock.Object);
}
}
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.3" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.3" />
<PackageReference Include="coverlet.collector" Version="3.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,14 @@
namespace System.Configuration
{
public sealed class DefaultOptionsManager : IOptionsManager
{
public T GetOptions<T>() where T : class
{
return default;
}
public void UpdateOptions<T>(T value) where T : class
{
}
}
}
@@ -0,0 +1,9 @@
using Microsoft.Extensions.Options;
namespace System.Configuration
{
public interface ILiveOptions<T> : IOptions<T>
where T : class
{
}
}
@@ -0,0 +1,7 @@
namespace System.Configuration
{
public interface ILiveUpdateableOptions<T> : ILiveOptions<T>, IUpdateableOptions<T>
where T : class
{
}
}
@@ -0,0 +1,10 @@
namespace System.Configuration
{
public interface IOptionsManager
{
T GetOptions<T>()
where T : class;
void UpdateOptions<T>(T value)
where T : class;
}
}
@@ -0,0 +1,13 @@
using Microsoft.Extensions.Options;
namespace System.Configuration
{
public interface IUpdateableOptions<out T> : IOptions<T>
where T : class
{
/// <summary>
/// Updates the configuration with the current value stored in <see cref="IOptions{TOptions}.Value"/>.
/// </summary>
void UpdateOption();
}
}
@@ -0,0 +1,27 @@
using Slim.Resolvers;
namespace System.Configuration
{
public sealed class LiveOptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(LiveUpdateableOptionsWrapper<>);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILiveOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
return Activator.CreateInstance(typedOptionsType, configurationManager);
}
}
}
@@ -0,0 +1,26 @@
using Slim.Resolvers;
namespace System.Configuration
{
public sealed class LiveUpdateableOptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(LiveUpdateableOptionsWrapper<>);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILiveUpdateableOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
return Activator.CreateInstance(typedOptionsType, configurationManager);
}
}
}
@@ -0,0 +1,31 @@
using System.Extensions;
namespace System.Configuration
{
public sealed class LiveUpdateableOptionsWrapper<T> : ILiveUpdateableOptions<T>
where T : class
{
private readonly IOptionsManager configurationManager;
private T value;
public T Value
{
get
{
this.value = this.configurationManager.GetOptions<T>();
return this.value;
}
}
public LiveUpdateableOptionsWrapper(IOptionsManager configurationManager)
{
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
}
public void UpdateOption()
{
this.configurationManager.UpdateOptions<T>(this.value);
}
}
}
@@ -0,0 +1,33 @@
using Microsoft.Extensions.Options;
using Slim.Resolvers;
namespace System.Configuration
{
public sealed class OptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(OptionsWrapper<>);
private static readonly Type configurationType = typeof(IOptionsManager);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
var optionsValue = configurationType
.GetMethod(nameof(IOptionsManager.GetOptions))
.MakeGenericMethod(type.GetGenericArguments())
.Invoke(configurationManager, Array.Empty<object>());
return Activator.CreateInstance(typedOptionsType, optionsValue);
}
}
}
@@ -0,0 +1,33 @@
using Slim.Resolvers;
using System.Extensions.Configuration;
namespace System.Configuration
{
public sealed class UpdateableOptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(UpdateableOptionsWrapper<>);
private static readonly Type configurationType = typeof(IOptionsManager);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IUpdateableOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
var optionsValue = configurationType
.GetMethod(nameof(IOptionsManager.GetOptions))
.MakeGenericMethod(type.GetGenericArguments())
.Invoke(configurationManager, Array.Empty<object>());
return Activator.CreateInstance(typedOptionsType, configurationManager, optionsValue);
}
}
}
@@ -0,0 +1,23 @@
using System.Configuration;
namespace System.Extensions.Configuration
{
public sealed class UpdateableOptionsWrapper<T> : IUpdateableOptions<T>
where T : class
{
private readonly IOptionsManager configurationManager;
public T Value { get; }
public UpdateableOptionsWrapper(IOptionsManager configurationManager, T options)
{
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
this.Value = options;
}
public void UpdateOption()
{
this.configurationManager.UpdateOptions(this.Value);
}
}
}
@@ -0,0 +1,158 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Slim;
using System.Configuration;
using System.Http;
using System.Logging;
using System.Net.Http;
namespace System.Extensions
{
public static class ServiceManagerExtensions
{
/// <summary>
/// Registers a <see cref="IOptionsManager"/> with the default <see cref="DefaultOptionsManager"/>.
/// This call also registers the resolver that resolves <see cref="IUpdateableOptions{T}"/> and <see cref="IOptions{T}"/>.
/// </summary>
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
/// <returns>Provided <see cref="IServiceManager"/>.</returns>
public static IServiceManager RegisterOptionsManager(this IServiceManager serviceManager)
{
serviceManager.RegisterSingleton<IOptionsManager, DefaultOptionsManager>();
serviceManager.RegisterOptionsResolver();
return serviceManager;
}
/// <summary>
/// Registers a <see cref="IOptionsManager"/>.
/// This call also registers the resolver that resolves <see cref="IUpdateableOptions{T}"/> and <see cref="IOptions{T}"/>.
/// </summary>
/// <typeparam name="T">Implementation of <see cref="IOptionsManager"/>.</typeparam>
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
/// <returns>Provided <see cref="IServiceManager"/>.</returns>
public static IServiceManager RegisterOptionsManager<T>(this IServiceManager serviceManager)
where T : IOptionsManager
{
serviceManager.RegisterSingleton<IOptionsManager, T>();
serviceManager.RegisterOptionsResolver();
return serviceManager;
}
/// <summary>
/// Registers resolvers for <see cref="IOptions{TOptions}"/> and <see cref="IUpdateableOptions{T}"/>.
/// Depends on a <see cref="IOptionsManager"/> in order to properly resolve options.
/// </summary>
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
/// <returns><see cref="IServiceManager"/>.</returns>
public static IServiceManager RegisterOptionsResolver(this IServiceManager serviceManager)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterResolver(new OptionsResolver());
serviceManager.RegisterResolver(new UpdateableOptionsResolver());
serviceManager.RegisterResolver(new LiveOptionsResolver());
serviceManager.RegisterResolver(new LiveUpdateableOptionsResolver());
return serviceManager;
}
/// <summary>
/// Registers a <see cref="ILogsWriter"/> with the default <see cref="CVLoggerProvider"/>.
/// </summary>
/// <typeparam name="TLogsWriter">Implementation of <see cref="ILogsWriter"/>.</typeparam>
/// <param name="serviceManager"><see cref="IServiceProducer"/>.</param>
/// <returns>Provided <see cref="IServiceProducer"/>.</returns>
public static IServiceProducer RegisterLogWriter<TLogsWriter>(this IServiceProducer serviceManager)
where TLogsWriter : ILogsWriter
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterSingleton<ILogsWriter, TLogsWriter>();
serviceManager.RegisterScoped<ILoggerFactory, LoggerFactory>(sp =>
{
var factory = new LoggerFactory();
factory.AddProvider(new CVLoggerProvider(sp.GetService<ILogsWriter>()));
return factory;
});
return serviceManager;
}
/// <summary>
/// Registers a <see cref="ILogsWriter"/> with the default <see cref="CVLoggerProvider"/>.
/// </summary>
/// <typeparam name="TILogsWriter">Interface of <see cref="ILogsWriter"/>.</typeparam>
/// <typeparam name="TLogsWriter">Implementation of <see cref="ILogsWriter"/>.</typeparam>
/// <param name="serviceManager"><see cref="IServiceProducer"/>.</param>
/// <returns>Provided <see cref="IServiceProducer"/>.</returns>
public static IServiceProducer RegisterLogWriter<TILogsWriter, TLogsWriter>(this IServiceProducer serviceManager)
where TLogsWriter : TILogsWriter
where TILogsWriter : class, ILogsWriter
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterSingleton<TILogsWriter, TLogsWriter>();
serviceManager.RegisterScoped<ILoggerFactory, LoggerFactory>(sp =>
{
var factory = new LoggerFactory();
factory.AddProvider(new CVLoggerProvider(sp.GetService<TILogsWriter>()));
return factory;
});
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));
serviceManager.RegisterSingleton<ILoggerFactory, ILoggerFactory>(loggerFactory);
return serviceManager;
}
public static IServiceManager RegisterDebugLoggerFactory(this IServiceManager serviceManager)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterLogWriter<ILogsWriter, DebugLogsWriter>();
return serviceManager;
}
public static IServiceManager RegisterHttpFactory(this IServiceManager serviceManager)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterResolver(new HttpClientResolver());
return serviceManager;
}
public static IServiceManager RegisterHttpFactory(this IServiceManager serviceManager, Func<Slim.IServiceProvider, Type, HttpMessageHandler> handlerFactory)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterResolver(
new HttpClientResolver()
.WithHttpMessageHandlerFactory(handlerFactory));
return serviceManager;
}
}
}
@@ -0,0 +1,47 @@
using Slim.Resolvers;
using System.Linq;
using System.Net.Http;
namespace System.Http
{
public sealed class HttpClientResolver : IDependencyResolver
{
private static readonly Type clientType = typeof(HttpClient<>);
/// <summary>
/// Factory method. <see cref="Type"/> parameter of the factory is the scope of <see cref="IHttpClient{TScope}"/>.
/// </summary>
public Func<Slim.IServiceProvider, Type, HttpMessageHandler> HttpMessageHandlerFactory { get; set; }
/// <summary>
/// Sets the <see cref="HttpMessageHandlerFactory"/>.
/// </summary>
/// <param name="factory">Factory method. <see cref="Type"/> parameter of the factory is the scope of <see cref="IHttpClient{TScope}"/>.</param>
/// <returns></returns>
public HttpClientResolver WithHttpMessageHandlerFactory(Func<Slim.IServiceProvider, Type, HttpMessageHandler> factory)
{
this.HttpMessageHandlerFactory = factory;
return this;
}
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IHttpClient<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedClientType = clientType.MakeGenericType(type.GetGenericArguments());
var handler = this.HttpMessageHandlerFactory?.Invoke(serviceProvider, type.GetGenericArguments().First());
var httpClient = handler is null ?
Activator.CreateInstance(typedClientType) :
Activator.CreateInstance(typedClientType, new object[] { handler });
return httpClient;
}
}
}
@@ -0,0 +1,44 @@
using Microsoft.Extensions.Logging;
using System.Extensions;
namespace System.Logging
{
public sealed class CVLogger : ILogger
{
private readonly string category;
private readonly ICVLoggerProvider cvLoggerProvider;
public CVLogger(string category, ICVLoggerProvider cvLoggerProvider)
{
this.category = category;
this.cvLoggerProvider = cvLoggerProvider.ThrowIfNull(nameof(cvLoggerProvider));
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var message = formatter(state, exception);
var log = new Log
{
Exception = exception,
LogLevel = logLevel,
EventId = eventId.Name,
Message = message,
Category = category,
LogTime = DateTime.Now
};
this.cvLoggerProvider.LogEntry(log);
}
}
}
@@ -0,0 +1,39 @@
using Microsoft.CorrelationVector;
using Microsoft.Extensions.Logging;
using System.Extensions;
namespace System.Logging
{
public sealed class CVLoggerProvider : ICVLoggerProvider
{
private readonly ILogsWriter logsManager;
private readonly CorrelationVector correlationVector;
public CVLoggerProvider(ILogsWriter logsWriter)
{
this.logsManager = logsWriter.ThrowIfNull(nameof(logsWriter));
this.correlationVector = new CorrelationVector();
}
public void LogEntry(Log log)
{
if (this.correlationVector is not null)
{
log.CorrelationVector = this.correlationVector.Value.ToString();
this.correlationVector.Increment();
}
this.logsManager.WriteLog(log);
}
public ILogger CreateLogger(string categoryName)
{
return new CVLogger(categoryName, this);
}
public void Dispose()
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,12 @@
using System.Diagnostics;
namespace System.Logging
{
public sealed class DebugLogsWriter : ILogsWriter
{
public void WriteLog(Log log)
{
Debug.WriteLine($"{log.LogTime} - {log.Category} - {log.EventId} - {log.CorrelationVector} - {log.LogLevel} - {log.Message}{Environment.NewLine}{log.Exception}");
}
}
}
@@ -0,0 +1,9 @@
using Microsoft.Extensions.Logging;
namespace System.Logging
{
public interface ICVLoggerProvider : ILoggerProvider
{
void LogEntry(Log log);
}
}
@@ -0,0 +1,7 @@
namespace System.Logging
{
public interface ILogsWriter
{
void WriteLog(Log log);
}
}
@@ -0,0 +1,50 @@
using Microsoft.Extensions.Logging;
using Slim.Resolvers;
using System.Linq;
namespace System.Logging
{
public sealed class LoggerResolver : IDependencyResolver
{
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILogger<>) ||
type == typeof(ILogger))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILogger<>))
{
return ResolveScopedLogger(serviceProvider, type);
}
else if (type == typeof(ILogger))
{
return ResolveLogger(serviceProvider);
}
else
{
throw new InvalidOperationException($"{nameof(LoggerResolver)} cannot resolve an object of type {type.Name}");
}
}
private static object ResolveScopedLogger(Slim.IServiceProvider serviceProvider, Type type)
{
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
var categoryTypes = type.GetGenericArguments();
var createLoggerMethod = typeof(LoggerFactoryExtensions).GetMethods().Where(m => m.IsGenericMethodDefinition && m.Name == nameof(LoggerFactoryExtensions.CreateLogger)).First();
return createLoggerMethod.MakeGenericMethod(categoryTypes.First()).Invoke(null, new object[] { loggerFactory });
}
private static object ResolveLogger(Slim.IServiceProvider serviceProvider)
{
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
return loggerFactory.CreateLogger(string.Empty);
}
}
}
@@ -0,0 +1,15 @@
using Microsoft.Extensions.Logging;
namespace System.Logging
{
public sealed record Log
{
public Exception Exception { get; set; }
public DateTime LogTime { get; set; }
public string Category { get; set; }
public string EventId { get; set; }
public LogLevel LogLevel { get; set; }
public string Message { get; set; }
public string CorrelationVector { get; set; }
}
}
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>System.DependencyInjection</RootNamespace>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<LangVersion>latest</LangVersion>
<Version>1.1.5</Version>
<Authors>Alexandru Macocian</Authors>
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<None Include="..\LICENSE" Link="LICENSE">
<PackagePath></PackagePath>
<Pack>True</Pack>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Slim" Version="1.5.4" />
<PackageReference Include="SystemExtensions.NetStandard" Version="1.3.1" />
</ItemGroup>
</Project>
@@ -0,0 +1,105 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions.NetStandard.Security.Encryption;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public class AesEncrypterTests
{
private ISymmetricEncrypter symmetricEncrypter;
private string keyString;
private byte[] keyBytes;
private byte[] ivBytes;
private string ivString;
private string toEncryptString;
private byte[] toEncryptBytes;
[TestInitialize]
public void TestInitialize()
{
this.symmetricEncrypter = new AesEncrypter();
this.keyBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2 };
this.keyString = Convert.ToBase64String(this.keyBytes);
this.ivBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
this.ivString = Convert.ToBase64String(this.ivBytes);
this.toEncryptBytes = Encoding.UTF8.GetBytes("toEncrypt");
this.toEncryptString = Convert.ToBase64String(this.toEncryptBytes);
}
[TestMethod]
public async Task EncryptDecryptStringWithStringKeyStringIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyString, this.ivString, this.toEncryptString).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyString, this.ivString, encrypted).ConfigureAwait(false);
this.toEncryptString.Should().Be(decrypted);
}
[TestMethod]
public async Task EncryptDecryptStringWithByteKeyByteIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyBytes, this.ivBytes, this.toEncryptString).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyBytes, this.ivBytes, encrypted).ConfigureAwait(false);
this.toEncryptString.Should().Be(decrypted);
}
[TestMethod]
public async Task EncryptDecryptByteWithStringKeyStringIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyString, this.ivString, this.toEncryptBytes).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyString, this.ivString, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(decrypted);
}
[TestMethod]
public async Task EncryptDecryptByteWithByteKeyByteIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyBytes, this.ivBytes, this.toEncryptBytes).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyBytes, this.ivBytes, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(decrypted);
}
[TestMethod]
public async Task EncryptDecryptStreamWithStringKeyStringIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyString, this.ivString, new MemoryStream(this.toEncryptBytes)).ConfigureAwait(false);
encrypted.Position = 0;
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyString, this.ivString, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(((MemoryStream)decrypted).ToArray());
}
[TestMethod]
public async Task EncryptDecryptStreamWithByteKeyByteIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyBytes, this.ivBytes, new MemoryStream(this.toEncryptBytes)).ConfigureAwait(false);
encrypted.Position = 0;
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyBytes, this.ivBytes, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(((MemoryStream)decrypted).ToArray());
}
[TestMethod]
public void GetEncryptionStreamReturnsCryptoStream()
{
var encryptionStream = this.symmetricEncrypter.GetEncryptionStream(this.keyBytes, this.ivBytes, new MemoryStream());
encryptionStream.Should().BeAssignableTo<CryptoStream>();
}
[TestMethod]
public void GetDecryptionStreamReturnsCryptoStream()
{
var encryptionStream = this.symmetricEncrypter.GetDecryptionStream(this.keyBytes, this.ivBytes, new MemoryStream());
encryptionStream.Should().BeAssignableTo<CryptoStream>();
}
}
}
@@ -0,0 +1,55 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using System.Rng;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public class CryptoRngProviderTests
{
private CryptoRngProvider cryptoRngProvider;
[TestInitialize]
public void TestInitialize()
{
this.cryptoRngProvider = new CryptoRngProvider();
}
[TestMethod]
public void GetBytes_ShouldSetValues()
{
var bytes = new byte[100];
this.cryptoRngProvider.GetBytes(bytes);
bytes.All(b => b == 0).Should().BeFalse();
}
[TestMethod]
public void GetNonZeroBytes_ShouldSetNonZeroValues()
{
var bytes = new byte[100];
this.cryptoRngProvider.GetNonZeroBytes(bytes);
bytes.All(b => b != 0).Should().BeTrue();
}
[TestMethod]
public void GetBytes_ShouldReturnBytes()
{
var bytes = this.cryptoRngProvider.GetBytes(10);
bytes.Length.Should().Be(10);
}
[TestMethod]
public void GetNonZeroBytes_ShouldReturnBytes()
{
var bytes = this.cryptoRngProvider.GetNonZeroBytes(10);
bytes.Length.Should().Be(10);
}
}
}
@@ -0,0 +1,123 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Encryption;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public class SecureStringTests
{
[TestMethod]
public void SecureString_NewSecureString_ReturnsValue()
{
var str = new SecureString("hello");
str.Value.Should().Be("hello");
}
[TestMethod]
public void SecureStringEmpty_AreEqual()
{
var str = SecureString.Empty;
str.Should().Be(SecureString.Empty);
}
[TestMethod]
public void SecureStringEmpty_Equals_StringEmpty()
{
var ss = SecureString.Empty;
var s = string.Empty;
ss.Should().Be(s);
}
[TestMethod]
public void SecureString_Equals_OtherSecureString()
{
var ss1 = new SecureString("Hello");
var ss2 = new SecureString("Hello");
ss1.Equals(ss2).Should().BeTrue();
}
[TestMethod]
[DataRow("hello", "hello", true)]
[DataRow("hello", "henlo", false)]
public void SecureString_EqualOperator_OtherSecureString(string str1, string str2, bool isEqual)
{
var ss1 = new SecureString(str1);
var ss2 = new SecureString(str2);
(ss1 == ss2).Should().Be(isEqual);
}
[TestMethod]
[DataRow("hello", "hello", false)]
[DataRow("hello", "henlo", true)]
public void SecureString_DifferentOperator_OtherSecureString(string str1, string str2, bool isDifferent)
{
var ss1 = new SecureString(str1);
var ss2 = new SecureString(str2);
(ss1 != ss2).Should().Be(isDifferent);
}
[TestMethod]
[DataRow("hello", "hello", true)]
[DataRow("hello", "henlo", false)]
public void SecureString_EqualOperator_String(string str1, string str2, bool isEqual)
{
var ss1 = new SecureString(str1);
(ss1 == str2).Should().Be(isEqual);
}
[TestMethod]
[DataRow("hello", "hello", false)]
[DataRow("hello", "henlo", true)]
public void SecureString_DifferentOperator_String(string str1, string str2, bool isDifferent)
{
var ss1 = new SecureString(str1);
(ss1 != str2).Should().Be(isDifferent);
}
[TestMethod]
public void SecureString_PlusOperator_SecureString()
{
var ss1 = new SecureString("Hello ");
var ss2 = new SecureString("World");
(ss1 + ss2).Should().Be("Hello World");
}
[TestMethod]
public void SecureString_PlusOperator_String()
{
var ss1 = new SecureString("Hello ");
var ss2 = "World";
(ss1 + ss2).Should().Be("Hello World");
}
[TestMethod]
public void SecureString_PlusOperator_Char()
{
var ss1 = new SecureString("Hello ");
var c = 'W';
(ss1 + c).Should().Be("Hello W");
}
[TestMethod]
public void SecureString_WithOptionalEntropy_Matches()
{
SecureString.AddOptionalEntropy(new byte[] { 10, 20, 25, 34, 56, 12, 10, 81, 200, 155, 123, 144, 123, 192, 122, 1 });
var ss1 = new SecureString("Hello");
var ss2 = new SecureString("Hello");
ss1.Should().Be(ss2);
}
}
}
@@ -0,0 +1,48 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions.NetStandard.Security.Hashing;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public sealed class Sha256HashingServiceTests
{
private readonly IHashingService hashingService = new Sha256HashingService();
private string toHashtString;
private byte[] toHashtBytes;
private Stream toHashStream;
[TestInitialize]
public void TestInitialize()
{
this.toHashtBytes = Encoding.UTF8.GetBytes("toEncrypt");
this.toHashtString = Convert.ToBase64String(this.toHashtBytes);
this.toHashStream = new MemoryStream(this.toHashtBytes);
}
[TestMethod]
public async Task HashString()
{
var hash = await this.hashingService.Hash(this.toHashtString).ConfigureAwait(false);
hash.Should().BeOfType<string>();
}
[TestMethod]
public async Task HashBytes()
{
var hash = await this.hashingService.Hash(this.toHashtBytes).ConfigureAwait(false);
hash.Should().BeOfType<byte[]>();
}
[TestMethod]
public async Task HashStream()
{
var hash = await this.hashingService.Hash(this.toHashStream).ConfigureAwait(false);
hash.Should().BeAssignableTo<Stream>();
}
}
}
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.3" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.3" />
<PackageReference Include="coverlet.collector" Version="3.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,215 @@
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using SystemExtensions.NetStandard.Security.Utilities;
namespace SystemExtensions.NetStandard.Security.Encryption
{
public sealed class AesEncrypter : ISymmetricEncrypter
{
public async Task<string> Decrypt(string key, string iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToString(decryptedStream);
}
public async Task<string> Decrypt(byte[] key, byte[] iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToString(decryptedStream);
}
public async Task<byte[]> Decrypt(string key, string iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToBytes(decryptedStream);
}
public async Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToBytes(decryptedStream);
}
public async Task<Stream> Decrypt(string key, string iv, Stream value)
{
return await DecryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
}
public async Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value)
{
return await DecryptInternal(key, iv, value).ConfigureAwait(false);
}
public async Task<string> Encrypt(string key, string iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToString(encryptedStream);
}
public async Task<string> Encrypt(byte[] key, byte[] iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToString(encryptedStream);
}
public async Task<byte[]> Encrypt(string key, string iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToBytes(encryptedStream);
}
public async Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToBytes(encryptedStream);
}
public async Task<Stream> Encrypt(string key, string iv, Stream value)
{
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)
{
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)
{
return GetEncryptionStreamInternal(StringToBytes(key), StringToBytes(iv), outStream);
}
public Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream)
{
return GetEncryptionStreamInternal(key, iv, outStream);
}
public Stream GetDecryptionStream(string key, string iv, Stream inStream)
{
return GetDecryptionStreamInternal(StringToBytes(key), StringToBytes(iv), inStream);
}
public Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream)
{
return GetDecryptionStreamInternal(key, iv, inStream);
}
private static byte[] StreamToBytes(Stream value)
{
value.Position = 0;
var buffer = new byte[1024];
using var ms = new MemoryStream();
var read = -1;
do
{
read = value.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, read);
} while (read > 0);
return ms.ToArray();
}
private static string StreamToString(Stream value)
{
return Convert.ToBase64String(StreamToBytes(value));
}
private static byte[] StringToBytes(string value)
{
return Convert.FromBase64String(value);
}
private static Stream BytesToStream(byte[] value)
{
return new MemoryStream(value);
}
private static async Task<Stream> EncryptInternal(byte[] key, byte[] iv, Stream toEncryptStream)
{
if (key.Length < 32)
{
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
}
if (iv.Length < 16)
{
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
}
key = key.Take(32).ToArray();
iv = iv.Take(16).ToArray();
var encryptedMemoryStream = new MemoryStream();
using var cryptoStream = GetEncryptionStreamInternal(key, iv, encryptedMemoryStream);
await toEncryptStream.CopyToAsync(cryptoStream).ConfigureAwait(false);
if (!cryptoStream.HasFlushedFinalBlock)
{
cryptoStream.FlushFinalBlock();
}
encryptedMemoryStream.Position = 0;
return encryptedMemoryStream;
}
private static async Task<Stream> DecryptInternal(byte[] key, byte[] iv, Stream toDecryptStream)
{
if (key.Length < 32)
{
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
}
if (iv.Length < 16)
{
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
}
key = key.Take(32).ToArray();
iv = iv.Take(16).ToArray();
var decryptedMemoryStream = new MemoryStream();
using var cryptoStream = GetDecryptionStreamInternal(key, iv, toDecryptStream);
await cryptoStream.CopyToAsync(decryptedMemoryStream).ConfigureAwait(false);
if (!cryptoStream.HasFlushedFinalBlock)
{
cryptoStream.FlushFinalBlock();
}
decryptedMemoryStream.Position = 0;
return decryptedMemoryStream;
}
private static CryptoStream GetEncryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
{
using var aes = Aes.Create();
aes.Padding = PaddingMode.PKCS7;
var crypto = aes.CreateEncryptor(key, iv);
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Write);
return cryptoStream;
}
private static CryptoStream GetDecryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
{
using var aes = Aes.Create();
aes.Padding = PaddingMode.PKCS7;
var crypto = aes.CreateDecryptor(key, iv);
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Read);
return cryptoStream;
}
}
}
@@ -0,0 +1,25 @@
using System.IO;
using System.Threading.Tasks;
namespace SystemExtensions.NetStandard.Security.Encryption
{
public interface ISymmetricEncrypter
{
Stream GetEncryptionStream(string key, string iv, Stream outStream);
Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream);
Stream GetDecryptionStream(string key, string iv, Stream inStream);
Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream);
Task<string> Encrypt(string key, string iv, string value);
Task<string> Encrypt(byte[] key, byte[] iv, string value);
Task<byte[]> Encrypt(string key, string iv, byte[] value);
Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value);
Task<Stream> Encrypt(string key, string iv, Stream value);
Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value);
Task<string> Decrypt(string key, string iv, string value);
Task<string> Decrypt(byte[] key, byte[] iv, string value);
Task<byte[]> Decrypt(string key, string iv, byte[] value);
Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value);
Task<Stream> Decrypt(string key, string iv, Stream value);
Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value);
}
}
@@ -0,0 +1,102 @@
using System.Security.Cryptography;
using System.Text;
namespace System.Encryption
{
public sealed class SecureString
{
private static byte[] optionalEntropy;
private byte[] encryptedValue;
public string Value {
get => this.encryptedValue is not null ? Encoding.UTF8.GetString(ProtectedData.Unprotect(this.encryptedValue, optionalEntropy, DataProtectionScope.CurrentUser)) : null;
private set => this.encryptedValue = ProtectedData.Protect(Encoding.UTF8.GetBytes(value), optionalEntropy, DataProtectionScope.CurrentUser);
}
public SecureString(string value)
{
this.Value = value;
}
public override bool Equals(object obj)
{
if (obj is string)
{
return this == (obj as string);
}
else if (obj is SecureString)
{
return this == (obj as SecureString);
}
else
{
return base.Equals(obj);
}
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
public static readonly SecureString Empty = new(string.Empty);
public static implicit operator string(SecureString ss) => ss is null ? string.Empty : ss.Value;
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));
}
return new SecureString(ss1.Value + ss2.Value);
}
public static SecureString operator +(SecureString ss1, string s2)
{
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));
}
return new SecureString(ss1.Value + c);
}
public static bool operator ==(SecureString ss1, SecureString ss2)
{
return ss1?.Value == ss2?.Value;
}
public static bool operator !=(SecureString ss1, SecureString ss2)
{
return !(ss1 == ss2);
}
public static bool operator ==(SecureString ss1, string s2)
{
return ss1?.Value == s2;
}
public static bool operator !=(SecureString ss1, string s2)
{
return !(ss1?.Value == s2);
}
public static void AddOptionalEntropy(byte[] entropy)
{
optionalEntropy = entropy;
}
}
}
@@ -0,0 +1,12 @@
using System.IO;
using System.Threading.Tasks;
namespace SystemExtensions.NetStandard.Security.Hashing
{
public interface IHashingService
{
Task<string> Hash(string raw);
Task<byte[]> Hash(byte[] raw);
Task<Stream> Hash(Stream raw);
}
}
@@ -0,0 +1,63 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace SystemExtensions.NetStandard.Security.Hashing
{
public sealed class Sha256HashingService : IHashingService
{
public async Task<string> Hash(string raw)
{
using var rawStream = BytesToStream(StringToBytes(raw));
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
return StreamToString(hashedStream);
}
public async Task<byte[]> Hash(byte[] raw)
{
using var rawStream = BytesToStream(raw);
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
return StreamToBytes(hashedStream);
}
public async Task<Stream> Hash(Stream raw)
{
return await HashInternal(raw);
}
private static byte[] StreamToBytes(Stream value)
{
value.Position = 0;
var buffer = new byte[1024];
using var ms = new MemoryStream();
var read = -1;
do
{
read = value.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, read);
} while (read > 0);
return ms.ToArray();
}
private static string StreamToString(Stream value)
{
return Convert.ToBase64String(StreamToBytes(value));
}
private static byte[] StringToBytes(string value)
{
return Convert.FromBase64String(value);
}
private static Stream BytesToStream(byte[] value)
{
return new MemoryStream(value);
}
private static async Task<Stream> HashInternal(Stream raw)
{
if (raw is null)
{
throw new ArgumentNullException(nameof(raw));
}
using var sha256 = SHA256.Create();
return await Task.Run(() => new MemoryStream(sha256.ComputeHash(raw)));
}
}
}
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Macocian Alexandru Victor
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,59 @@
using System.Security.Cryptography;
namespace System.Rng
{
public sealed class CryptoRngProvider : ICryptoRngProvider, IDisposable
{
private readonly RNGCryptoServiceProvider rngProvider;
private bool disposedValue;
public CryptoRngProvider()
{
this.rngProvider = new RNGCryptoServiceProvider();
}
public CryptoRngProvider(CspParameters cspParams)
{
this.rngProvider = new RNGCryptoServiceProvider(cspParams);
}
public void GetBytes(byte[] data)
{
this.rngProvider.GetBytes(data);
}
public void GetNonZeroBytes(byte[] data)
{
this.rngProvider.GetNonZeroBytes(data);
}
public byte[] GetBytes(int byteCount)
{
var bytes = new byte[byteCount];
this.GetBytes(bytes);
return bytes;
}
public byte[] GetNonZeroBytes(int byteCount)
{
var bytes = new byte[byteCount];
this.GetNonZeroBytes(bytes);
return bytes;
}
private void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
this.rngProvider.Dispose();
}
this.disposedValue = true;
}
}
public void Dispose()
{
this.Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
@@ -0,0 +1,10 @@
namespace System.Rng
{
public interface ICryptoRngProvider
{
public void GetBytes(byte[] data);
public byte[] GetBytes(int byteCount);
public void GetNonZeroBytes(byte[] data);
public byte[] GetNonZeroBytes(int byteCount);
}
}
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RootNamespace>System</RootNamespace>
<Version>1.1.1</Version>
<Authors>Alexandru Macocian</Authors>
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<None Include="../LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
</ItemGroup>
</Project>
@@ -0,0 +1,23 @@
using System.IO;
using System.Security.Cryptography;
namespace SystemExtensions.NetStandard.Security.Utilities
{
internal sealed class NotClosingCryptoStream : CryptoStream
{
public NotClosingCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
: base(stream, transform, mode)
{
}
protected override void Dispose(bool disposing)
{
if (!this.HasFlushedFinalBlock)
{
this.FlushFinalBlock();
}
base.Dispose(false);
}
}
}
@@ -1,11 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// AVL tree implementation.
@@ -14,7 +9,7 @@ namespace SystemExtensions.Collections
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class AVLTree<T> : ICollection<T> where T : IComparable<T>
public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
{
#region Fields
[Serializable]
@@ -30,13 +25,14 @@ namespace SystemExtensions.Collections
}
AVLNode<T> root;
private int count = 0;
private bool isReadOnly = false;
private readonly bool isReadOnly = false;
#endregion
#region Properties
/// <summary>
/// Count of items currently stored in the tree.
/// </summary>
public int Count {
public int Count
{
get
{
return count;
@@ -51,7 +47,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Initializes a new instance of an AVLTree collection.
/// </summary>
/// <param name="comparator"></param>
public AVLTree()
{
@@ -65,7 +60,7 @@ namespace SystemExtensions.Collections
public void Add(T value)
{
count++;
AVLNode<T> newItem = new AVLNode<T>(value);
var newItem = new AVLNode<T>(value);
if (root == null)
{
root = newItem;
@@ -82,8 +77,8 @@ namespace SystemExtensions.Collections
/// <returns>True if the value is in the tree.</returns>
public bool Contains(T value)
{
AVLNode<T> node = Find(value, root);
if(node == null)
var node = Find(value, root);
if (node == null)
{
return false;
}
@@ -110,19 +105,19 @@ namespace SystemExtensions.Collections
/// </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)
while (queue.Count > 0)
{
AVLNode<T> currentNode = queue.Dequeue();
if(currentNode.Left != null)
var currentNode = queue.Dequeue();
if (currentNode.Left != null)
{
queue.Enqueue(currentNode.Left);
currentNode.Left = null;
count--;
}
if(currentNode.Right != null)
if (currentNode.Right != null)
{
queue.Enqueue(currentNode.Right);
currentNode.Right = null;
@@ -139,11 +134,11 @@ namespace SystemExtensions.Collections
/// <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)
{
@@ -169,7 +164,7 @@ namespace SystemExtensions.Collections
/// <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;
}
@@ -196,7 +191,7 @@ namespace SystemExtensions.Collections
}
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)
@@ -293,7 +288,7 @@ namespace SystemExtensions.Collections
}
private AVLNode<T> Find(T target, AVLNode<T> current)
{
if(current == null)
if (current == null)
{
return null;
}
@@ -304,7 +299,9 @@ namespace SystemExtensions.Collections
return current;
}
else
{
return Find(target, current.Left);
}
}
else
{
@@ -313,7 +310,9 @@ namespace SystemExtensions.Collections
return current;
}
else
{
return Find(target, current.Right);
}
}
}
@@ -323,46 +322,46 @@ namespace SystemExtensions.Collections
}
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);
}
@@ -372,12 +371,12 @@ namespace SystemExtensions.Collections
}
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)
{
@@ -390,7 +389,5 @@ namespace SystemExtensions.Collections
}
}
#endregion
}
}
@@ -1,22 +1,19 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Binary heap implementation.
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class BinaryHeap<T> : IEnumerable<T> where T : IComparable<T>
public sealed class BinaryHeap<T> : IEnumerable<T> where T : IComparable<T>
{
#region Fields
T[] items;
int capacity, count, initialCapacity;
private int capacity;
private int count;
private readonly int initialCapacity;
#endregion
#region Properties
/// <summary>
@@ -42,10 +39,12 @@ namespace SystemExtensions.Collections
/// <summary>
/// Capacity of the heap.
/// </summary>
public int Capacity { get => capacity;
public int Capacity
{
get => capacity;
set
{
if(value > capacity)
if (value > capacity)
{
Array.Resize(ref items, value);
capacity = value;
@@ -61,7 +60,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for a binary heap data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
public BinaryHeap()
{
capacity = 10;
@@ -71,7 +69,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for a binary heap data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
/// <param name="capacity">Initial capacity of the heap. Used for initial alocation of the array.</param>
public BinaryHeap(int capacity)
{
@@ -87,12 +84,12 @@ namespace SystemExtensions.Collections
/// <param name="value">Value to be added.</param>
public void Add(T value)
{
if(count == Capacity - 1)
if (count == Capacity - 1)
{
Capacity = 2 * Capacity;
}
int position = ++count;
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position = position / 2)
var position = ++count;
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position /= 2)
{
items[position] = items[position / 2];
}
@@ -108,7 +105,7 @@ namespace SystemExtensions.Collections
{
throw new IndexOutOfRangeException("Heap is empty!");
}
T min = items[1];
var min = items[1];
items[1] = items[count--];
BubbleDown(1);
return min;
@@ -123,7 +120,7 @@ namespace SystemExtensions.Collections
{
throw new IndexOutOfRangeException("Heap is empty!");
}
T min = items[1];
var min = items[1];
return min;
}
/// <summary>
@@ -132,7 +129,7 @@ namespace SystemExtensions.Collections
/// <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;
}
@@ -159,8 +156,11 @@ namespace SystemExtensions.Collections
public void Clear(bool completeClear)
{
count = 0;
capacity = initialCapacity;
items = new T[initialCapacity];
if (completeClear)
{
capacity = initialCapacity;
items = new T[initialCapacity];
}
}
/// <summary>
/// Returns an enumerator that iterates over the heap.
@@ -168,7 +168,7 @@ namespace SystemExtensions.Collections
/// <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,16 +181,16 @@ namespace SystemExtensions.Collections
/// <param name="index">Index of element to bubble</param>
private void BubbleDown(int index)
{
T temp = items[index];
int childIndex = 0;
for(; 2*index <= count; index = childIndex)
var temp = items[index];
int childIndex;
for (; 2 * index <= count; index = childIndex)
{
childIndex = 2 * index;
if(childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0)
if (childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0)
{
childIndex++;
}
if(temp.CompareTo(items[childIndex]) > 0)
if (temp.CompareTo(items[childIndex]) > 0)
{
items[index] = items[childIndex];
}
@@ -202,16 +202,6 @@ namespace SystemExtensions.Collections
items[index] = temp;
}
/// <summary>
/// Build heap from unordered array
/// </summary>
private void BuildHeap()
{
for(int i = count / 2; i > 0; i--)
{
BubbleDown(i);
}
}
/// <summary>
/// Implementation of IEnumerator.
/// </summary>
/// <returns>Enumerator over the array.</returns>
@@ -1,18 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Fibonacci Heap implementation.
/// </summary>
/// <typeparam name="T">Provided type</typeparam>
[Serializable]
public class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
{
#region Fields
private FibonacciNode<T> root;
@@ -44,7 +37,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for Fibonacci heap data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
public FibonacciHeap()
{
@@ -57,14 +49,16 @@ namespace SystemExtensions.Collections
/// <param name="value">Value to be added.</param>
public void Add(T value)
{
FibonacciNode<T> node = new FibonacciNode<T>();
node.Value = value;
var node = new FibonacciNode<T>
{
Value = value,
Marked = false,
Child = null,
Parent = null,
Degree = 0
};
node.Previous = node.Next = node;
node.Degree = 0;
node.Marked = false;
node.Child = null;
node.Parent = null;
root = Merge(root, node);
root = this.Merge(root, node);
count++;
}
/// <summary>
@@ -83,7 +77,7 @@ namespace SystemExtensions.Collections
/// <returns>Minimum value.</returns>
public T Remove()
{
FibonacciNode<T> currentRoot = root;
var currentRoot = root;
if (currentRoot != null)
{
root = RemoveMinimum(root);
@@ -102,7 +96,7 @@ namespace SystemExtensions.Collections
/// <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>
@@ -131,11 +125,11 @@ namespace SystemExtensions.Collections
/// <returns>Array with values from the heap.</returns>
public T[] ToArray()
{
if(count == 0)
if (count == 0)
{
return null;
}
T[] array = new T[count];
var array = new T[count];
if (count == 1)
{
array[0] = root.Value;
@@ -143,7 +137,7 @@ namespace SystemExtensions.Collections
}
else
{
int index = 0;
var index = 0;
RecursiveFillArray(root, ref array, ref index);
return array;
}
@@ -166,7 +160,7 @@ namespace SystemExtensions.Collections
/// <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;
@@ -184,12 +178,12 @@ namespace SystemExtensions.Collections
/// <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)
while (queue.Count > 0)
{
currentNode = queue.Dequeue();
FibonacciNode<T> oldNode = currentNode;
var oldNode = currentNode;
do
{
yield return currentNode.Value;
@@ -199,8 +193,8 @@ namespace SystemExtensions.Collections
}
currentNode = currentNode.Previous;
} while (currentNode != oldNode);
}
}
}
/// <summary>
/// Recursively remove the node and its children from the heap.
@@ -208,9 +202,9 @@ namespace SystemExtensions.Collections
/// <param name="node">Node to be removed.</param>
private void Remove(FibonacciNode<T> node)
{
if(node != null)
if (node != null)
{
FibonacciNode<T> current = node;
var current = node;
do
{
Remove(current.Child);
@@ -230,22 +224,22 @@ namespace SystemExtensions.Collections
/// <param name="node2">Root of second heap.</param>
private FibonacciNode<T> Merge(FibonacciNode<T> node1, FibonacciNode<T> node2)
{
if(node1 == null)
if (node1 == null)
{
return node2;
}
if(node2 == null)
if (node2 == null)
{
return node1;
}
if(node1.Value.CompareTo(node2.Value) > 0)
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;
@@ -270,11 +264,11 @@ namespace SystemExtensions.Collections
/// <param name="node">Node to be removed from its parent.</param>
private void RemoveParent(FibonacciNode<T> node)
{
if(node == null)
if (node == null)
{
return;
}
FibonacciNode<T> current = node;
var current = node;
do
{
current.Marked = false;
@@ -290,7 +284,7 @@ namespace SystemExtensions.Collections
private FibonacciNode<T> RemoveMinimum(FibonacciNode<T> node)
{
RemoveParent(node.Child);
if(node.Next == node)
if (node.Next == node)
{
node = node.Child;
}
@@ -300,23 +294,23 @@ namespace SystemExtensions.Collections
node.Previous.Next = node.Next;
node = Merge(node.Next, node.Child);
}
if(node == null)
if (node == null)
{
return node;
}
FibonacciNode<T>[] trees = new FibonacciNode<T>[64];
var trees = new FibonacciNode<T>[64];
while (true)
{
if(trees[node.Degree] != null)
if (trees[node.Degree] != null)
{
FibonacciNode<T> t = trees[node.Degree];
if(t == node)
var t = trees[node.Degree];
if (t == node)
{
break;
}
trees[node.Degree] = null;
if(node.Value.CompareTo(t.Value) < 0)
if (node.Value.CompareTo(t.Value) < 0)
{
t.Previous.Next = t.Next;
t.Next.Previous = t.Previous;
@@ -326,7 +320,7 @@ namespace SystemExtensions.Collections
{
t.Previous.Next = t.Next;
t.Next.Previous = t.Previous;
if(node.Next == node)
if (node.Next == node)
{
t.Next = t.Previous = t;
AddChild(t, node);
@@ -350,11 +344,11 @@ namespace SystemExtensions.Collections
}
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)
if (node.Value.CompareTo(min.Value) < 0)
{
min = node;
}
@@ -370,7 +364,7 @@ namespace SystemExtensions.Collections
/// <returns></returns>
private FibonacciNode<T> Cut(FibonacciNode<T> root, FibonacciNode<T> node)
{
if(node.Next == node)
if (node.Next == node)
{
node.Parent.Child = null;
}
@@ -393,26 +387,26 @@ namespace SystemExtensions.Collections
/// <returns></returns>
private FibonacciNode<T> DecreaseKey(FibonacciNode<T> root, FibonacciNode<T> node, T value)
{
if(node.Value.CompareTo(value) < 0)
if (node.Value.CompareTo(value) < 0)
{
return root;
}
node.Value = value;
if(node.Parent != null)
if (node.Parent != null)
{
if(node.Value.CompareTo(node.Parent.Value) < 0)
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)
while (parent != null && parent.Marked)
{
root = Cut(root, parent);
node = parent;
parent = node.Parent;
node.Parent = null;
}
if(parent != null && parent.Parent != null)
if (parent != null && parent.Parent != null)
{
parent.Marked = true;
}
@@ -420,7 +414,7 @@ namespace SystemExtensions.Collections
}
else
{
if(node.Value.CompareTo(root.Value) < 0)
if (node.Value.CompareTo(root.Value) < 0)
{
root = node;
}
@@ -435,19 +429,19 @@ namespace SystemExtensions.Collections
/// <returns></returns>
private FibonacciNode<T> Find(FibonacciNode<T> root, T value)
{
FibonacciNode<T> node = root;
if(node == null)
var node = root;
if (node == null)
{
return null;
}
do
{
if(node.Value.CompareTo(value) == 0)
if (node.Value.CompareTo(value) == 0)
{
return node;
}
FibonacciNode<T> ret = Find(node.Child, value);
if(ret != null)
var ret = Find(node.Child, value);
if (ret != null)
{
return ret;
}
@@ -462,7 +456,7 @@ namespace SystemExtensions.Collections
#endregion
}
[Serializable]
internal class FibonacciNode<T>
internal sealed class FibonacciNode<T>
{
#region Fields
private FibonacciNode<T> previous;
@@ -537,7 +531,7 @@ namespace SystemExtensions.Collections
}
set
{
this.value = value;
this.value = value;
}
}
public int Degree
@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Interface for queue implementations.
@@ -1,11 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Priority Queue data structure. The implementation is based on an array-based implementation of Binary Heap.
@@ -13,10 +6,10 @@ namespace SystemExtensions.Collections
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class PriorityQueue<T> : IQueue<T> where T : IComparable<T>
public sealed class PriorityQueue<T> : IQueue<T> where T : IComparable<T>
{
#region Fields
private BinaryHeap<T> binaryHeap;
private readonly BinaryHeap<T> binaryHeap;
#endregion
#region Properties
/// <summary>
@@ -34,7 +27,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for priority queue data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
public PriorityQueue()
{
binaryHeap = new BinaryHeap<T>();
@@ -1,18 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Skip list implementation.
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class SkipList<T> : ICollection<T> where T : IComparable<T>
public sealed class SkipList<T> : ICollection<T> where T : IComparable<T>
{
#region Fields
[Serializable]
@@ -30,10 +23,10 @@ namespace SystemExtensions.Collections
}
}
private int count;
private Random random;
private NodeSet<T> head;
private NodeSet<T> end;
private int maxLevel = 10;
private readonly Random random;
private readonly NodeSet<T> head;
private readonly NodeSet<T> end;
private readonly int maxLevel = 10;
private int level;
#endregion
#region Properties
@@ -53,11 +46,11 @@ namespace SystemExtensions.Collections
/// <param name="maxLevel">Maximum level of the skip list.</param>
public SkipList(int maxLevel = 10)
{
this.maxLevel = maxLevel;
this.maxLevel = maxLevel;
random = new Random();
head = new NodeSet<T>(default(T), maxLevel);
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;
}
@@ -71,8 +64,8 @@ namespace SystemExtensions.Collections
/// <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++;
@@ -81,10 +74,10 @@ namespace SystemExtensions.Collections
{
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)
if (i > curNode.Level)
{
curNode = head;
}
@@ -104,11 +97,11 @@ namespace SystemExtensions.Collections
/// <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)
if (i > curNode.Level)
{
curNode = head;
}
@@ -141,7 +134,7 @@ namespace SystemExtensions.Collections
/// </summary>
public void Clear()
{
for(int i = 0; i < maxLevel; i++)
for (var i = 0; i < maxLevel; i++)
{
head.Next[i] = end;
}
@@ -154,7 +147,7 @@ namespace SystemExtensions.Collections
/// <returns>True if item is present in the collection.</returns>
public bool Contains(T item)
{
if(Find(item) != null)
if (Find(item) != null)
{
return true;
}
@@ -167,8 +160,8 @@ namespace SystemExtensions.Collections
/// <param name="arrayIndex">Index to start insertion in the array.</param>
public void CopyTo(T[] array, int arrayIndex)
{
NodeSet<T> node = head.Next[0];
while(node != end)
var node = head.Next[0];
while (node != end)
{
array[arrayIndex] = node.Key;
arrayIndex++;
@@ -181,10 +174,10 @@ namespace SystemExtensions.Collections
/// <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];
while(curNode != end)
var array = new T[count];
var index = 0;
var curNode = head.Next[0];
while (curNode != end)
{
array[index] = curNode.Key;
index++;
@@ -198,8 +191,8 @@ namespace SystemExtensions.Collections
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
NodeSet<T> curNode = head.Next[0];
while(curNode != end)
var curNode = head.Next[0];
while (curNode != end)
{
yield return curNode.Key;
curNode = curNode.Next[0];
@@ -213,17 +206,17 @@ namespace SystemExtensions.Collections
}
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)
while (curNode.Next[i] != end)
{
if(curNode.Next[i].Key.CompareTo(key) > 0)
if (curNode.Next[i].Key.CompareTo(key) > 0)
{
break;
}
else if(curNode.Next[i].Key.CompareTo(key) == 0)
else if (curNode.Next[i].Key.CompareTo(key) == 0)
{
return curNode.Next[i];
}
@@ -232,7 +225,7 @@ namespace SystemExtensions.Collections
}
curNode = curNode.Next[0];
if(curNode != end && curNode.Key.CompareTo(key) == 0)
if (curNode != end && curNode.Key.CompareTo(key) == 0)
{
return curNode;
}
@@ -1,18 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Treap implementation.
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class Treap<T> : ICollection<T> where T : IComparable<T>
public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
{
#region Fields
[Serializable]
@@ -29,7 +22,7 @@ namespace SystemExtensions.Collections
Right = null;
}
}
private Random randomGen;
private readonly Random randomGen;
private Node<T> root;
private int count;
#endregion
@@ -44,14 +37,15 @@ namespace SystemExtensions.Collections
return count;
}
}
public bool IsReadOnly => throw new NotImplementedException();
/// <summary>
/// Not implemented.
/// </summary>
public bool IsReadOnly => false;
#endregion
#region Constructors
/// <summary>
/// Constructor for treap.
/// </summary>
/// <param name="comparator">Comparator method used to compare values.</param>
public Treap()
{
randomGen = new Random();
@@ -103,8 +97,8 @@ namespace SystemExtensions.Collections
{
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;
}
@@ -134,14 +128,15 @@ namespace SystemExtensions.Collections
#region Private Methods
private Node<T> InsertNode(Node<T> node, T key)
{
if(node == null) {
if (node == null)
{
node = new Node<T>(key, randomGen.Next(0, 100));
return node;
}
else if (key.CompareTo(node.Key) <= 0)
{
node.Left = InsertNode(node.Left, key);
if(node.Left.Priority > node.Priority)
if (node.Left.Priority > node.Priority)
{
node = RotateRight(node);
}
@@ -149,7 +144,7 @@ namespace SystemExtensions.Collections
else
{
node.Right = InsertNode(node.Right, key);
if(node.Right.Priority > node.Priority)
if (node.Right.Priority > node.Priority)
{
node = RotateLeft(node);
}
@@ -158,27 +153,27 @@ namespace SystemExtensions.Collections
}
private Node<T> RemoveNode(Node<T> node, T key)
{
if(node == null)
if (node == null)
{
return node;
return node;
}
if(key.CompareTo(node.Key) < 0)
if (key.CompareTo(node.Key) < 0)
{
node.Left = RemoveNode(node.Left, key);
}
else if(key.CompareTo(node.Key) > 0)
else if (key.CompareTo(node.Key) > 0)
{
node.Right = RemoveNode(node.Right, key);
}
}
else if (node.Left == null)
{
node = node.Right;
}
else if(node.Right == null)
else if (node.Right == null)
{
node = node.Left;
}
else if(node.Left.Priority < node.Right.Priority)
else if (node.Left.Priority < node.Right.Priority)
{
node = RotateLeft(node);
node.Left = RemoveNode(node.Left, key);
@@ -206,11 +201,11 @@ namespace SystemExtensions.Collections
}
private void Clear(Node<T> node)
{
if(node.Left != null)
if (node.Left != null)
{
Clear(node.Left);
}
if(node.Right != null)
if (node.Right != null)
{
Clear(node.Right);
}
@@ -218,24 +213,24 @@ namespace SystemExtensions.Collections
}
private Node<T> Find(Node<T> node, T key)
{
if(node == null)
if (node == null)
{
return node;
}
else
{
if(node.Key.CompareTo(key) < 0)
if (node.Key.CompareTo(key) < 0)
{
Node<T> found = Find(node.Left, key);
if(found == null)
var found = Find(node.Left, key);
if (found == null)
{
found = Find(node.Right, key);
}
return found;
}
else if(node.Key.CompareTo(key) > 0)
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);
@@ -250,7 +245,7 @@ namespace SystemExtensions.Collections
}
private void ToArray(Node<T> node, ref T[] array, ref int index)
{
if(node != null)
if (node != null)
{
ToArray(node.Left, ref array, ref index);
array[index] = node.Key;
@@ -260,17 +255,17 @@ namespace SystemExtensions.Collections
}
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)
while (queue.Count > 0)
{
currentNode = queue.Dequeue();
yield return currentNode.Key;
if(currentNode.Left != null)
if (currentNode.Left != null)
{
queue.Enqueue(currentNode.Left);
}
if(currentNode.Right != null)
if (currentNode.Right != null)
{
queue.Enqueue(currentNode.Right);
}
@@ -0,0 +1,27 @@
using System.IO;
namespace System.Extensions
{
public static class BytesExtensions
{
public static byte[] ReadAllBytes(this Stream stream)
{
if (stream is null)
{
throw new ArgumentNullException(nameof(stream));
}
var buffer = new byte[256];
using (var ms = new MemoryStream())
{
int read;
while ((read = stream.Read(buffer, 0, 256)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
}
}
@@ -0,0 +1,50 @@
namespace System.Extensions
{
public static class CastExtensions
{
public static int Floor(this double value)
{
return (int)Math.Floor(value);
}
public static int Ceiling(this double value)
{
return (int)Math.Ceiling(value);
}
public static int Round(this double value)
{
return (int)Math.Round(value);
}
public static int Floor(this float value)
{
return (int)Math.Floor(value);
}
public static int Ceiling(this float value)
{
return (int)Math.Ceiling(value);
}
public static int Round(this float value)
{
return (int)Math.Round(value);
}
public static int ToInt(this double value)
{
return (int)value;
}
public static int ToInt(this float value)
{
return (int)value;
}
public static int ToInt(this decimal value)
{
return (int)value;
}
}
}
@@ -0,0 +1,88 @@
using System.Collections.Generic;
using System.Linq;
namespace System.Extensions
{
public static class LinqExtensions
{
public static bool None<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
{
enumerable.ThrowIfNull(nameof(enumerable));
predicate.ThrowIfNull(nameof(predicate));
return !enumerable.Any(predicate);
}
public static bool None<T>(this IEnumerable<T> enumerable)
{
enumerable.ThrowIfNull(nameof(enumerable));
return !enumerable.Any();
}
public static ICollection<T> ClearAnd<T>(this ICollection<T> collection)
{
if (collection is null)
{
throw new ArgumentNullException(nameof(collection));
}
collection.Clear();
return collection;
}
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));
}
foreach (var item in values)
{
collection.Add(item);
}
return collection;
}
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));
}
var index = 0;
foreach (var item in collection)
{
if (selector(item))
{
return index;
}
index++;
}
return -1;
}
public static IEnumerable<T> Do<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach(var value in enumerable)
{
action(value);
yield return value;
}
}
}
}
@@ -0,0 +1,59 @@
using Newtonsoft.Json;
namespace System.Extensions
{
public static class ObjectExtensions
{
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));
}
return JsonConvert.DeserializeObject<T>(serialized);
}
public static string Serialize<T>(this T obj)
where T : class
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
return JsonConvert.SerializeObject(obj);
}
public static T Cast<T>(this object obj)
{
return (T)obj;
}
public static T As<T>(this object obj) where T : class
{
return obj as T;
}
public static Optional<T> ToOptional<T>(this T obj)
{
return Optional.FromValue(obj);
}
public static T ThrowIfNull<T>([ValidatedNotNull] this T obj, string name) where T : class
{
if (obj is null)
{
throw new ArgumentNullException(name);
}
return obj;
}
[AttributeUsage(AttributeTargets.Parameter)]
sealed class ValidatedNotNullAttribute : Attribute
{
}
}
}
@@ -0,0 +1,192 @@
namespace System.Extensions
{
public static class Optional
{
public static Optional<T> None<T>()
{
return new Optional<T>.None();
}
public static Optional<T> FromValue<T>(T value)
{
if (value == null)
{
return new Optional<T>.None();
}
return new Optional<T>.Some(value);
}
}
public abstract class Optional<T> : IEquatable<Optional<T>>
{
public Optional(T value)
{
this.Value = value;
}
private T Value { get; }
public T ExtractValue()
{
if (this is None)
{
return default;
}
else
{
return Value;
}
}
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 (this is Some)
{
onSome.Invoke(this.Value);
}
else
{
onNone.Invoke();
}
return this;
}
public Optional<T> DoAny(Action<T> onSome = null, Action onNone = null)
{
if (this is Some)
{
onSome?.Invoke(this.Value);
}
else
{
onNone?.Invoke();
}
return this;
}
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 (this is Some)
{
return Optional.FromValue(onSome.Invoke(this.Value));
}
else
{
return Optional.FromValue(onNone.Invoke());
}
}
public Optional<V> SwitchAny<V>(Func<T, V> onSome = null, Func<V> onNone = null)
{
if (this is Some)
{
return onSome != null ? Optional.FromValue(onSome.Invoke(this.Value)) : Optional.FromValue(default(V));
}
else
{
return onNone != null ? Optional.FromValue(onNone.Invoke()) : Optional.FromValue(default(V));
}
}
public override bool Equals(object obj)
{
if (obj is Optional<T>)
{
return this.Equals(obj);
}
return base.Equals(obj);
}
public bool Equals(Optional<T> other)
{
if (this is Some && other is Some)
{
return this.As<Some>().Equals(other.As<Some>());
}
return false;
}
public static implicit operator Optional<T>(T value)
{
return Optional.FromValue(value);
}
public override int GetHashCode()
{
return this.Value == null ? base.GetHashCode() : this.Value.GetHashCode();
}
internal class Some : Optional<T>, IEquatable<Some>
{
public Some(T value) : base(value)
{
}
public override bool Equals(object obj)
{
if (obj is Some)
{
return this.Equals(obj.As<Some>());
}
return base.Equals(obj);
}
public bool Equals(Some other)
{
if (other is None)
{
return false;
}
if (other is Some)
{
return this.Value.Equals(other.Value);
}
return false;
}
public static bool operator ==(Some left, Some right)
{
return left?.Equals(right) == true;
}
public static bool operator !=(Some left, Some right)
{
return left?.Equals(right) != true;
}
public override int GetHashCode()
{
return this.Value is object ? this.Value.GetHashCode() : this.As<object>().GetHashCode();
}
}
internal class None : Optional<T>
{
public None() : base(default)
{
}
}
}
}
@@ -0,0 +1,209 @@
namespace System.Extensions
{
public class Result<TSuccess, TFailure>
{
private readonly object value;
public Result(TSuccess successValue)
{
value = successValue;
}
public Result(TFailure failureValue)
{
value = failureValue;
}
public bool TryExtractSuccess(out TSuccess successValue)
{
if (value is TSuccess success)
{
successValue = success;
return true;
}
else
{
successValue = default;
return false;
}
}
public bool TryExtractFailure(out TFailure failureValue)
{
if (value is TFailure failure)
{
failureValue = failure;
return true;
}
else
{
failureValue = default;
return false;
}
}
public Result<TSuccess, TFailure> Do(Action onSuccess, Action onFailure)
{
if (onSuccess is null)
{
throw new ArgumentNullException(nameof(onSuccess));
}
if (onFailure is null)
{
throw new ArgumentNullException(nameof(onFailure));
}
if (value is TSuccess)
{
onSuccess.Invoke();
}
else if (value is TFailure)
{
onFailure.Invoke();
}
return this;
}
public Result<TSuccess, TFailure> DoAny(Action onSuccess = null, Action onFailure = null)
{
if (value is TSuccess)
{
onSuccess?.Invoke();
}
else if (value is TFailure)
{
onFailure?.Invoke();
}
return this;
}
public Result<TSuccess, TFailure> Do(Action<TSuccess> onSuccess, Action<TFailure> onFailure)
{
if (onSuccess is null)
{
throw new ArgumentNullException(nameof(onSuccess));
}
if (onFailure is null)
{
throw new ArgumentNullException(nameof(onFailure));
}
if (value is TSuccess success)
{
onSuccess.Invoke(success);
}
else if (value is TFailure failure)
{
onFailure.Invoke(failure);
}
return this;
}
public Result<TSuccess, TFailure> DoAny(Action<TSuccess> onSuccess = null, Action<TFailure> onFailure = null)
{
if (value is TSuccess success)
{
onSuccess?.Invoke(success);
}
else if (value is TFailure failure)
{
onFailure?.Invoke(failure);
}
return this;
}
public T Switch<T>(Func<TSuccess, T> onSuccess, Func<TFailure, T> onFailure)
{
if (onSuccess is null)
{
throw new ArgumentNullException(nameof(onSuccess));
}
if (onFailure is null)
{
throw new ArgumentNullException(nameof(onFailure));
}
if (value is TSuccess success)
{
return onSuccess.Invoke(success);
}
else if (value is TFailure failure)
{
return onFailure.Invoke(failure);
}
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
}
public T SwitchAny<T>(Func<TSuccess, T> onSuccess = null, Func<TFailure, T> onFailure = null)
{
if (value is TSuccess success)
{
return onSuccess is null ? default : onSuccess.Invoke(success);
}
else if (value is TFailure failure)
{
return onFailure is null ? default : onFailure.Invoke(failure);
}
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
}
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 (onFailure is null)
{
throw new ArgumentNullException(nameof(onFailure));
}
if (value is TSuccess success)
{
return Result<V, K>.Success(onSuccess.Invoke(success));
}
else if (value is TFailure failure)
{
return Result<V, K>.Failure(onFailure.Invoke(failure));
}
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
}
public Result<V, K> SwitchAny<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
{
if (value is TSuccess success)
{
return Result<V, K>.Success(onSuccess is null ? default : onSuccess.Invoke(success));
}
else if (value is TFailure failure)
{
return Result<V, K>.Failure(onFailure is null ? default : onFailure.Invoke(failure));
}
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
}
public Optional<TSuccess> ToOptional()
{
if (value is TSuccess)
{
return Optional.FromValue(value.Cast<TSuccess>());
}
return Optional.None<TSuccess>();
}
public static implicit operator Result<TSuccess, TFailure>(TSuccess success)
{
return Success(success);
}
public static implicit operator Result<TSuccess, TFailure>(TFailure failure)
{
return Failure(failure);
}
public static Result<TSuccess, TFailure> Success(TSuccess value)
{
return new Result<TSuccess, TFailure>(value);
}
public static Result<TSuccess, TFailure> Failure(TFailure value)
{
return new Result<TSuccess, TFailure>(value);
}
}
}
@@ -0,0 +1,85 @@
using System.IO;
using System.Text;
namespace System.Extensions
{
public static class StreamExtensions
{
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));
}
var buffer = new byte[bufferLength];
var read = stream.Read(buffer, 0, bufferLength);
while(read > 0)
{
action(bufferLength, buffer);
read = stream.Read(buffer, 0, bufferLength);
}
}
public static byte[] ReadBytes(this Stream stream, int count)
{
if (stream is null)
{
throw new ArgumentNullException(nameof(stream));
}
var buffer = new byte[count];
stream.Read(buffer, 0, count);
return buffer;
}
public static Stream Rewind(this Stream stream)
{
if (stream is null)
{
throw new ArgumentNullException(nameof(stream));
}
if (!stream.CanSeek)
{
throw new InvalidOperationException("Stream doesn't support rewinding");
}
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
public static string ReadUntil(this StreamReader sr, string delim)
{
var sb = new StringBuilder();
var found = false;
while (!found && !sr.EndOfStream)
{
for (var i = 0; i < delim.Length; i++)
{
var c = (char)sr.Read();
sb.Append(c);
if (c != delim[i])
{
break;
}
if (i == delim.Length - 1)
{
sb.Remove(sb.Length - delim.Length, delim.Length);
found = true;
}
}
}
return sb.ToString();
}
}
}
@@ -0,0 +1,27 @@
using System.Text;
namespace System.Extensions
{
public static class StringExtensions
{
public static bool IsNullOrEmpty(this string s)
{
return string.IsNullOrEmpty(s);
}
public static bool IsNullOrWhiteSpace(this string s)
{
return string.IsNullOrWhiteSpace(s);
}
public static byte[] GetBytes(this string s)
{
return Encoding.UTF8.GetBytes(s);
}
public static string GetString(this byte[] bytes)
{
return Encoding.UTF8.GetString(bytes);
}
}
}
@@ -0,0 +1,184 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace System.Extensions
{
public static class TaskExtensions
{
/// <summary>
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
/// </summary>
/// <typeparam name="T">Result type.</typeparam>
/// <param name="task">Task.</param>
/// <returns>The started <see cref="Task{TResult}"/></returns>
public static Task<T> LongRunning<T>(this Task<T> task)
{
return Task.Factory.StartNew(async () =>
{
return await task;
}, TaskCreationOptions.LongRunning).Unwrap();
}
/// <summary>
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
/// </summary>
/// <param name="task">Task.</param>
/// <returns>The started <see cref="Task"/></returns>
public static Task LongRunning(this Task task)
{
return Task.Factory.StartNew(async () =>
{
await task;
}, TaskCreationOptions.LongRunning).Unwrap();
}
/// <summary>
/// Execute action periodically and asynchronously.
/// </summary>
/// <param name="onTick">Action to be executed.</param>
/// <param name="dueTime">Time to pass before starting to execute.</param>
/// <param name="interval">Interval between procs.</param>
/// <param name="token">Cancellation token used to cancel the cycle.</param>
/// <returns></returns>
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);
}
}
}
/// <summary>
/// Execute's an async Task<T> method which has a void return value synchronously
/// </summary>
/// <param name="task">Task<T> method to execute</param>
public static void RunSync(this Func<Task> task)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
synch.Post(async _ =>
{
try
{
await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
}
/// <summary>
/// Execute's an async Task<T> method which has a T return type synchronously
/// </summary>
/// <typeparam name="T">Return Type</typeparam>
/// <param name="task">Task<T> method to execute</param>
/// <returns></returns>
public static T RunSync<T>(this Func<Task<T>> task)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
var ret = default(T);
synch.Post(async _ =>
{
try
{
ret = await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
return ret;
}
private class ExclusiveSynchronizationContext : SynchronizationContext
{
private bool done;
public Exception InnerException { get; set; }
readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
readonly Queue<Tuple<SendOrPostCallback, object>> items =
new Queue<Tuple<SendOrPostCallback, object>>();
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("We cannot send to our same thread");
}
public override void Post(SendOrPostCallback d, object state)
{
lock (items)
{
items.Enqueue(Tuple.Create(d, state));
}
workItemsWaiting.Set();
}
public void EndMessageLoop()
{
Post(_ => done = true, null);
}
public void BeginMessageLoop()
{
while (!done)
{
Tuple<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > 0)
{
task = items.Dequeue();
}
}
if (task != null)
{
task.Item1(task.Item2);
if (InnerException != null) // the method threw an exeption
{
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
}
}
else
{
workItemsWaiting.WaitOne();
}
}
}
public override SynchronizationContext CreateCopy()
{
return this;
}
}
}
}
@@ -0,0 +1,72 @@
using System.Collections.Generic;
namespace System.Extensions
{
public static class Try
{
public static Try<TResult> Action<TResult>(Func<TResult> act)
{
return new Try<TResult>(act);
}
}
public class Try<TResult>
{
private readonly Func<TResult> action;
private readonly List<Func<Exception, TResult>> catchActions = new List<Func<Exception, TResult>>();
internal Try(Func<TResult> action)
{
this.action = action;
}
public static Try<TResult> Action(Func<TResult> act)
{
return new Try<TResult>(act);
}
public Try<TResult> Catch<TException>(Func<TException, TResult> act) where TException : Exception
{
this.catchActions.Add((Func<Exception, TResult>)act);
return this;
}
public TResult Run()
{
try
{
return action();
}
catch (Exception ex)
{
foreach (var catchAction in this.catchActions)
{
return catchAction(ex);
}
throw;
}
}
public TResult Finally(Action act)
{
if (act is null)
{
throw new ArgumentNullException(nameof(act));
}
try
{
return this.action();
}
catch (Exception ex)
{
foreach (var catchAction in this.catchActions)
{
return catchAction(ex);
}
throw;
}
finally
{
act();
}
}
}
}
@@ -0,0 +1,217 @@
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
namespace System.Http
{
public sealed class HttpClient<Tscope> : IHttpClient<Tscope>, IDisposable
{
private readonly HttpClient httpClient;
private readonly Type scope;
private EventHandler<HttpClientEventMessage> eventEmitted;
public event EventHandler<HttpClientEventMessage> EventEmitted
{
add
{
this.eventEmitted += value;
}
remove
{
this.eventEmitted -= value;
}
}
public Uri BaseAddress { get => this.httpClient.BaseAddress; set => this.httpClient.BaseAddress = value; }
public HttpRequestHeaders DefaultRequestHeaders => this.httpClient.DefaultRequestHeaders;
public long MaxResponseContentBufferSize { get => this.httpClient.MaxResponseContentBufferSize; set => this.httpClient.MaxResponseContentBufferSize = value; }
public TimeSpan Timeout { get => this.httpClient.Timeout; set => this.httpClient.Timeout = value; }
public HttpClient()
{
this.httpClient = new HttpClient();
this.scope = typeof(Tscope);
}
public HttpClient(
HttpMessageHandler handler)
{
this.httpClient = new HttpClient(handler);
this.scope = typeof(Tscope);
}
public HttpClient(
HttpMessageHandler handler,
bool disposeHandler)
{
this.httpClient = new HttpClient(handler, disposeHandler);
this.scope = typeof(Tscope);
}
public void CancelPendingRequests()
{
this.LogInformation(string.Empty, "Canceling request");
this.httpClient.CancelPendingRequests();
}
public Task<HttpResponseMessage> DeleteAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri);
}
public Task<HttpResponseMessage> DeleteAsync(string requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri, cancellationToken);
}
public Task<HttpResponseMessage> DeleteAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri);
}
public Task<HttpResponseMessage> DeleteAsync(Uri requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri);
}
public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption);
}
public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(string requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, cancellationToken);
}
public Task<byte[]> GetByteArrayAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetByteArrayAsync));
return this.httpClient.GetByteArrayAsync(requestUri);
}
public Task<byte[]> GetByteArrayAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetByteArrayAsync));
return this.httpClient.GetByteArrayAsync(requestUri);
}
public Task<Stream> GetStreamAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetStreamAsync));
return this.httpClient.GetStreamAsync(requestUri);
}
public Task<Stream> GetStreamAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetStreamAsync));
return this.httpClient.GetStreamAsync(requestUri);
}
public Task<string> GetStringAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetStringAsync));
return this.httpClient.GetStringAsync(requestUri);
}
public Task<string> GetStringAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetStringAsync));
return this.httpClient.GetStringAsync(requestUri);
}
public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)
{
this.LogInformation(requestUri, nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content);
}
public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content)
{
this.LogInformation(requestUri.ToString(), nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content);
}
public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content)
{
this.LogInformation(requestUri, nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content);
}
public Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content)
{
this.LogInformation(requestUri.ToString(), nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content);
}
public Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request, completionOption);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request, completionOption, cancellationToken);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request, cancellationToken);
}
public void Dispose()
{
this.httpClient.Dispose();
}
private void LogInformation(string url, string method)
{
this.eventEmitted?.Invoke(this, new HttpClientEventMessage(this.scope, method, url));
}
}
}
@@ -0,0 +1,16 @@
namespace System.Http
{
public sealed class HttpClientEventMessage
{
public Type Scope { get; }
public string Method { get; }
public string Url { get; }
internal HttpClientEventMessage(Type scope, string method, string url)
{
this.Scope = scope;
this.Method = method;
this.Url = url;
}
}
}
@@ -0,0 +1,49 @@
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
namespace System.Http
{
public interface IHttpClient<TScope>
{
event EventHandler<HttpClientEventMessage> EventEmitted;
Uri BaseAddress { get; set; }
HttpRequestHeaders DefaultRequestHeaders { get; }
long MaxResponseContentBufferSize { get; set; }
TimeSpan Timeout { get; set; }
void CancelPendingRequests();
Task<HttpResponseMessage> DeleteAsync(string requestUri);
Task<HttpResponseMessage> DeleteAsync(string requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> DeleteAsync(Uri requestUri);
Task<HttpResponseMessage> DeleteAsync(Uri requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(string requestUri);
Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption);
Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(string requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(Uri requestUri);
Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption);
Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(Uri requestUri, CancellationToken cancellationToken);
Task<byte[]> GetByteArrayAsync(string requestUri);
Task<byte[]> GetByteArrayAsync(Uri requestUri);
Task<Stream> GetStreamAsync(string requestUri);
Task<Stream> GetStreamAsync(Uri requestUri);
Task<string> GetStringAsync(string requestUri);
Task<string> GetStringAsync(Uri requestUri);
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content);
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content);
Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content);
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content);
Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
}
@@ -0,0 +1,175 @@
namespace System.Structures.BitStructures
{
public struct Int32BitStruct : IEquatable<Int32BitStruct>
{
public Int32BitStruct(uint value) => this.Value = value;
public Int32BitStruct(int value) { unchecked { this.Value = (uint)value; } }
public uint Value { get; set; }
public uint Bit0 { get => this.Value & 0x1; set => this.Value = (this.Value & ~(0x1U) | (0x1 & value)); }
public uint Bit1 { get => this.Value >> 1 & 0x1; set => this.Value = (this.Value & ~(0x1U << 1)) | ((0x1 & value) << 1); }
public uint Bit2 { get => this.Value >> 2 & 0x1; set => this.Value = (this.Value & ~(0x1U << 2)) | ((0x1 & value) << 2); }
public uint Bit3 { get => this.Value >> 3 & 0x1; set => this.Value = (this.Value & ~(0x1U << 3)) | ((0x1 & value) << 3); }
public uint Bit4 { get => this.Value >> 4 & 0x1; set => this.Value = (this.Value & ~(0x1U << 4)) | ((0x1 & value) << 4); }
public uint Bit5 { get => this.Value >> 5 & 0x1; set => this.Value = (this.Value & ~(0x1U << 5)) | ((0x1 & value) << 5); }
public uint Bit6 { get => this.Value >> 6 & 0x1; set => this.Value = (this.Value & ~(0x1U << 6)) | ((0x1 & value) << 6); }
public uint Bit7 { get => this.Value >> 7 & 0x1; set => this.Value = (this.Value & ~(0x1U << 7)) | ((0x1 & value) << 7); }
public uint Bit8 { get => this.Value >> 8 & 0x1; set => this.Value = (this.Value & ~(0x1U << 8)) | ((0x1 & value) << 8); }
public uint Bit9 { get => this.Value >> 9 & 0x1; set => this.Value = (this.Value & ~(0x1U << 9)) | ((0x1 & value) << 9); }
public uint Bit10 { get => this.Value >> 10 & 0x1; set => this.Value = (this.Value & ~(0x1U << 10)) | ((0x1 & value) << 10); }
public uint Bit11 { get => this.Value >> 11 & 0x1; set => this.Value = (this.Value & ~(0x1U << 11)) | ((0x1 & value) << 11); }
public uint Bit12 { get => this.Value >> 12 & 0x1; set => this.Value = (this.Value & ~(0x1U << 12)) | ((0x1 & value) << 12); }
public uint Bit13 { get => this.Value >> 13 & 0x1; set => this.Value = (this.Value & ~(0x1U << 13)) | ((0x1 & value) << 13); }
public uint Bit14 { get => this.Value >> 14 & 0x1; set => this.Value = (this.Value & ~(0x1U << 14)) | ((0x1 & value) << 14); }
public uint Bit15 { get => this.Value >> 15 & 0x1; set => this.Value = (this.Value & ~(0x1U << 15)) | ((0x1 & value) << 15); }
public uint Bit16 { get => this.Value >> 16 & 0x1; set => this.Value = (this.Value & ~(0x1U << 16)) | ((0x1 & value) << 16); }
public uint Bit17 { get => this.Value >> 17 & 0x1; set => this.Value = (this.Value & ~(0x1U << 17)) | ((0x1 & value) << 17); }
public uint Bit18 { get => this.Value >> 18 & 0x1; set => this.Value = (this.Value & ~(0x1U << 18)) | ((0x1 & value) << 18); }
public uint Bit19 { get => this.Value >> 19 & 0x1; set => this.Value = (this.Value & ~(0x1U << 19)) | ((0x1 & value) << 19); }
public uint Bit20 { get => this.Value >> 20 & 0x1; set => this.Value = (this.Value & ~(0x1U << 20)) | ((0x1 & value) << 20); }
public uint Bit21 { get => this.Value >> 21 & 0x1; set => this.Value = (this.Value & ~(0x1U << 21)) | ((0x1 & value) << 21); }
public uint Bit22 { get => this.Value >> 22 & 0x1; set => this.Value = (this.Value & ~(0x1U << 22)) | ((0x1 & value) << 22); }
public uint Bit23 { get => this.Value >> 23 & 0x1; set => this.Value = (this.Value & ~(0x1U << 23)) | ((0x1 & value) << 23); }
public uint Bit24 { get => this.Value >> 24 & 0x1; set => this.Value = (this.Value & ~(0x1U << 24)) | ((0x1 & value) << 24); }
public uint Bit25 { get => this.Value >> 25 & 0x1; set => this.Value = (this.Value & ~(0x1U << 25)) | ((0x1 & value) << 25); }
public uint Bit26 { get => this.Value >> 26 & 0x1; set => this.Value = (this.Value & ~(0x1U << 26)) | ((0x1 & value) << 26); }
public uint Bit27 { get => this.Value >> 27 & 0x1; set => this.Value = (this.Value & ~(0x1U << 27)) | ((0x1 & value) << 27); }
public uint Bit28 { get => this.Value >> 28 & 0x1; set => this.Value = (this.Value & ~(0x1U << 28)) | ((0x1 & value) << 28); }
public uint Bit29 { get => this.Value >> 29 & 0x1; set => this.Value = (this.Value & ~(0x1U << 29)) | ((0x1 & value) << 29); }
public uint Bit30 { get => this.Value >> 30 & 0x1; set => this.Value = (this.Value & ~(0x1U << 30)) | ((0x1 & value) << 30); }
public uint Bit31 { get => this.Value >> 31 & 0x1; set => this.Value = (this.Value & ~(0x1U << 31)) | ((0x1 & value) << 31); }
public static implicit operator Int32BitStruct(uint value) => new Int32BitStruct(value);
public static implicit operator Int32BitStruct(int value) => new Int32BitStruct(value);
public static implicit operator int(Int32BitStruct value) => (int)value.Value;
public static implicit operator uint(Int32BitStruct value) => value.Value;
public static bool operator ==(Int32BitStruct first, Int32BitStruct second)
{
return first.Value == second.Value;
}
public static bool operator !=(Int32BitStruct first, Int32BitStruct second)
{
return first.Value != second.Value;
}
public static bool operator ==(Int32BitStruct first, uint second)
{
return first.Value == second;
}
public static bool operator !=(Int32BitStruct first, uint second)
{
return first.Value != second;
}
public static bool operator ==(Int32BitStruct first, int second)
{
unchecked
{
return first.Value == (uint)second;
}
}
public static bool operator !=(Int32BitStruct first, int second)
{
unchecked
{
return first.Value != (uint)second;
}
}
public static bool operator >=(Int32BitStruct first, Int32BitStruct second)
{
return first.Value >= second.Value;
}
public static bool operator <=(Int32BitStruct first, Int32BitStruct second)
{
return first.Value <= second.Value;
}
public static bool operator >=(Int32BitStruct first, int second)
{
unchecked
{
return first.Value >= (uint)second;
}
}
public static bool operator <=(Int32BitStruct first, int second)
{
unchecked
{
return first.Value <= (uint)second;
}
}
public static bool operator >=(Int32BitStruct first, uint second)
{
return first.Value >= second;
}
public static bool operator <=(Int32BitStruct first, uint second)
{
return first.Value <= second;
}
public static bool operator >(Int32BitStruct first, Int32BitStruct second)
{
return first.Value > second.Value;
}
public static bool operator <(Int32BitStruct first, Int32BitStruct second)
{
return first.Value < second.Value;
}
public static bool operator >(Int32BitStruct first, int second)
{
unchecked
{
return first.Value > (uint)second;
}
}
public static bool operator <(Int32BitStruct first, int second)
{
unchecked
{
return first.Value < (uint)second;
}
}
public static bool operator >(Int32BitStruct first, uint second)
{
return first.Value > second;
}
public static bool operator <(Int32BitStruct first, uint second)
{
return first.Value < second;
}
public bool Equals(Int32BitStruct other)
{
return this.Value == other.Value;
}
public override bool Equals(object obj)
{
if (obj is Int32BitStruct)
{
return this.Equals((Int32BitStruct)obj);
}
else
{
return base.Equals(obj);
}
}
public override int GetHashCode()
{
return (this.Value).GetHashCode();
}
}
}
@@ -0,0 +1,205 @@
using System;
namespace System.Structures.BitStructures
{
public struct Int64BitStruct : IEquatable<Int64BitStruct>
{
public Int64BitStruct(uint low, uint high)
{
this.Value = low + ((ulong)high << 32);
}
public Int64BitStruct(int low, int high)
{
unchecked
{
this.Value = (uint)low + ((ulong)high << 32);
}
}
public Int64BitStruct(long value)
{
unchecked
{
this.Value = (ulong)value;
}
}
public Int64BitStruct(ulong value)
{
this.Value = value;
}
public ulong Value { get; set; }
public uint Low { get => (uint)(this.Value & 0xFFFFFFFF); set => this.Value = (this.Value & ~(0xFFFFFFFF)) | (0xFFFFFFFF & value); }
public uint High { get => (uint)((this.Value >> 32) & 0xFFFFFFFF); set => this.Value = (this.Value & ~(0xFFFFFFFF00000000)) | ((ulong)(0xFFFFFFFF & value) << 32); }
public ulong Bit0 { get => this.Value & 0x1; set => this.Value = (this.Value & ~(0x1UL) | (0x1 & value)); }
public ulong Bit1 { get => this.Value >> 1 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 1)) | ((0x1 & value) << 1); }
public ulong Bit2 { get => this.Value >> 2 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 2)) | ((0x1 & value) << 2); }
public ulong Bit3 { get => this.Value >> 3 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 3)) | ((0x1 & value) << 3); }
public ulong Bit4 { get => this.Value >> 4 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 4)) | ((0x1 & value) << 4); }
public ulong Bit5 { get => this.Value >> 5 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 5)) | ((0x1 & value) << 5); }
public ulong Bit6 { get => this.Value >> 6 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 6)) | ((0x1 & value) << 6); }
public ulong Bit7 { get => this.Value >> 7 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 7)) | ((0x1 & value) << 7); }
public ulong Bit8 { get => this.Value >> 8 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 8)) | ((0x1 & value) << 8); }
public ulong Bit9 { get => this.Value >> 9 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 9)) | ((0x1 & value) << 9); }
public ulong Bit10 { get => this.Value >> 10 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 10)) | ((0x1 & value) << 10); }
public ulong Bit11 { get => this.Value >> 11 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 11)) | ((0x1 & value) << 11); }
public ulong Bit12 { get => this.Value >> 12 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 12)) | ((0x1 & value) << 12); }
public ulong Bit13 { get => this.Value >> 13 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 13)) | ((0x1 & value) << 13); }
public ulong Bit14 { get => this.Value >> 14 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 14)) | ((0x1 & value) << 14); }
public ulong Bit15 { get => this.Value >> 15 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 15)) | ((0x1 & value) << 15); }
public ulong Bit16 { get => this.Value >> 16 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 16)) | ((0x1 & value) << 16); }
public ulong Bit17 { get => this.Value >> 17 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 17)) | ((0x1 & value) << 17); }
public ulong Bit18 { get => this.Value >> 18 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 18)) | ((0x1 & value) << 18); }
public ulong Bit19 { get => this.Value >> 19 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 19)) | ((0x1 & value) << 19); }
public ulong Bit20 { get => this.Value >> 20 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 20)) | ((0x1 & value) << 20); }
public ulong Bit21 { get => this.Value >> 21 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 21)) | ((0x1 & value) << 21); }
public ulong Bit22 { get => this.Value >> 22 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 22)) | ((0x1 & value) << 22); }
public ulong Bit23 { get => this.Value >> 23 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 23)) | ((0x1 & value) << 23); }
public ulong Bit24 { get => this.Value >> 24 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 24)) | ((0x1 & value) << 24); }
public ulong Bit25 { get => this.Value >> 25 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 25)) | ((0x1 & value) << 25); }
public ulong Bit26 { get => this.Value >> 26 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 26)) | ((0x1 & value) << 26); }
public ulong Bit27 { get => this.Value >> 27 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 27)) | ((0x1 & value) << 27); }
public ulong Bit28 { get => this.Value >> 28 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 28)) | ((0x1 & value) << 28); }
public ulong Bit29 { get => this.Value >> 29 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 29)) | ((0x1 & value) << 29); }
public ulong Bit30 { get => this.Value >> 30 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 30)) | ((0x1 & value) << 30); }
public ulong Bit31 { get => this.Value >> 31 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 31)) | ((0x1 & value) << 31); }
public ulong Bit32 { get => this.Value >> 32 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 32)) | ((0x1 & value) << 32); }
public ulong Bit33 { get => this.Value >> 33 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 33)) | ((0x1 & value) << 33); }
public ulong Bit34 { get => this.Value >> 34 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 34)) | ((0x1 & value) << 34); }
public ulong Bit35 { get => this.Value >> 35 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 35)) | ((0x1 & value) << 35); }
public ulong Bit36 { get => this.Value >> 36 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 36)) | ((0x1 & value) << 36); }
public ulong Bit37 { get => this.Value >> 37 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 37)) | ((0x1 & value) << 37); }
public ulong Bit38 { get => this.Value >> 38 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 38)) | ((0x1 & value) << 38); }
public ulong Bit39 { get => this.Value >> 39 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 39)) | ((0x1 & value) << 39); }
public ulong Bit40 { get => this.Value >> 40 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 40)) | ((0x1 & value) << 40); }
public ulong Bit41 { get => this.Value >> 41 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 41)) | ((0x1 & value) << 41); }
public ulong Bit42 { get => this.Value >> 42 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 42)) | ((0x1 & value) << 42); }
public ulong Bit43 { get => this.Value >> 43 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 43)) | ((0x1 & value) << 43); }
public ulong Bit44 { get => this.Value >> 44 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 44)) | ((0x1 & value) << 44); }
public ulong Bit45 { get => this.Value >> 45 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 45)) | ((0x1 & value) << 45); }
public ulong Bit46 { get => this.Value >> 46 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 46)) | ((0x1 & value) << 46); }
public ulong Bit47 { get => this.Value >> 47 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 47)) | ((0x1 & value) << 47); }
public ulong Bit48 { get => this.Value >> 48 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 48)) | ((0x1 & value) << 48); }
public ulong Bit49 { get => this.Value >> 49 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 49)) | ((0x1 & value) << 49); }
public ulong Bit50 { get => this.Value >> 50 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 50)) | ((0x1 & value) << 50); }
public ulong Bit51 { get => this.Value >> 51 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 51)) | ((0x1 & value) << 51); }
public ulong Bit52 { get => this.Value >> 52 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 52)) | ((0x1 & value) << 52); }
public ulong Bit53 { get => this.Value >> 53 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 53)) | ((0x1 & value) << 53); }
public ulong Bit54 { get => this.Value >> 54 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 54)) | ((0x1 & value) << 54); }
public ulong Bit55 { get => this.Value >> 55 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 55)) | ((0x1 & value) << 55); }
public ulong Bit56 { get => this.Value >> 56 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 56)) | ((0x1 & value) << 56); }
public ulong Bit57 { get => this.Value >> 57 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 57)) | ((0x1 & value) << 57); }
public ulong Bit58 { get => this.Value >> 58 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 58)) | ((0x1 & value) << 58); }
public ulong Bit59 { get => this.Value >> 59 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 59)) | ((0x1 & value) << 59); }
public ulong Bit60 { get => this.Value >> 60 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 60)) | ((0x1 & value) << 60); }
public ulong Bit61 { get => this.Value >> 61 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 61)) | ((0x1 & value) << 61); }
public ulong Bit62 { get => this.Value >> 62 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 62)) | ((0x1 & value) << 62); }
public ulong Bit63 { get => this.Value >> 63 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 63)) | ((0x1 & value) << 63); }
public static implicit operator Int64BitStruct(ulong value) => new Int64BitStruct(value);
public static implicit operator Int64BitStruct(long value) => new Int64BitStruct(value);
public static implicit operator long(Int64BitStruct value) => (long)value.Value;
public static implicit operator ulong(Int64BitStruct value) => value.Value;
public static bool operator ==(Int64BitStruct first, Int64BitStruct second)
{
return first.Value == second.Value;
}
public static bool operator !=(Int64BitStruct first, Int64BitStruct second)
{
return first.Value != second.Value;
}
public static bool operator ==(Int64BitStruct first, ulong second)
{
return first.Value == second;
}
public static bool operator !=(Int64BitStruct first, ulong second)
{
return first.Value != second;
}
public static bool operator ==(Int64BitStruct first, long second)
{
unchecked
{
return first.Value == (ulong)second;
}
}
public static bool operator !=(Int64BitStruct first, long second)
{
unchecked
{
return first.Value != (ulong)second;
}
}
public static bool operator >=(Int64BitStruct first, Int64BitStruct second)
{
return first.Value >= second.Value;
}
public static bool operator <=(Int64BitStruct first, Int64BitStruct second)
{
return first.Value <= second.Value;
}
public static bool operator >=(Int64BitStruct first, long second)
{
unchecked
{
return first.Value >= (ulong)second;
}
}
public static bool operator <=(Int64BitStruct first, long second)
{
unchecked
{
return first.Value <= (ulong)second;
}
}
public static bool operator >=(Int64BitStruct first, ulong second)
{
unchecked
{
return first.Value >= second;
}
}
public static bool operator <=(Int64BitStruct first, ulong second)
{
unchecked
{
return first.Value <= second;
}
}
public bool Equals(Int64BitStruct other)
{
return this.Value == other.Value;
}
public override bool Equals(object obj)
{
if (obj is Int64BitStruct)
{
return this.Equals((Int64BitStruct)obj);
}
else
{
return base.Equals(obj);
}
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
}
}
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RootNamespace>System</RootNamespace>
<Version>1.3.1</Version>
<Authors>Alexandru Macocian</Authors>
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<None Include="../LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SystemExtensions.Collections;
using System.Collections.Generic;
namespace SystemExtensions.Threading
namespace System.Threading
{
/// <summary>
/// Threadpool implementation that uses a priority queue as the queue for the tasks to execute.
@@ -17,9 +11,9 @@ namespace SystemExtensions.Threading
{
private class QueueEntry : IComparable<QueueEntry>
{
public TaskPriority TaskPriority;
public WaitCallback WaitCallback;
public Object Object;
public TaskPriority TaskPriority { get; }
public WaitCallback WaitCallback { get; }
public object Object { get; }
public QueueEntry(TaskPriority priority, WaitCallback callback, object obj)
{
this.TaskPriority = priority;
@@ -116,19 +110,22 @@ namespace SystemExtensions.Threading
private volatile List<WorkerThread> threadpool;
private volatile PriorityQueue<QueueEntry> tasks;
private Thread observer;
private CancellationTokenSource observerCancellationTokenSource = new CancellationTokenSource();
private int maxThreads;
private object tasksLock = new object();
private readonly object tasksLock = new object();
private struct WorkerThread
{
public Thread thread;
public bool running, working;
public Thread Thread { get; set; }
public bool Running { get; set; }
public bool Working { get; set; }
public CancellationTokenSource CancellationTokenSource { get; set; }
}
private struct Statistics
{
public bool Initialized;
public int PerformanceCounter;
public DateTime LastUpdate;
public double LoopFrequency;
public bool Initialized { get; set; }
public int PerformanceCounter { get; set; }
public DateTime LastUpdate { get; set; }
public double LoopFrequency { get; set; }
}
#endregion
#region Properties
@@ -139,7 +136,7 @@ namespace SystemExtensions.Threading
{
get
{
return threadpool.Count;
return this.threadpool is null ? 0 : this.threadpool.Count;
}
}
/// <summary>
@@ -149,7 +146,7 @@ namespace SystemExtensions.Threading
{
get
{
return tasks.Count == 0;
return this.tasks is null ? true : this.tasks.Count == 0;
}
}
/// <summary>
@@ -177,24 +174,15 @@ namespace SystemExtensions.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++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread();
}
observer = new Thread(() =>
observer = new Thread(() => ObserverLoop())
{
ObserverLoop();
});
observer.Name = "ThreadPool ObserverThread";
observer.Priority = ThreadPriority.BelowNormal;
Name = "ThreadPool ObserverThread",
Priority = ThreadPriority.BelowNormal
};
observer.Start();
}
/// <summary>
@@ -206,22 +194,11 @@ namespace SystemExtensions.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++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread();
}
observer = new Thread(() =>
{
ObserverLoop();
});
observer = new Thread(() => ObserverLoop());
observer.Name = "ThreadPool ObserverThread";
observer.Priority = ThreadPriority.BelowNormal;
observer.Start();
@@ -239,72 +216,27 @@ namespace SystemExtensions.Threading
{
threadpool = new List<WorkerThread>();
tasks = new PriorityQueue<QueueEntry>();
for(int i = 0; i < lowest; i++)
for (var i = 0; i < lowest; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.Lowest;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.Lowest);
}
for (int i = 0; i < belowNormal; i++)
for (var i = 0; i < belowNormal; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.BelowNormal;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.BelowNormal);
}
for (int i = 0; i < normal; i++)
for (var i = 0; i < normal; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.Normal;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.Normal);
}
for (int i = 0; i < aboveNormal; i++)
for (var i = 0; i < aboveNormal; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.AboveNormal;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.AboveNormal);
}
for (int i = 0; i < highest; i++)
for (var i = 0; i < highest; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.Highest;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.Highest);
}
}
}
#endregion
#region Public Methods
/// <summary>
@@ -315,7 +247,11 @@ namespace SystemExtensions.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);
}
@@ -330,26 +266,56 @@ namespace SystemExtensions.Threading
}
#endregion
#region Private Methods
private void CreateAndStartWorkerThread(ThreadPriority threadPriority)
{
var worker = new WorkerThread();
worker.Thread = new Thread(() => ThreadMainLoop(ref worker));
worker.Thread.Name = "ThreadPool WorkerThread";
worker.Thread.Priority = threadPriority;
worker.Running = true;
worker.CancellationTokenSource = new CancellationTokenSource();
worker.Thread.Start();
threadpool.Add(worker);
}
private void CreateAndStartWorkerThread()
{
var worker = new WorkerThread();
worker.Thread = new Thread(() => ThreadMainLoop(ref worker));
worker.Thread.Name = "ThreadPool WorkerThread";
worker.Running = true;
worker.CancellationTokenSource = new CancellationTokenSource();
worker.Thread.Start();
threadpool.Add(worker);
}
/// <summary>
/// Main loop that a thread from the pool is running.
/// </summary>
/// <threadId>Id of thread</threadId>
private void ThreadMainLoop(ref WorkerThread thisWorkerThread)
{
thisWorkerThread.running = true;
while (thisWorkerThread.running)
thisWorkerThread.Running = true;
while (thisWorkerThread.Running)
{
//Check if there are tasks
if (thisWorkerThread.CancellationTokenSource.Token.IsCancellationRequested)
{
thisWorkerThread.Running = false;
return;
}
//Check if there are tasks
if (tasks.Count > 0)
{
//If there are tasks, acquire a lock onto the list
//and try to dequeue the highest priority task.
//Finally, release the lock and invoke the task.
thisWorkerThread.working = true;
thisWorkerThread.Working = true;
QueueEntry task = null;
while (!Monitor.TryEnter(tasksLock)) ;
while (!Monitor.TryEnter(tasksLock))
{
;
}
if (tasks.Count > 0)
{
task = tasks.Dequeue();
@@ -358,10 +324,10 @@ namespace SystemExtensions.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;
thisWorkerThread.Working = false;
}
}
}
@@ -370,7 +336,7 @@ namespace SystemExtensions.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
@@ -380,11 +346,16 @@ namespace SystemExtensions.Threading
//If counter is under -10, it will try to remove a thread from the threadpool, unless the threadpool has reached less than
//max size / 4.
if (observerCancellationTokenSource.Token.IsCancellationRequested)
{
return;
}
//This part of code updates the statistics of the threadpool.
if (statistics.Initialized)
{
double loopDuration = (DateTime.Now - statistics.LastUpdate).TotalMilliseconds;
if(statistics.LoopFrequency == 0)
var loopDuration = (DateTime.Now - statistics.LastUpdate).TotalMilliseconds;
if (statistics.LoopFrequency == 0)
{
statistics.LoopFrequency = loopDuration;
}
@@ -403,10 +374,10 @@ namespace SystemExtensions.Threading
//This part of code adjusts the performance counter. Ideally, the value should be 0.
if(tasks.Count > 0)
if (tasks.Count > 0)
{
statistics.PerformanceCounter++;
if(statistics.PerformanceCounter > 5)
if (statistics.PerformanceCounter > 5)
{
statistics.PerformanceCounter = 5;
}
@@ -414,18 +385,18 @@ namespace SystemExtensions.Threading
else
{
statistics.PerformanceCounter--;
if(statistics.PerformanceCounter < -10)
if (statistics.PerformanceCounter < -10)
{
statistics.PerformanceCounter = -10;
}
}
//This part of code adjusts thread priorities based on the current performance of the threadpool
if(tasks.Count > 0)
if (tasks.Count > 0)
{
//If there are tasks pending, find a thread with priority under Normal and upgrade its priority.
Thread t = FindThreadWithLowPriority();
if(t != null)
var t = FindThreadWithLowPriority();
if (t != null)
{
UpgradeThreadPriority(t);
}
@@ -433,8 +404,8 @@ namespace SystemExtensions.Threading
else
{
//If there are no tasks pending, find a thread with priority above Lowest and downgrade its priority.
Thread t = FindThreadWithAcceptablePriority();
if(t != null)
var t = FindThreadWithAcceptablePriority();
if (t != null)
{
DowngradeThreadPriority(t);
}
@@ -449,18 +420,10 @@ namespace SystemExtensions.Threading
//Add a thread to the threadpool.
//Reset counter to 0.
statistics.PerformanceCounter = 0;
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread();
}
}
else if(statistics.PerformanceCounter <= -10)
else if (statistics.PerformanceCounter <= -10)
{
if (threadpool.Count > maxThreads / 4)
{
@@ -468,14 +431,14 @@ namespace SystemExtensions.Threading
//If thread is currently working, notify it to close.
//Else, abort the thread.
//Reset counter to 0.
WorkerThread worker = threadpool[threadpool.Count - 1];
if (worker.working)
var worker = threadpool[threadpool.Count - 1];
if (worker.Working)
{
worker.running = false;
worker.Running = false;
}
else
{
worker.thread.Abort();
worker.CancellationTokenSource.Cancel();
}
threadpool.RemoveAt(threadpool.Count - 1);
statistics.PerformanceCounter = 0;
@@ -489,11 +452,11 @@ namespace SystemExtensions.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)
if (t.Thread.Priority == ThreadPriority.Lowest || t.Thread.Priority == ThreadPriority.BelowNormal)
{
return t.thread;
return t.Thread;
}
}
return null;
@@ -504,11 +467,11 @@ namespace SystemExtensions.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)
if (t.Thread.Priority == ThreadPriority.Normal || t.Thread.Priority == ThreadPriority.BelowNormal)
{
return t.thread;
return t.Thread;
}
}
return null;
@@ -574,25 +537,27 @@ namespace SystemExtensions.Threading
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
if (!this.disposedValue)
{
if (disposing)
{
if (observer != null)
if (this.observer != null)
{
observer.Abort();
this.observerCancellationTokenSource.Cancel();
this.observer.Join();
}
foreach (WorkerThread worker in threadpool)
foreach (var worker in threadpool)
{
worker.thread.Abort();
worker.CancellationTokenSource.Cancel();
worker.Thread.Join();
}
threadpool.Clear();
tasks.Clear();
this.threadpool.Clear();
this.tasks.Clear();
}
threadpool = null;
tasks = null;
observer = null;
disposedValue = true;
this.threadpool = null;
this.tasks = null;
this.observer = null;
this.disposedValue = true;
}
}
/// <summary>
@@ -1,14 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class AVLTreeTests
@@ -25,7 +20,7 @@ namespace SystemExtensions.Collections.Tests
{
try
{
for (int i = 0; i < 100; i++)
for (var i = 0; i < 100; i++)
{
avlTree.Add(i * 20 - (50 + i));
}
@@ -43,7 +38,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void ContainsTest()
{
for (int i = 0; i < 100; i++)
for (var i = 0; i < 100; i++)
{
avlTree.Add(i);
}
@@ -57,7 +52,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void RemoveTest()
{
for (int i = 0; i < 100; i++)
for (var i = 0; i < 100; i++)
{
avlTree.Add(i);
}
@@ -73,7 +68,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void ClearTest()
{
for (int i = 0; i < 100; i++)
for (var i = 0; i < 100; i++)
{
avlTree.Add(i);
}
@@ -87,24 +82,24 @@ namespace SystemExtensions.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);
@@ -119,34 +114,34 @@ namespace SystemExtensions.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)
{
@@ -1,16 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class BinaryHeapTests
@@ -38,7 +31,7 @@ namespace SystemExtensions.Collections.Tests
{
try
{
for (int i = 0; i < 100; i++)
for (var i = 0; i < 100; i++)
{
binaryHeap.Add(i * 20 - (50 + i));
}
@@ -59,7 +52,7 @@ namespace SystemExtensions.Collections.Tests
{
try
{
int tries = binaryHeap.Count;
var tries = binaryHeap.Count;
while (binaryHeap.Count > 0)
{
if (tries == 0)
@@ -79,7 +72,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void MinMaxTest()
{
for (int i = 0; i < 1000; i++)
for (var i = 0; i < 1000; i++)
{
binaryHeap.Add(i);
}
@@ -92,7 +85,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void ClearTest()
{
for (int i = 0; i < 100; i++)
for (var i = 0; i < 100; i++)
{
binaryHeap.Add(i);
}
@@ -106,13 +99,13 @@ namespace SystemExtensions.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();
if (binaryHeap.Count > 0 || binaryHeap.Capacity != 10)
var array = binaryHeap.ToArray();
if (binaryHeap.Count > 0 || binaryHeap.Capacity == 10)
{
Assert.Fail();
}
@@ -140,11 +133,11 @@ namespace SystemExtensions.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();
@@ -158,12 +151,12 @@ namespace SystemExtensions.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++;
@@ -180,22 +173,22 @@ namespace SystemExtensions.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)
{
@@ -1,15 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class FibonacciHeapTests
@@ -18,7 +12,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void InsertTest()
{
for (int i = 0; i < 1000; i++)
for (var i = 0; i < 1000; i++)
{
fibonacciHeap.Add(i);
}
@@ -37,21 +31,21 @@ namespace SystemExtensions.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))
{
@@ -76,11 +70,11 @@ namespace SystemExtensions.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)
{
@@ -110,7 +104,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void ContainsTest()
{
for(int i = 0; i < 10000; i++)
for(var i = 0; i < 10000; i++)
{
fibonacciHeap.Add(i);
}
@@ -123,7 +117,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void ClearTest()
{
for(int i = 0; i < 10000; i++)
for(var i = 0; i < 10000; i++)
{
fibonacciHeap.Add(i);
}
@@ -138,14 +132,14 @@ namespace SystemExtensions.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)
{
@@ -157,14 +151,14 @@ namespace SystemExtensions.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++;
@@ -181,23 +175,23 @@ namespace SystemExtensions.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)
{
@@ -1,15 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class PriorityQueueTests
@@ -35,7 +29,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void EnqueueTest()
{
for(int i = 0; i < 100; i++)
for(var i = 0; i < 100; i++)
{
priorityQueue.Enqueue(i);
}
@@ -48,11 +42,11 @@ namespace SystemExtensions.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())
{
@@ -87,23 +81,23 @@ namespace SystemExtensions.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)
{
@@ -1,14 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class SkipListTests
@@ -17,19 +12,19 @@ namespace SystemExtensions.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);
}
@@ -38,7 +33,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void ClearTest()
{
for (int i = 0; i < 200; i++)
for (var i = 0; i < 200; i++)
{
skipList.Add(i);
}
@@ -52,7 +47,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void ContainsTest()
{
for (int i = 0; i < 200; i++)
for (var i = 0; i < 200; i++)
{
skipList.Add(i);
}
@@ -66,13 +61,13 @@ namespace SystemExtensions.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)
{
@@ -84,13 +79,13 @@ namespace SystemExtensions.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)
{
@@ -102,12 +97,12 @@ namespace SystemExtensions.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);
}
@@ -116,7 +111,7 @@ namespace SystemExtensions.Collections.Tests
[TestMethod()]
public void RemoveTest()
{
for (int i = 0; i < 200; i++)
for (var i = 0; i < 200; i++)
{
skipList.Add(i);
}
@@ -128,25 +123,26 @@ namespace SystemExtensions.Collections.Tests
}
[TestMethod()]
[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)
{
@@ -1,14 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class TreapTests
@@ -23,8 +18,8 @@ namespace SystemExtensions.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));
}
@@ -46,8 +41,8 @@ namespace SystemExtensions.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));
}
@@ -76,12 +71,12 @@ namespace SystemExtensions.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)
{
@@ -93,13 +88,13 @@ namespace SystemExtensions.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++;
@@ -114,25 +109,26 @@ namespace SystemExtensions.Collections.Tests
}
[TestMethod()]
[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,111 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Extensions.Tests
{
[TestClass]
public class OptionalTests
{
[TestMethod]
public void SomeValueShouldEqualOptional()
{
var value = string.Empty;
var optional = value.ToOptional();
Assert.IsTrue(optional.Equals(value));
}
[TestMethod]
public void OptionalFromNullShouldNotEqual()
{
object value = null;
var optional = value.ToOptional();
Assert.IsFalse(optional.Equals(value));
}
[TestMethod]
public void OptionalFromValueShouldBeSome()
{
var optional = Optional.FromValue<object>(new object());
optional.DoAny(
onNone: () => throw new InvalidOperationException());
}
[TestMethod]
public void OptionalFromNullShouldBeNone()
{
var optional = Optional.FromValue<object>(null);
optional.DoAny(
onSome: _ => throw new InvalidOperationException());
}
[TestMethod]
public void DoShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
optional.Do(
onSome: _ => { },
onNone: () => throw new InvalidOperationException());
nullOptional.Do(
onSome: _ => throw new InvalidOperationException(),
onNone: () => { });
}
[TestMethod]
public void DoAnyShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
optional.DoAny(
onNone: () => throw new InvalidOperationException());
nullOptional.DoAny(
onSome: _ => throw new InvalidOperationException());
}
[TestMethod]
public void SwitchShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
var newValue = optional.Switch(
onSome: _ => string.Empty,
onNone: () => throw new InvalidOperationException())
.ExtractValue();
var newNullValue = nullOptional.Switch<string>(
onSome: _ => throw new InvalidOperationException(),
onNone: () => null)
.ExtractValue();
newValue.Should().Be(string.Empty);
newNullValue.Should().Be(null);
}
[TestMethod]
public void SwitchAnyShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
var newValue = optional.SwitchAny(
onSome: _ => string.Empty)
.ExtractValue();
var newNullValue = nullOptional.SwitchAny<string>(
onNone: () => null)
.ExtractValue();
newValue.Should().Be(string.Empty);
newNullValue.Should().Be(null);
}
}
}
@@ -0,0 +1,117 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Extensions.Tests
{
[TestClass]
public class ResultTests
{
[TestMethod]
public void SuccessResultShouldCreateFromSuccess()
{
var success = string.Empty;
var result = Result<string, object>.Success(success);
result.DoAny(
onFailure: () => throw new InvalidOperationException());
}
[TestMethod]
public void FailureResultShouldCreateFromFailure()
{
var failure = new object();
var result = Result<string, object>.Failure(failure);
result.DoAny(
onSuccess: () => throw new InvalidOperationException());
}
[TestMethod]
public void DoShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
successResult.Do(
onSuccess: _ => { },
onFailure: _ => throw new InvalidOperationException());
failedResult.Do(
onSuccess: _ => throw new InvalidOperationException(),
onFailure: _ => { });
}
[TestMethod]
public void DoAnyShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
successResult.DoAny(
onSuccess: _ => { });
failedResult.DoAny(
onFailure: _ => { });
}
[TestMethod]
public void SwitchShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
var successSwitch = successResult.Switch(
onSuccess: _ => string.Empty,
onFailure: _ => throw new InvalidOperationException());
var failedSwitch = failedResult.Switch(
onSuccess: _ => throw new InvalidOperationException(),
onFailure: _ => string.Empty);
success.Should().Be(failedSwitch);
}
[TestMethod]
public void SwitchAnyShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
var successSwitch = successResult.SwitchAny(
onSuccess: _ => string.Empty);
var failedSwitch = failedResult.SwitchAny(
onFailure: _ => string.Empty);
success.Should().Be(failedSwitch);
}
[TestMethod]
public void ToOptionalShouldConvert()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
var successOptional = successResult.ToOptional();
var failureOptional = failedResult.ToOptional();
successOptional.Should().NotBeNull();
failureOptional.Should().NotBeNull();
}
}
}
@@ -0,0 +1,321 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Http;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using SystemExtensionsTests.Utils;
namespace SystemExtensionsTests.Http
{
[TestClass]
public class HttpClientTests
{
private const string resourceUrl = "resource";
private static readonly Uri TestAddressUrl = new("https://helloworld.xyz");
private readonly MockHttpMessageHandler handler = new();
private IHttpClient<object> httpClient;
[TestInitialize]
public void TestInitialize()
{
this.httpClient = new HttpClient<object>(this.handler, false)
{
BaseAddress = TestAddressUrl
};
}
[TestMethod]
public async Task HttpClientEmitsCorrectMessages()
{
var messagesEmitted = 0;
this.httpClient.EventEmitted += (sender, message) =>
{
messagesEmitted++;
message.Scope.Should().Be(typeof(object));
message.Method.Should().Be("GetAsync");
message.Url.Should().Be(TestAddressUrl.ToString());
};
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
await this.httpClient.GetAsync(TestAddressUrl);
messagesEmitted.Should().Be(1);
}
[TestMethod]
public void SetBaseAddress()
{
this.httpClient.BaseAddress = TestAddressUrl;
this.httpClient.BaseAddress.Should().Be(TestAddressUrl);
}
[TestMethod]
public void SetDefaultRequestHeaders()
{
this.httpClient.DefaultRequestHeaders.TryAddWithoutValidation("someheader", "thisvalue");
this.httpClient.DefaultRequestHeaders.GetValues("someheader").Should().BeEquivalentTo("thisvalue");
}
[TestMethod]
public void SetMaxResponseContentBufferSize()
{
this.httpClient.MaxResponseContentBufferSize = 2000;
this.httpClient.MaxResponseContentBufferSize.Should().Be(2000);
}
[TestMethod]
public void SetTimeout()
{
this.httpClient.Timeout = TimeSpan.FromSeconds(1);
this.httpClient.Timeout.Should().Be(TimeSpan.FromSeconds(1));
}
[TestMethod]
public async Task DeleteAsyncStringReturns200()
{
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK);
var response = await this.httpClient.DeleteAsync(resourceUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
public async Task DeleteAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.DeleteAsync(TestAddressUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task DeleteAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.DeleteAsync(TestAddressUrl, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task GetAsyncStringReturns200()
{
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK);
var response = await this.httpClient.GetAsync(resourceUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
public async Task GetAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.GetAsync(TestAddressUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task GetAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.GetAsync(TestAddressUrl, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task PostAsyncStringReturns200()
{
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK);
var response = await this.httpClient.PostAsync(resourceUrl, null);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
public async Task PostAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.PostAsync(TestAddressUrl, null);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task PostAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.PostAsync(TestAddressUrl, null, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task SendAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.SendAsync(new HttpRequestMessage { RequestUri = TestAddressUrl });
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task SendAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.SendAsync(new HttpRequestMessage { RequestUri = TestAddressUrl }, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task GetStreamAsyncStringReturns200()
{
var ms = new MemoryStream(new byte[] { 13, 10, 11, 12 });
var sc = new StreamContent(ms);
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStreamAsync(resourceUrl);
var responseBuffer = new byte[4];
await response.ReadAsync(responseBuffer, 0, 4);
responseBuffer[0].Should().Be(13);
responseBuffer[1].Should().Be(10);
responseBuffer[2].Should().Be(11);
responseBuffer[3].Should().Be(12);
}
[TestMethod]
public async Task GetStreamAsyncUriReturns200()
{
var ms = new MemoryStream(new byte[] { 13, 10, 11, 12 });
var sc = new StreamContent(ms);
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStreamAsync(TestAddressUrl);
var responseBuffer = new byte[4];
await response.ReadAsync(responseBuffer, 0, 4);
responseBuffer[0].Should().Be(13);
responseBuffer[1].Should().Be(10);
responseBuffer[2].Should().Be(11);
responseBuffer[3].Should().Be(12);
}
[TestMethod]
public async Task GetStringAsyncStringReturns200()
{
var sc = new StringContent("hello");
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStringAsync(resourceUrl);
response.Should().Be("hello");
}
[TestMethod]
public async Task GetStringAsyncUriReturns200()
{
var sc = new StringContent("hello");
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStringAsync(TestAddressUrl);
response.Should().Be("hello");
}
[TestMethod]
public async Task GetByteArrayAsyncStringReturns200()
{
var sc = new ByteArrayContent(new byte[4] { 13, 10, 11, 12 });
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK, sc);
var response = await this.httpClient.GetByteArrayAsync(resourceUrl);
response[0].Should().Be(13);
response[1].Should().Be(10);
response[2].Should().Be(11);
response[3].Should().Be(12);
}
[TestMethod]
public async Task GetByteArrayAsyncUriReturns200()
{
var sc = new ByteArrayContent(new byte[4] { 13, 10, 11, 12 });
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK, sc);
var response = await this.httpClient.GetByteArrayAsync(TestAddressUrl);
response[0].Should().Be(13);
response[1].Should().Be(10);
response[2].Should().Be(11);
response[3].Should().Be(12);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task CancelPendingRequestThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var responseTask = this.httpClient.GetAsync(TestAddressUrl);
this.httpClient.CancelPendingRequests();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
private void SetupResponse(Uri expectedUri, HttpStatusCode statusCode, HttpContent httpContent = null)
{
this.handler.ResponseResolver = (request) =>
{
request.RequestUri.Should().Be(expectedUri);
return new HttpResponseMessage { StatusCode = statusCode, Content = httpContent };
};
}
private void SetupLongResponse(Uri expectedUri, HttpStatusCode statusCode, HttpContent httpContent = null)
{
this.handler.ResponseResolverAsync = async (request) =>
{
request.RequestUri.Should().Be(expectedUri);
for (var i = 0; i < 10; i++)
{
await Task.Delay(100);
}
return new HttpResponseMessage { StatusCode = statusCode, Content = httpContent };
};
}
}
}
@@ -0,0 +1,72 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Structures.BitStructures.Tests
{
[TestClass]
public class Int32BitStructTests
{
[DataTestMethod]
[DataRow(-1)]
[DataRow(int.MaxValue)]
public void TestSetValueInt(int value)
{
Int32BitStruct int32 = value;
Assert.IsTrue(int32 == value);
}
[DataTestMethod]
[DataRow(1)]
public void TestSetValueUint(int value)
{
Int32BitStruct int32 = value;
Assert.IsTrue(int32 == value);
}
public void TestSetMaxValueUint()
{
Int32BitStruct int32 = uint.MaxValue;
Assert.IsTrue(int32 == uint.MaxValue);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(int.MaxValue)]
[DataRow(int.MinValue)]
public void TestGetBit(int value)
{
Int32BitStruct int32 = value;
Assert.IsTrue(value >= 0 ? int32.Bit31 == 0 : int32.Bit31 == 1);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(1)]
public void TestSetBit(int value)
{
Int32BitStruct int32 = 0;
int32.Bit0 = (uint)value;
Assert.IsTrue(int32 == value);
}
[TestMethod]
public void TestUseCaseExample()
{
// Set value = -1, represented as MSB being 1 and the rest 0.
Int32BitStruct int32 = int.MinValue;
// Test that MSB is 1.
Assert.IsTrue(int32.Bit31 == 1);
// Set MSB to 0 and test that everything else is 0.
int32.Bit31 = 0;
Assert.IsTrue(int32 == 0);
// Set the least 31 significant bits (all besides MSB) to 1.
int32 = int.MaxValue;
// Set the MSB to 1 and test that everything is 1.
int32.Bit31 = 1;
Assert.IsTrue(int32 == uint.MaxValue);
}
}
}
@@ -0,0 +1,108 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Structures.BitStructures.Tests
{
[TestClass]
public class Int64BitStructTests
{
[DataTestMethod]
[DataRow(-1L)]
[DataRow(long.MaxValue)]
public void TestSetValueInt(long value)
{
Int64BitStruct int64 = value;
Assert.IsTrue(int64 == value);
}
[DataTestMethod]
[DataRow(1UL)]
public void TestSetValueUint(long value)
{
Int64BitStruct int64 = value;
Assert.IsTrue(int64 == value);
}
[TestMethod]
public void TestSetMaxValueUint()
{
Int64BitStruct int64 = ulong.MaxValue;
Assert.IsTrue(int64 == ulong.MaxValue);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(long.MaxValue)]
[DataRow(long.MinValue)]
public void TestGetBit(long value)
{
Int64BitStruct int64 = value;
Assert.IsTrue(value >= 0L ? int64.Bit63 == 0 : int64.Bit63 == 1);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(1)]
public void TestSetBit(long value)
{
Int64BitStruct int64 = 0L;
int64.Bit0 = (ulong)value;
Assert.IsTrue(int64 == value);
}
[DataTestMethod]
[DataRow(int.MaxValue, int.MinValue)]
public void TestLowHigh(int low, int high)
{
var int64 = new Int64BitStruct(low, high);
Int32BitStruct lowStruct = low;
Int32BitStruct highStruct = high;
Assert.IsTrue(int64.Low == lowStruct);
Assert.IsTrue(int64.High == highStruct);
unchecked
{
Assert.IsTrue(int64 == ((ulong)low + ((ulong)high << 32)));
}
}
[TestMethod]
public void TestUseCaseExample()
{
// Set value = -1, represented as MSB being 1 and the rest 0.
Int64BitStruct int64 = long.MinValue;
// Test that MSB is 1.
Assert.IsTrue(int64.Bit63 == 1);
// Set MSB to 0 and test that everything else is 0.
int64.Bit63 = 0;
Assert.IsTrue(int64 == 0UL);
// Set the least 31 significant bits (all besides MSB) to 1.
int64 = long.MaxValue;
// Set the MSB to 1 and test that everything is 1.
int64.Bit63 = 1;
Assert.IsTrue(int64 == ulong.MaxValue);
}
[TestMethod]
public void TestUseCaseExample2()
{
// Set all bits to 1. Check low and high values to be equal to having all 32 bits set.
Int64BitStruct int64 = ulong.MaxValue;
Assert.IsTrue(int64.Low == uint.MaxValue && int64.High == uint.MaxValue);
// Set all 63 least significant bits to 1 and MSB to 0.
int64 = long.MaxValue;
Assert.IsTrue(int64.Bit63 == 0);
// Check that high has all bits besides MSB set to 1 and that low has all bits set to 1.
Assert.IsTrue(int64.High == int.MaxValue && int64.Low == uint.MaxValue);
// Set the MSB back to 1 and check that all bits are set to 1.
int64.Bit63 = 1;
Assert.IsTrue(int64 == ulong.MaxValue);
Assert.IsTrue(int64.High == uint.MaxValue && int64.Low == uint.MaxValue);
}
}
}
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.4" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.4" />
<PackageReference Include="coverlet.collector" Version="3.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj" />
</ItemGroup>
</Project>
@@ -1,15 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using static SystemExtensions.Threading.PriorityThreadPool;
using static System.Threading.PriorityThreadPool;
namespace SystemExtensions.Threading.Tests
namespace System.Threading.Tests
{
[TestClass()]
public class PriorityThreadPoolTests
@@ -22,7 +14,7 @@ namespace SystemExtensions.Threading.Tests
{
threadPool.Dispose();
threadPool = new PriorityThreadPool();
if (threadPool.NumberOfThreads != System.Environment.ProcessorCount)
if (threadPool.NumberOfThreads != Environment.ProcessorCount)
{
Assert.Fail();
}
@@ -57,7 +49,7 @@ namespace SystemExtensions.Threading.Tests
Thread.Sleep(100);
try
{
int x = threadPool.NumberOfThreads;
var x = threadPool.NumberOfThreads;
Assert.Fail();
}
catch(Exception e)
@@ -71,17 +63,17 @@ namespace SystemExtensions.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);
@@ -106,11 +98,11 @@ namespace SystemExtensions.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);
}
@@ -134,11 +126,11 @@ namespace SystemExtensions.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)
{
@@ -161,7 +153,7 @@ namespace SystemExtensions.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);
@@ -176,9 +168,9 @@ namespace SystemExtensions.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;
@@ -0,0 +1,29 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace SystemExtensionsTests.Utils
{
public sealed class MockHttpMessageHandler : HttpMessageHandler
{
public Func<HttpRequestMessage, HttpResponseMessage> ResponseResolver { get; set; }
public Func<HttpRequestMessage, Task<HttpResponseMessage>> ResponseResolverAsync { get; set; }
public MockHttpMessageHandler()
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (this.ResponseResolver is object)
{
return Task.FromResult(this.ResponseResolver(request));
}
else
{
return this.ResponseResolverAsync(request);
}
}
}
}
+39 -12
View File
@@ -1,11 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.572
# Visual Studio Version 16
VisualStudioVersion = 16.0.31005.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions", "SystemExtensions\SystemExtensions.csproj", "{55850FF3-70E4-4828-BEEE-39837AC0D24C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard", "SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj", "{4CE9E55C-6016-4631-B8D4-4D763DD05F23}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensionsTests", "SystemExtensionsTests\SystemExtensionsTests.csproj", "{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.Tests", "SystemExtensions.Tests\SystemExtensions.NetStandard.Tests.csproj", "{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}"
ProjectSection(ProjectDependencies) = postProject
{4CE9E55C-6016-4631-B8D4-4D763DD05F23} = {4CE9E55C-6016-4631-B8D4-4D763DD05F23}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.DependencyInjection", "SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj", "{53510F19-2E51-423A-BE79-5DE66103E7FC}"
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}"
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}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -13,14 +24,30 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Release|Any CPU.Build.0 = Release|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Release|Any CPU.Build.0 = Release|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Release|Any CPU.Build.0 = Release|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Release|Any CPU.Build.0 = Release|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Release|Any CPU.Build.0 = Release|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Release|Any CPU.Build.0 = Release|Any CPU
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Release|Any CPU.Build.0 = Release|Any CPU
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
-39
View File
@@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions
{
/// <summary>
/// Custom implementation of an exception.
/// </summary>
public class ItemNotFoundException : Exception
{
/// <summary>
/// Initializes a new instance of ItemNotFoundException.
/// </summary>
public ItemNotFoundException()
{
}
/// <summary>
/// Initializes a new instance of ItemNotFoundException with a specified error.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ItemNotFoundException(string message) : base(message)
{
}
/// <summary>
/// Initializes a new instance of ItemNotFoundException with a specified error and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or null in case there is no inner exception.</param>
public ItemNotFoundException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SystemExtensions")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SystemExtensions")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("55850ff3-70e4-4828-beee-39837ac0d24c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
-61
View File
@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{55850FF3-70E4-4828-BEEE-39837AC0D24C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SystemExtensions</RootNamespace>
<AssemblyName>SystemExtensions</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\SystemExtensions.xml</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Collections\AVLTree.cs" />
<Compile Include="Collections\BinaryHeap.cs" />
<Compile Include="Collections\FibonacciHeap.cs" />
<Compile Include="Collections\IQueue.cs" />
<Compile Include="Collections\PriorityQueue.cs" />
<Compile Include="Collections\SkipList.cs" />
<Compile Include="Collections\Treap.cs" />
<Compile Include="ItemNotFoundException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Threading\PriorityThreadPool.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SystemExtensionsTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SystemExtensionsTests")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f9b61261-0a08-4b53-baea-44e05dbbbfe5")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,113 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SystemExtensionsTests</RootNamespace>
<AssemblyName>SystemExtensionsTests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise />
</Choose>
<ItemGroup>
<Compile Include="Collections\AVLTreeTests.cs" />
<Compile Include="Collections\BinaryHeapTests.cs" />
<Compile Include="Collections\FibonacciHeapTests.cs" />
<Compile Include="Collections\PriorityQueueTests.cs" />
<Compile Include="Collections\SkipListTests.cs" />
<Compile Include="Collections\TreapTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Threading\PriorityThreadPoolTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions\SystemExtensions.csproj">
<Project>{55850ff3-70e4-4828-beee-39837ac0d24c}</Project>
<Name>SystemExtensions</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net461" />
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net461" />
</packages>