package com.eternus.ratelimit.circuitbreaker;
import static org.junit.Assert.*;
import org.junit.Test;
public class TestCircuitBreaker {
@Test
public void basicUsage() throws Exception {
CircuitBreakerConfiguration config = new CircuitBreakerConfiguration();
config.setThreshold(1);
config.setTimeoutInMillis(100);
CircuitBreaker circuitBreaker = config.createCircuitBreaker();
assertEquals(0L, circuitBreaker.getTripCount());
assertEquals("CLOSED", circuitBreaker.getCurrentState());
Runnable failingOperation = new Runnable() {
/**
* {@inheritDoc}
*/
public void run() {
doFailingOp();
}
};
tryGuardedOperation(circuitBreaker, failingOperation);
assertEquals(0L, circuitBreaker.getTripCount());
assertEquals("CLOSED", circuitBreaker.getCurrentState());
tryGuardedOperation(circuitBreaker, failingOperation);
assertEquals("circuit breaker has been tripped after second failure", 1L, circuitBreaker.getTripCount());
assertEquals("OPEN", circuitBreaker.getCurrentState());
}
@Test
public void willAttemptReset() throws Exception {
CircuitBreakerConfiguration config = new CircuitBreakerConfiguration();
config.setThreshold(1);
config.setTimeoutInMillis(100);
CircuitBreaker circuitBreaker = config.createCircuitBreaker();
assertEquals(0L, circuitBreaker.getTripCount());
assertEquals("CLOSED", circuitBreaker.getCurrentState());
Runnable failingOperation = new Runnable() {
/**
* {@inheritDoc}
*/
public void run() {
doFailingOp();
}
};
tryGuardedOperation(circuitBreaker, failingOperation);
assertEquals(0L, circuitBreaker.getTripCount());
assertEquals("CLOSED", circuitBreaker.getCurrentState());
tryGuardedOperation(circuitBreaker, failingOperation);
assertEquals("circuit breaker has been tripped after second failure", 1L, circuitBreaker.getTripCount());
assertEquals("OPEN", circuitBreaker.getCurrentState());
Thread.sleep(100);
tryGuardedOperation(circuitBreaker, new Runnable() {
/**
* {@inheritDoc}
*/
public void run() {
// no-op - simulate successful operation
}
});
assertEquals("Operation was successful and the CircuitBreaker is now closed again", "CLOSED", circuitBreaker
.getCurrentState());
}
@Test
public void canBeResetAndSuccessfullyCarryOn() throws Exception {
CircuitBreakerConfiguration config = new CircuitBreakerConfiguration();
config.setThreshold(0);
config.setTimeoutInMillis(100);
CircuitBreaker circuitBreaker = config.createCircuitBreaker();
assertEquals(0L, circuitBreaker.getTripCount());
assertEquals("CLOSED", circuitBreaker.getCurrentState());
Runnable failingOperation = new Runnable() {
/**
* {@inheritDoc}
*/
public void run() {
doFailingOp();
}
};
tryGuardedOperation(circuitBreaker, failingOperation);
assertEquals("circuit breaker has been tripped after first failure", 1L, circuitBreaker.getTripCount());
assertEquals("OPEN", circuitBreaker.getCurrentState());
circuitBreaker.reset();
assertEquals("CLOSED", circuitBreaker.getCurrentState());
tryGuardedOperation(circuitBreaker, new Runnable() {
/**
* {@inheritDoc}
*/
public void run() {
// no-op - simulate successful operation
}
});
assertEquals("Operation was successful and the CircuitBreaker is now closed again", "CLOSED", circuitBreaker
.getCurrentState());
}
private void tryGuardedOperation(CircuitBreaker circuitBreaker, Runnable operation) {
try {
circuitBreaker.before();
operation.run();
circuitBreaker.after();
} catch (Throwable e) {
circuitBreaker.handleFailure();
}
}
private void doFailingOp() {
throw new RuntimeException("Simulate failing operation");
}
}