예제 #1
0
        public void Test_TryAdd_ToFullBuffer(int capacity)
        {
            using (StandardTaskBuffer buffer = new StandardTaskBuffer(capacity))
            {
                //Fill buffer
                for (int i = 0; i < buffer.Capacity; i++)
                {
                    buffer.TryAddNewTask(new MockQueuedTaskToken(Guid.NewGuid()));
                }

                //Now attempt to add one more
                Assert.IsFalse(buffer.TryAddNewTask(new MockQueuedTaskToken(Guid.NewGuid())));
            }
        }
예제 #2
0
        public void Test_CanGet_FromNonEmptyBuffer(int capacity)
        {
            using (StandardTaskBuffer buffer = new StandardTaskBuffer(capacity))
            {
                //Add some items
                int actualItemNumber = ProduceItemNumber(capacity);
                List <IQueuedTaskToken> addedTasks = new List <IQueuedTaskToken>();

                for (int i = 0; i < actualItemNumber; i++)
                {
                    addedTasks.Add(new MockQueuedTaskToken(Guid.NewGuid()));
                    buffer.TryAddNewTask(addedTasks[i]);
                }

                for (int i = 0; i < actualItemNumber; i++)
                {
                    IQueuedTaskToken queuedTaskToken = buffer.TryGetNextTask();

                    Assert.NotNull(queuedTaskToken);
                    Assert.IsTrue(addedTasks.Any(t => t.DequeuedTask.Id == queuedTaskToken.DequeuedTask.Id));
                }

                Assert.IsFalse(buffer.IsFull);
                Assert.IsFalse(buffer.IsCompleted);
            }
        }
예제 #3
0
        public void Test_CanRaiseItemAdditionEvents()
        {
            bool handlerCalled = false;

            using (StandardTaskBuffer buffer = new StandardTaskBuffer(10))
            {
                buffer.QueuedTaskAdded += (s, e) => handlerCalled = true;
                buffer.TryAddNewTask(new MockQueuedTaskToken(Guid.NewGuid()));
            }

            Assert.IsTrue(handlerCalled);
        }
예제 #4
0
        public void Test_CanAdd_NonFullBuffer(int capacity)
        {
            using (StandardTaskBuffer buffer = new StandardTaskBuffer(capacity))
            {
                for (int i = 0; i < buffer.Capacity; i++)
                {
                    Assert.IsTrue(buffer.TryAddNewTask(new MockQueuedTaskToken(Guid.NewGuid())));
                }

                Assert.AreEqual(buffer.Capacity, buffer.Count);
                Assert.IsTrue(buffer.IsFull);
                Assert.IsFalse(buffer.IsCompleted);
            }
        }
예제 #5
0
        public void Test_CanCompleteAdding(int capacity)
        {
            using (StandardTaskBuffer buffer = new StandardTaskBuffer(capacity))
            {
                int actualItemNumber = ProduceItemNumber(capacity);

                for (int i = 0; i < actualItemNumber; i++)
                {
                    Assert.IsTrue(buffer.TryAddNewTask(new MockQueuedTaskToken(Guid.NewGuid())));
                }

                //Complete adding
                buffer.CompleteAdding();

                if (buffer.Count > 0)
                {
                    Assert.IsFalse(buffer.IsCompleted);
                }
                else
                {
                    Assert.IsTrue(buffer.IsCompleted);
                }

                //We can no longer add items
                Assert.IsFalse(buffer.TryAddNewTask(new MockQueuedTaskToken(Guid.NewGuid())));

                //We must be able to retrieve the other items
                for (int i = 0; i < actualItemNumber; i++)
                {
                    Assert.NotNull(buffer.TryGetNextTask());
                }

                //Now it must be marked as completed
                Assert.IsTrue(buffer.IsCompleted);
            }
        }
예제 #6
0
        public void Test_ConsumerProducerScenario(int nProducers, int nConsumers)
        {
            Task coordinator;

            Task[] allProducers = new Task[nProducers];
            Task[] allConsumers = new Task[nConsumers];

            int expectedTotal = 0;
            ConcurrentBag <IQueuedTaskToken> processedTasks = new ConcurrentBag <IQueuedTaskToken>();

            using (StandardTaskBuffer buffer = new StandardTaskBuffer(10))
            {
                for (int iProducer = 0; iProducer < nProducers; iProducer++)
                {
                    allProducers[iProducer] = Task.Run(() =>
                    {
                        //Generate a number of items to produce
                        // and add that to the expected total
                        int nItems = new Random().Next(1, 100);
                        Interlocked.Add(ref expectedTotal, nItems);

                        while (nItems > 0)
                        {
                            bool isAdded = buffer.TryAddNewTask(new MockQueuedTaskToken(Guid.NewGuid()));
                            if (isAdded)
                            {
                                nItems--;
                            }
                            else
                            {
                                Task.Delay(10).Wait();
                            }
                        }
                    });
                }

                for (int iConsumer = 0; iConsumer < nConsumers; iConsumer++)
                {
                    allConsumers[iConsumer] = Task.Run(() =>
                    {
                        //Consumers run until the buffer is completed:
                        //  - marked as completed with respect to additons
                        //      AND
                        //  - has no more items
                        while (!buffer.IsCompleted)
                        {
                            IQueuedTaskToken queuedTaskToken = buffer.TryGetNextTask();
                            if (queuedTaskToken != null)
                            {
                                processedTasks.Add(queuedTaskToken);
                            }
                            else
                            {
                                Task.Delay(10).Wait();
                            }
                        }
                    });
                }

                coordinator = Task.Run(() =>
                {
                    //The coordinator waits for all producers
                    //  to finish and then marks buffer
                    //  addition operations as being completed
                    Task.WaitAll(allProducers);
                    buffer.CompleteAdding();
                });

                //Wait for all threads to stop
                Task.WaitAll(coordinator);
                Task.WaitAll(allConsumers);

                //Check that:
                //  a) we have the exact number of items we added
                //  b) there are no items that have been processed two times

                Assert.AreEqual(expectedTotal,
                                processedTasks.Count);

                foreach (IQueuedTaskToken queuedTaskToken in processedTasks)
                {
                    Assert.AreEqual(1, processedTasks.Count(t => t.DequeuedTask.Id == queuedTaskToken.DequeuedTask.Id));
                }
            }
        }