A queue of items waiting to be processed.
        public void ShouldHandleShouldExposeQueueAndPositionInQueue()
        {
            var queue = new ProcessQueue();
            Action action = () => { };

            var handle1 = queue.Add(action);
            var handle2 = queue.Add(action);
            var handle3 = queue.Add(action);

            handle1.Queue.ShouldBe(queue);

            // --

            var notInQueueHandle = new ProcessQueue().Add(action);

            queue.GetPosition(null).ShouldBe(-1);
            queue.GetPosition(notInQueueHandle).ShouldBe(-1);
            queue.GetPosition(handle1).ShouldBe(0);
            queue.GetPosition(handle2).ShouldBe(1);
            queue.GetPosition(handle3).ShouldBe(2);

            // --

            handle1.Position.ShouldBe(0);
            handle2.Position.ShouldBe(1);
            handle3.Position.ShouldBe(2);
        }
        public void ShouldDetermineIfHandleIsContainedWithinQueue()
        {
            var queue = new ProcessQueue();
            Action action = () => { };
            queue.Contains(null).ShouldBe(false);

            var handle1 = queue.Add(action);
            queue.Contains(handle1).ShouldBe(true);

            queue.Remove(handle1);
            queue.Contains(handle1).ShouldBe(false);
        }
        public void ShouldReturnHandleWhenItemAddedToQueue()
        {
            var queue = new ProcessQueue();
            queue.Count.ShouldBe(0);

            Action action = () => { };
            var handle = queue.Add(action);
            
            handle.ShouldNotBe(null);
            handle.Action.ShouldBe(action);
            queue.Count.ShouldBe(1);

            Should.Throw<ArgumentNullException>(() => queue.Add(null));
        }
        public void ShouldRemoveHandleFromQueue()
        {
            var queue = new ProcessQueue();
            Action action = () => { };

            var handle1 = queue.Add(action);
            var handle2 = queue.Add(action);
            var handle3 = queue.Add(action);

            queue.Count.ShouldBe(3);
            queue.Remove(null);
            queue.Count.ShouldBe(3);

            queue.Remove(handle1);
            queue.Count.ShouldBe(2);
            queue.Contains(handle1).ShouldBe(false);

            handle2.Position.ShouldBe(0);
            handle3.Position.ShouldBe(1);

            queue.Remove(handle2);
            queue.Remove(handle3);
            queue.Count.ShouldBe(0);

            // --
            queue.Remove(handle1);
            queue.Remove(handle2);
            queue.Remove(handle3);
        }
        public void ShouldProcessNext()
        {
            var queue = new ProcessQueue();

            var processCount = 0;
            Action action = () => { processCount++; };

            queue.Add(action);
            queue.Add(action);
            queue.Add(action);

            queue.ProcessNext().ShouldBe(true);
            queue.ProcessNext().ShouldBe(true);
            queue.ProcessNext().ShouldBe(true);
            queue.ProcessNext().ShouldBe(false); // Empty

            processCount.ShouldBe(3);
        }
        public void ShouldExposeTheNextItem()
        {
            var queue = new ProcessQueue();
            queue.NextItem.ShouldBe(null);

            Action action = () => { };
            var handle1 = queue.Add(action);
            var handle2 = queue.Add(action);
            var handle3 = queue.Add(action);

            queue.NextItem.ShouldBe(handle1);

            handle1.Process();
            queue.NextItem.ShouldBe(handle2);

            queue.Remove(handle2);
            queue.NextItem.ShouldBe(handle3);

            handle3.Process();
            queue.Count.ShouldBe(0);
            queue.NextItem.ShouldBe(null);
        }
        public void ShouldFirePreAndPostProcessEventsFromQueue()
        {
            var queue = new ProcessQueue();
            Action action = () => { };
            var handle1 = queue.Add(action);

            var processingCount = 0;
            queue.Processing += (s, e) =>
                                            {
                                                processingCount++;
                                                e.Handle.ShouldBe(handle1);
                                                e.Cancel.ShouldBe(false);
                                            };

            var processedCount = 0;
            queue.Processed += (s, e) =>
                                            {
                                                processedCount++;
                                                e.Handle.ShouldBe(handle1);
                                                e.Cancel.ShouldBe(false);
                                                handle1.IsProcessed.ShouldBe(true);
                                            };

            handle1.Process();
            processingCount.ShouldBe(1);
            processedCount.ShouldBe(1);
            handle1.IsProcessed.ShouldBe(true);
        }
        public void ShouldCancelProcessViaQueueEvent()
        {
            var queue = new ProcessQueue();
            var processCount = 0;
            Action action = () => { processCount++; };

            var handle1 = queue.Add(action);
            queue.Contains(handle1).ShouldBe(true);

            // Cancel the process when the pre-event fires.
            queue.Processing += (s, e) => { e.Cancel = true; };

            // Attempt to process.
            handle1.Process();
            processCount.ShouldBe(0);
            handle1.IsProcessed.ShouldBe(false);
            handle1.IsQueued.ShouldBe(false);

            // Cancelled item should be removed from queue.
            queue.Contains(handle1).ShouldBe(false);
        }
        public void ShouldBeAbleToProcessInAnyOrder()
        {
            var queue = new ProcessQueue();

            var processCount = 0;
            Action action = () => { processCount++; };

            var handle1 = queue.Add(action);
            var handle2 = queue.Add(action);

            handle2.Process();
            handle1.Process();

            processCount.ShouldBe(2);
            queue.Count.ShouldBe(0);
        }
        public void ShouldBeAbleToProcessEvenIfRemovedFromQueue()
        {
            var queue = new ProcessQueue();

            var processCount = 0;
            Action action = () => { processCount++; };

            var handle1 = queue.Add(action);
            handle1.Remove();
            queue.Contains(handle1).ShouldBe(false);
            queue.Count.ShouldBe(0);

            handle1.IsProcessed.ShouldBe(false);
            handle1.IsQueued.ShouldBe(false);
            processCount.ShouldBe(0);

            handle1.Process();
            processCount.ShouldBe(1);
            handle1.IsProcessed.ShouldBe(true);
        }
        public void ShouldNotProcessMoreThanOnce()
        {
            var queue = new ProcessQueue();

            var processCount = 0;
            Action action = () => { processCount++; };

            var handle1 = queue.Add(action);

            handle1.Process();
            processCount.ShouldBe(1);

            handle1.Process();
            handle1.Process();
            handle1.Process();
            processCount.ShouldBe(1);
        }
        public void ShouldProcessAndBeRemovedFromQueue()
        {
            var queue = new ProcessQueue();
            Action action = () => { };

            var handle1 = queue.Add(action);
            var handle2 = queue.Add(action);

            handle1.IsProcessed.ShouldBe(false);
            handle2.IsProcessed.ShouldBe(false);

            handle1.Process();
            handle1.IsProcessed.ShouldBe(true);
            queue.Count.ShouldBe(1);
            queue.Contains(handle1).ShouldBe(false);
        }
        public void ShouldReportIsQueued()
        {
            var queue = new ProcessQueue();
            Action action = () => { };

            var handle1 = queue.Add(action);
            var handle2 = queue.Add(action);
            var handle3 = queue.Add(action);

            handle1.IsQueued.ShouldBe(true);
            handle2.IsQueued.ShouldBe(true);

            queue.Remove(handle1);

            handle1.IsQueued.ShouldBe(false);
            handle2.IsQueued.ShouldBe(true);
            handle3.IsQueued.ShouldBe(true);
        }