package org.distributeme.core.routing; import junit.framework.Assert; import org.distributeme.core.ClientSideCallContext; import org.distributeme.core.failing.FailDecision; import org.junit.Ignore; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; /** * Junit test. * * @author h3llka */ public class AbstractRouterWithFailOversToNextNodeTest { private static final String METHOD1 = "method1"; private static final String METHOD2 = "method2"; @Test public void testWithDefaultServersAmount() { RoundRobinFailOverOn rrFon = new RoundRobinFailOverOn(); RoundRobinFailOverOFF rrfOff = new RoundRobinFailOverOFF(); ModRouterWithEnabledFailing modFon = new ModRouterWithEnabledFailing(); ModRouterWithDisabledFailing modfOff = new ModRouterWithDisabledFailing(); //let's call customization with illegal argument! rrfOff.customize("asd"); rrFon.customize("asd"); modfOff.customize("asd"); modFon.customize("asd"); ClientSideCallContext callContext = new ClientSideCallContext("Service_default", METHOD1, Arrays.asList("11")); Assert.assertEquals("Illegal behaviour is RR-FailOver off router", callContext.getServiceId(), rrfOff.getServiceIdForCall(callContext)); Assert.assertEquals("Illegal behaviour is RR-FailOver on router", callContext.getServiceId(), rrFon.getServiceIdForCall(callContext)); Assert.assertEquals("Illegal behaviour is MOD-FailOver off router", callContext.getServiceId(), modfOff.getServiceIdForCall(callContext)); Assert.assertEquals("Illegal behaviour is MOD-FailOver on router", callContext.getServiceId(), modFon.getServiceIdForCall(callContext)); } @Test public void testFailingWithDefaults() { RoundRobinFailOverOn rrFon = new RoundRobinFailOverOn(); RoundRobinFailOverOFF rrfOff = new RoundRobinFailOverOFF(); ModRouterWithEnabledFailing modFon = new ModRouterWithEnabledFailing(); ModRouterWithDisabledFailing modfOff = new ModRouterWithDisabledFailing(); //let's call customization with illegal argument! rrfOff.customize("asd"); rrFon.customize("asd"); modfOff.customize("asd"); modFon.customize("asd"); ClientSideCallContext callContext = new ClientSideCallContext("Service_default", METHOD1, Arrays.asList("11")); Assert.assertEquals("rrFoff - failing bahaviour failed!", FailDecision.fail().getReaction(), rrfOff.callFailed(callContext).getReaction()); Assert.assertEquals("rrFon - failing bahaviour failed!", FailDecision.fail().getReaction(), rrFon.callFailed(callContext).getReaction()); Assert.assertEquals("modfOff - failing bahaviour failed!", FailDecision.fail().getReaction(), modfOff.callFailed(callContext).getReaction()); Assert.assertEquals("modFon - failing bahaviour failed!", FailDecision.fail().getReaction(), modFon.callFailed(callContext).getReaction()); } //this test doesn't work with the new logic. @Test @Ignore public void testFailingWith3Nodes() { RoundRobinFailOverOn rrFon = new RoundRobinFailOverOn(); RoundRobinFailOverOFF rrfOff = new RoundRobinFailOverOFF(); ModRouterWithEnabledFailing modFon = new ModRouterWithEnabledFailing(); ModRouterWithDisabledFailing modfOff = new ModRouterWithDisabledFailing(); //let's call customization with illegal argument! rrfOff.customize("3"); rrFon.customize("3"); modfOff.customize("3"); modFon.customize("3"); ClientSideCallContext callContext = new ClientSideCallContext("Service_0", METHOD1, Arrays.asList("11")); callContext.setCallCount(0); Assert.assertEquals("rrFoff - failing bahaviour failed! FAILING disabled at all!", FailDecision.fail().getReaction(), rrfOff.callFailed(callContext).getReaction()); Assert.assertEquals("modfOff - failing bahaviour failed! Failing disabled at all", FailDecision.fail().getReaction(), modfOff.callFailed(callContext).getReaction()); Assert.assertEquals("rrFon - failing bahaviour failed!", FailDecision.retry().getReaction(), rrFon.callFailed(callContext).getReaction()); Assert.assertEquals("modFon - failing bahaviour failed!", FailDecision.retry().getReaction(), modFon.callFailed(callContext).getReaction()); callContext.setCallCount(1); Assert.assertEquals("rrFoff - failing bahaviour failed! FAILING disabled at all!", FailDecision.fail().getReaction(), rrfOff.callFailed(callContext).getReaction()); Assert.assertEquals("modfOff - failing bahaviour failed! Failing disabled at all", FailDecision.fail().getReaction(), modfOff.callFailed(callContext).getReaction()); Assert.assertEquals("rrFon - failing bahaviour failed!", FailDecision.retry().getReaction(), rrFon.callFailed(callContext).getReaction()); Assert.assertEquals("rrFON should return Service_1", "Service_1", rrFon.getServiceIdForCall(callContext)); Assert.assertEquals("modFon - failing bahaviour failed!", FailDecision.retry().getReaction(), modFon.callFailed(callContext).getReaction()); Assert.assertEquals("rrFON should return Service_1", "Service_1", modFon.getServiceIdForCall(callContext)); //increase fail counter! callContext.setCallCount(2); Assert.assertEquals("rrFon - failing bahaviour failed!", FailDecision.fail().getReaction(), rrFon.callFailed(callContext).getReaction()); Assert.assertEquals("modFon - failing bahaviour failed!", FailDecision.fail().getReaction(), modFon.callFailed(callContext).getReaction()); } @Test public void testModRoutingOn3Nodes() { ModRouterWithEnabledFailing modFon = new ModRouterWithEnabledFailing(); ModRouterWithDisabledFailing modfOff = new ModRouterWithDisabledFailing(); modFon.customize("3"); modfOff.customize("3"); for (int i = 0; i < 50; i++) { ClientSideCallContext callContext = new ClientSideCallContext("Service", METHOD1, Arrays.asList(i)); String serviceId1 = modfOff.getServiceIdForCall(callContext); String serviceId2 = modFon.getServiceIdForCall(callContext); Assert.assertTrue("Should be in range from 0 to 2", getNodeId(serviceId1) >= 0 && getNodeId(serviceId1) <= 2); Assert.assertTrue("Should be in range from 0 to 2", getNodeId(serviceId2) >= 0 && getNodeId(serviceId2) <= 2); int mod = i % 3; Assert.assertEquals("Should be equal - to calculated mod! - ", "Service_" + mod, serviceId1); Assert.assertEquals("Should be equal - to calculated mod!", "Service_" + mod, serviceId2); } // checking NOT mod routable methods!!! int prevNodeId1 = -1; int prevNodeId2 = -1; //METHOD2 is not routable by mod! ! So let's expect some RR - based result! ClientSideCallContext callContext = new ClientSideCallContext("Service", METHOD2, Arrays.asList("11")); for (int i = 0; i < 100; i++) { String serviceId1 = modfOff.getServiceIdForCall(callContext); String serviceId2 = modFon.getServiceIdForCall(callContext); Assert.assertTrue("Should be in range from 0 to 2", getNodeId(serviceId1) >= 0 && getNodeId(serviceId1) <= 2); Assert.assertTrue("Should be in range from 0 to 2", getNodeId(serviceId2) >= 0 && getNodeId(serviceId2) <= 2); if (prevNodeId1 != -1) { int current = getNodeId(serviceId1); Assert.assertEquals("Should be same number - prevNode1=[" + prevNodeId1 + "], step : " + i + "", prevNodeId1 == 2 ? 0 : prevNodeId1 + 1, current); } prevNodeId1 = getNodeId(serviceId1); if (prevNodeId2 != -1) { int current = getNodeId(serviceId1); Assert.assertEquals("Should be same number - prevNode2=[" + prevNodeId2 + "], step :" + i + "", prevNodeId2 == 2 ? 0 : prevNodeId2 + 1, current); } prevNodeId2 = getNodeId(serviceId2); } } @Test public void testRRRoutingOn3Nodes() { RoundRobinFailOverOn rrFon = new RoundRobinFailOverOn(); RoundRobinFailOverOFF rrfOff = new RoundRobinFailOverOFF(); rrfOff.customize("3"); rrFon.customize("3"); ClientSideCallContext callContext = new ClientSideCallContext("Service", METHOD1, Arrays.asList("11")); int prevNodeId1 = -1; int prevNodeId2 = -1; for (int i = 0; i < 100; i++) { String serviceId1 = rrFon.getServiceIdForCall(callContext); String serviceId2 = rrfOff.getServiceIdForCall(callContext); Assert.assertTrue("Should be in range from 0 to 2", getNodeId(serviceId1) >= 0 && getNodeId(serviceId1) <= 2); Assert.assertTrue("Should be in range from 0 to 2", getNodeId(serviceId2) >= 0 && getNodeId(serviceId2) <= 2); if (prevNodeId1 != -1) { int current = getNodeId(serviceId1); Assert.assertEquals("Should be same number - prevNode1=[" + prevNodeId1 + "], step : " + i + "", prevNodeId1 == 2 ? 0 : prevNodeId1 + 1, current); } prevNodeId1 = getNodeId(serviceId1); if (prevNodeId2 != -1) { int current = getNodeId(serviceId1); Assert.assertEquals("Should be same number - prevNode2=[" + prevNodeId2 + "], step :" + i + "", prevNodeId2 == 2 ? 0 : prevNodeId2 + 1, current); } prevNodeId2 = getNodeId(serviceId2); } } /** * Return node number! * * @param serviceId some service id - to which call will be delegated * @return int */ private int getNodeId(String serviceId) { int lastUnderscore = serviceId.lastIndexOf("_"); try { return Integer.parseInt(serviceId.substring(lastUnderscore + 1)); } catch (NumberFormatException e) { Assert.fail("Unexpected error occurred " + e.getMessage()); } return 0; } @Test public void failuresTest() { RoundRobinFailOverOFF testRR = new RoundRobinFailOverOFF(); try { testRR.customize("-100"); Assert.fail("Not positive value passe to customise!!!"); } catch (Error e) { Assert.assertTrue(e instanceof AssertionError); } ModRouterWithDisabledFailing testMM = new ModRouterWithDisabledFailing(); testMM.customize("2"); try { testMM.getServiceIdForCall(new ClientSideCallContext("SS", METHOD1, null)); Assert.fail("Illegal argument! Can't mod route - without Incoming parameters for MOD counting"); } catch (Error e) { Assert.assertTrue(e instanceof AssertionError); } try { testMM.getServiceIdForCall(new ClientSideCallContext("SS", METHOD1, new ArrayList<Object>())); Assert.fail("Illegal argument! Modabe parameters are BLANK!"); } catch (Error e) { Assert.assertTrue(e instanceof AssertionError); } } /** * RR - with enabled fail over. */ private static class RoundRobinFailOverOn extends AbstractRouterWithFailOverToNextNode { @Override protected boolean failingSupported() { return true; } @Override protected RouterStrategy getStrategy() { return RouterStrategy.RR_ROUTER; } @Override protected long getModableValue(Object parameter) { return 0l; // not required for RR routing } } /** * RR - with disabled fail over. */ private static class RoundRobinFailOverOFF extends AbstractRouterWithFailOverToNextNode { @Override protected boolean failingSupported() { return false; } @Override protected RouterStrategy getStrategy() { return RouterStrategy.RR_ROUTER; } @Override protected long getModableValue(Object parameter) { return 0l; // not required for RR routing } } /** * Mod router with enabled failing. */ private static class ModRouterWithEnabledFailing extends AbstractParameterBasedModRouterWithFailOverToNextNode { /** * Constructor - which add to registry some methods which should be modable routed. */ public ModRouterWithEnabledFailing() { super(); addModRoutedMethod("method1"); } @Override protected long getModableValue(Object parameter) { if (parameter instanceof String) return Long.valueOf(String.class.cast(parameter)); if (parameter instanceof Integer) return Integer.class.cast(parameter); if (parameter instanceof Long) return Long.class.cast(parameter); throw new AssertionError("NOT supported parameter " + parameter); } } /** * Mod router with enabled failing. */ private static class ModRouterWithDisabledFailing extends AbstractParameterBasedModRouterWithFailOverToNextNode { /** * Constructor - which add to registry some methods which should be modable routed. */ public ModRouterWithDisabledFailing() { super(); addModRoutedMethod("method1"); } @Override // disable failing by this! protected boolean failingSupported() { return false; } @Override protected long getModableValue(Object parameter) { if (parameter instanceof String) return Long.valueOf(String.class.cast(parameter)); if (parameter instanceof Integer) return Integer.class.cast(parameter); if (parameter instanceof Long) return Long.class.cast(parameter); throw new AssertionError("NOT supported parameter " + parameter); } } }