package dk.thoerup.circuitbreaker; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; import org.junit.Before; import org.junit.Test; import dk.thoerup.circuitbreaker.CircuitBreaker; import dk.thoerup.circuitbreaker.CircuitBreakerException; import dk.thoerup.circuitbreaker.config.StaticConfig; public class TestCircuitBreaker { public static final int DELAY = 50; public static final int THRESHOLD = 2; CircuitBreaker cb; @Before public void setup() { cb = new CircuitBreaker<>("test", new StaticConfig(THRESHOLD, DELAY) ); } @Test public void defaultState() { assertTrue(cb.isClosed()); assertTrue(cb.getFailureCount() == 0); } @Test public void simpleTest() throws Exception { String retval = (String) cb.invoke( new SucceedingInvocation() ); assertEquals(retval, "OK"); assertTrue( cb.isClosed() ); assertTrue(cb.getFailureCount() == 0); } @Test(expected=IOException.class) public void simpleFailingTest() throws Exception { cb.invoke( new FailingInvocation() ); } @Test public void failingTest() { try { cb.invoke( new FailingInvocation() ); }catch (Exception e) {} assertTrue(cb.getFailureCount() == 1); assertTrue(cb.isClosed()); } @Test public void failAndResetTest() throws Exception { try { cb.invoke( new FailingInvocation() ); }catch (Exception e) {} cb.invoke(new SucceedingInvocation() ); //after one good it should reset back to closed assertTrue(cb.isClosed()); assertTrue(cb.getFailureCount() == 0); } @Test public void normalOpenTest() throws Exception { try{ cb.invoke( new FailingInvocation() ); } catch (IOException e) {} try{ cb.invoke( new FailingInvocation() ); } catch (IOException e) {} assertTrue( cb.isOpen() ); } @Test public void forcedTrip() { assertTrue( cb.isClosed() ); cb.tripBreaker(); assertTrue( cb.isOpen() ); } @Test public void forcedResetTest() throws Exception { try{ cb.invoke( new FailingInvocation() ); } catch (IOException e) {} try{ cb.invoke( new FailingInvocation() ); } catch (IOException e) {} cb.reset(); assertTrue( cb.isClosed() ); assertTrue( cb.getFailureCount() == 0 ); } @Test(expected=CircuitBreakerException.class) public void openAndFailingTest1() throws Exception { cb.tripBreaker(); assertTrue(cb.isOpen()); cb.invoke( new FailingInvocation() ); } @Test(expected=CircuitBreakerException.class) public void openAndFailingTest2() throws Exception { cb.tripBreaker(); assertTrue(cb.isOpen()); cb.invoke( new SucceedingInvocation() ); } @Test public void halfOpen1() throws Exception { cb.tripBreaker(); assertTrue( cb.isOpen() ); Thread.sleep(DELAY*2); cb.invoke( new SucceedingInvocation() ); assertTrue( cb.isClosed() ); } @Test(expected=CircuitBreakerException.class) public void halfOpen2() throws Exception { cb.tripBreaker(); assertTrue( cb.isOpen() ); Thread.sleep(DELAY*2); cb.invoke( new FailingInvocation() ); //in half-open this will cause a CircuitBreakerException, as if it was in open mode } @Test public void halfOpen3() throws Exception { cb.tripBreaker(); assertTrue( cb.isOpen() ); Thread.sleep(DELAY*2); try{ cb.invoke( new FailingInvocation() ); } catch (CircuitBreakerException e) {} assertTrue( cb.isOpen() ); //after failing in half-open go back to open } }