[corlib] Don't use DateTime.Now for measuring elapsed time
[mono.git] / mcs / class / corlib / Test / System.Threading / ThreadPoolTest.cs
index 88803e5c2d53e3e8f275677bf695629cfa299843..9dace8484e5e06c64f6c7a83e3e896cebe2a24f7 100644 (file)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Diagnostics;
 using System.Threading;
 using NUnit.Framework;
 
@@ -35,6 +36,25 @@ namespace MonoTests.System.Threading
        [TestFixture]
        public class ThreadPoolTests
        {
+               int minWorkerThreads;
+               int minCompletionPortThreads;
+               int maxWorkerThreads;
+               int maxCompletionPortThreads;
+
+               [SetUp]
+               public void SetUp ()
+               {
+                       ThreadPool.GetMinThreads (out minWorkerThreads, out minCompletionPortThreads);
+                       ThreadPool.GetMaxThreads (out maxWorkerThreads, out maxCompletionPortThreads);
+               }
+
+               [TearDown]
+               public void TearDown ()
+               {
+                       ThreadPool.SetMinThreads (minWorkerThreads, minCompletionPortThreads);
+                       ThreadPool.SetMaxThreads (maxWorkerThreads, maxCompletionPortThreads);
+               }
+
                [Test]
                public void RegisterWaitForSingleObject_InvalidArguments ()
                {
@@ -61,7 +81,24 @@ namespace MonoTests.System.Threading
                        }
                }
 
-#if NET_4_0
+               [Test]
+               public void QueueUserWorkItem ()
+               {
+                       int n = 100000;
+                       int total = 0, sum = 0;
+                       for (int i = 0; i < n; ++i) {
+                               if (i % 2 == 0)
+                                       ThreadPool.QueueUserWorkItem (_ => { Interlocked.Decrement (ref sum); Interlocked.Increment (ref total); });
+                               else
+                                       ThreadPool.QueueUserWorkItem (_ => { Interlocked.Increment (ref sum); Interlocked.Increment (ref total); });
+                       }
+                       var sw = Stopwatch.StartNew ();
+                       while ((total != n || sum != 0) && sw.Elapsed.TotalSeconds < 60)
+                               Thread.Sleep (1000);
+                       Assert.IsTrue (total == n, "#1");
+                       Assert.IsTrue (sum   == 0, "#2");
+               }
+
                event WaitCallback e;
 
                [Test]
@@ -80,6 +117,87 @@ namespace MonoTests.System.Threading
                        ThreadPool.UnsafeQueueUserWorkItem (e, null);
                        Assert.IsTrue (ev.Wait (3000));
                }
-#endif
+
+               [Test]
+               public void SetAndGetMinThreads ()
+               {
+                       int workerThreads, completionPortThreads;
+                       int workerThreads_new, completionPortThreads_new;
+
+                       ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
+                       Assert.IsTrue (workerThreads > 0, "#1");
+                       Assert.IsTrue (completionPortThreads > 0, "#2");
+
+                       workerThreads_new = workerThreads == 1 ? 2 : 1;
+                       completionPortThreads_new = completionPortThreads == 1 ? 2 : 1;
+                       ThreadPool.SetMinThreads (workerThreads_new, completionPortThreads_new);
+
+                       ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
+                       Assert.IsTrue (workerThreads == workerThreads_new, "#3");
+                       Assert.IsTrue (completionPortThreads == completionPortThreads_new, "#4");
+               }
+
+               [Test]
+               public void SetAndGetMaxThreads ()
+               {
+                       int cpuCount = Environment.ProcessorCount;
+                       int workerThreads, completionPortThreads;
+                       int workerThreads_new, completionPortThreads_new;
+
+                       ThreadPool.GetMaxThreads (out workerThreads, out completionPortThreads);
+                       Assert.IsTrue (workerThreads > 0, "#1");
+                       Assert.IsTrue (completionPortThreads > 0, "#2");
+
+                       workerThreads_new = workerThreads == cpuCount ? cpuCount + 1 : cpuCount;
+                       completionPortThreads_new = completionPortThreads == cpuCount ? cpuCount + 1 : cpuCount;
+                       ThreadPool.SetMaxThreads (workerThreads_new, completionPortThreads_new);
+
+                       ThreadPool.GetMaxThreads (out workerThreads, out completionPortThreads);
+                       Assert.IsTrue (workerThreads == workerThreads_new, "#3");
+                       Assert.IsTrue (completionPortThreads == completionPortThreads_new, "#4");
+               }
+
+               [Test]
+               public void GetAvailableThreads ()
+               {
+                       ManualResetEvent mre = new ManualResetEvent (false);
+                       var sw = Stopwatch.StartNew ();
+                       int i, workerThreads, completionPortThreads;
+
+                       try {
+                               Assert.IsTrue (ThreadPool.SetMaxThreads (Environment.ProcessorCount, Environment.ProcessorCount));
+
+                               while (true) {
+                                       ThreadPool.GetAvailableThreads (out workerThreads, out completionPortThreads);
+                                       if (workerThreads == 0)
+                                               break;
+
+                                       Console.WriteLine ("workerThreads = {0}, completionPortThreads = {1}", workerThreads, completionPortThreads);
+
+                                       if (sw.Elapsed.TotalSeconds >= 10)
+                                               Assert.Fail ("did not reach 0 available threads");
+
+                                       ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
+                                       Thread.Sleep (1);
+                               }
+                       } finally {
+                               mre.Set ();
+                       }
+               }
+
+               void GetAvailableThreads_Callback (object state)
+               {
+                       ManualResetEvent mre = (ManualResetEvent) state;
+
+                       if (mre.WaitOne (0))
+                               return;
+
+                       ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
+                       ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
+                       ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
+                       ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
+
+                       mre.WaitOne ();
+               }
        }
 }
\ No newline at end of file