public void Command_ExecutionHookFailureWithSemaphoreIsolation() { /* test with Execute() */ TryableSemaphore semaphore = new TryableSemaphore(HystrixPropertyFactory.AsProperty(0)); TestSemaphoreCommand command = new TestSemaphoreCommand(new TestCircuitBreaker(), semaphore, TimeSpan.FromMilliseconds(200)); try { command.Execute(); Assert.Fail("we expect a failure"); } catch (Exception) { // expected } Assert.IsFalse(command.IsExecutedInThread); Assert.IsTrue(command.IsResponseRejected); // the run() method should not run as we are rejected Assert.AreEqual(0, command.Builder.ExecutionHook.StartRun); // null as run() does not get invoked Assert.IsNull(command.Builder.ExecutionHook.RunSuccessResponse); // null as run() does not get invoked Assert.IsNull(command.Builder.ExecutionHook.RunFailureException); // the fallback() method should run because of rejection Assert.AreEqual(1, command.Builder.ExecutionHook.StartFallback); // null since there is no fallback Assert.IsNull(command.Builder.ExecutionHook.FallbackSuccessResponse); // not null since the fallback is not implemented Assert.IsNotNull(command.Builder.ExecutionHook.FallbackFailureException); // the Execute() method was used Assert.AreEqual(1, command.Builder.ExecutionHook.StartExecute); // we should not have a response since fallback has nothing Assert.IsNull(command.Builder.ExecutionHook.EndExecuteSuccessResponse); // we won't have an exception because rejection doesn't have one Assert.IsNull(command.Builder.ExecutionHook.EndExecuteFailureException); // but we do expect to receive a onError call with FailureType.Shortcircuit Assert.AreEqual(FailureType.RejectedSemaphoreExecution, command.Builder.ExecutionHook.EndExecuteFailureType); // thread execution Assert.AreEqual(0, command.Builder.ExecutionHook.ThreadStart); Assert.AreEqual(0, command.Builder.ExecutionHook.ThreadComplete); Hystrix.Reset(); }
public void Command_ExecutionSemaphoreWithExecution() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); // single thread should work try { TestSemaphoreCommand command = new TestSemaphoreCommand(circuitBreaker, 1, TimeSpan.FromMilliseconds(200)); bool result = command.Execute(); Assert.IsFalse(command.IsExecutedInThread); Assert.IsTrue(result); } catch (Exception e) { // we shouldn't fail on this one throw new Exception("Unexpected exception.", e); } ArrayBlockingQueue<bool> results = new ArrayBlockingQueue<bool>(2); AtomicBoolean exceptionReceived = new AtomicBoolean(); TryableSemaphore semaphore = new TryableSemaphore(HystrixPropertyFactory.AsProperty(1)); IRunnable r = new HystrixContextRunnable(new Runnable(() => { try { results.Add(new TestSemaphoreCommand(circuitBreaker, semaphore, TimeSpan.FromMilliseconds(200)).Execute()); } catch (Exception) { exceptionReceived.Value = true; } })); // 2 threads, the second should be rejected by the semaphore Thread t1 = new Thread(r.Run); Thread t2 = new Thread(r.Run); t1.Start(); t2.Start(); try { t1.Join(); t2.Join(); } catch (Exception) { Assert.Fail("failed waiting on threads"); } if (!exceptionReceived.Value) { Assert.Fail("We expected an exception on the 2nd get"); } // only 1 value is expected as the other should have thrown an exception Assert.AreEqual(1, results.Count); // should contain only a true result Assert.IsTrue(results.Contains(true)); Assert.IsFalse(results.Contains(false)); Assert.AreEqual(2, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Success)); Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ExceptionThrown)); // no failure ... we throw an exception because of rejection but the command does not fail execution Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Failure)); // there is no fallback implemented so no failure can occur on it Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackFailure)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackRejection)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackSuccess)); // we rejected via semaphore Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.SemaphoreRejected)); // the rest should not be involved in this test Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ShortCircuited)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ThreadPoolRejected)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Timeout)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ResponseFromCache)); Assert.AreEqual(3, HystrixRequestLog.GetCurrentRequest().ExecutedCommands.Count()); Hystrix.Reset(); }
public void Command_ExecutionHookSuccessfulCommandWithSemaphoreIsolation() { /* test with Execute() */ TestSemaphoreCommand command = new TestSemaphoreCommand(new TestCircuitBreaker(), 1, TimeSpan.FromMilliseconds(10)); command.Execute(); Assert.IsFalse(command.IsExecutedInThread); // the run() method should run as we're not short-circuited or rejected Assert.AreEqual(1, command.Builder.ExecutionHook.StartRun); // we expect a successful response from run() Assert.IsNotNull(command.Builder.ExecutionHook.RunSuccessResponse); // we do not expect an exception Assert.IsNull(command.Builder.ExecutionHook.RunFailureException); // the fallback() method should not be run as we were successful Assert.AreEqual(0, command.Builder.ExecutionHook.StartFallback); // null since it didn't run Assert.IsNull(command.Builder.ExecutionHook.FallbackSuccessResponse); // null since it didn't run Assert.IsNull(command.Builder.ExecutionHook.FallbackFailureException); // the Execute() method was used Assert.AreEqual(1, command.Builder.ExecutionHook.StartExecute); // we should have a response from Execute() since run() succeeded Assert.IsNotNull(command.Builder.ExecutionHook.EndExecuteSuccessResponse); // we should not have an exception since run() succeeded Assert.IsNull(command.Builder.ExecutionHook.EndExecuteFailureException); // thread execution Assert.AreEqual(0, command.Builder.ExecutionHook.ThreadStart); Assert.AreEqual(0, command.Builder.ExecutionHook.ThreadComplete); /* test with queue() */ command = new TestSemaphoreCommand(new TestCircuitBreaker(), 1, TimeSpan.FromMilliseconds(10)); try { command.Queue().Get(); } catch (Exception e) { throw new Exception("Unexpected exception.", e); } Assert.IsFalse(command.IsExecutedInThread); // the run() method should run as we're not short-circuited or rejected Assert.AreEqual(1, command.Builder.ExecutionHook.StartRun); // we expect a successful response from run() Assert.IsNotNull(command.Builder.ExecutionHook.RunSuccessResponse); // we do not expect an exception Assert.IsNull(command.Builder.ExecutionHook.RunFailureException); // the fallback() method should not be run as we were successful Assert.AreEqual(0, command.Builder.ExecutionHook.StartFallback); // null since it didn't run Assert.IsNull(command.Builder.ExecutionHook.FallbackSuccessResponse); // null since it didn't run Assert.IsNull(command.Builder.ExecutionHook.FallbackFailureException); // the queue() method was used Assert.AreEqual(1, command.Builder.ExecutionHook.StartExecute); // we should have a response from queue() since run() succeeded Assert.IsNotNull(command.Builder.ExecutionHook.EndExecuteSuccessResponse); // we should not have an exception since run() succeeded Assert.IsNull(command.Builder.ExecutionHook.EndExecuteFailureException); // thread execution Assert.AreEqual(0, command.Builder.ExecutionHook.ThreadStart); Assert.AreEqual(0, command.Builder.ExecutionHook.ThreadComplete); Hystrix.Reset(); }
public void Command_ExecutionSemaphoreWithQueue() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); // single thread should work try { bool result = new TestSemaphoreCommand(circuitBreaker, 1, TimeSpan.FromMilliseconds(200)).Queue().Get(); Assert.IsTrue(result); } catch (Exception e) { // we shouldn't fail on this one throw new Exception("Unexpected exception.", e); } AtomicBoolean exceptionReceived = new AtomicBoolean(); TryableSemaphore semaphore = new TryableSemaphore(HystrixPropertyFactory.AsProperty(1)); IRunnable r = new HystrixContextRunnable(new Runnable(() => { try { new TestSemaphoreCommand(circuitBreaker, semaphore, TimeSpan.FromMilliseconds(200)).Queue().Get(); } catch (Exception) { exceptionReceived.Value = true; } })); // 2 threads, the second should be rejected by the semaphore Thread t1 = new Thread(r.Run); Thread t2 = new Thread(r.Run); t1.Start(); t2.Start(); try { t1.Join(); t2.Join(); } catch (Exception) { Assert.Fail("failed waiting on threads"); } if (!exceptionReceived.Value) { Assert.Fail("We expected an exception on the 2nd get"); } Assert.AreEqual(2, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Success)); // we don't have a fallback so threw an exception when rejected Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ExceptionThrown)); // not a failure as the command never executed so can't fail Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Failure)); // no fallback failure as there isn't a fallback implemented Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackFailure)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackRejection)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.FallbackSuccess)); // we should have rejected via semaphore Assert.AreEqual(1, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.SemaphoreRejected)); // the rest should not be involved in this test Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ShortCircuited)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ThreadPoolRejected)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.Timeout)); Assert.AreEqual(0, circuitBreaker.Metrics.GetRollingCount(HystrixRollingNumberEvent.ResponseFromCache)); Assert.AreEqual(3, HystrixRequestLog.GetCurrentRequest().ExecutedCommands.Count()); Hystrix.Reset(); }