public void WorkerThreadIdleTimeOutTest()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(800, 2, 4);

            // İş parçası süresi / İş parçası eklenme süresi = 400 / 100 => 4 İşçi Thread gerekli.
            int   workItemDuration = 400;
            Timer timer            = new Timer(100);

            timer.AutoReset = true;
            timer.Elapsed  += (sender, args) =>
            {
                workerThreadPool.QueueWorkItem(
                    new ActionWorkItem(
                        () =>
                {
                    Thread.Sleep(workItemDuration);
                }));
            };
            timer.Start();

            Thread.Sleep(3000);

            Assert.AreEqual(4, workerThreadPool.WorkerThreadsCount);

            // İş parçası süresi / İş parçası eklenme süresi = 150 / 100 => 2 İşçi Thread gerekli.
            Interlocked.Add(ref workItemDuration, -250); // 400 - 250 = 150

            Thread.Sleep(3000);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);

            timer.Stop();

            workerThreadPool.Shutdown(true, 3000);
        }
        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 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 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 ConstructorShouldCreateMinimumNumberWorkerThreadsWhenThereIsNoWorkItemInTheQueue()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(3, 4);

            Assert.AreEqual(3, workerThreadPool.WorkerThreadsCount);

            workerThreadPool.Shutdown(true, 500);
        }
        public void SetMinimumWorkerThreadsCountShouldThrowExceptionWhenMinimumThreadsCountIsLessThanZero()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(0, 1);

            Assert.Throws <ArgumentOutOfRangeException>(() => workerThreadPool.SetMinimumWorkerThreadsCount(-1));

            workerThreadPool.Shutdown(true, 500);
        }
        public void SetMinimumWorkerThreadsCountShouldThrowExceptionWhenMinimumThreadsCountIsBiggerThanMaximumCount()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(2, 3);

            Assert.Throws <ArgumentOutOfRangeException>(() => workerThreadPool.SetMinimumWorkerThreadsCount(4));

            workerThreadPool.Shutdown(true, 500);
        }
        public void QueueWorkItemShouldThrowExceptionWhenWorkerThreadPoolIsShutDown()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool();

            workerThreadPool.Shutdown();

            Assert.Throws <LaboThreadingException>(() => workerThreadPool.QueueWorkItem(Substitute.For <IWorkItem>()));
        }
        public void DefaultConstructorShouldSetTheDefaultMaxWorkerThreadsCount()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool();

            Assert.AreEqual(WorkerThreadPool.DEFAULT_MAX_WORKER_THREADS_PER_CORE * Environment.ProcessorCount, workerThreadPool.MaxWorkerThreads);

            workerThreadPool.Shutdown(true, 500);
        }
        public void DefaultConstructorShouldSetTheDefaultWorkerThreadIdleTimeout()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool();
            WorkItemQueue    workItemQueue    = (WorkItemQueue)workerThreadPool.WorkItemQueue;

            Assert.AreEqual(WorkerThreadPool.DEFAULT_WORKER_THREAD_IDLE_TIMEOUT, workItemQueue.WorkItemWaiterTimeOutInMilliSeconds);

            workerThreadPool.Shutdown(true, 500);
        }
        public void DefaultConstructorShouldSetTheDefaultWorkerThreadIdleTimeout()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool();
            WorkItemQueue workItemQueue = (WorkItemQueue)workerThreadPool.WorkItemQueue;

            Assert.AreEqual(WorkerThreadPool.DEFAULT_WORKER_THREAD_IDLE_TIMEOUT, workItemQueue.WorkItemWaiterTimeOutInMilliSeconds);

            workerThreadPool.Shutdown(true, 500);
        }
        public void ConstructorTestInitialWorkerThreadsCount(int workItemQueueCount, int minWorkerThreads, int maxWorkerThreads, int expected)
        {
            IWorkItemQueue workItemQueue = Substitute.For <IWorkItemQueue>();

            workItemQueue.Count.Returns(workItemQueueCount);
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(workItemQueue, minWorkerThreads, maxWorkerThreads);

            Assert.AreEqual(expected, workerThreadPool.WorkerThreadsCount);

            workerThreadPool.Shutdown(true, 500);
        }
        public void ConstructorShouldCreateOptimumWorkerThreadsWhenThereAreWorkItemsInTheQueue(int workItemCount, int expected)
        {
            IWorkItemQueue workItemQueue = Substitute.For <IWorkItemQueue>();

            workItemQueue.Count.Returns(workItemCount);

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

            Assert.AreEqual(expected, workerThreadPool.WorkerThreadsCount);

            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);
        }
        public void A()
        {
            Random           random           = new Random();
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(6 * 10 * 1000, 8, 8);
            const int        workItemsCount   = 100;
            int counter = 0;
            int totalSleepMilliseconds = 0;

            IList <IWorkItem> workItems = new List <IWorkItem>(workItemsCount);

            for (int i = 0; i < workItemsCount; i++)
            {
                ActionWorkItem workItem = new ActionWorkItem(
                    () =>
                {
                    int sleepMilliseconds = random.Next(1000, 2000);
                    Interlocked.Add(ref totalSleepMilliseconds, sleepMilliseconds);
                    Thread.Sleep(sleepMilliseconds);
                    Interlocked.Increment(ref counter);
                });
                workItems.Add(workItem);
            }

            Stopwatch stopwatch = Stopwatch.StartNew();

            stopwatch.Start();

            for (int i = 0; i < workItems.Count; i++)
            {
                IWorkItem workItem = workItems[i];
                workerThreadPool.QueueWorkItem(workItem);
            }

            workerThreadPool.Shutdown(true, 500);

            stopwatch.Stop();

            TimeSpan totalExecutionTime = TimeSpan.Zero;

            for (int i = 0; i < workItems.Count; i++)
            {
                IWorkItem workItem = workItems[i];
                totalExecutionTime += workItem.ExecutionTime;
            }

            totalExecutionTime.ToString();
        }
        public void ConstructorShoulStartMinimumCountWorkerThreadsAlthoughThereIsNoWorkItemsInTheQueue()
        {
            IWorkItemQueue workItemQueue = Substitute.For <IWorkItemQueue>();

            workItemQueue.Count.Returns(0);
            workItemQueue.Dequeue().Returns((IWorkItem)null);

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

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);

            Wait.While(() => !workerThreadPool.WorkerThreads.All(x => x.Thread.IsAlive), 500);

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

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

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

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

            workerThreadPool.SetMaximumWorkerThreadsCount(4);

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

            manualFinishWorkItemQueueStub.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }
        public void A()
        {
            Random random = new Random();
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(6 * 10 * 1000, 8, 8);
            const int workItemsCount = 100;
            int counter = 0;
            int totalSleepMilliseconds = 0;
            
            IList<IWorkItem> workItems = new List<IWorkItem>(workItemsCount);
            for (int i = 0; i < workItemsCount; i++)
            {
                ActionWorkItem workItem = new ActionWorkItem(
                    () =>
                        {
                            int sleepMilliseconds = random.Next(1000, 2000);
                            Interlocked.Add(ref totalSleepMilliseconds, sleepMilliseconds);
                            Thread.Sleep(sleepMilliseconds);
                            Interlocked.Increment(ref counter);
                        });
                workItems.Add(workItem);                
            }

            Stopwatch stopwatch = Stopwatch.StartNew();
            stopwatch.Start();

            for (int i = 0; i < workItems.Count; i++)
            {
                IWorkItem workItem = workItems[i];
                workerThreadPool.QueueWorkItem(workItem);
            }

            workerThreadPool.Shutdown(true, 500);

            stopwatch.Stop();

            TimeSpan totalExecutionTime = TimeSpan.Zero;
            for (int i = 0; i < workItems.Count; i++)
            {
                IWorkItem workItem = workItems[i];
                totalExecutionTime += workItem.ExecutionTime;
            }

            totalExecutionTime.ToString();
        }
        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 SetMaximumWorkerThreadsCountShouldAddNoNewWorkerThreadWhenMaxThreadCountIncreasedAndThereIsNoWorkItemsInTheQueue()
        {
            ManualFinishWorkItemQueueStub workItemQueue = new ManualFinishWorkItemQueueStub();

            workItemQueue.Enqueue(new ManualFinishWorkItem());

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

            Assert.AreEqual(1, workerThreadPool.WorkerThreadsCount);

            workItemQueue.WaitAllStart(500);
            workerThreadPool.SetMaximumWorkerThreadsCount(2);

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

            workItemQueue.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }
        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 ConstructorShouldCreateMinimumNumberWorkerThreadsWhenThereIsNoWorkItemInTheQueue()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(3, 4);

            Assert.AreEqual(3, workerThreadPool.WorkerThreadsCount);

            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 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 DefaultConstructorShouldSetTheDefaultMaxWorkerThreadsCount()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool();
            Assert.AreEqual(WorkerThreadPool.DEFAULT_MAX_WORKER_THREADS_PER_CORE * Environment.ProcessorCount, workerThreadPool.MaxWorkerThreads);

            workerThreadPool.Shutdown(true, 500);
        }
        public void ConstructorShouldCreateOptimumWorkerThreadsWhenThereAreWorkItemsInTheQueue(int workItemCount, int expected)
        {
            IWorkItemQueue workItemQueue = Substitute.For<IWorkItemQueue>();
            workItemQueue.Count.Returns(workItemCount);

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

            Assert.AreEqual(expected, workerThreadPool.WorkerThreadsCount);

            workerThreadPool.Shutdown(true, 500);
        }
        public void WorkerThreadIdleTimeOutTest()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(800, 2, 4);
            
            // İş parçası süresi / İş parçası eklenme süresi = 400 / 100 => 4 İşçi Thread gerekli.
            int workItemDuration = 400;
            Timer timer = new Timer(100);
            timer.AutoReset = true;
            timer.Elapsed += (sender, args) =>
                {
                    workerThreadPool.QueueWorkItem(
                        new ActionWorkItem(
                            () =>
                                {
                                    Thread.Sleep(workItemDuration);
                                }));
                };
            timer.Start();

            Thread.Sleep(3000);

            Assert.AreEqual(4, workerThreadPool.WorkerThreadsCount);

            // İş parçası süresi / İş parçası eklenme süresi = 150 / 100 => 2 İşçi Thread gerekli.
            Interlocked.Add(ref workItemDuration, -250); // 400 - 250 = 150

            Thread.Sleep(3000);

            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);

            timer.Stop();

            workerThreadPool.Shutdown(true, 3000);
        }
        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 QueueWorkItemShouldThrowExceptionWhenWorkerThreadPoolIsShutDown()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool();
            workerThreadPool.Shutdown();

            Assert.Throws<LaboThreadingException>(() => workerThreadPool.QueueWorkItem(Substitute.For<IWorkItem>()));
        }
        public void ConstructorShoulStartMinimumCountWorkerThreadsAlthoughThereIsNoWorkItemsInTheQueue()
        {
            IWorkItemQueue workItemQueue = Substitute.For<IWorkItemQueue>();
            workItemQueue.Count.Returns(0);
            workItemQueue.Dequeue().Returns((IWorkItem)null);

            WorkerThreadPool workerThreadPool = new WorkerThreadPool(workItemQueue, 2, 2);
            
            Assert.AreEqual(2, workerThreadPool.WorkerThreadsCount);

            Wait.While(() => !workerThreadPool.WorkerThreads.All(x => x.Thread.IsAlive), 500);
            
            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 SetMinimumWorkerThreadsCountShouldThrowExceptionWhenMinimumThreadsCountIsBiggerThanMaximumCount()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(2, 3);

            Assert.Throws<ArgumentOutOfRangeException>(() => workerThreadPool.SetMinimumWorkerThreadsCount(4));

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

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

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

            workerThreadPool.SetMaximumWorkerThreadsCount(4);

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

            manualFinishWorkItemQueueStub.StopAll();

            workerThreadPool.Shutdown(true, 500);
        }
        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 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);
        }
        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 ConstructorTestInitialWorkerThreadsCount(int workItemQueueCount, int minWorkerThreads, int maxWorkerThreads, int expected)
        {
            IWorkItemQueue workItemQueue = Substitute.For<IWorkItemQueue>();
            workItemQueue.Count.Returns(workItemQueueCount);
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(workItemQueue, minWorkerThreads, maxWorkerThreads);
            Assert.AreEqual(expected, workerThreadPool.WorkerThreadsCount);

            workerThreadPool.Shutdown(true, 500);
        }
        public void SetMinimumWorkerThreadsCountShouldThrowExceptionWhenMinimumThreadsCountIsLessThanZero()
        {
            WorkerThreadPool workerThreadPool = new WorkerThreadPool(0, 1);

            Assert.Throws<ArgumentOutOfRangeException>(() => workerThreadPool.SetMinimumWorkerThreadsCount(-1));

            workerThreadPool.Shutdown(true, 500);
        }