public void AllItemsShouldBeProcessedBeforePipeLineCompletion(int testActionDurationMs, int numberOfProducers, int maximumPipelineCapacity) { var pipeLine = new ProducerConsumerPipeLine <Action>(_consumerMock.Object, maximumPipelineCapacity); // Dummy test action. Action testAction = () => { Thread.Sleep(testActionDurationMs); }; List <Task> producerTasks = new List <Task>(); for (int producerCounter = 0; producerCounter < numberOfProducers; producerCounter++) { var producer = Task.Run(async() => await pipeLine.EnqueueAsync(testAction)); producerTasks.Add(producer); } Task.WaitAll(producerTasks.ToArray()); pipeLine.CompleteProducing(); pipeLine.PipeLineCompletion.Wait(); _consumerMock.Verify(consumerMock => consumerMock.Consume(It.IsAny <Action>()), Times.Exactly(numberOfProducers)); }
public void ItemsAreProcessedInCorrectOrder(int testActionDurationMs, int numberOfProducers, int maximumPipelineCapacity) { var pipeLine = new ProducerConsumerPipeLine <Action>(_consumerMock.Object, maximumPipelineCapacity); object pushOrderLocker = new object(); BlockingCollection <int> testActionsPushOrder = new BlockingCollection <int>(); BlockingCollection <int> testActionsInvocationOrder = new BlockingCollection <int>(); List <Task> producerTasks = new List <Task>(); for (int producerCounter = 0; producerCounter < numberOfProducers; producerCounter++) { var testActionId = producerCounter; Action testAction = () => { testActionsInvocationOrder.Add(testActionId); Thread.Sleep(testActionDurationMs); }; var producer = Task.Run(() => { lock (pushOrderLocker) { pipeLine.EnqueueAsync(testAction).Wait(); testActionsPushOrder.Add(testActionId); } }); producerTasks.Add(producer); } Task.WaitAll(producerTasks.ToArray()); pipeLine.CompleteProducing(); pipeLine.PipeLineCompletion.Wait(); _consumerMock.Verify(consumerMock => consumerMock.Consume(It.IsAny <Action>()), Times.Exactly(numberOfProducers)); CollectionAssert.AreEqual(testActionsPushOrder, testActionsInvocationOrder); }
public void OneItemAtATimeIsProcessedByTheConsumer(int testActionDurationMs, int numberOfProducers, int maximumPipelineCapacity) { int sharedCounter = 0; int sharedCounterMismatchNumber = 0; var pipeLine = new ProducerConsumerPipeLine <Action>(_consumerMock.Object, maximumPipelineCapacity); // Increments the shared counter to 1 before performing a long-running task and decrements immediately after. Action testAction = () => { // No interlocking is needed when comparing a shared value to a constant. if (!Equals(sharedCounter, 0)) { Interlocked.Increment(ref sharedCounterMismatchNumber); } Interlocked.Increment(ref sharedCounter); Thread.Sleep(testActionDurationMs); Interlocked.Decrement(ref sharedCounter); }; List <Task> producerTasks = new List <Task>(); for (int producerCounter = 0; producerCounter < numberOfProducers; producerCounter++) { var producer = Task.Run(async() => await pipeLine.EnqueueAsync(testAction)); producerTasks.Add(producer); } Task.WaitAll(producerTasks.ToArray()); pipeLine.CompleteProducing(); pipeLine.PipeLineCompletion.Wait(); // If the actions were invoked in a one-at-a-time fashion, there must be no mismathes. Assert.AreEqual(sharedCounterMismatchNumber, 0); }