Example #1
0
        public void Should_control_executions_per_specification(int maxParallelization, int maxQueuingActions, int totalActions, bool cancelQueuing, bool cancelExecuting, string scenario)
        {
            if (totalActions < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(totalActions));
            }

            MaxParallelization = maxParallelization;
            MaxQueuingActions  = maxQueuingActions;
            TotalActions       = totalActions;
            Scenario           = $"MaxParallelization {maxParallelization}; MaxQueuing {maxQueuingActions}; TotalActions {totalActions}; CancelQueuing {cancelQueuing}; CancelExecuting {cancelExecuting}: {scenario}";

            IBulkheadPolicy bulkhead = GetBulkhead(maxParallelization, maxQueuingActions);

            using (bulkhead)
            {
                BulkheadForStats = bulkhead;

                // Set up delegates which we can track whether they've started; and control when we allow them to complete (to release their semaphore slot).
                Actions = new TraceableAction[totalActions];
                for (int i = 0; i < totalActions; i++)
                {
                    Actions[i] = new TraceableAction(i, StatusChangedEvent, TestOutputHelper);
                }

                // Throw all the delegates at the bulkhead simultaneously.
                Tasks = new Task[totalActions];
                for (int i = 0; i < totalActions; i++)
                {
                    Tasks[i] = ExecuteOnBulkhead(bulkhead, Actions[i]);
                }

                OutputStatus("Immediately after queueing...");

                // Assert the expected distributions of executing, queuing, rejected and completed - when all delegates thrown at bulkhead.
                ExpectedCompleted    = 0;
                ExpectedCancelled    = 0;
                ExpectedExecuting    = Math.Min(totalActions, maxParallelization);
                ExpectedRejects      = Math.Max(0, totalActions - maxParallelization - maxQueuingActions);
                ExpectedQueuing      = Math.Min(maxQueuingActions, Math.Max(0, totalActions - maxParallelization));
                ExpectedBulkheadFree = maxParallelization - ExpectedExecuting;
                ExpectedQueueFree    = maxQueuingActions - ExpectedQueuing;

                try
                {
                    Within(CohesionTimeLimit, ActualsMatchExpecteds);
                }
                finally
                {
                    OutputStatus("Expected initial state verified...");
                }

                // Complete or cancel delegates one by one, and expect others to take their place (if a slot released and others remain queueing); until all work is done.
                while (ExpectedExecuting > 0)
                {
                    if (cancelQueuing)
                    {
                        TestOutputHelper.WriteLine("Cancelling a queueing task...");

                        Actions.First(a => a.Status == TraceableActionStatus.QueueingForSemaphore).Cancel();

                        ExpectedCancelled++;
                        ExpectedQueuing--;
                        ExpectedQueueFree++;

                        cancelQueuing = false;
                    }
                    else if (cancelExecuting)
                    {
                        TestOutputHelper.WriteLine("Cancelling an executing task...");

                        Actions.First(a => a.Status == TraceableActionStatus.Executing).Cancel();

                        ExpectedCancelled++;
                        if (ExpectedQueuing > 0)
                        {
                            ExpectedQueuing--;
                            ExpectedQueueFree++;
                        }
                        else
                        {
                            ExpectedExecuting--;
                            ExpectedBulkheadFree++;
                        }

                        cancelExecuting = false;
                    }
                    else // Complete an executing delegate.
                    {
                        TestOutputHelper.WriteLine("Completing a task...");

                        Actions.First(a => a.Status == TraceableActionStatus.Executing).AllowCompletion();

                        ExpectedCompleted++;

                        if (ExpectedQueuing > 0)
                        {
                            ExpectedQueuing--;
                            ExpectedQueueFree++;
                        }
                        else
                        {
                            ExpectedExecuting--;
                            ExpectedBulkheadFree++;
                        }
                    }

                    try
                    {
                        Within(CohesionTimeLimit, ActualsMatchExpecteds);
                    }
                    finally
                    {
                        OutputStatus("End of next loop iteration...");
                    }
                }

                EnsureNoUnbservedTaskExceptions();

                TestOutputHelper.WriteLine("Verifying all tasks completed...");
                Within(CohesionTimeLimit, AllTasksCompleted);
            }
        }
Example #2
0
 protected abstract Task ExecuteOnBulkhead(IBulkheadPolicy bulkhead, TraceableAction action);
 protected override Task ExecuteOnBulkhead(IBulkheadPolicy bulkhead, TraceableAction action)
 {
     return(action.ExecuteOnBulkheadAsync((AsyncBulkheadPolicy)bulkhead));
 }
Example #4
0
 protected override Task ExecuteOnBulkhead(IBulkheadPolicy bulkhead, TraceableAction action)
 {
     return(action.ExecuteOnBulkhead <ResultPrimitive>((BulkheadPolicy <ResultPrimitive>)bulkhead));
 }
Example #5
0
        public void Should_be_able_to_use_BulkheadAvailableCount_via_interface()
        {
            IBulkheadPolicy bulkhead = Policy.Bulkhead(20, 10);

            bulkhead.BulkheadAvailableCount.Should().Be(20);
        }