use of com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker in project Hystrix by Netflix.
the class HystrixCommandTest method testBadRequestExceptionViaExecuteInSemaphore.
/**
* Test that a BadRequestException can be thrown and not count towards errors and bypasses fallback.
*/
@Test
public void testBadRequestExceptionViaExecuteInSemaphore() {
TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
BadRequestCommand command1 = new BadRequestCommand(circuitBreaker, ExecutionIsolationStrategy.SEMAPHORE);
try {
command1.execute();
fail("we expect to receive a " + HystrixBadRequestException.class.getSimpleName());
} catch (HystrixBadRequestException e) {
// success
e.printStackTrace();
}
assertCommandExecutionEvents(command1, HystrixEventType.BAD_REQUEST);
assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
assertSaneHystrixRequestLog(1);
}
use of com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker in project Hystrix by Netflix.
the class HystrixCommandTest method testExceptionConvertedToBadRequestExceptionInExecutionHookBypassesCircuitBreaker.
@Test
public void testExceptionConvertedToBadRequestExceptionInExecutionHookBypassesCircuitBreaker() {
TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
ExceptionToBadRequestByExecutionHookCommand command = new ExceptionToBadRequestByExecutionHookCommand(circuitBreaker, ExecutionIsolationStrategy.THREAD);
try {
command.execute();
fail("we expect to receive a " + HystrixBadRequestException.class.getSimpleName());
} catch (HystrixBadRequestException e) {
// success
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
fail("We expect a " + HystrixBadRequestException.class.getSimpleName() + " but got a " + e.getClass().getSimpleName());
}
assertCommandExecutionEvents(command, HystrixEventType.BAD_REQUEST);
assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
assertSaneHystrixRequestLog(1);
}
use of com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker in project Hystrix by Netflix.
the class HystrixCommandTest method testSemaphorePermitsInUse.
/**
* Tests that semaphores are counted separately for commands with unique keys
*/
@Test
public void testSemaphorePermitsInUse() throws Exception {
final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
// this semaphore will be shared across multiple command instances
final TryableSemaphoreActual sharedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(3));
// used to wait until all commands have started
final CountDownLatch startLatch = new CountDownLatch((sharedSemaphore.numberOfPermits.get() * 2) + 1);
// used to signal that all command can finish
final CountDownLatch sharedLatch = new CountDownLatch(1);
// tracks failures to obtain semaphores
final AtomicInteger failureCount = new AtomicInteger();
final Runnable sharedSemaphoreRunnable = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
public void run() {
try {
new LatchedSemaphoreCommand("Command-Shared", circuitBreaker, sharedSemaphore, startLatch, sharedLatch).execute();
} catch (Exception e) {
startLatch.countDown();
e.printStackTrace();
failureCount.incrementAndGet();
}
}
});
// creates group of threads each using command sharing a single semaphore
// I create extra threads and commands so that I can verify that some of them fail to obtain a semaphore
final int sharedThreadCount = sharedSemaphore.numberOfPermits.get() * 2;
final Thread[] sharedSemaphoreThreads = new Thread[sharedThreadCount];
for (int i = 0; i < sharedThreadCount; i++) {
sharedSemaphoreThreads[i] = new Thread(sharedSemaphoreRunnable);
}
// creates thread using isolated semaphore
final TryableSemaphoreActual isolatedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(1));
final CountDownLatch isolatedLatch = new CountDownLatch(1);
final Thread isolatedThread = new Thread(new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {
public void run() {
try {
new LatchedSemaphoreCommand("Command-Isolated", circuitBreaker, isolatedSemaphore, startLatch, isolatedLatch).execute();
} catch (Exception e) {
startLatch.countDown();
e.printStackTrace();
failureCount.incrementAndGet();
}
}
}));
// verifies no permits in use before starting threads
assertEquals("before threads start, shared semaphore should be unused", 0, sharedSemaphore.getNumberOfPermitsUsed());
assertEquals("before threads start, isolated semaphore should be unused", 0, isolatedSemaphore.getNumberOfPermitsUsed());
for (int i = 0; i < sharedThreadCount; i++) {
sharedSemaphoreThreads[i].start();
}
isolatedThread.start();
// waits until all commands have started
startLatch.await(1000, TimeUnit.MILLISECONDS);
// verifies that all semaphores are in use
assertEquals("immediately after command start, all shared semaphores should be in-use", sharedSemaphore.numberOfPermits.get().longValue(), sharedSemaphore.getNumberOfPermitsUsed());
assertEquals("immediately after command start, isolated semaphore should be in-use", isolatedSemaphore.numberOfPermits.get().longValue(), isolatedSemaphore.getNumberOfPermitsUsed());
// signals commands to finish
sharedLatch.countDown();
isolatedLatch.countDown();
for (int i = 0; i < sharedThreadCount; i++) {
sharedSemaphoreThreads[i].join();
}
isolatedThread.join();
// verifies no permits in use after finishing threads
System.out.println("REQLOG : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());
assertEquals("after all threads have finished, no shared semaphores should be in-use", 0, sharedSemaphore.getNumberOfPermitsUsed());
assertEquals("after all threads have finished, isolated semaphore not in-use", 0, isolatedSemaphore.getNumberOfPermitsUsed());
// verifies that some executions failed
assertEquals("expected some of shared semaphore commands to get rejected", sharedSemaphore.numberOfPermits.get().longValue(), failureCount.get());
assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
}
use of com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker in project Hystrix by Netflix.
the class HystrixCommandTest method testRejectedThreadWithFallbackFailure.
/**
* Test when a command fails to get queued up in the threadpool where the command implemented getFallback but it fails.
* <p>
* We specifically want to protect against developers getting random thread exceptions and instead just correctly receives an HystrixRuntimeException.
*/
@Test
public void testRejectedThreadWithFallbackFailure() throws ExecutionException, InterruptedException {
TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
SingleThreadedPoolWithQueue pool = new SingleThreadedPoolWithQueue(1);
HystrixCommandKey key = HystrixCommandKey.Factory.asKey("Rejection-A");
//this should pass through the queue and sit in the pool
TestCommandRejection command1 = new TestCommandRejection(key, circuitBreaker, pool, 500, 600, TestCommandRejection.FALLBACK_FAILURE);
//this should sit in the queue
TestCommandRejection command2 = new TestCommandRejection(key, circuitBreaker, pool, 500, 600, TestCommandRejection.FALLBACK_SUCCESS);
//this should observe full queue and get rejected
TestCommandRejection command3 = new TestCommandRejection(key, circuitBreaker, pool, 500, 600, TestCommandRejection.FALLBACK_FAILURE);
Future<Boolean> f1 = null;
Future<Boolean> f2 = null;
try {
f1 = command1.queue();
f2 = command2.queue();
//should get thread-pool rejected
assertEquals(false, command3.queue().get());
fail("we shouldn't get here");
} catch (Exception e) {
e.printStackTrace();
if (e instanceof HystrixRuntimeException && e.getCause() instanceof RejectedExecutionException) {
HystrixRuntimeException de = (HystrixRuntimeException) e;
assertNotNull(de.getFallbackException());
assertFalse(de.getFallbackException() instanceof UnsupportedOperationException);
assertNotNull(de.getImplementingClass());
assertNotNull(de.getCause());
assertTrue(de.getCause() instanceof RejectedExecutionException);
} else {
fail("the exception should be HystrixRuntimeException with cause as RejectedExecutionException");
}
}
//still in-flight, no events yet
assertCommandExecutionEvents(command1);
//still in-flight, no events yet
assertCommandExecutionEvents(command2);
assertCommandExecutionEvents(command3, HystrixEventType.THREAD_POOL_REJECTED, HystrixEventType.FALLBACK_FAILURE);
int numInFlight = circuitBreaker.metrics.getCurrentConcurrentExecutionCount();
//pool-filler still going
assertTrue("Expected at most 1 in flight but got : " + numInFlight, numInFlight <= 1);
//This is a case where we knowingly walk away from executing Hystrix threads. They should have an in-flight status ("Executed"). You should avoid this in a production environment
HystrixRequestLog requestLog = HystrixRequestLog.getCurrentRequest();
assertEquals(3, requestLog.getAllExecutedCommands().size());
assertTrue(requestLog.getExecutedCommandsAsString().contains("Executed"));
//block on the outstanding work, so we don't inadvertently affect any other tests
long startTime = System.currentTimeMillis();
f1.get();
f2.get();
assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
System.out.println("Time blocked : " + (System.currentTimeMillis() - startTime));
}
use of com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker in project Hystrix by Netflix.
the class HystrixCommandTest method testCheckedExceptionViaObserve.
/**
* Test a java.lang.Error being thrown
*
* @throws InterruptedException
*/
@Test
public void testCheckedExceptionViaObserve() throws InterruptedException {
TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
CommandWithCheckedException command = new CommandWithCheckedException(circuitBreaker);
final AtomicReference<Throwable> t = new AtomicReference<Throwable>();
final CountDownLatch latch = new CountDownLatch(1);
try {
command.observe().subscribe(new Observer<Boolean>() {
@Override
public void onCompleted() {
latch.countDown();
}
@Override
public void onError(Throwable e) {
t.set(e);
latch.countDown();
}
@Override
public void onNext(Boolean args) {
}
});
} catch (Exception e) {
e.printStackTrace();
fail("we should not get anything thrown, it should be emitted via the Observer#onError method");
}
latch.await(1, TimeUnit.SECONDS);
assertNotNull(t.get());
t.get().printStackTrace();
assertTrue(t.get() instanceof HystrixRuntimeException);
assertEquals("simulated checked exception message", t.get().getCause().getMessage());
assertEquals("simulated checked exception message", command.getFailedExecutionException().getMessage());
assertTrue(command.getExecutionTimeInMilliseconds() > -1);
assertTrue(command.isFailedExecution());
assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING);
assertNotNull(command.getExecutionException());
assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
assertSaneHystrixRequestLog(1);
}
Aggregations