diff --git a/build.fsx b/build.fsx
index 4a081c5..54806d5 100644
--- a/build.fsx
+++ b/build.fsx
@@ -10,13 +10,13 @@ open Fake.DotNetCli
open Fake.DocFxHelper
// Information about the project for Nuget and Assembly info files
-let product = "Akka.Streams.Kafka"
+let product = "Helios.DedicatedThreadPool"
let configuration = "Release"
// Metadata used when signing packages and DLLs
-let signingName = "Akka.Streams.Kafka"
-let signingDescription = "Apache Kafka adapter for Akka.NET Streams"
-let signingUrl = "https://github.com/akkadotnet/Akka.Streams.Kafka"
+let signingName = "Helios.DedicatedThreadPool"
+let signingDescription = "Stand-alone .NET Threadpool"
+let signingUrl = "https://github.com/helios-io/DedicatedThreadPool"
// Read release notes and version
let codeDirectory = __SOURCE_DIRECTORY__ @@ "src"
@@ -24,22 +24,26 @@ let solutionFile = FindFirstMatchingFile "*.sln" codeDirectory // dynamically l
let buildNumber = environVarOrDefault "BUILD_NUMBER" "0"
let hasTeamCity = (not (buildNumber = "0")) // check if we have the TeamCity environment variable for build # set
let preReleaseVersionSuffix = "beta" + (if (not (buildNumber = "0")) then (buildNumber) else DateTime.UtcNow.Ticks.ToString())
+let versionSuffix =
+ match (getBuildParam "nugetprerelease") with
+ | "dev" -> preReleaseVersionSuffix
+ | "" -> ""
+ | str -> str
let releaseNotes =
File.ReadLines (__SOURCE_DIRECTORY__ @@ "RELEASE_NOTES.md")
|> ReleaseNotesHelper.parseReleaseNotes
+let dockerTagVersion =
+ match versionSuffix with
+ | "" -> releaseNotes.AssemblyVersion
+ | str -> releaseNotes.AssemblyVersion + "-" + versionSuffix
+
let versionFromReleaseNotes =
match releaseNotes.SemVer.PreRelease with
| Some r -> r.Origin
| None -> ""
-let versionSuffix =
- match (getBuildParam "nugetprerelease") with
- | "dev" -> preReleaseVersionSuffix
- | "" -> versionFromReleaseNotes
- | str -> str
-
// Directories
let toolsDir = __SOURCE_DIRECTORY__ @@ "tools"
let output = __SOURCE_DIRECTORY__ @@ "bin"
@@ -252,6 +256,92 @@ Target "PublishNuget" (fun _ ->
projects |> Seq.iter (runSingleProject)
)
+//--------------------------------------------------------------------------------
+// Docker images
+//--------------------------------------------------------------------------------
+let GetDockerProjects =
+ let dockerFiles = !! "src/**/Dockerfile" // folders with Dockerfiles in it
+
+ let projects = dockerFiles
+ |> Seq.map (fun dFile -> Path.GetDirectoryName(dFile))
+ |> Seq.map (fun folder -> !! (folder + "/*.csproj"))
+ |> Seq.concat
+
+ projects
+
+Target "PublishCode" (fun _ ->
+ ActivateFinalTarget "KillCreatedProcesses"
+ let projects = GetDockerProjects
+
+ let runSingleProject project =
+ DotNetCli.Publish
+ (fun p ->
+ { p with
+ Project = project
+ Configuration = configuration
+ })
+
+ projects|> Seq.iter (runSingleProject)
+)
+
+let mapDockerImageName (projectName:string) =
+ match projectName with
+ | str -> Some(str.ToLowerInvariant())
+
+Target "BuildDockerImages" (fun _ ->
+ let projects = GetDockerProjects
+
+ let remoteRegistryUrl = getBuildParamOrDefault "remoteRegistry" ""
+
+ let composedGetFileNameWithoutExtension (p:string) =
+ System.IO.Path.GetFileNameWithoutExtension p
+
+ let buildDockerImage imageName projectPath =
+
+ let args =
+ if(hasBuildParam "remoteRegistry") then
+ StringBuilder()
+ |> append "build"
+ |> append "-t"
+ |> append (imageName + ":" + dockerTagVersion)
+ |> append "-t"
+ |> append (imageName + ":latest")
+ |> append "-t"
+ |> append (remoteRegistryUrl + "/" + imageName + ":" + dockerTagVersion)
+ |> append "-t"
+ |> append (remoteRegistryUrl + "/" + imageName + ":latest")
+ |> append "."
+ |> toText
+ else
+ StringBuilder()
+ |> append "build"
+ |> append "-t"
+ |> append (imageName + ":" + dockerTagVersion)
+ |> append "-t"
+ |> append (imageName + ":latest")
+ |> append "."
+ |> toText
+
+ let composedGetDirName (p:string) =
+ System.IO.Path.GetDirectoryName p
+
+
+ ExecProcess(fun info ->
+ info.FileName <- "docker"
+ info.WorkingDirectory <- composedGetDirName projectPath
+ info.Arguments <- args) (System.TimeSpan.FromMinutes 5.0) (* Reasonably long-running task. *)
+
+ let runSingleProject project =
+ let projectName = composedGetFileNameWithoutExtension project
+ let imageName = mapDockerImageName projectName
+ let result = match imageName with
+ | None -> 0
+ | Some(name) -> buildDockerImage name project
+ if result <> 0 then failwithf "docker build failed. %s" project
+
+ projects |> Seq.iter (runSingleProject)
+)
+
//--------------------------------------------------------------------------------
// Documentation
//--------------------------------------------------------------------------------
@@ -308,6 +398,7 @@ Target "Help" <| fun _ ->
Target "BuildRelease" DoNothing
Target "All" DoNothing
+Target "Docker" DoNothing
Target "Nuget" DoNothing
// build dependencies
@@ -323,6 +414,9 @@ Target "Nuget" DoNothing
// docs
"Clean" ==> "RestorePackages" ==> "BuildRelease" ==> "Docfx"
+// Docker
+"BuildRelease" ==> "PublishCode" ==> "BuildDockerImages" ==> "Docker"
+
// all
"BuildRelease" ==> "All"
"RunTests" ==> "All"
diff --git a/src/.dockerignore b/src/.dockerignore
new file mode 100644
index 0000000..3729ff0
--- /dev/null
+++ b/src/.dockerignore
@@ -0,0 +1,25 @@
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/azds.yaml
+**/bin
+**/charts
+**/docker-compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md
\ No newline at end of file
diff --git a/src/Helios.DedicatedThreadPool.sln b/src/Helios.DedicatedThreadPool.sln
index b918e85..4ac5f45 100644
--- a/src/Helios.DedicatedThreadPool.sln
+++ b/src/Helios.DedicatedThreadPool.sln
@@ -1,11 +1,11 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.24720.0
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool", "core\Helios.DedicatedThreadPool\Helios.DedicatedThreadPool.csproj", "{6C8F359E-E479-44D5-8FA0-02BFD38C3860}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool", "core\Helios.DedicatedThreadPool\Helios.DedicatedThreadPool.csproj", "{6C8F359E-E479-44D5-8FA0-02BFD38C3860}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool.Tests", "tests\Helios.DedicatedThreadPool.Tests\Helios.DedicatedThreadPool.Tests.csproj", "{BD7B3C66-14D8-4F01-AECE-F7F3F440A899}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool.Tests", "tests\Helios.DedicatedThreadPool.Tests\Helios.DedicatedThreadPool.Tests.csproj", "{BD7B3C66-14D8-4F01-AECE-F7F3F440A899}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{741F51D5-FB48-4AE3-837E-3C32FAC6584E}"
EndProject
@@ -23,7 +23,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{39EF5B
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool.Tests.Performance", "tests\Helios.DedicatedThreadPool.Tests.Performance\Helios.DedicatedThreadPool.Tests.Performance.csproj", "{428DF580-1734-4AB6-B80E-F5ABABCE61D6}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool.Tests.Performance", "tests\Helios.DedicatedThreadPool.Tests.Performance\Helios.DedicatedThreadPool.Tests.Performance.csproj", "{428DF580-1734-4AB6-B80E-F5ABABCE61D6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool.IdleCpu.Program", "tests\Helios.DedicatedThreadPool.IdleCpu.Program\Helios.DedicatedThreadPool.IdleCpu.Program.csproj", "{876973A9-060F-402E-9434-733F8320AA6B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool.IdleCpu.Tests", "tests\Helios.DedicatedThreadPool.IdleCpu.Tests\Helios.DedicatedThreadPool.IdleCpu.Tests.csproj", "{F0A0B730-337D-4FE2-AA41-54535CF70726}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -43,6 +47,14 @@ Global
{428DF580-1734-4AB6-B80E-F5ABABCE61D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{428DF580-1734-4AB6-B80E-F5ABABCE61D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{428DF580-1734-4AB6-B80E-F5ABABCE61D6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {876973A9-060F-402E-9434-733F8320AA6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {876973A9-060F-402E-9434-733F8320AA6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {876973A9-060F-402E-9434-733F8320AA6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {876973A9-060F-402E-9434-733F8320AA6B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F0A0B730-337D-4FE2-AA41-54535CF70726}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F0A0B730-337D-4FE2-AA41-54535CF70726}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F0A0B730-337D-4FE2-AA41-54535CF70726}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F0A0B730-337D-4FE2-AA41-54535CF70726}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -51,5 +63,10 @@ Global
{6C8F359E-E479-44D5-8FA0-02BFD38C3860} = {E86B275F-E912-47C5-8F5E-BA62D5959EBD}
{BD7B3C66-14D8-4F01-AECE-F7F3F440A899} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
{428DF580-1734-4AB6-B80E-F5ABABCE61D6} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
+ {876973A9-060F-402E-9434-733F8320AA6B} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
+ {F0A0B730-337D-4FE2-AA41-54535CF70726} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DD52A4C9-1308-4946-82E0-9AD4884CAA85}
EndGlobalSection
EndGlobal
diff --git a/src/core/Helios.DedicatedThreadPool/Helios.Concurrency.DedicatedThreadPool.cs b/src/core/Helios.DedicatedThreadPool/Helios.Concurrency.DedicatedThreadPool.cs
index b45310c..977792f 100644
--- a/src/core/Helios.DedicatedThreadPool/Helios.Concurrency.DedicatedThreadPool.cs
+++ b/src/core/Helios.DedicatedThreadPool/Helios.Concurrency.DedicatedThreadPool.cs
@@ -304,18 +304,18 @@ public void Dispose()
///
/// TBD
///
- public void WaitForThreadsExit()
+ public async Task WaitForThreadsExit()
{
- WaitForThreadsExit(Timeout.InfiniteTimeSpan);
+ await WaitForThreadsExit(Timeout.InfiniteTimeSpan);
}
///
/// TBD
///
/// TBD
- public void WaitForThreadsExit(TimeSpan timeout)
+ public async Task WaitForThreadsExit(TimeSpan timeout)
{
- Task.WaitAll(_workers.Select(worker => worker.ThreadExit).ToArray(), timeout);
+ await Task.WhenAll(_workers.Select(worker => worker.ThreadExit));
}
#region Pool worker implementation
diff --git a/src/core/Helios.DedicatedThreadPool/_Visibility.cs b/src/core/Helios.DedicatedThreadPool/_Visibility.cs
index 916444f..61935f9 100644
--- a/src/core/Helios.DedicatedThreadPool/_Visibility.cs
+++ b/src/core/Helios.DedicatedThreadPool/_Visibility.cs
@@ -2,5 +2,4 @@
[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.Tests")]
[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.Tests.Performance")]
-[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.VsThreadpoolBenchmark")]
-[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.VsDedicatedThreadFiber")]
+[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.IdleCpu.Program")]
diff --git a/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Dockerfile b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Dockerfile
new file mode 100644
index 0000000..9ad29f9
--- /dev/null
+++ b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Dockerfile
@@ -0,0 +1,8 @@
+#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim AS base
+WORKDIR /app
+
+COPY ./bin/Release/netcoreapp3.1/publish /app
+
+ENTRYPOINT ["dotnet", "Helios.DedicatedThreadPool.IdleCpu.Program.dll"]
\ No newline at end of file
diff --git a/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Helios.DedicatedThreadPool.IdleCpu.Program.csproj b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Helios.DedicatedThreadPool.IdleCpu.Program.csproj
new file mode 100644
index 0000000..c6939e0
--- /dev/null
+++ b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Helios.DedicatedThreadPool.IdleCpu.Program.csproj
@@ -0,0 +1,17 @@
+
+
+
+ Exe
+ netcoreapp3.1
+ false
+ Linux
+ ..\..
+
+
+
+
+
+
+
+
+
diff --git a/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Program.cs b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Program.cs
new file mode 100644
index 0000000..57cb8f8
--- /dev/null
+++ b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Program.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Concurrent;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Helios.Concurrency;
+
+namespace Helios.DedicatedThreadPool.IdleCpu.Program
+{
+ ///
+ /// Create random numbers with Thread-specific seeds.
+ ///
+ /// Borrowed form Jon Skeet's brilliant C# in Depth: http://csharpindepth.com/Articles/Chapter12/Random.aspx
+ ///
+ public static class ThreadLocalRandom
+ {
+ private static int _seed = Environment.TickCount;
+
+ private static ThreadLocal _rng = new ThreadLocal(() => new Random(Interlocked.Increment(ref _seed)));
+
+ ///
+ /// The current random number seed available to this thread
+ ///
+ public static Random Current
+ {
+ get
+ {
+ return _rng.Value;
+ }
+ }
+ }
+
+ class Program
+ {
+ static async Task Main(string[] args)
+ {
+ // set a huge number of threads per core to exaggerate idle CPU effects when we pre-allocate
+ var maxThreads = Math.Max(4, Environment.ProcessorCount)*100;
+
+ Console.WriteLine("Starting Idle Cpu Test with Following Configuration");
+ Console.WriteLine("MaxThreads: {0}", maxThreads);
+
+ var settings = new DedicatedThreadPoolSettings(maxThreads);
+ var threadPool = new Concurrency.DedicatedThreadPool(settings);
+ var concurrentBag = new ConcurrentBag();
+
+ void DoWork(int count)
+ {
+ Console.WriteLine("Count: {0}", count);
+ Thread.Sleep(100);
+ concurrentBag.Add(Thread.CurrentThread.ManagedThreadId);
+ if (count % 3 == 0)
+ threadPool.QueueUserWorkItem(() => DoWork(ThreadLocalRandom.Current.Next(0,7)));
+ }
+
+
+
+ foreach (var i in Enumerable.Range(0, maxThreads*100))
+ {
+ threadPool.QueueUserWorkItem(() =>
+ {
+ DoWork(i);
+ });
+ }
+
+ threadPool.QueueUserWorkItem(() =>
+ {
+ Console.WriteLine("Found {0} active threads", concurrentBag.ToArray().Distinct().Count());
+ });
+
+ // force background Helios threads to run
+ await Task.Delay(TimeSpan.FromMinutes(3));
+
+ Console.WriteLine("Exited with {0} active threads", concurrentBag.ToArray().Distinct().Count());
+ }
+ }
+}
diff --git a/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Properties/launchSettings.json b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Properties/launchSettings.json
new file mode 100644
index 0000000..00fd40b
--- /dev/null
+++ b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "Helios.DedicatedThreadPool.IdleCpu.Program": {
+ "commandName": "Project"
+ },
+ "Docker": {
+ "commandName": "Docker"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/tests/Helios.DedicatedThreadPool.IdleCpu.Tests/Helios.DedicatedThreadPool.IdleCpu.Tests.csproj b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Tests/Helios.DedicatedThreadPool.IdleCpu.Tests.csproj
new file mode 100644
index 0000000..4ad54c8
--- /dev/null
+++ b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Tests/Helios.DedicatedThreadPool.IdleCpu.Tests.csproj
@@ -0,0 +1,23 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
diff --git a/src/tests/Helios.DedicatedThreadPool.IdleCpu.Tests/UnitTest1.cs b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Tests/UnitTest1.cs
new file mode 100644
index 0000000..8ec6423
--- /dev/null
+++ b/src/tests/Helios.DedicatedThreadPool.IdleCpu.Tests/UnitTest1.cs
@@ -0,0 +1,16 @@
+using System;
+using Xunit;
+
+namespace Helios.DedicatedThreadPool.IdleCpu.Tests.Performance
+{
+ public class UnitTest1
+ {
+ [Fact]
+ public void Test1()
+ {
+
+ }
+ }
+
+
+}
diff --git a/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTaskSchedulerTests.cs b/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTaskSchedulerTests.cs
index 0bd8937..5a2b5ac 100644
--- a/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTaskSchedulerTests.cs
+++ b/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTaskSchedulerTests.cs
@@ -3,33 +3,25 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using NUnit.Framework;
+using Xunit;
namespace Helios.Concurrency.Tests
{
- [TestFixture]
- public class DedicatedThreadPoolTaskSchedulerTests
+ public class DedicatedThreadPoolTaskSchedulerTests : IDisposable
{
protected TaskScheduler Scheduler;
protected TaskFactory Factory;
private DedicatedThreadPool Pool;
- [SetUp]
- public void SetUp()
+ public DedicatedThreadPoolTaskSchedulerTests()
{
Pool = new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount));
Scheduler = new DedicatedThreadPoolTaskScheduler(Pool);
Factory = new TaskFactory(Scheduler);
}
- [TearDown]
- public void TearDown()
- {
- Pool.Dispose();
- }
-
- [Test(Description = "Shouldn't immediately try to schedule all threads for task execution")]
- [Ignore("Totally unpredictable on low powered machines")]
+ // "Shouldn't immediately try to schedule all threads for task execution"
+ [Fact(Skip = "Totally unpredictable on low powered machines")]
public void Should_only_use_one_thread_for_single_task_request()
{
var allThreadIds = new ConcurrentBag();
@@ -51,10 +43,11 @@ public void Should_only_use_one_thread_for_single_task_request()
task.Wait();
- Assert.AreEqual(Pool.Settings.NumThreads, allThreadIds.Count);
+ Assert.Equal(Pool.Settings.NumThreads, allThreadIds.Count);
}
- [Test(Description = "Should be able to utilize the entire DedicatedThreadPool for queuing tasks")]
+ // "Should be able to utilize the entire DedicatedThreadPool for queuing tasks"
+ [Fact]
public void Should_use_all_threads_for_many_tasks()
{
var threadIds = new ConcurrentBag();
@@ -74,5 +67,10 @@ public void Should_use_all_threads_for_many_tasks()
Assert.True(threadIds.Distinct().Count() <= Pool.Settings.NumThreads);
}
+
+ public void Dispose()
+ {
+ Pool?.Dispose();
+ }
}
}
diff --git a/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTests.cs b/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTests.cs
index 4b28721..794a9da 100644
--- a/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTests.cs
+++ b/src/tests/Helios.DedicatedThreadPool.Tests/DedicatedThreadPoolTests.cs
@@ -3,14 +3,13 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using NUnit.Framework;
+using Xunit;
namespace Helios.Concurrency.Tests
{
- [TestFixture]
public class DedicatedThreadPoolTests
{
- [Test(Description = "Simple test to ensure that the entire thread pool doesn't just crater")]
+ [Fact()]
public void Should_process_multithreaded_workload()
{
var atomicCounter = new AtomicCounter(0);
@@ -22,10 +21,10 @@ public void Should_process_multithreaded_workload()
}
SpinWait.SpinUntil(() => atomicCounter.Current == 1000, TimeSpan.FromSeconds(1));
}
- Assert.Pass(string.Format("Passed! Final counter value: {0} / Expected {1}", atomicCounter.Current, 1000));
+ Assert.True(true, $"Passed! Final counter value: {atomicCounter.Current} / Expected {1000}");
}
- [Test(Description = "Ensure that the number of threads running in the pool concurrently equal is AtMost equal to the DedicatedThreadPoolSettings.NumThreads property")]
+ [Fact(DisplayName = "Ensure that the number of threads running in the pool concurrently equal is AtMost equal to the DedicatedThreadPoolSettings.NumThreads property")]
public void Should_process_workload_across_AtMost_DedicatedThreadPoolSettings_NumThreads()
{
var numThreads = Environment.ProcessorCount;
@@ -49,7 +48,7 @@ public void Should_process_workload_across_AtMost_DedicatedThreadPoolSettings_Nu
Assert.True(threadIds.Distinct().Count() <= numThreads);
}
- [Test(Description = "Have a user-defined method that throws an exception? The world should not end.")]
+ [Fact(DisplayName = "Have a user-defined method that throws an exception? The world should not end.")]
public void World_should_not_end_if_exception_thrown_in_user_callback()
{
var numThreads = 3;
@@ -73,7 +72,7 @@ public void World_should_not_end_if_exception_thrown_in_user_callback()
}
//sanity check
- Assert.AreEqual(numThreads, threadIds.Distinct().Count());
+ Assert.Equal(numThreads, threadIds.Distinct().Count());
//run the job again. Should get the same thread IDs as before
for (var i = 0; i < numThreads*10; i++)
@@ -84,7 +83,7 @@ public void World_should_not_end_if_exception_thrown_in_user_callback()
}
// half of thread IDs should belong to failed threads, other half to successful ones
- Assert.AreEqual(numThreads, threadIds.Distinct().Count());
+ Assert.Equal(numThreads, threadIds.Distinct().Count());
}
}
}
diff --git a/src/tests/Helios.DedicatedThreadPool.Tests/Helios.DedicatedThreadPool.Tests.csproj b/src/tests/Helios.DedicatedThreadPool.Tests/Helios.DedicatedThreadPool.Tests.csproj
index a7f0cb8..0e00c98 100644
--- a/src/tests/Helios.DedicatedThreadPool.Tests/Helios.DedicatedThreadPool.Tests.csproj
+++ b/src/tests/Helios.DedicatedThreadPool.Tests/Helios.DedicatedThreadPool.Tests.csproj
@@ -1,17 +1,20 @@
-
-
- netcoreapp3.1
- false
-
-
-
-
-
-
-
-
-
-
-
+
+
+ netcoreapp3.1
+ false
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+