package jmri.jmrit.logixng.actions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicReference; import jmri.*; import jmri.jmrit.logixng.*; import jmri.jmrit.logixng.expressions.AnalogExpressionConstant; import jmri.jmrit.logixng.expressions.AnalogExpressionMemory; import jmri.jmrit.logixng.expressions.ExpressionMemory; import jmri.jmrit.logixng.expressions.ExpressionSensor; import jmri.jmrit.logixng.implementation.DefaultConditionalNGScaffold; import jmri.util.JUnitAppender; import jmri.util.JUnitUtil; import jmri.util.junit.annotations.ToDo; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Test ActionThrottle * * @author Daniel Bergqvist 2019 */ public class ActionThrottleTest extends AbstractDigitalActionTestBase { private LogixNG logixNG; private ConditionalNG conditionalNG; private ActionThrottle actionThrottle; @Override public ConditionalNG getConditionalNG() { return conditionalNG; } @Override public LogixNG getLogixNG() { return logixNG; } @Override public MaleSocket getConnectableChild() { AnalogExpressionBean childExpression = new AnalogExpressionConstant("IQAE999", null); MaleSocket maleSocketChild = InstanceManager.getDefault(AnalogExpressionManager.class).registerExpression(childExpression); return maleSocketChild; } @Override public String getExpectedPrintedTree() { return String.format( "Throttle. Don't wait for throttle. Stop loco when switching loco ::: Use default%n" + " ?~ Address%n" + " Socket not connected%n" + " ?~ Speed%n" + " Socket not connected%n" + " ? Direction%n" + " Socket not connected%n" + " ?~ Function%n" + " Socket not connected%n" + " ? FunctionOnOff%n" + " Socket not connected%n"); } @Override public String getExpectedPrintedTreeFromRoot() { return String.format( "LogixNG: A new logix for test%n" + " ConditionalNG: A conditionalNG%n" + " ! A%n" + " Throttle. Don't wait for throttle. Stop loco when switching loco ::: Use default%n" + " ?~ Address%n" + " Socket not connected%n" + " ?~ Speed%n" + " Socket not connected%n" + " ? Direction%n" + " Socket not connected%n" + " ?~ Function%n" + " Socket not connected%n" + " ? FunctionOnOff%n" + " Socket not connected%n"); } @Override public NamedBean createNewBean(String systemName) { return new ActionThrottle(systemName, null); } @Override public boolean addNewSocket() { return false; } @Test public void testCtor() { ActionThrottle action2; action2 = new ActionThrottle("IQDA321", null); assertNotNull( action2, "object exists"); assertNull( action2.getUserName(), "Username matches"); assertEquals( "Throttle. Don't wait for throttle. Stop loco when switching loco", action2.getLongDescription(), "String matches"); action2 = new ActionThrottle("IQDA321", "My throttle"); assertNotNull( action2, "object exists"); assertEquals( "My throttle", action2.getUserName(), "Username matches"); assertEquals( "Throttle. Don't wait for throttle. Stop loco when switching loco", action2.getLongDescription(), "String matches"); IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, () -> { ActionThrottle at = new ActionThrottle("IQA55:12:XY11", null); fail( "Action Thtottle created: " + at.toString()); }, "Illegal system name Expected exception thrown"); assertNotNull(ex); ex = assertThrows( IllegalArgumentException.class, () -> { ActionThrottle at = new ActionThrottle("IQA55:12:XY11", "A name"); fail( "Action Thtottle created: " + at.toString()); }, "Illegal system name Expected exception thrown"); assertNotNull(ex); } @Test public void testCtorAndSetup1() { ActionThrottle expression = new ActionThrottle("IQDA321", null); assertNotNull( expression, "exists"); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); expression.getChild(0).setName("XYZ123"); expression.setLocoAddressSocketSystemName("IQAE52"); expression.getChild(1).setName("ZH12"); expression.setLocoSpeedSocketSystemName("IQAE554"); expression.getChild(2).setName("Bj23"); expression.setLocoDirectionSocketSystemName("IQDE594"); assertEquals( "XYZ123", expression.getChild(0).getName(), "expression female socket name is XYZ123"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(0).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(0).isConnected(), "expression female socket is not connected"); assertEquals( "ZH12", expression.getChild(1).getName(), "expression female socket name is ZH12"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(1).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(1).isConnected(), "expression female socket is not connected"); assertEquals( "Bj23", expression.getChild(2).getName(), "expression female socket name is Bj23"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$DigitalSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleDigitalExpressionSocket", expression.getChild(2).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(2).isConnected(), "expression female socket is not connected"); // Setup action. This connects the child actions to this action expression.setup(); JUnitAppender.assertMessage("cannot load analog expression IQAE52"); JUnitAppender.assertMessage("cannot load analog expression IQAE554"); JUnitAppender.assertMessage("cannot load digital expression IQDE594"); assertEquals( "XYZ123", expression.getChild(0).getName(), "expression female socket name is XYZ123"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(0).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(0).isConnected(), "expression female socket is not connected"); assertEquals( "ZH12", expression.getChild(1).getName(), "expression female socket name is ZH12"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(1).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(1).isConnected(), "expression female socket is not connected"); assertEquals( "Bj23", expression.getChild(2).getName(), "expression female socket name is Bj23"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$DigitalSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleDigitalExpressionSocket", expression.getChild(2).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(2).isConnected(), "expression female socket is not connected"); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); } @Test public void testCtorAndSetup2() { ActionThrottle expression = new ActionThrottle("IQDA321", null); assertNotNull( expression, "exists"); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); expression.getChild(0).setName("XYZ123"); expression.setLocoAddressSocketSystemName(null); expression.getChild(1).setName("ZH12"); expression.setLocoSpeedSocketSystemName(null); expression.getChild(2).setName("Bj23"); expression.setLocoDirectionSocketSystemName(null); assertEquals( "XYZ123", expression.getChild(0).getName(), "expression female socket name is XYZ123"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(0).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(0).isConnected(), "expression female socket is not connected"); assertEquals( "ZH12", expression.getChild(1).getName(), "expression female socket name is ZH12"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(1).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(1).isConnected(), "expression female socket is not connected"); assertEquals( "Bj23", expression.getChild(2).getName(), "expression female socket name is Bj23"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$DigitalSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleDigitalExpressionSocket", expression.getChild(2).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(2).isConnected(), "expression female socket is not connected"); // Setup action. This connects the child actions to this action expression.setup(); assertEquals( "XYZ123", expression.getChild(0).getName(), "expression female socket name is XYZ123"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(0).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(0).isConnected(), "expression female socket is not connected"); assertEquals( "ZH12", expression.getChild(1).getName(), "expression female socket name is ZH12"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(1).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(1).isConnected(), "expression female socket is not connected"); assertEquals( "Bj23", expression.getChild(2).getName(), "expression female socket name is Bj23"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$DigitalSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleDigitalExpressionSocket", expression.getChild(2).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(2).isConnected(), "expression female socket is not connected"); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); } @Test public void testCtorAndSetup3() { AnalogExpressionManager m0 = InstanceManager.getDefault(AnalogExpressionManager.class); DigitalExpressionManager m2 = InstanceManager.getDefault(DigitalExpressionManager.class); m0.registerExpression(new AnalogExpressionMemory("IQAE52", null)); m0.registerExpression(new AnalogExpressionMemory("IQAE554", null)); m2.registerExpression(new ExpressionMemory("IQDE594", null)); ActionThrottle expression = new ActionThrottle("IQDA321", null); assertNotNull( expression, "exists"); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); expression.getChild(0).setName("XYZ123"); expression.setLocoAddressSocketSystemName("IQAE52"); expression.getChild(1).setName("ZH12"); expression.setLocoSpeedSocketSystemName("IQAE554"); expression.getChild(2).setName("Bj23"); expression.setLocoDirectionSocketSystemName("IQDE594"); assertEquals( "XYZ123", expression.getChild(0).getName(), "expression female socket name is XYZ123"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(0).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(0).isConnected(), "expression female socket is not connected"); assertEquals( "ZH12", expression.getChild(1).getName(), "expression female socket name is ZH12"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$AnalogSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleAnalogExpressionSocket", expression.getChild(1).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(1).isConnected(), "expression female socket is not connected"); assertEquals( "Bj23", expression.getChild(2).getName(), "expression female socket name is Bj23"); assertEquals( // "jmri.jmrit.logixng.implementation.DefaultFemaleGenericExpressionSocket$DigitalSocket", "jmri.jmrit.logixng.implementation.DefaultFemaleDigitalExpressionSocket", expression.getChild(2).getClass().getName(), "expression female socket is of correct class"); assertFalse( expression.getChild(2).isConnected(), "expression female socket is not connected"); // Setup action. This connects the child actions to this action expression.setup(); assertTrue( expression.getChild(0).isConnected(), "expression female socket is connected"); // assertEquals( // childSocket0, // expression.getChild(0).getConnectedSocket(), "child is correct bean"); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); assertTrue( expression.getChild(1).isConnected(), "expression female socket is connected"); // Assert.assertEquals("child is correct bean", // childSocket1, // expression.getChild(1).getConnectedSocket()); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); assertTrue( expression.getChild(2).isConnected(), "expression female socket is connected"); // Assert.assertEquals("child is correct bean", // childSocket2, // expression.getChild(2).getConnectedSocket()); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); // Try run setup() again. That should not cause any problems. expression.setup(); assertEquals( 5, expression.getChildCount(), "expression has 5 female sockets"); } @Test public void testGetChild() { assertEquals( 5, actionThrottle.getChildCount(), "getChildCount() returns 5"); assertNotNull( actionThrottle.getChild(0), "getChild(0) returns a non null value"); assertNotNull( actionThrottle.getChild(1), "getChild(1) returns a non null value"); assertNotNull( actionThrottle.getChild(2), "getChild(2) returns a non null value"); assertNotNull( actionThrottle.getChild(3), "getChild(3) returns a non null value"); assertNotNull( actionThrottle.getChild(4), "getChild(4) returns a non null value"); IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, () -> actionThrottle.getChild(5), "Exception is thrown"); assertEquals( "index has invalid value: 5", ex.getMessage(), "Error message is correct"); } @Test public void testCategory() { assertEquals( LogixNG_Category.ITEM, _base.getCategory(), "Category matches"); } @Test public void testShortDescription() { assertEquals( "Throttle", _base.getShortDescription(), "String matches"); } @Test public void testLongDescription() { assertEquals( "Throttle. Don't wait for throttle. Stop loco when switching loco", _base.getLongDescription(), "String matches"); } @Test public void testChild() { MaleSocket analogExpressionMaleSocket = InstanceManager.getDefault(AnalogExpressionManager.class) .registerExpression(new AnalogExpressionConstant("IQAE1", null)); MaleSocket digitalExpressionMaleSocket = InstanceManager.getDefault(DigitalExpressionManager.class) .registerExpression(new ExpressionSensor("IQDE1", null)); assertEquals( 5, _base.getChildCount(), "Num children is correct"); // Socket LOCO_ADDRESS_SOCKET is loco address assertTrue( _base.getChild(ActionThrottle.LOCO_ADDRESS_SOCKET).isCompatible(analogExpressionMaleSocket), "Child LOCO_ADDRESS_SOCKET supports analog male socket"); // Socket LOCO_SPEED_SOCKET is loco speed assertTrue( _base.getChild(ActionThrottle.LOCO_SPEED_SOCKET).isCompatible(analogExpressionMaleSocket), "Child LOCO_SPEED_SOCKET supports analog male socket"); // Socket LOCO_DIRECTION_SOCKET is loco direction assertTrue( _base.getChild(ActionThrottle.LOCO_DIRECTION_SOCKET).isCompatible(digitalExpressionMaleSocket), "Child LOCO_DIRECTION_SOCKET supports digital male socket"); // Socket LOCO_DIRECTION_SOCKET is loco direction assertTrue( _base.getChild(ActionThrottle.LOCO_FUNCTION_SOCKET).isCompatible(analogExpressionMaleSocket), "Child LOCO_FUNCTION_SOCKET supports analog male socket"); // Socket LOCO_DIRECTION_SOCKET is loco direction assertTrue( _base.getChild(ActionThrottle.LOCO_FUNCTION_ONOFF_SOCKET).isCompatible(digitalExpressionMaleSocket), "Child LOCO_FUNCTION_STATE_SOCKET supports digital male socket"); IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, () -> _base.getChild(5), "Exception is thrown"); assertEquals( "index has invalid value: 5", ex.getMessage(), "Error message is correct"); } @Disabled("This method fails too often") @ToDo("This method fails too often") @Test public void testExecute() throws SocketAlreadyConnectedException, JmriException { ThrottleManager tm = InstanceManager.getDefault(ThrottleManager.class); int locoAddress = 1234; int locoAddress2 = 1235; assertEquals( 0, tm.getThrottleUsageCount(locoAddress), "Throttle is used 0 times"); assertEquals( 0, tm.getThrottleUsageCount(locoAddress2), "Throttle is used 0 times"); logixNG.setEnabled(false); ConditionalNG conditionalNG_2 = InstanceManager.getDefault(ConditionalNG_Manager.class) .createConditionalNG(logixNG, "A second conditionalNG"); // NOI18N logixNG.addConditionalNG(conditionalNG_2); ActionThrottle actionThrottle2 = new ActionThrottle("IQDA999", null); MaleSocket maleSocket2 = InstanceManager.getDefault(DigitalActionManager.class).registerAction(actionThrottle2); conditionalNG_2.getChild(0).connect(maleSocket2); logixNG.setEnabled(true); assertTrue(logixNG.setParentForAllChildren(new ArrayList<>())); // Test execute when no children are connected actionThrottle2.execute(); assertNotNull( actionThrottle2.getConditionalNG(), "getConditionalNG() returns not null"); conditionalNG.unregisterListeners(); AtomicReference myThrottleRef = new AtomicReference<>(); MyThrottleListener myThrottleListener = new MyThrottleListener(myThrottleRef); boolean result = tm.requestThrottle(locoAddress, myThrottleListener); assertTrue( result, () -> "loco " + locoAddress + " cannot be aquired"); assertNotNull( myThrottleRef.get(), "has throttle"); Memory locoAddressMemory = InstanceManager.getDefault(MemoryManager.class).provide("Loco address memory"); locoAddressMemory.setValue(locoAddress); AnalogExpressionMemory locoAddressExpression = new AnalogExpressionMemory("IQAE111", null); locoAddressExpression.getSelectNamedBean().setNamedBean(locoAddressMemory); Memory locoSpeedMemory = InstanceManager.getDefault(MemoryManager.class).provide("Loco speed memory"); locoSpeedMemory.setValue(0); AnalogExpressionMemory locoSpeedExpression = new AnalogExpressionMemory("IQAE112", null); locoSpeedExpression.getSelectNamedBean().setNamedBean(locoSpeedMemory); Sensor locoDirectionSensor = InstanceManager.getDefault(SensorManager.class).provide("Loco direction sensor"); locoDirectionSensor.setState(Sensor.ACTIVE); ExpressionSensor locoDirectionExpression = new ExpressionSensor("IQDE113", null); locoDirectionExpression.getSelectNamedBean().setNamedBean(locoDirectionSensor); // Set loco address of actionThrottle2 conditionalNG_2.unregisterListeners(); MaleSocket locoAddressSocket = InstanceManager.getDefault(AnalogExpressionManager.class) .registerExpression(locoAddressExpression); actionThrottle2.getChild(ActionThrottle.LOCO_ADDRESS_SOCKET).connect(locoAddressSocket); conditionalNG_2.registerListeners(); // Test execute when loco address socket is connected actionThrottle2.execute(); assertEquals( 0.0, myThrottleRef.get().getSpeedSetting(), 0.0001, "loco speed is correct"); // Set loco address of actionThrottle2 conditionalNG_2.unregisterListeners(); MaleSocket locoSpeedSocket = InstanceManager.getDefault(AnalogExpressionManager.class) .registerExpression(locoSpeedExpression); actionThrottle2.getChild(ActionThrottle.LOCO_SPEED_SOCKET).connect(locoSpeedSocket); assertTrue( myThrottleRef.get().getIsForward(), "loco direction is correct"); conditionalNG_2.registerListeners(); // Test execute when loco speed socket is connected actionThrottle2.execute(); // Set loco address of actionThrottle2 conditionalNG_2.unregisterListeners(); MaleSocket locoDirectionSocket = InstanceManager.getDefault(DigitalExpressionManager.class) .registerExpression(locoDirectionExpression); actionThrottle2.getChild(ActionThrottle.LOCO_DIRECTION_SOCKET).connect(locoDirectionSocket); conditionalNG_2.registerListeners(); // Test execute when loco direction socket is connected actionThrottle2.execute(); // Set a different speed locoSpeedMemory.setValue(0.5); // Test execute when loco speed is changed actionThrottle2.execute(); assertEquals( 0.5, myThrottleRef.get().getSpeedSetting(), 0.0001, "loco speed is correct"); assertTrue( myThrottleRef.get().getIsForward(), "loco direction is correct"); // Set a different direction locoDirectionSensor.setState(Sensor.INACTIVE); // Test execute when loco direction is changed actionThrottle2.execute(); assertEquals( 0.5, myThrottleRef.get().getSpeedSetting(), 0.0001, "loco speed is correct"); assertFalse( myThrottleRef.get().getIsForward(), "loco direction is correct"); // Test execute when loco address is changed actionThrottle2.execute(); // Test execute when loco address socket is connected actionThrottle2.execute(); // Test execute when loco address is changed AtomicReference myThrottleRef2 = new AtomicReference<>(); MyThrottleListener myThrottleListener2 = new MyThrottleListener(myThrottleRef2); result = tm.requestThrottle(locoAddress2, myThrottleListener2); assertTrue( result, () -> "loco " + locoAddress + " cannot be aquired"); assertNotNull( myThrottleRef2.get(), "has throttle"); myThrottleRef2.get().setSpeedSetting(1); assertEquals( 0.5, myThrottleRef.get().getSpeedSetting(), 0.0001, "loco speed is correct"); assertEquals( 1.0, myThrottleRef2.get().getSpeedSetting(), 0.0001, "loco speed is correct"); // Change loco address locoAddressMemory.setValue(locoAddress2); // Execute the action actionThrottle2.execute(); assertEquals( 0.0, myThrottleRef.get().getSpeedSetting(), 0.0001, "loco speed is correct"); assertEquals( 0.5, myThrottleRef2.get().getSpeedSetting(), 0.0001, "loco speed is correct"); // Test execute when loco address socket is disconnected conditionalNG_2.unregisterListeners(); actionThrottle2.getChild(ActionThrottle.LOCO_ADDRESS_SOCKET).disconnect(); conditionalNG_2.registerListeners(); actionThrottle2.execute(); // This test is not reliable. Why? // Assert.assertEquals("Throttle is used 1 times", 1, tm.getThrottleUsageCount(locoAddress2)); // Test disposeMe(). ActionThrottle does not have a throttle now. actionThrottle2.disposeMe(); // This test is not reliable. Why? // Assert.assertEquals("Throttle is used 1 times", 1, tm.getThrottleUsageCount(locoAddress2)); } @Test public void testDisposeMe() throws SocketAlreadyConnectedException, JmriException { ThrottleManager tm = InstanceManager.getDefault(ThrottleManager.class); logixNG.setEnabled(false); ConditionalNG conditionalNG_2 = InstanceManager.getDefault(ConditionalNG_Manager.class) .createConditionalNG(logixNG, "A second conditionalNG"); // NOI18N conditionalNG_2.setRunDelayed(false); ActionThrottle actionThrottle2 = new ActionThrottle("IQDA999", null); MaleSocket maleSocket2 = InstanceManager.getDefault(DigitalActionManager.class).registerAction(actionThrottle2); conditionalNG_2.getChild(0).connect(maleSocket2); assertTrue( logixNG.setParentForAllChildren(new ArrayList<>())); int locoAddress = 1234; AtomicReference myThrottleRef = new AtomicReference<>(); MyThrottleListener myThrottleListener = new MyThrottleListener(myThrottleRef); boolean result = tm.requestThrottle(locoAddress, myThrottleListener); assertTrue( result, () -> "loco " + locoAddress + " cannot be aquired"); assertNotNull( myThrottleRef.get(), "has throttle"); Memory locoAddressMemory = InstanceManager.getDefault(MemoryManager.class).provide("Loco address memory"); locoAddressMemory.setValue(locoAddress); AnalogExpressionMemory locoAddressExpression = new AnalogExpressionMemory("IQAE111", null); locoAddressExpression.getSelectNamedBean().setNamedBean(locoAddressMemory); Memory locoSpeedMemory = InstanceManager.getDefault(MemoryManager.class).provide("Loco speed memory"); locoSpeedMemory.setValue(0); AnalogExpressionMemory locoSpeedExpression = new AnalogExpressionMemory("IQAE112", null); locoSpeedExpression.getSelectNamedBean().setNamedBean(locoSpeedMemory); Sensor locoDirectionSensor = InstanceManager.getDefault(SensorManager.class).provide("Loco direction sensor"); locoDirectionSensor.setState(Sensor.ACTIVE); ExpressionSensor locoDirectionExpression = new ExpressionSensor("IQDE113", null); locoDirectionExpression.getSelectNamedBean().setNamedBean(locoDirectionSensor); // Set loco address of actionThrottle2 MaleSocket locoAddressSocket = InstanceManager.getDefault(AnalogExpressionManager.class) .registerExpression(locoAddressExpression); actionThrottle2.getChild(ActionThrottle.LOCO_ADDRESS_SOCKET).connect(locoAddressSocket); assertEquals( 1, tm.getThrottleUsageCount(locoAddress), "Throttle is used 1 times"); // Test execute when loco address socket is connected conditionalNG_2.execute(); assertEquals( 0.0, myThrottleRef.get().getSpeedSetting(), 0.0001, "loco speed is correct"); assertEquals( 2, tm.getThrottleUsageCount(locoAddress), "Throttle is used 2 times"); // Test disposeMe(). ActionThrottle has a throttle now which must be released. actionThrottle2.disposeMe(); assertEquals( 1, tm.getThrottleUsageCount(locoAddress), "Throttle is used 1 times"); } @Test public void testConnectedDisconnected() throws SocketAlreadyConnectedException { _baseMaleSocket.setEnabled(false); assertEquals( 5, _base.getChildCount(), "Num children is correct"); MaleSocket analogExpressionMaleSocket = InstanceManager.getDefault(AnalogExpressionManager.class) .registerExpression(new AnalogExpressionConstant("IQAE1", null)); MaleSocket digitalExpressionMaleSocket = InstanceManager.getDefault(DigitalExpressionManager.class) .registerExpression(new ExpressionSensor("IQDE1", null)); actionThrottle.getChild(ActionThrottle.LOCO_ADDRESS_SOCKET).disconnect(); assertNull( actionThrottle.getLocoAddressSocketSystemName(), "socket name is null"); actionThrottle.getChild(ActionThrottle.LOCO_ADDRESS_SOCKET).connect(analogExpressionMaleSocket); assertEquals( "IQAE1", actionThrottle.getLocoAddressSocketSystemName(), "socket name is correct"); actionThrottle.getChild(ActionThrottle.LOCO_ADDRESS_SOCKET).disconnect(); assertNull( actionThrottle.getLocoAddressSocketSystemName(), "socket name is null"); actionThrottle.getChild(ActionThrottle.LOCO_SPEED_SOCKET).disconnect(); assertNull( actionThrottle.getLocoAddressSocketSystemName(), "socket name is null"); actionThrottle.getChild(ActionThrottle.LOCO_SPEED_SOCKET).connect(analogExpressionMaleSocket); assertEquals( "IQAE1", actionThrottle.getLocoSpeedSocketSystemName(), "socket name is correct"); actionThrottle.getChild(ActionThrottle.LOCO_SPEED_SOCKET).disconnect(); assertNull( actionThrottle.getLocoAddressSocketSystemName(), "socket name is null"); actionThrottle.getChild(ActionThrottle.LOCO_DIRECTION_SOCKET).disconnect(); assertNull( actionThrottle.getLocoAddressSocketSystemName(), "socket name is null"); actionThrottle.getChild(ActionThrottle.LOCO_DIRECTION_SOCKET).connect(digitalExpressionMaleSocket); assertEquals( "IQDE1", actionThrottle.getLocoDirectionSocketSystemName(), "socket name is correct"); actionThrottle.getChild(ActionThrottle.LOCO_DIRECTION_SOCKET).disconnect(); assertNull( actionThrottle.getLocoAddressSocketSystemName(), "socket name is null"); FemaleSocket badFemaleSocket = InstanceManager.getDefault(AnalogExpressionManager.class) .createFemaleSocket(actionThrottle, actionThrottle, "E1"); IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, () -> actionThrottle.connected(badFemaleSocket), "Exception is thrown"); assertEquals( "unkown socket", ex.getMessage(), "Error message is correct"); ex = assertThrows( IllegalArgumentException.class, () -> actionThrottle.disconnected(badFemaleSocket), "Exception is thrown"); assertEquals( "unkown socket", ex.getMessage(), "Error message is correct"); } @Test public void testToString() { ActionThrottle a1 = new ActionThrottle("IQDA321", null); assertEquals( "Throttle", a1.getShortDescription(), "strings are equal"); ActionThrottle a2 = new ActionThrottle("IQDA321", null); assertEquals( "Throttle. Don't wait for throttle. Stop loco when switching loco", a2.getLongDescription(), "strings are equal"); } @BeforeEach public void setUp() throws SocketAlreadyConnectedException { JUnitUtil.setUp(); JUnitUtil.resetInstanceManager(); JUnitUtil.resetProfileManager(); JUnitUtil.initConfigureManager(); JUnitUtil.initInternalSensorManager(); JUnitUtil.initInternalTurnoutManager(); JUnitUtil.initDebugThrottleManager(); JUnitUtil.initLogixNGManager(); _category = LogixNG_Category.ITEM; _isExternal = true; logixNG = InstanceManager.getDefault(LogixNG_Manager.class).createLogixNG("A new logix for test"); // NOI18N conditionalNG = new DefaultConditionalNGScaffold("IQC1", "A conditionalNG"); // NOI18N; InstanceManager.getDefault(ConditionalNG_Manager.class).register(conditionalNG); conditionalNG.setEnabled(true); conditionalNG.setRunDelayed(false); logixNG.addConditionalNG(conditionalNG); actionThrottle = new ActionThrottle("IQDA321", null); MaleSocket maleSocket = InstanceManager.getDefault(DigitalActionManager.class).registerAction(actionThrottle); conditionalNG.getChild(0).connect(maleSocket); _base = actionThrottle; _baseMaleSocket = maleSocket; assertTrue( logixNG.setParentForAllChildren(new ArrayList<>())); logixNG.activate(); logixNG.setEnabled(true); } @AfterEach public void tearDown() { jmri.jmrit.logixng.util.LogixNG_Thread.stopAllLogixNGThreads(); JUnitUtil.deregisterBlockManagerShutdownTask(); JUnitUtil.tearDown(); } private static class MyThrottleListener implements ThrottleListener { private final AtomicReference _myThrottleRef; MyThrottleListener(AtomicReference myThrottleRef) { _myThrottleRef = myThrottleRef; } @Override public void notifyThrottleFound(DccThrottle t) { _myThrottleRef.set(t); } @Override public void notifyFailedThrottleRequest(LocoAddress address, String reason) { fail("loco " + address.getNumber() + " cannot be aquired " + reason); } @Override public void notifyDecisionRequired(LocoAddress address, ThrottleListener.DecisionType question) { fail("loco " + address.getNumber() + " cannot be aquired. Decision required. " + question); } } // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionThrottleTest.class); }