public void SetMaximumWorkerThreadsCountShouldRemoveIdleWorkerThreadsWhenDecreased()
        {
            ManualFinishWorkItemQueueStub workItemQueue = new ManualFinishWorkItemQueueStub();
            workItemQueue.Enqueue(new ManualFinishWorkItem());
            workItemQueue.Enqueue(new ManualFinishWorkItem());

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(workItemQueue, 0, 2);
            workerThreadPool.WorkerThreadExiting += (sender, args) =>
                {
                    manualResetEvent.Set();
                };

            workItemQueue.WaitAllStart(500);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workerThreadPool.SetMaximumWorkerThreadsCount(1);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workItemQueue.WorkItems[0].Stop();
            workItemQueue.Enqueue(new ManualFinishWorkItem());

            Assert.AreEqual(1, workItemQueue.Count);

            manualResetEvent.WaitOne(300);

            Assert.AreEqual(1, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(1, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workItemQueue.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }
        public void QueueWorkItemShouldAddANewWorkerThreadWhenMaxThreadCountIsNotReached()
        {
            ManualFinishWorkItemQueueStub workItemQueue = new ManualFinishWorkItemQueueStub();
            workItemQueue.Enqueue(new ManualFinishWorkItem());

            WorkerThreadPool workerThreadPool = new WorkerThreadPool(workItemQueue, 0, 2);

            Assert.AreEqual(1, workerThreadPool.WorkerThreadsCount);

            workItemQueue.WaitAllStart(500);

            Assert.AreEqual(1, workerThreadPool.WorkerThreadsCount);

            ManualFinishWorkItem newWorkItem = new ManualFinishWorkItem();
            workerThreadPool.QueueWorkItem(newWorkItem);
            newWorkItem.WaitStart(500);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workItemQueue.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }
        public void SetMaximumWorkerThreadsCountShouldAddANewWorkerThreadWhenMaxThreadCountIncreasedAndThereAreWorkItemsInTheQueue()
        {
            ManualFinishWorkItemQueueStub workItemQueue = new ManualFinishWorkItemQueueStub();
            workItemQueue.Enqueue(new ManualFinishWorkItem());
            workItemQueue.Enqueue(new ManualFinishWorkItem());

            WorkerThreadPool workerThreadPool = new WorkerThreadPool(workItemQueue, 0, 1);

            Assert.AreEqual(1, workerThreadPool.WorkerThreadsCount);

            workerThreadPool.SetMaximumWorkerThreadsCount(2);

            workItemQueue.WaitAllStart(500);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workItemQueue.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }
        public void SetMinimumWorkerThreadsCountShouldNotAddWorkerThreadsWhenMinimumThreadsCountIncreasesAndThereIsWorkItemsInTheQueue()
        {
            ManualFinishWorkItemQueueStub manualFinishWorkItemQueueStub = new ManualFinishWorkItemQueueStub();
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            int exitedWorkerThreadCount = 0;
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(manualFinishWorkItemQueueStub, 2, 4);
            workerThreadPool.WorkerThreadExiting += (sender, args) =>
            {
                if (Interlocked.Increment(ref exitedWorkerThreadCount) >= 1)
                {
                    manualResetEvent.Set();
                }
            };

            manualFinishWorkItemQueueStub.WaitAllStart(500);

            Assert.AreEqual(4, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(4, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));
            Assert.AreEqual(1, manualFinishWorkItemQueueStub.Count);

            workerThreadPool.SetMinimumWorkerThreadsCount(3);

            Assert.AreEqual(4, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(4, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));
            Assert.AreEqual(1, manualFinishWorkItemQueueStub.Count);

            manualFinishWorkItemQueueStub.StopAll();

            manualResetEvent.WaitOne();

            Assert.AreEqual(3, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(0, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workerThreadPool.Shutdown(true, 500);
        }
        public void ConstructorShouldCreateOptimumWorkerThreadsWhenThereAreWorkItemsInTheQueue()
        {
            ManualFinishWorkItemQueueStub workItemQueue = new ManualFinishWorkItemQueueStub();
            for (int i = 0; i < 5; i++)
            {
                workItemQueue.Enqueue(new ManualFinishWorkItem());
            }

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            int exitedWorkerThreadCount = 0;
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(workItemQueue, 2, 4);
            workerThreadPool.WorkerThreadExiting += (sender, args) =>
                {
                    if (Interlocked.Increment(ref exitedWorkerThreadCount) >= 2)
                    {
                        manualResetEvent.Set();
                    }
                };

            workItemQueue.WaitAllStart(500);

            Assert.AreEqual(4, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(4, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workItemQueue.StopAll();

            manualResetEvent.WaitOne(500);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(0, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workerThreadPool.Shutdown(true, 500);
        }
        public void SetMaximumWorkerThreadsCountShouldAddNoWorkerThreadsToReachTheMaximumThreadCountWhenMaximumThreadsCountIncreasesAndThereAreWorkItemsInTheQueue()
        {
            ManualFinishWorkItemQueueStub manualFinishWorkItemQueueStub = new ManualFinishWorkItemQueueStub();
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());

            WorkerThreadPool workerThreadPool = new WorkerThreadPool(manualFinishWorkItemQueueStub, 1, 2);

            manualFinishWorkItemQueueStub.WaitAllStart(500);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workerThreadPool.QueueWorkItem(new ManualFinishWorkItem());
            workerThreadPool.QueueWorkItem(new ManualFinishWorkItem());

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            Assert.AreEqual(2, manualFinishWorkItemQueueStub.Count);

            workerThreadPool.SetMaximumWorkerThreadsCount(4);

            manualFinishWorkItemQueueStub.WaitAllStart(500);

            Assert.AreEqual(4, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(4, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            Assert.AreEqual(0, manualFinishWorkItemQueueStub.Count);

            manualFinishWorkItemQueueStub.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }
        public void SetMaximumWorkerThreadsCountShouldRemoveWorkerThreadsWhenMaximumThreadsCountDecreases()
        {
            ManualFinishWorkItemQueueStub manualFinishWorkItemQueueStub = new ManualFinishWorkItemQueueStub();
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());

            AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(manualFinishWorkItemQueueStub, 1, 3);
            workerThreadPool.WorkerThreadExiting += (sender, args) => { autoResetEvent.Set(); };

            manualFinishWorkItemQueueStub.WaitAllStart(500);

            Assert.AreEqual(3, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(3, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            workerThreadPool.SetMaximumWorkerThreadsCount(2);

            manualFinishWorkItemQueueStub.WorkItems[0].Stop();
            manualFinishWorkItemQueueStub.Enqueue(new ManualFinishWorkItem());

            autoResetEvent.WaitOne(500);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            manualFinishWorkItemQueueStub.WorkItems[1].Stop();

            autoResetEvent.WaitOne(500);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(2, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            manualFinishWorkItemQueueStub.WorkItems[2].Stop();

            autoResetEvent.WaitOne(500);

            Assert.AreEqual(1, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(1, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            manualFinishWorkItemQueueStub.WorkItems[3].Stop();

            autoResetEvent.WaitOne(500);

            Assert.AreEqual(1, workerThreadPool.WorkerThreadsCount);
            Assert.AreEqual(0, workerThreadPool.WorkerThreads.Count(x => x.IsBusy));

            manualFinishWorkItemQueueStub.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }