package jmri.jmrit.ussctc; import java.beans.*; import java.util.*; import jmri.*; import jmri.util.*; import jmri.util.JUnitAppender; import org.junit.Assert; import org.junit.jupiter.api.*; /** * Tests for SignalHeadSection class in the jmri.jmrit.ussctc package * * @author Bob Jacobsen Copyright 2007 */ @SuppressWarnings("unchecked") public class SignalHeadSectionTest { @Test public void testConstruction() { SignalHeadSection signalHeadSection = new SignalHeadSection(new ArrayList<>(), new ArrayList<>(), // empty "Sec 1 Sign 1 L", "Sec 1 Sign 1 C", "Sec 1 Sign 1 R", "Sec 1 Sign 1 L", "Sec 1 Sign 1 R", station); Assertions.assertNotNull(signalHeadSection); } @Test public void testEmptyToString() { SignalHeadSection s = new SignalHeadSection(new ArrayList<>(), new ArrayList<>(), // empty "Sec 1 Sign 1 L", "Sec 1 Sign 1 C", "Sec 1 Sign 1 R", "Sec 1 Sign 1 L", "Sec 1 Sign 1 R", station); Assert.assertEquals("SignalHeadSection state: SET_STOP time: false defer: false", s.toString()); } @Test public void testNamesToString() { SignalHeadSection s = new SignalHeadSection(Arrays.asList(new String[]{"IH1", "IH2"}), Arrays.asList(new String[]{"IH3"}), "Sec 1 Sign 1 L", "Sec 1 Sign 1 C", "Sec 1 Sign 1 R", "Sec 1 Sign 1 L", "Sec 1 Sign 1 R", station); Assert.assertEquals("SignalHeadSection state: SET_STOP time: false defer: false\n \"IH1\" held: true clear: false stop: false\n \"IH2\" held: true clear: false stop: false\n \"IH3\" held: true clear: false stop: false", s.toString()); } boolean listened; @Test public void testListener() { final SignalHeadSection s = new SignalHeadSection(new ArrayList<>(), new ArrayList<>(), // empty "Sec 1 Sign 1 L", "Sec 1 Sign 1 C", "Sec 1 Sign 1 R", "Sec 1 Sign 1 L", "Sec 1 Sign 1 R", station); s.setLastIndication(CodeGroupThreeBits.Triple001); listened = false; PropertyChangeListener p = (PropertyChangeEvent e) -> { listened = true; Assert.assertEquals("LastIndication", e.getPropertyName()); Assert.assertEquals(CodeGroupThreeBits.Triple001, e.getOldValue()); Assert.assertEquals(CodeGroupThreeBits.Triple100, e.getNewValue()); Assert.assertEquals(s, e.getSource()); }; s.addPropertyChangeListener(p); Assert.assertTrue(! listened); s.setLastIndication(CodeGroupThreeBits.Triple100); Assert.assertTrue(listened); listened = false; s.removePropertyChangeListener(p); s.setLastIndication(CodeGroupThreeBits.Triple100); Assert.assertTrue(!listened); } /** * Set up and do a single check of the logic for calculating a current indication in the field. * Takes a set of right and left * signal appearances to show, plus the last command that was send, * then changes the signals (as needed) and checks for * the result. * The test condition appears as the calling method name in the traceback, * not as a separate string. */ private void checkOneCI(int l1before, int l2before, int r1before, int r2before, CodeGroupThreeBits lastIndication, int l1after, int l2after, int r1after, int r2after, CodeGroupThreeBits checkIndication) { SignalHeadSection s = new SignalHeadSection(Arrays.asList(new String[]{"IH1", "IH2"}), Arrays.asList(new String[]{"IH3", "IH4"}), "Sec 1 Sign 1 L", "Sec 1 Sign 1 C", "Sec 1 Sign 1 R", "Sec 1 Sign 1 L", "Sec 1 Sign 1 R", station) { // for testing purposes, turn off action on signal changes @Override void layoutSignalHeadChanged(java.beans.PropertyChangeEvent e) {} }; Assertions.assertNotNull(ih1); Assertions.assertNotNull(ih2); Assertions.assertNotNull(ih3); Assertions.assertNotNull(ih4); // set up ih1.setHeld(false); ih2.setHeld(false); ih3.setHeld(false); ih4.setHeld(false); JUnitUtil.setBeanStateAndWait(ih1, r1before); JUnitUtil.setBeanStateAndWait(ih2, r2before); JUnitUtil.setBeanStateAndWait(ih3, l1before); JUnitUtil.setBeanStateAndWait(ih4, l2before); s.setLastIndication(lastIndication); // sequence changes to test if (ih1.getAppearance() != r1after) JUnitUtil.setBeanStateAndWait(ih1, r1after); if (ih2.getAppearance() != r2after) JUnitUtil.setBeanStateAndWait(ih2, r2after); if (ih3.getAppearance() != l1after) JUnitUtil.setBeanStateAndWait(ih3, l1after); if (ih4.getAppearance() != l2after) JUnitUtil.setBeanStateAndWait(ih4, l2after); // final check Assert.assertEquals(checkIndication, s.getCurrentIndication()); } @Test public void testCI_StopAndAllRed() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010); } // we do each test in left and right to make sure we've got the code correct // normal case of signal going from clear to stop in field @Test public void testCI_LeftGreenGoesToAllRed() { checkOneCI(SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010); } @Test public void testCI_RightGreenGoesToAllRed() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.YELLOW, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010); } @Test public void testCI_LeftYellowGoesToAllRed() { checkOneCI(SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010); } @Test public void testCI_RightYellowGoesToAllRed() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.YELLOW, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010); } // normal case of signals in the field clearing after a time @Test public void testCI_LeftClears() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100); } @Test public void testCI_RightClears() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple001); } // normal case of signals in the field changing, while staying clear @Test public void testCI_LeftChanges() { checkOneCI(SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.YELLOW, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100); } @Test public void testCI_RightChanges() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.YELLOW, CodeGroupThreeBits.Triple001); } // signal has been set to stop, but it taking some time - not typical? @Test public void testCI_LeftHasntDroppedYet() { checkOneCI(SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple000); } @Test public void testCI_RightHasntDroppedYet() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); } // signal was at stop, but cleared in field - not typical! @Test public void testCI_StopClearsLeft() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.YELLOW, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple000); } @Test public void testCI_StopClearsRight() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); } // tests of restricting cases @Test public void testCI_BothRestrictingAtStop() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.FLASHRED, SignalHead.RED,SignalHead.FLASHRED, CodeGroupThreeBits.Triple000); } @Test public void testCI_BothRestrictingWhenLeft() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.FLASHRED, SignalHead.RED,SignalHead.FLASHRED, CodeGroupThreeBits.Triple000); } @Test public void testCI_BothRestrictingWhenRight() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.FLASHRED, SignalHead.RED,SignalHead.FLASHRED, CodeGroupThreeBits.Triple000); } // tests of some odd states and conditions @Test public void testCI_BothLeftAndRightFoundClearInsteadOfStop() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); JUnitAppender.assertErrorMessageStartsWith("Found both left and right clear: "); } @Test public void testCI_BothLeftAndRightFoundClearInsteadOfLeftOnly() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); JUnitAppender.assertErrorMessageStartsWith("Found both left and right clear: "); } @Test public void testCI_BothLeftAndRightFoundClearInsteadOfRightOnly() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); JUnitAppender.assertErrorMessageStartsWith("Found both left and right clear: "); } @Test public void testCI_BothLeftRestrictingAndRightClearInsteadOfStop() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.FLASHRED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); JUnitAppender.assertWarnMessageStartsWith("Found left at restricting and right clear: "); } @Test public void testCI_BothLeftRestrictingAndRightClearInsteadOfLeftOnly() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.FLASHRED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); JUnitAppender.assertWarnMessageStartsWith("Found left at restricting and right clear: "); } @Test public void testCI_BothLeftRestrictingAndRightClearInsteadOfRightOnly() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.FLASHRED, SignalHead.RED,SignalHead.GREEN, CodeGroupThreeBits.Triple000); JUnitAppender.assertWarnMessageStartsWith("Found left at restricting and right clear: "); } @Test public void testCI_BothLeftClearAndRightRestrictingInsteadOfStop() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple010, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.FLASHRED, CodeGroupThreeBits.Triple000); JUnitAppender.assertWarnMessageStartsWith("Found left clear and right at restricting: "); } @Test public void testCI_BothLeftClearAndRightRestrictingInsteadOfLeftOnly() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple100, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.FLASHRED, CodeGroupThreeBits.Triple000); JUnitAppender.assertWarnMessageStartsWith("Found left clear and right at restricting: "); } @Test public void testCI_BothLeftClearAndRightRestrictingInsteadOfRightOnly() { checkOneCI(SignalHead.RED,SignalHead.RED, SignalHead.RED,SignalHead.RED, CodeGroupThreeBits.Triple001, SignalHead.RED,SignalHead.GREEN, SignalHead.RED,SignalHead.FLASHRED, CodeGroupThreeBits.Triple000); JUnitAppender.assertWarnMessageStartsWith("Found left clear and right at restricting: "); } @Test public void testImplListener(){ Assertions.assertFalse(requestIndicationStart); Assertions.assertNotNull(station); station.requestIndicationStart(); Assertions.assertTrue(requestIndicationStart); } // common infrastructure CodeLine codeline; Station station = null; boolean requestIndicationStart; private SignalHead ih1 = null; private SignalHead ih2 = null; private SignalHead ih3 = null; private SignalHead ih4 = null; private class StationImpl extends Station { StationImpl(String name, CodeLine codeline, CodeButton button) { super(name, codeline, button); requestIndicationStart = false; } @Override public void requestIndicationStart() { requestIndicationStart = true; } } @BeforeEach public void setUp() { JUnitUtil.setUp(); JUnitUtil.resetProfileManager(); JUnitUtil.initConfigureManager(); JUnitUtil.initInternalTurnoutManager(); JUnitUtil.initInternalSensorManager(); JUnitUtil.initInternalSignalHeadManager(); codeline = new CodeLine("Code Indication Start", "Code Send Start", "IT101", "IT102", "IT103", "IT104"); ih1 = new jmri.implementation.VirtualSignalHead("IH1"); InstanceManager.getDefault(jmri.SignalHeadManager.class).register(ih1); ih2 = new jmri.implementation.VirtualSignalHead("IH2"); InstanceManager.getDefault(jmri.SignalHeadManager.class).register(ih2); ih3 = new jmri.implementation.VirtualSignalHead("IH3"); InstanceManager.getDefault(jmri.SignalHeadManager.class).register(ih3); ih4 = new jmri.implementation.VirtualSignalHead("IH4"); InstanceManager.getDefault(jmri.SignalHeadManager.class).register(ih4); requestIndicationStart = false; station = new StationImpl("test", codeline, new CodeButton("IS221", "IS222")); } @AfterEach public void tearDown() { JUnitUtil.tearDown(); } }