public void StateHasBeenDisposedHoweverFailedRequestComesIn()
        {
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);
            bool exit = false;

            Task t1 = state.ExecuteAsync <bool>(async() =>
            {
                while (!exit)
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(100));
                }
                throw new DivideByZeroException("Fail");
            });

            state.Dispose();
            exit = true;

            try
            {
                t1.Wait();
            }
            catch (AggregateException ex)
            {
                throw ex.InnerException;
            }
        }
        public void NestedInvoker()
        {
            PassThroughInvoker passThrough = new PassThroughInvoker();

            this.parameters = new CircuitBreakerStateParameters
            {
                stateMachine = this.parameters.stateMachine,
                settings     = this.parameters.settings,
                invoker      = passThrough
            };
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);

            int  counter = 0;
            Task t       = state.ExecuteAsync <bool>(async() =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(1));
                counter++;
                return(true);
            });

            t.Wait();

            Assert.AreEqual(1, counter);
            Assert.IsTrue(passThrough.Verify);
        }
        public void NormalToAttempt()
        {
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);

            state.TransitionToAttempt();

            this.stateMachine.VerifySet(m => m.State = It.IsAny <CircuitBreakerStateInternal>(), Times.Never());
        }
        public void NormalFailNoRecordExceptionFilter()
        {
            this.settings.ExceptionTypes.Add(typeof(ArgumentNullException));
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);

            Task task = state.ExecuteAsync <bool>(() =>
            {
                throw new ApplicationException();
            });

            Assert.AreEqual(0, state.FailureCount);
        }
        public void NormalFailNoTrip()
        {
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);

            Task task = state.ExecuteAsync <bool>(() =>
            {
                throw new ApplicationException();
            });

            Assert.AreEqual(1, state.FailureCount);
            Assert.IsTrue(task.IsFaulted);
            Assert.IsNotNull(task.Exception);
            Assert.IsNotNull(task.Exception.InnerException);
            this.stateMachine.VerifySet(m => m.State = It.IsAny <CircuitBreakerStateInternal>(), Times.Never());
        }
        public void NormalFailureReset()
        {
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);
            Task t1 = state.ExecuteAsync <bool>(() =>
            {
                throw new ApplicationException();
            });

            this.stateMachine.VerifySet(m => m.State = It.IsAny <CircuitBreakerStateInternal>(), Times.Never());
            Assert.AreEqual(1, state.FailureCount);

            state.ResetCallback(null);

            Assert.AreEqual(0, state.FailureCount);
        }
        public void NormalToTripped()
        {
            this.settings.FailureThreshold = 1;
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);

            Task task = state.ExecuteAsync <bool>(() =>
            {
                throw new ApplicationException();
            });

            Assert.IsTrue(task.IsFaulted);
            Assert.IsNotNull(task.Exception);
            Assert.IsNotNull(task.Exception.InnerException);
            this.stateMachine.VerifySet(m => m.State = It.IsAny <CircuitBreakerStateTripped>(), Times.Once());
            throw task.Exception.InnerException;
        }
        public void Normal()
        {
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);
            int counter = 0;

            Task t1 = state.ExecuteAsync <bool>(async() =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(1));
                counter++;
                return(true);
            });

            t1.Wait();

            Assert.AreEqual(1, counter);
            this.stateMachine.VerifySet(m => m.State = It.IsAny <CircuitBreakerStateInternal>(), Times.Never());
        }
        public void NormalToTrippedMultiple()
        {
            this.settings.FailureThreshold = 2;
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);

            Task t1 = state.ExecuteAsync <bool>(() =>
            {
                throw new ApplicationException();
            });

            this.stateMachine.VerifySet(m => m.State = It.IsAny <CircuitBreakerStateInternal>(), Times.Never());
            Task t2 = state.ExecuteAsync <bool>(() =>
            {
                throw new ApplicationException();
            });

            this.stateMachine.VerifySet(m => m.State = It.IsAny <CircuitBreakerStateTripped>(), Times.Once());
        }
        public void NormalFailureResetUsingTimer()
        {
            this.settings.FailureExpiryPeriod = TimeSpan.FromMilliseconds(1);
            var state = new CircuitBreakerStateNormal(this.parameters);

            this.stateMachine.SetupProperty(m => m.State, state);
            Task t1 = state.ExecuteAsync <bool>(() =>
            {
                throw new ApplicationException();
            });

            try
            {
                t1.Wait();
            }
            catch
            {
            }

            Thread.Sleep(TimeSpan.FromMilliseconds(50));

            Assert.AreEqual(0, state.FailureCount);
        }
        public void StateChangedNotification()
        {
            var parameters = new CircuitBreakerStateParameters
            {
                stateMachine = this.stateMachine,
                settings     = new CircuitBreakerSettings(),
                invoker      = new InnerCommandInvoker()
            };
            var  newState  = new CircuitBreakerStateNormal(parameters);
            bool wasCalled = false;

            this.stateMachine.StateChanged += (sender, e) =>
            {
                wasCalled = true;

                Assert.AreEqual(this.initialState.Object, e.Previous);
                Assert.AreEqual(newState, e.Current);
            };
            this.stateMachine.State = newState;

            Assert.IsTrue(wasCalled);
            Assert.AreEqual(newState, this.stateMachine.State);
        }