public void TestQueueUserWorkItem()
 {
     using (TestTask task = new TestTask()) {
         AffineThreadPool.QueueUserWorkItem(task.Callback);
         Assert.IsTrue(task.CallbackEvent.WaitOne(1000));
     }
 }
 public void TestDefaultExceptionHandler()
 {
     Assert.Throws <ArrayTypeMismatchException>(
         delegate() {
         AffineThreadPool.ExceptionHandler(new ArrayTypeMismatchException("Test"));
     }
         );
 }
 public void TestDefaultAssertionHandler()
 {
     // We can't test a failing assertion because our tests need to run
     // unattended on a build server without blocking for user input.
     AffineThreadPool.DefaultAssertionHandler(
         true, "Unit test", "This should not fail"
         );
 }
        public void TestQueueUserWorkItemWithState()
        {
            using (TestTask task = new TestTask()) {
                object state = new object();

                AffineThreadPool.QueueUserWorkItem(task.Callback, state);

                Assert.IsTrue(task.CallbackEvent.WaitOne(1000));
                Assert.AreSame(state, task.LastCallbackState);
            }
        }
        public void TestGetProcessThread()
        {
            Thread.BeginThreadAffinity();
            try {
                int threadId = AffineThreadPool.GetCurrentThreadId();

                Assert.IsNotNull(AffineThreadPool.GetProcessThread(threadId));
                Assert.IsNull(AffineThreadPool.GetProcessThread(0));
            }
            finally {
                Thread.EndThreadAffinity();
            }
        }
        public void TestExceptionFromUserWorkItem()
        {
            using (ManualResetEvent exceptionEvent = new ManualResetEvent(false)) {
                AffineThreadPool.ExceptionDelegate oldExceptionHandler =
                    AffineThreadPool.ExceptionHandler;

                AffineThreadPool.ExceptionHandler = delegate(Exception exception) {
                    exceptionEvent.Set();
                };
                try {
                    AffineThreadPool.QueueUserWorkItem(
                        delegate(object state) { throw new KeyNotFoundException(); }
                        );
                    Assert.IsTrue(exceptionEvent.WaitOne(1000));
                }
                finally {
                    AffineThreadPool.ExceptionHandler = oldExceptionHandler;
                }
            }
        }
        public void TestWaitingWorkItemsProperty()
        {
            int eventCount = AffineThreadPool.Processors;

            WaitTask[] tasks = new WaitTask[eventCount];

            int createdTasks = 0;

            try {
                // CHECK: Is there danger that the thread pool still has not finished
                //        queued items for other unit tests, thereby failing to meet
                //        our expected task counts?

                // Create the tasks, counting up the created task counter. If an exception
                // occurs, we will roll back from there.
                for (createdTasks = 0; createdTasks < eventCount; ++createdTasks)
                {
                    tasks[createdTasks] = new WaitTask();
                }

                // Schedule the blocking tasks in the thread pool so it will not be able
                // to process the next task we add to the queue
                for (int index = 0; index < eventCount; ++index)
                {
                    AffineThreadPool.QueueUserWorkItem(tasks[index].Callback);
                }

                // Wait for the tasks to start so they aren't preempted by the tasks we're
                // going to add (which would finish immediately). The affine thread pool
                // works on a first come first serve basis, but we don't want to rely on this
                // implementation detail in the unit test.
                for (int index = 0; index < eventCount; ++index)
                {
                    Assert.IsTrue(
                        tasks[index].StartEvent.WaitOne(10000),
                        "Task " + index.ToString() + " was started"
                        );
                }

                // All Thread should now be active and no work items should be waiting
                Assert.AreEqual(
                    createdTasks, AffineThreadPool.ActiveThreads,
                    "ActiveThreads property equals number of tasks"
                    );
                Assert.AreEqual(
                    0, AffineThreadPool.WaitingWorkItems,
                    "No waiting work items are in the queue"
                    );

                // Add a task to the queue and make sure the waiting work item count goes up
                AffineThreadPool.QueueUserWorkItem(delegate(object state) { });
                Assert.AreEqual(
                    1, AffineThreadPool.WaitingWorkItems,
                    "Added work item is waiting in the queue"
                    );

                // The same again. Now we should have 2 work items sitting in the queue
                AffineThreadPool.QueueUserWorkItem(delegate(object state) { });
                Assert.AreEqual(
                    2, AffineThreadPool.WaitingWorkItems,
                    "Both added work items are waiting in the queue"
                    );

                // Let the WaitTasks finish so we're not blocking the thread pool any longer
                for (int index = 0; index < eventCount; ++index)
                {
                    tasks[index].WaitEvent.Set();
                }

                // Wait for the tasks to end before we get rid of them
                for (int index = 0; index < eventCount; ++index)
                {
                    Assert.IsTrue(
                        tasks[index].FinishEvent.WaitOne(1000),
                        "Task " + index.ToString() + " has finished"
                        );
                }
            }
            finally {
                for (--createdTasks; createdTasks >= 0; --createdTasks)
                {
                    tasks[createdTasks].Dispose();
                }
            }
        }