/** * Copyright 2015 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.netflix.hystrix; import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy; import com.netflix.hystrix.AbstractTestHystrixCommand.CacheEnabled; import com.netflix.hystrix.AbstractTestHystrixCommand.ExecutionResult; import com.netflix.hystrix.AbstractTestHystrixCommand.FallbackResult; import com.netflix.hystrix.exception.HystrixBadRequestException; import com.netflix.hystrix.strategy.HystrixPlugins; import com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler; import com.netflix.hystrix.strategy.properties.HystrixProperty; import org.junit.Test; import rx.Observable; import rx.Scheduler; import rx.Subscriber; import rx.functions.Action1; import rx.functions.Func0; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.junit.Assert.*; /** * Place to share code and tests between {@link HystrixCommandTest} and {@link HystrixObservableCommandTest}. * @param <C> */ public abstract class CommonHystrixCommandTests<C extends AbstractTestHystrixCommand<Integer>> { /** * Run the command in multiple modes and check that the hook assertions hold in each and that the command succeeds * @param ctor {@link AbstractTestHystrixCommand} constructor * @param assertion sequence of assertions to check after the command has completed */ abstract void assertHooksOnSuccess(Func0<C> ctor, Action1<C> assertion); /** * Run the command in multiple modes and check that the hook assertions hold in each and that the command fails * @param ctor {@link AbstractTestHystrixCommand} constructor * @param assertion sequence of assertions to check after the command has completed */ abstract void assertHooksOnFailure(Func0<C> ctor, Action1<C> assertion); /** * Run the command in multiple modes and check that the hook assertions hold in each and that the command fails * @param ctor {@link AbstractTestHystrixCommand} constructor * @param assertion sequence of assertions to check after the command has completed */ abstract void assertHooksOnFailure(Func0<C> ctor, Action1<C> assertion, boolean failFast); /** * Run the command in multiple modes and check that the hook assertions hold in each and that the command fails as soon as possible * @param ctor {@link AbstractTestHystrixCommand} constructor * @param assertion sequence of assertions to check after the command has completed */ protected void assertHooksOnFailFast(Func0<C> ctor, Action1<C> assertion) { assertHooksOnFailure(ctor, assertion, true); } /** * Run the command via {@link com.netflix.hystrix.HystrixCommand#observe()}, immediately block and then assert * @param command command to run * @param assertion assertions to check * @param isSuccess should the command succeed? */ protected void assertBlockingObserve(C command, Action1<C> assertion, boolean isSuccess) { System.out.println("Running command.observe(), immediately blocking and then running assertions..."); if (isSuccess) { try { command.observe().toList().toBlocking().single(); } catch (Exception ex) { throw new RuntimeException(ex); } } else { try { command.observe().toList().toBlocking().single(); fail("Expected a command failure!"); } catch (Exception ex) { System.out.println("Received expected ex : " + ex); ex.printStackTrace(); } } assertion.call(command); } /** * Run the command via {@link com.netflix.hystrix.HystrixCommand#observe()}, let the {@link rx.Observable} terminal * states unblock a {@link java.util.concurrent.CountDownLatch} and then assert * @param command command to run * @param assertion assertions to check * @param isSuccess should the command succeed? */ protected void assertNonBlockingObserve(C command, Action1<C> assertion, boolean isSuccess) { System.out.println("Running command.observe(), awaiting terminal state of Observable, then running assertions..."); final CountDownLatch latch = new CountDownLatch(1); Observable<Integer> o = command.observe(); o.subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { latch.countDown(); } @Override public void onError(Throwable e) { latch.countDown(); } @Override public void onNext(Integer i) { //do nothing } }); try { latch.await(3, TimeUnit.SECONDS); assertion.call(command); } catch (Exception e) { throw new RuntimeException(e); } if (isSuccess) { try { o.toList().toBlocking().single(); } catch (Exception ex) { throw new RuntimeException(ex); } } else { try { o.toList().toBlocking().single(); fail("Expected a command failure!"); } catch (Exception ex) { System.out.println("Received expected ex : " + ex); ex.printStackTrace(); } } } protected void assertSaneHystrixRequestLog(final int numCommands) { HystrixRequestLog currentRequestLog = HystrixRequestLog.getCurrentRequest(); try { assertEquals(numCommands, currentRequestLog.getAllExecutedCommands().size()); assertFalse(currentRequestLog.getExecutedCommandsAsString().contains("Executed")); assertTrue(currentRequestLog.getAllExecutedCommands().iterator().next().getExecutionEvents().size() >= 1); //Most commands should have 1 execution event, but fallbacks / responses from cache can cause more than 1. They should never have 0 } catch (Throwable ex) { System.out.println("Problematic Request log : " + currentRequestLog.getExecutedCommandsAsString() + " , expected : " + numCommands); throw new RuntimeException(ex); } } protected void assertCommandExecutionEvents(HystrixInvokableInfo<?> command, HystrixEventType... expectedEventTypes) { boolean emitExpected = false; int expectedEmitCount = 0; boolean fallbackEmitExpected = false; int expectedFallbackEmitCount = 0; List<HystrixEventType> condensedEmitExpectedEventTypes = new ArrayList<HystrixEventType>(); for (HystrixEventType expectedEventType: expectedEventTypes) { if (expectedEventType.equals(HystrixEventType.EMIT)) { if (!emitExpected) { //first EMIT encountered, add it to condensedEmitExpectedEventTypes condensedEmitExpectedEventTypes.add(HystrixEventType.EMIT); } emitExpected = true; expectedEmitCount++; } else if (expectedEventType.equals(HystrixEventType.FALLBACK_EMIT)) { if (!fallbackEmitExpected) { //first FALLBACK_EMIT encountered, add it to condensedEmitExpectedEventTypes condensedEmitExpectedEventTypes.add(HystrixEventType.FALLBACK_EMIT); } fallbackEmitExpected = true; expectedFallbackEmitCount++; } else { condensedEmitExpectedEventTypes.add(expectedEventType); } } List<HystrixEventType> actualEventTypes = command.getExecutionEvents(); assertEquals(expectedEmitCount, command.getNumberEmissions()); assertEquals(expectedFallbackEmitCount, command.getNumberFallbackEmissions()); assertEquals(condensedEmitExpectedEventTypes, actualEventTypes); } /** * Threadpool with 1 thread, queue of size 1 */ protected static class SingleThreadedPoolWithQueue implements HystrixThreadPool { final LinkedBlockingQueue<Runnable> queue; final ThreadPoolExecutor pool; private final int rejectionQueueSizeThreshold; public SingleThreadedPoolWithQueue(int queueSize) { this(queueSize, 100); } public SingleThreadedPoolWithQueue(int queueSize, int rejectionQueueSizeThreshold) { queue = new LinkedBlockingQueue<Runnable>(queueSize); pool = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, queue); this.rejectionQueueSizeThreshold = rejectionQueueSizeThreshold; } @Override public ThreadPoolExecutor getExecutor() { return pool; } @Override public Scheduler getScheduler() { return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this); } @Override public Scheduler getScheduler(Func0<Boolean> shouldInterruptThread) { return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this, shouldInterruptThread); } @Override public void markThreadExecution() { // not used for this test } @Override public void markThreadCompletion() { // not used for this test } @Override public void markThreadRejection() { // not used for this test } @Override public boolean isQueueSpaceAvailable() { return queue.size() < rejectionQueueSizeThreshold; } } /** * Threadpool with 1 thread, queue of size 1 */ protected static class SingleThreadedPoolWithNoQueue implements HystrixThreadPool { final SynchronousQueue<Runnable> queue; final ThreadPoolExecutor pool; public SingleThreadedPoolWithNoQueue() { queue = new SynchronousQueue<Runnable>(); pool = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, queue); } @Override public ThreadPoolExecutor getExecutor() { return pool; } @Override public Scheduler getScheduler() { return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this); } @Override public Scheduler getScheduler(Func0<Boolean> shouldInterruptThread) { return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this, shouldInterruptThread); } @Override public void markThreadExecution() { // not used for this test } @Override public void markThreadCompletion() { // not used for this test } @Override public void markThreadRejection() { // not used for this test } @Override public boolean isQueueSpaceAvailable() { return true; //let the thread pool reject } } /** ********************* SEMAPHORE-ISOLATED Execution Hook Tests *********************************** */ /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : NO * Execution Result: SUCCESS */ @Test public void testExecutionHookSemaphoreSuccess() { assertHooksOnSuccess( new Func0<C>() { @Override public C call() { return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, FallbackResult.SUCCESS); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(1, 0, 1)); assertTrue(hook.executionEventsMatch(1, 0, 1)); assertTrue(hook.fallbackEventsMatch(0, 0, 0)); assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionEmit - !onRunSuccess - !onComplete - onEmit - onExecutionSuccess - onSuccess - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : NO * Execution Result: synchronous HystrixBadRequestException */ @Test public void testExecutionHookSemaphoreBadRequestException() { assertHooksOnFailure( new Func0<C>() { @Override public C call() { return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.BAD_REQUEST, FallbackResult.SUCCESS); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(0, 1, 0)); assertTrue(hook.executionEventsMatch(0, 1, 0)); assertTrue(hook.fallbackEventsMatch(0, 0, 0)); assertEquals(HystrixBadRequestException.class, hook.getCommandException().getClass()); assertEquals(HystrixBadRequestException.class, hook.getExecutionException().getClass()); assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onError - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : NO * Execution Result: synchronous HystrixRuntimeException * Fallback: UnsupportedOperationException */ @Test public void testExecutionHookSemaphoreExceptionNoFallback() { assertHooksOnFailure( new Func0<C>() { @Override public C call() { return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.FAILURE, FallbackResult.UNIMPLEMENTED); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(0, 1, 0)); assertTrue(hook.executionEventsMatch(0, 1, 0)); assertTrue(hook.fallbackEventsMatch(0, 0, 0)); assertEquals(RuntimeException.class, hook.getCommandException().getClass()); assertEquals(RuntimeException.class, hook.getExecutionException().getClass()); assertNull(hook.getFallbackException()); assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onError - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : NO * Execution Result: synchronous HystrixRuntimeException * Fallback: SUCCESS */ @Test public void testExecutionHookSemaphoreExceptionSuccessfulFallback() { assertHooksOnSuccess( new Func0<C>() { @Override public C call() { return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.FAILURE, FallbackResult.SUCCESS); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(1, 0, 1)); assertTrue(hook.executionEventsMatch(0, 1, 0)); assertTrue(hook.fallbackEventsMatch(1, 0, 1)); assertEquals(RuntimeException.class, hook.getExecutionException().getClass()); assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onFallbackStart - onFallbackEmit - !onFallbackSuccess - !onComplete - onEmit - onFallbackSuccess - onSuccess - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : NO * Execution Result: synchronous HystrixRuntimeException * Fallback: synchronous HystrixRuntimeException */ @Test public void testExecutionHookSemaphoreExceptionUnsuccessfulFallback() { assertHooksOnFailure( new Func0<C>() { @Override public C call() { return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.FAILURE, FallbackResult.FAILURE); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(0, 1, 0)); assertTrue(hook.executionEventsMatch(0, 1, 0)); assertTrue(hook.fallbackEventsMatch(0, 1, 0)); assertEquals(RuntimeException.class, hook.getCommandException().getClass()); assertEquals(RuntimeException.class, hook.getExecutionException().getClass()); assertEquals(RuntimeException.class, hook.getFallbackException().getClass()); assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onFallbackStart - onFallbackError - onError - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : YES * Fallback: UnsupportedOperationException */ @Test public void testExecutionHookSemaphoreRejectedNoFallback() { assertHooksOnFailFast( new Func0<C>() { @Override public C call() { AbstractCommand.TryableSemaphore semaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(2)); final C cmd1 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.UNIMPLEMENTED, semaphore); final C cmd2 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.UNIMPLEMENTED, semaphore); //saturate the semaphore new Thread() { @Override public void run() { cmd1.observe(); } }.start(); new Thread() { @Override public void run() { cmd2.observe(); } }.start(); try { //give the saturating threads a chance to run before we run the command we want to get rejected Thread.sleep(200); } catch (InterruptedException ie) { throw new RuntimeException(ie); } return getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.UNIMPLEMENTED, semaphore); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(0, 1, 0)); assertTrue(hook.executionEventsMatch(0, 0, 0)); assertTrue(hook.fallbackEventsMatch(0, 0, 0)); assertEquals(RuntimeException.class, hook.getCommandException().getClass()); assertNull(hook.getFallbackException()); assertEquals("onStart - onError - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : YES * Fallback: SUCCESS */ @Test public void testExecutionHookSemaphoreRejectedSuccessfulFallback() { assertHooksOnSuccess( new Func0<C>() { @Override public C call() { AbstractCommand.TryableSemaphore semaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(2)); final C cmd1 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 1500, FallbackResult.SUCCESS, semaphore); final C cmd2 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 1500, FallbackResult.SUCCESS, semaphore); //saturate the semaphore new Thread() { @Override public void run() { cmd1.observe(); } }.start(); new Thread() { @Override public void run() { cmd2.observe(); } }.start(); try { //give the saturating threads a chance to run before we run the command we want to get rejected Thread.sleep(200); } catch (InterruptedException ie) { throw new RuntimeException(ie); } return getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.SUCCESS, semaphore); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(1, 0, 1)); assertTrue(hook.executionEventsMatch(0, 0, 0)); assertTrue(hook.fallbackEventsMatch(1, 0, 1)); assertEquals("onStart - onFallbackStart - onFallbackEmit - !onFallbackSuccess - !onComplete - onEmit - onFallbackSuccess - onSuccess - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : NO * Thread/semaphore: SEMAPHORE * Semaphore Permit reached? : YES * Fallback: synchronous HystrixRuntimeException */ @Test public void testExecutionHookSemaphoreRejectedUnsuccessfulFallback() { assertHooksOnFailFast( new Func0<C>() { @Override public C call() { AbstractCommand.TryableSemaphore semaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(2)); final C cmd1 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.FAILURE, semaphore); final C cmd2 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.FAILURE, semaphore); //saturate the semaphore new Thread() { @Override public void run() { cmd1.observe(); } }.start(); new Thread() { @Override public void run() { cmd2.observe(); } }.start(); try { //give the saturating threads a chance to run before we run the command we want to get rejected Thread.sleep(200); } catch (InterruptedException ie) { throw new RuntimeException(ie); } return getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.FAILURE, semaphore); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(0, 1, 0)); assertTrue(hook.executionEventsMatch(0, 0, 0)); assertTrue(hook.fallbackEventsMatch(0, 1, 0)); assertEquals(RuntimeException.class, hook.getCommandException().getClass()); assertEquals(RuntimeException.class, hook.getFallbackException().getClass()); assertEquals("onStart - onFallbackStart - onFallbackError - onError - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : YES * Thread/semaphore: SEMAPHORE * Fallback: UnsupportedOperationException */ @Test public void testExecutionHookSemaphoreShortCircuitNoFallback() { assertHooksOnFailFast( new Func0<C>() { @Override public C call() { return getCircuitOpenCommand(ExecutionIsolationStrategy.SEMAPHORE, FallbackResult.UNIMPLEMENTED); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(0, 1, 0)); assertTrue(hook.executionEventsMatch(0, 0, 0)); assertTrue(hook.fallbackEventsMatch(0, 0, 0)); assertEquals(RuntimeException.class, hook.getCommandException().getClass()); assertNull(hook.getFallbackException()); assertEquals("onStart - onError - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : YES * Thread/semaphore: SEMAPHORE * Fallback: SUCCESS */ @Test public void testExecutionHookSemaphoreShortCircuitSuccessfulFallback() { assertHooksOnSuccess( new Func0<C>() { @Override public C call() { return getCircuitOpenCommand(ExecutionIsolationStrategy.SEMAPHORE, FallbackResult.SUCCESS); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(1, 0, 1)); assertTrue(hook.executionEventsMatch(0, 0, 0)); assertTrue(hook.fallbackEventsMatch(1, 0, 1)); assertEquals("onStart - onFallbackStart - onFallbackEmit - !onFallbackSuccess - !onComplete - onEmit - onFallbackSuccess - onSuccess - ", hook.executionSequence.toString()); } }); } /** * Short-circuit? : YES * Thread/semaphore: SEMAPHORE * Fallback: synchronous HystrixRuntimeException */ @Test public void testExecutionHookSemaphoreShortCircuitUnsuccessfulFallback() { assertHooksOnFailFast( new Func0<C>() { @Override public C call() { return getCircuitOpenCommand(ExecutionIsolationStrategy.SEMAPHORE, FallbackResult.FAILURE); } }, new Action1<C>() { @Override public void call(C command) { TestableExecutionHook hook = command.getBuilder().executionHook; assertTrue(hook.commandEmissionsMatch(0, 1, 0)); assertTrue(hook.executionEventsMatch(0, 0, 0)); assertTrue(hook.fallbackEventsMatch(0, 1, 0)); assertEquals(RuntimeException.class, hook.getCommandException().getClass()); assertEquals(RuntimeException.class, hook.getFallbackException().getClass()); assertEquals("onStart - onFallbackStart - onFallbackError - onError - ", hook.executionSequence.toString()); } }); } /** ********************* END SEMAPHORE-ISOLATED Execution Hook Tests *********************************** */ /** * Abstract methods defining a way to instantiate each of the described commands. * {@link HystrixCommandTest} and {@link HystrixObservableCommandTest} should each provide concrete impls for * {@link HystrixCommand}s and {@link} HystrixObservableCommand}s, respectively. */ C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult) { return getCommand(isolationStrategy, executionResult, FallbackResult.UNIMPLEMENTED); } C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency) { return getCommand(isolationStrategy, executionResult, executionLatency, FallbackResult.UNIMPLEMENTED); } C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, FallbackResult fallbackResult) { return getCommand(isolationStrategy, executionResult, 0, fallbackResult); } C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult) { return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, (executionLatency * 2) + 200, CacheEnabled.NO, "foo", 10, 10); } C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int timeout) { return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, timeout, CacheEnabled.NO, "foo", 10, 10); } C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, int fallbackSemaphoreCount) { return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphoreCount, fallbackSemaphoreCount, false); } C getCommand(HystrixCommandKey key, ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, int fallbackSemaphoreCount) { AbstractCommand.TryableSemaphoreActual executionSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(executionSemaphoreCount)); AbstractCommand.TryableSemaphoreActual fallbackSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(fallbackSemaphoreCount)); return getCommand(key, isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphore, fallbackSemaphore, false); } C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, int fallbackSemaphoreCount, boolean circuitBreakerDisabled) { AbstractCommand.TryableSemaphoreActual executionSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(executionSemaphoreCount)); AbstractCommand.TryableSemaphoreActual fallbackSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(fallbackSemaphoreCount)); return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphore, fallbackSemaphore, circuitBreakerDisabled); } C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, AbstractCommand.TryableSemaphore fallbackSemaphore, boolean circuitBreakerDisabled) { AbstractCommand.TryableSemaphoreActual executionSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(executionSemaphoreCount)); return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphore, fallbackSemaphore, circuitBreakerDisabled); } abstract C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, AbstractCommand.TryableSemaphore executionSemaphore, AbstractCommand.TryableSemaphore fallbackSemaphore, boolean circuitBreakerDisabled); abstract C getCommand(HystrixCommandKey commandKey, ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, AbstractCommand.TryableSemaphore executionSemaphore, AbstractCommand.TryableSemaphore fallbackSemaphore, boolean circuitBreakerDisabled); C getLatentCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int timeout) { return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, timeout, CacheEnabled.NO, "foo", 10, 10); } C getLatentCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout) { return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, circuitBreaker, threadPool, timeout, CacheEnabled.NO, "foo", 10, 10); } C getLatentCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, AbstractCommand.TryableSemaphore executionSemaphore) { AbstractCommand.TryableSemaphoreActual fallbackSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(10)); return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, (executionLatency * 2) + 200, CacheEnabled.NO, "foo", executionSemaphore, fallbackSemaphore, false); } C getCircuitOpenCommand(ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult) { HystrixCircuitBreakerTest.TestCircuitBreaker openCircuit = new HystrixCircuitBreakerTest.TestCircuitBreaker().setForceShortCircuit(true); return getCommand(isolationStrategy, ExecutionResult.SUCCESS, 0, fallbackResult, 0, openCircuit, null, 500, CacheEnabled.NO, "foo", 10, 10, false); } C getSharedCircuitBreakerCommand(HystrixCommandKey commandKey, ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker) { return getCommand(commandKey, isolationStrategy, ExecutionResult.FAILURE, 0, fallbackResult, 0, circuitBreaker, null, 500, CacheEnabled.NO, "foo", 10, 10); } C getCircuitBreakerDisabledCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult) { return getCommand(isolationStrategy, executionResult, 0, FallbackResult.UNIMPLEMENTED, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, 500, CacheEnabled.NO, "foo", 10, 10, true); } C getRecoverableErrorCommand(ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult) { return getCommand(isolationStrategy, ExecutionResult.RECOVERABLE_ERROR, 0, fallbackResult); } C getUnrecoverableErrorCommand(ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult) { return getCommand(isolationStrategy, ExecutionResult.UNRECOVERABLE_ERROR, 0, fallbackResult); } }