Files
2026-06-17 14:00:51 +02:00

849 lines
33 KiB
Java

package jmri.implementation;
import jmri.*;
import jmri.util.JUnitAppender;
import jmri.util.JUnitUtil;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.jupiter.api.*;
/**
* Tests for the LightControl class.
*
* @author Paul Bender Copyright (C) 2016
* @author Steve Young Copyright (C) 2019
*/
public class LightControlTest {
@Test
public void testCtor() {
LightControl lca = new DefaultLightControl();
Assert.assertNotNull("LightControl not null", lca);
}
@Test
public void testCLighttor() {
Assert.assertNotNull("LightControl not null", lc);
}
@Test
public void testLightControlCopyCtor() {
LightControl copyOfl = new DefaultLightControl(lc);
Assert.assertNotNull("LightControl Copy not null", copyOfl);
}
@Test
@SuppressWarnings("unlikely-arg-type") // String seems to be unrelated to LightControl
public void testEquals() {
Light o = new AbstractLight("IL1", "test light") {
};
LightControl l1 = new DefaultLightControl(o);
Assert.assertFalse(l1.equals(null));
Assert.assertTrue(l1.equals(l1));
Assert.assertFalse(l1.equals(""));
LightControl l2 = new DefaultLightControl(o);
Assert.assertTrue(l1.equals(l2));
l1.setControlType(999);
Assert.assertFalse(l1.equals(l2));
l2.setControlType(999);
Assert.assertTrue(l1.equals(l2));
JUnitAppender.assertWarnMessage("Unexpected _controlType = 999");
l1.setControlType(Light.SENSOR_CONTROL);
Assert.assertFalse(l1.equals(l2));
l2.setControlType(Light.SENSOR_CONTROL);
Assert.assertTrue(l1.equals(l2));
l1.setControlSensorName("S2");
Assert.assertFalse(l1.equals(l2));
l2.setControlSensorName("S2");
Assert.assertTrue(l1.equals(l2));
l1.setControlSensorSense(Sensor.ACTIVE);
Assert.assertTrue(l1.equals(l2)); // default is ACTIVE
l1.setControlSensorSense(Sensor.INACTIVE);
Assert.assertFalse(l1.equals(l2));
l2.setControlSensorSense(Sensor.INACTIVE);
Assert.assertTrue(l1.equals(l2));
l1.setControlType(Light.FAST_CLOCK_CONTROL);
Assert.assertFalse(l1.equals(l2));
l2.setControlType(Light.FAST_CLOCK_CONTROL);
Assert.assertTrue(l1.equals(l2));
l1.setFastClockControlSchedule(0, 0, 0, 0); // onHr, OnMin, OffHr, OffMin default
Assert.assertTrue(l1.equals(l2));
l1.setFastClockControlSchedule(1, 0, 0, 0); // onHr, OnMin, OffHr, OffMin
Assert.assertFalse(l1.equals(l2));
l1.setFastClockControlSchedule(0, 1, 0, 0); // onHr, OnMin, OffHr, OffMin
Assert.assertFalse(l1.equals(l2));
l1.setFastClockControlSchedule(0, 0, 1, 0); // onHr, OnMin, OffHr, OffMin
Assert.assertFalse(l1.equals(l2));
l1.setFastClockControlSchedule(0, 0, 0, 1); // onHr, OnMin, OffHr, OffMin
Assert.assertFalse(l1.equals(l2));
l1.setControlType(Light.TURNOUT_STATUS_CONTROL);
Assert.assertFalse(l1.equals(l2));
l2.setControlType(Light.TURNOUT_STATUS_CONTROL);
Assert.assertTrue(l1.equals(l2));
l1.setControlTurnout("T1");
Assert.assertFalse(l1.equals(l2));
l2.setControlTurnout("T1");
Assert.assertTrue(l1.equals(l2));
l1.setControlTurnoutState(Turnout.CLOSED); // default CLOSED
Assert.assertTrue(l1.equals(l2));
l1.setControlTurnoutState(Turnout.THROWN);
Assert.assertFalse(l1.equals(l2));
l2.setControlTurnoutState(Turnout.THROWN);
Assert.assertTrue(l1.equals(l2));
l1.setControlType(Light.TIMED_ON_CONTROL);
Assert.assertFalse(l1.equals(l2));
l2.setControlType(Light.TIMED_ON_CONTROL);
Assert.assertTrue(l1.equals(l2));
l1.setControlTimedOnSensorName("S1");
Assert.assertFalse(l1.equals(l2));
l2.setControlTimedOnSensorName("S1");
Assert.assertTrue(l1.equals(l2));
l1.setTimedOnDuration(77);
Assert.assertFalse(l1.equals(l2));
l2.setTimedOnDuration(77);
Assert.assertTrue(l1.equals(l2));
l1.setControlType(Light.TWO_SENSOR_CONTROL);
Assert.assertFalse(l1.equals(l2));
l2.setControlType(Light.TWO_SENSOR_CONTROL);
Assert.assertTrue(l1.equals(l2));
l1.setControlSensorName("S1");
Assert.assertFalse(l1.equals(l2));
l2.setControlSensorName("S1");
Assert.assertTrue(l1.equals(l2));
l1.setControlSensor2Name("S2");
Assert.assertFalse(l1.equals(l2));
l2.setControlSensor2Name("S2");
Assert.assertTrue(l1.equals(l2));
l1.setControlSensorSense(Sensor.ACTIVE);
Assert.assertFalse(l1.equals(l2));
l2.setControlSensorSense(Sensor.ACTIVE);
Assert.assertTrue(l1.equals(l2));
Assert.assertNotNull("Has Hashcode", l1.hashCode());
}
@Test
public void testSetGetNames() {
// used while editing the control with no Sensors / turnouts etc. attached
lc.setControlSensorName("MySensor");
Assert.assertEquals("Same Name", "MySensor", lc.getControlSensorName());
lc.setControlTimedOnSensorName("Shirley");
Assert.assertEquals("Same Name", "Shirley", lc.getControlTimedOnSensorName());
lc.setControlSensor2Name("DownMain7");
Assert.assertEquals("Same Name", "DownMain7", lc.getControlSensor2Name());
}
@Test
public void testInvalidControlType() {
lc.activateLightControl();
JUnitAppender.assertErrorMessage("Unexpected control type when activating Light: ILL1");
}
@Test
public void testActivateNoLight() {
lc.setParentLight(null);
lc.activateLightControl();
JUnitAppender.assertErrorMessage("No Parent Light when activating LightControl");
}
@Test
public void testSingleSensorFollower() throws jmri.JmriException {
Sensor s = InstanceManager.getDefault(jmri.SensorManager.class).provideSensor("S2");
int startListeners = s.getPropertyChangeListeners().length;
lc.setControlType(Light.SENSOR_CONTROL);
lc.setControlSensorName("S2");
lc.setControlSensorSense(Sensor.ACTIVE);
l.addLightControl(lc);
l.activateLight();
Assert.assertEquals("+1 listener", startListeners + 1, s.getPropertyChangeListeners().length);
Assert.assertEquals("Sensor unknown state", Sensor.UNKNOWN, s.getState());
Assert.assertEquals("Light OFF state", Light.OFF, l.getState()); // lights are OFF by default
s.setState(Sensor.ON);
Assert.assertEquals("ON state", Light.ON, l.getState());
s.setState(Sensor.OFF);
Assert.assertEquals("OFF state", Light.OFF, l.getState());
s.setState(Sensor.ON);
Assert.assertEquals("ON state", Light.ON, l.getState());
l.deactivateLight();
Assert.assertEquals("releases listener", startListeners, s.getPropertyChangeListeners().length);
lc.setControlSensorSense(Sensor.INACTIVE);
Assert.assertEquals("ON state", Light.ON, l.getState());
l.activateLight();
Assert.assertEquals("OFF state", Light.OFF, l.getState());
s.setState(Sensor.OFF);
Assert.assertEquals("ON state", Light.ON, l.getState());
s.setState(Sensor.ON);
Assert.assertEquals("OFF state", Light.OFF, l.getState());
l.setEnabled(false);
s.setState(Sensor.OFF);
Assert.assertEquals("does not change", Light.OFF, l.getState());
}
@Test
public void testNoSensor() {
lc.setControlType(Light.SENSOR_CONTROL);
l.addLightControl(lc);
l.activateLight();
JUnitAppender.assertErrorMessage("Light ILL1 is linked to a Sensor that does not exist:");
}
@Test
public void testNoTurnout() {
lc.setControlType(Light.TURNOUT_STATUS_CONTROL);
l.addLightControl(lc);
l.activateLight();
JUnitAppender.assertErrorMessageStartsWith("Invalid system name for Turnout: System name must start with \"IT\".");
JUnitAppender.assertErrorMessageStartsWith("Light ILL1 is linked to a Turnout that does not exist");
lc.setControlTurnoutState(999);
JUnitAppender.assertErrorMessageStartsWith("Incorrect Turnout State Set");
}
@Test
public void testTurnoutFollower() throws jmri.JmriException {
Turnout t = InstanceManager.getDefault(jmri.TurnoutManager.class).provideTurnout("T1");
int startListeners = t.getPropertyChangeListeners().length;
lc.setControlType(Light.TURNOUT_STATUS_CONTROL);
lc.setControlTurnout("T1");
lc.setControlTurnoutState(Turnout.THROWN);
l.addLightControl(lc);
l.activateLight();
Assert.assertEquals("+1 listener", startListeners + 1, t.getPropertyChangeListeners().length);
Assert.assertEquals("Turnout unknown state", Turnout.UNKNOWN, t.getState());
Assert.assertEquals("Light OFF state", Light.OFF, l.getState()); // lights are OFF by default
t.setState(Turnout.THROWN);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
t.setState(Turnout.CLOSED);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
t.setState(Turnout.THROWN);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
t.setState(Turnout.UNKNOWN);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
t.setState(Turnout.CLOSED);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
l.deactivateLight();
Assert.assertEquals("releases turnout listener", startListeners, t.getPropertyChangeListeners().length);
lc.setControlTurnoutState(Turnout.CLOSED);
l.activateLight();
Assert.assertEquals("Activation polls the Turnout", Light.ON, l.getState());
t.setState(Turnout.THROWN);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
t.setState(Turnout.CLOSED);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
l.setEnabled(false);
t.setState(Turnout.THROWN);
Assert.assertEquals("does not update when light not enabled", Light.ON, l.getState());
}
@Test
public void testFastClockFollowingOneControl() throws TimebaseRateException {
Timebase timebase = InstanceManager.getDefault(Timebase.class);
timebase.setRun(false);
java.util.Calendar cal = new java.util.GregorianCalendar();
cal.set(2018, 1, 12, 2, 00, 00); // 02:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("OFF state by default", Light.OFF, l.getState()); // lights are OFF by default
Assert.assertEquals("enabled by default", true, l.getEnabled()); // lights are enabled by default
int startListeners = timebase.getMinuteChangeListeners().length;
lc.setControlType(Light.FAST_CLOCK_CONTROL);
lc.setFastClockControlSchedule(3, 0, 4, 0); // onHr, OnMin, OffHr, OffMin
Assert.assertTrue("Total On Time",180==lc.getFastClockOnCombined());
Assert.assertTrue("Total Off Time",240==lc.getFastClockOffCombined());
l.addLightControl(lc);
l.activateLight();
Assert.assertEquals("+1 listener", startListeners + 1, timebase.getMinuteChangeListeners().length);
// JUnitUtil.waitFor(()->{return l.getState()==Light.OFF;},"Light goes OFF at 02:00");
Assert.assertEquals("OFF at 02:00 when control 03:00 - 04:00", Light.OFF, l.getState());
cal.set(2018, 1, 12, 2, 59, 00); // 02:59:00
timebase.setTime(cal.getTime());
Assert.assertEquals("OFF at 02:59 when control 03:00 - 04:00", Light.OFF, l.getState());
cal.set(2018, 1, 12, 3, 00, 00); // 03:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("ON at 03:00 when control 03:00 - 04:00", Light.ON, l.getState());
cal.set(2018, 1, 12, 3, 59, 00); // 03:59:00
timebase.setTime(cal.getTime());
Assert.assertEquals("ON at 03:59 when control 03:00 - 04:00", Light.ON, l.getState());
cal.set(2018, 1, 12, 4, 00, 00); // 04:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("OFF at 04:00 when control 03:00 - 04:00", Light.OFF, l.getState());
cal.set(2018, 1, 12, 4, 01, 00); // 04:01:00
timebase.setTime(cal.getTime());
Assert.assertEquals("OFF at 04:01 when control 03:00 - 04:00", Light.OFF, l.getState());
l.deactivateLight();
Assert.assertEquals("listener removed", startListeners, timebase.getMinuteChangeListeners().length);
}
@Test
public void testFastClockFollowingOneControlStartOn() throws TimebaseRateException {
Timebase timebase = InstanceManager.getDefault(Timebase.class);
timebase.setRun(false);
java.util.Calendar cal = new java.util.GregorianCalendar();
cal.set(2018, 1, 12, 21, 00, 00); // 21:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("OFF state by default", Light.OFF, l.getState()); // lights are OFF by default
lc.setControlType(Light.FAST_CLOCK_CONTROL);
lc.setFastClockControlSchedule(18, 0, 7, 0); // onHr, OnMin, OffHr, OffMin
l.addLightControl(lc);
l.activateLight();
Assert.assertEquals("ON when starting at 21:00 control 18:00 - 07:00", Light.ON, l.getState());
l.setState(Light.OFF);
Assert.assertEquals("goes OFF when set by something else", Light.OFF, l.getState());
cal.set(2018, 1, 12, 21, 01, 00); // 21:01:00
timebase.setTime(cal.getTime());
Assert.assertEquals("goes back ON on next minute update", Light.ON, l.getState());
l.setEnabled(false);
cal.set(2018, 1, 12, 7, 59, 00); // 07:59:00
timebase.setTime(cal.getTime());
Assert.assertEquals("Light still on", Light.ON, l.getState());
cal.set(2018, 1, 12, 8, 00, 00); // 08:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("Light still on as not enabled", Light.ON, l.getState());
l.setEnabled(true);
cal.set(2018, 1, 12, 8, 01, 00); // 08:01:00
timebase.setTime(cal.getTime());
Assert.assertEquals("Light goes off on next update re-enabled", Light.OFF, l.getState());
}
@Test
public void testFastClockFollowingTwoControls() throws TimebaseRateException {
Timebase timebase = InstanceManager.getDefault(Timebase.class);
timebase.setRun(false);
java.util.Calendar cal = new java.util.GregorianCalendar();
cal.set(2018, 1, 12, 21, 00, 00); // 21:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("OFF state by default", Light.OFF, l.getState()); // lights are OFF by default
lc.setControlType(Light.FAST_CLOCK_CONTROL);
lc.setFastClockControlSchedule(3, 0, 4, 0); // onHr, OnMin, OffHr, OffMin
LightControl lcb = new DefaultLightControl(l);
lcb.setControlType(Light.FAST_CLOCK_CONTROL);
lcb.setFastClockControlSchedule(5, 0, 6, 0); // onHr, OnMin, OffHr, OffMin
l.addLightControl(lc);
l.addLightControl(lcb);
l.activateLight();
Assert.assertEquals("OFF starting at 21:00 controls 03:00-04:00, 05:00-06:00", Light.OFF, l.getState());
// adding the PCL to check that we don't get flickering on the Light
// ie "normal" amount of PCEvents for a state change.
// NOT testing the actual PCListeners
l.addPropertyChangeListener(new ControlListen());
cal.set(2018, 1, 12, 2, 59, 00); // 02:59:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still OFF", Light.OFF, l.getState());
Assert.assertEquals("0 Light PropertyChangeEvents", 0, _listenerkicks);
cal.set(2018, 1, 12, 3, 00, 00); // 03:00:00
timebase.setTime(cal.getTime());
// JUnitUtil.waitFor(()->{return l.getState()==Light.ON;},"Light goes ON at 03:00");
Assert.assertEquals("goes ON", Light.ON, l.getState());
// At time of writing there are 2 PCE's on Light state change
// "TargetIntensity" and "KnownState"
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
cal.set(2018, 1, 12, 3, 59, 00); // 03:59:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still ON", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
cal.set(2018, 1, 12, 4, 00, 00); // 04:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("goes OFF", Light.OFF, l.getState());
Assert.assertEquals("4 Light PropertyChangeEvents", 4, _listenerkicks);
cal.set(2018, 1, 12, 4, 59, 00); // 04:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still OFF", Light.OFF, l.getState());
Assert.assertEquals("4 Light PropertyChangeEvents", 4, _listenerkicks);
cal.set(2018, 1, 12, 5, 00, 00); // 05:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("goes ON", Light.ON, l.getState());
Assert.assertEquals("6 Light PropertyChangeEvents", 6, _listenerkicks);
cal.set(2018, 1, 12, 5, 59, 00); // 05:59:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still ON", Light.ON, l.getState());
Assert.assertEquals("6 Light PropertyChangeEvents", 6, _listenerkicks);
cal.set(2018, 1, 12, 6, 00, 00); // 06:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("goes OFF", Light.OFF, l.getState());
Assert.assertEquals("8 Light PropertyChangeEvents for 4 actual changes", 8, _listenerkicks);
}
@Test
public void testFastClockFollowingTwoControlsOverlap() throws TimebaseRateException {
Timebase timebase = InstanceManager.getDefault(Timebase.class);
timebase.setRun(false);
java.util.Calendar cal = new java.util.GregorianCalendar();
cal.set(2018, 1, 12, 02, 59, 00); // 02:59:00
timebase.setTime(cal.getTime());
lc.setControlType(Light.FAST_CLOCK_CONTROL);
lc.setFastClockControlSchedule(3, 0, 4, 0); // onHr, OnMin, OffHr, OffMin
LightControl lcb = new DefaultLightControl(l);
lcb.setControlType(Light.FAST_CLOCK_CONTROL);
lcb.setFastClockControlSchedule(3, 30, 4, 30); // onHr, OnMin, OffHr, OffMin
Assert.assertTrue("Total On Time",210==lcb.getFastClockOnCombined());
Assert.assertTrue("Total Off Time",270==lcb.getFastClockOffCombined());
l.addLightControl(lc);
l.addLightControl(lcb);
l.activateLight();
Assert.assertEquals("OFF starting at 02:59 controls 03:00-04:00, 03:30-04:30", Light.OFF, l.getState());
// adding the PCL to check that we don't get flickering on the Light
// ie "normal" amount of PCEvents for a state change.
// NOT testing the actual PCListeners
l.addPropertyChangeListener(new ControlListen());
cal.set(2018, 1, 12, 3, 00, 00); // 03:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("goes ON", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
cal.set(2018, 1, 12, 3, 29, 00); // 03:29:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still ON", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
cal.set(2018, 1, 12, 3, 30, 00); // 03:30:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still ON", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
cal.set(2018, 1, 12, 3, 59, 00); // 03:59:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still ON", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
cal.set(2018, 1, 12, 4, 00, 00); // 04:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("goes OFF", Light.OFF, l.getState());
Assert.assertEquals("4 Light PropertyChangeEvents for 2 actual changes", 4, _listenerkicks);
cal.set(2018, 1, 12, 4, 29, 00); // 04:29:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still OFF", Light.OFF, l.getState());
Assert.assertEquals("4 Light PropertyChangeEvents for 2 actual changes", 4, _listenerkicks);
cal.set(2018, 1, 12, 4, 30, 00); // 06:00:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still OFF", Light.OFF, l.getState());
Assert.assertEquals("4 Light PropertyChangeEvents for 2 actual changes", 4, _listenerkicks);
cal.set(2018, 1, 12, 4, 31, 00); // 04:31:00
timebase.setTime(cal.getTime());
Assert.assertEquals("still OFF", Light.OFF, l.getState());
Assert.assertEquals("4 Light PropertyChangeEvents for 2 actual changes", 4, _listenerkicks);
}
@Test
public void testTimedSensorFollowing() throws jmri.JmriException {
Assume.assumeFalse("Ignoring intermittent test", Boolean.getBoolean("jmri.skipTestsRequiringSeparateRunning"));
Sensor s = InstanceManager.getDefault(jmri.SensorManager.class).provideSensor("S2");
int startListeners = s.getPropertyChangeListeners().length;
lc.setControlType(Light.TIMED_ON_CONTROL);
lc.setControlTimedOnSensorName("S2");
l.setState(Light.ON); // should go OFF when light enabled and Timed Sensor Control activated
// adding the PCL to check the Light changes
// ie "normal" amount of PCEvents for a state change.
// NOT testing the actual PCListeners
l.addPropertyChangeListener(new ControlListen());
l.addLightControl(lc);
l.activateLight();
Assert.assertEquals("+1 listener", startListeners + 1, s.getPropertyChangeListeners().length);
Assert.assertEquals("Sensor unknown state", Sensor.UNKNOWN, s.getState());
Assert.assertEquals("Light OFF state", Light.OFF, l.getState()); // light set OFF by default
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
s.setState(Sensor.ON);
JUnitUtil.waitFor(() -> {
return 6 == _listenerkicks;
}, "Light goes ON, then OFF v quickly as time is 0");
Assert.assertEquals("Light OFF state", Light.OFF, l.getState()); // light set OFF after timeout
s.setState(Sensor.OFF);
Assert.assertEquals("still 6 Light PropertyChangeEvents", 6, _listenerkicks);
l.deactivateLight();
Assert.assertEquals("releases listener", startListeners, s.getPropertyChangeListeners().length);
lc.setTimedOnDuration(40); // ms
l.activateLight();
s.setState(Sensor.ON);
s.setState(Sensor.OFF);
Assert.assertEquals("Light goes ON at start timer", Light.ON, l.getState());
Assert.assertEquals("8 Light PropertyChangeEvents", 8, _listenerkicks);
JUnitUtil.waitFor(() -> {
return Light.OFF == l.getState();
}, "Light goes back OFF after timer");
Assert.assertEquals("10 Light PropertyChangeEvents", 10, _listenerkicks);
l.setEnabled(false);
s.setState(Sensor.ON);
s.setState(Sensor.OFF);
Assert.assertEquals("Light not enabled", Light.OFF, l.getState());
l.deactivateLight();
l.setState(Light.ON);
l.activateLight();
Assert.assertEquals("Light not enabled so not switched off", Light.ON, l.getState());
l.deactivateLight();
// deactivate light mid-timing
l.setEnabled(true);
lc.setTimedOnDuration(4000); // ms
l.activateLight();
Assert.assertEquals("Light enabled", Light.OFF, l.getState());
s.setState(Sensor.ON);
s.setState(Sensor.OFF);
Assert.assertEquals("Light triggered", Light.ON, l.getState());
l.deactivateLight();
Assert.assertEquals("Light still on", Light.ON, l.getState());
l.activateLight();
Assert.assertEquals("Light enabled", Light.OFF, l.getState());
lc.activateLightControl();
Assert.assertEquals("Light still off", Light.OFF, l.getState());
}
@Test
public void testNoTimedSensor() {
lc.setControlType(Light.TIMED_ON_CONTROL);
l.addLightControl(lc);
l.activateLight();
JUnitAppender.assertErrorMessage("Light ILL1 is linked to a Sensor that does not exist:");
}
@Test
public void testTwoSensorFollowingNoSensorSet() {
lc.setControlType(Light.TWO_SENSOR_CONTROL);
lc.setControlSensorName("");
lc.setControlSensor2Name("");
l.addLightControl(lc);
l.activateLight();
JUnitAppender.assertErrorMessage("Light ILL1 with 2 Sensor Control is linked to a Sensor that does not exist.");
lc.setControlSensorName("S1");
lc.setControlSensor2Name("");
l.activateLight();
JUnitAppender.assertErrorMessage("Light ILL1 with 2 Sensor Control is linked to a Sensor that does not exist.");
lc.setControlSensorName("");
lc.setControlSensor2Name("S2");
l.activateLight();
JUnitAppender.assertErrorMessage("Light ILL1 with 2 Sensor Control is linked to a Sensor that does not exist.");
lc.setControlSensorSense(999);
JUnitAppender.assertErrorMessage("Incorrect Sensor State Set");
}
@Test
public void testTwoSensorFollowing() throws jmri.JmriException {
Sensor sOne = InstanceManager.getDefault(jmri.SensorManager.class).provideSensor("S1");
Sensor sTwo = InstanceManager.getDefault(jmri.SensorManager.class).provideSensor("S2");
lc.setControlType(Light.TWO_SENSOR_CONTROL);
lc.setControlSensorName("S1");
lc.setControlSensor2Name("S2");
lc.setControlSensorSense(Sensor.ACTIVE);
int startListenersOne = sOne.getPropertyChangeListeners().length;
int startListenersTwo = sTwo.getPropertyChangeListeners().length;
l.addLightControl(lc);
l.activateLight();
Assert.assertEquals("+1 listener", startListenersOne + 1, sOne.getPropertyChangeListeners().length);
Assert.assertEquals("+1 listener", startListenersTwo + 1, sTwo.getPropertyChangeListeners().length);
Assert.assertEquals("Sensor unknown state", Sensor.UNKNOWN, sOne.getState());
Assert.assertEquals("Sensor unknown state", Sensor.UNKNOWN, sTwo.getState());
Assert.assertEquals("Light OFF state", Light.OFF, l.getState()); // lights are OFF by default
sOne.setState(Sensor.ON);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
sOne.setState(Sensor.OFF);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
sTwo.setState(Sensor.ON);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
sTwo.setState(Sensor.OFF);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
sOne.setState(Sensor.ON);
sTwo.setState(Sensor.ON);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
sOne.setState(Sensor.OFF);
Assert.assertEquals("Light ON state as Stwo still ACTIVE", Light.ON, l.getState());
sOne.setState(Sensor.ON);
sTwo.setState(Sensor.OFF);
Assert.assertEquals("Light ON state as sOne still ACTIVE", Light.ON, l.getState());
sOne.setState(Sensor.OFF);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
l.deactivateLight();
Assert.assertEquals("releases listener", startListenersOne, sOne.getPropertyChangeListeners().length);
Assert.assertEquals("releases listener", startListenersTwo, sTwo.getPropertyChangeListeners().length);
sOne.setState(Sensor.ON);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
l.activateLight();
Assert.assertEquals("Light ON state", Light.ON, l.getState());
l.setEnabled(false);
sOne.setState(Sensor.OFF);
Assert.assertEquals("does not change", Light.ON, l.getState());
}
@Test
public void testTwoSensorFollowingInactive() throws jmri.JmriException {
Sensor sOne = InstanceManager.getDefault(jmri.SensorManager.class).provideSensor("S1");
Sensor sTwo = InstanceManager.getDefault(jmri.SensorManager.class).provideSensor("S2");
lc.setControlType(Light.TWO_SENSOR_CONTROL);
lc.setControlSensorName("S1");
lc.setControlSensor2Name("S2");
lc.setControlSensorSense(Sensor.INACTIVE);
l.addLightControl(lc);
l.activateLight();
// adding the PCL to check the Light changes
// ie "normal" amount of PCEvents for a state change.
// NOT testing the actual PCListeners
l.addPropertyChangeListener(new ControlListen());
Assert.assertEquals("Sensor unknown state", Sensor.UNKNOWN, sOne.getState());
Assert.assertEquals("Sensor unknown state", Sensor.UNKNOWN, sTwo.getState());
Assert.assertEquals("Light OFF state", Light.OFF, l.getState()); // lights are OFF by default
sOne.setState(Sensor.ACTIVE);
sTwo.setState(Sensor.ACTIVE);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
Assert.assertEquals("0 Light PropertyChangeEvents", 0, _listenerkicks);
sOne.setState(Sensor.INACTIVE);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
sTwo.setState(Sensor.INACTIVE);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
sOne.setState(Sensor.ACTIVE);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
sOne.setState(Sensor.ACTIVE);
sTwo.setState(Sensor.INACTIVE);
Assert.assertEquals("Light ON state", Light.ON, l.getState());
Assert.assertEquals("2 Light PropertyChangeEvents", 2, _listenerkicks);
sTwo.setState(Sensor.ACTIVE);
Assert.assertEquals("Light OFF state", Light.OFF, l.getState());
Assert.assertEquals("4 Light PropertyChangeEvents, 2 actual changes", 4, _listenerkicks);
}
@Test
public void testUniqueTimes() {
lc.setControlType(Light.FAST_CLOCK_CONTROL);
lc.setFastClockControlSchedule(0, 0, 0, 0); // onHr, OnMin, OffHr, OffMin
Assert.assertTrue(lc.onOffTimesFaulty());
lc.setFastClockControlSchedule(1, 2, 3, 4); // onHr, OnMin, OffHr, OffMin
Assert.assertFalse(lc.onOffTimesFaulty());
LightControl lcb = new DefaultLightControl(l);
lcb.setControlType(Light.FAST_CLOCK_CONTROL);
lcb.setFastClockControlSchedule(1, 2, 0, 0); // onHr, OnMin, OffHr, OffMin
l.addLightControl(lc);
Assert.assertFalse(lc.areFollowerTimesFaulty(l.getLightControlList()));
l.addLightControl(lcb);
Assert.assertTrue(lcb.areFollowerTimesFaulty(l.getLightControlList()));
lcb.setFastClockControlSchedule(0, 0, 0, 0); // onHr, OnMin, OffHr, OffMin
Assert.assertTrue(lcb.areFollowerTimesFaulty(l.getLightControlList()));
lcb.setFastClockControlSchedule(9, 0, 10, 0); // onHr, OnMin, OffHr, OffMin
Assert.assertFalse(lcb.areFollowerTimesFaulty(l.getLightControlList()));
lcb.setFastClockControlSchedule(0, 0, 3, 4); // onHr, OnMin, OffHr, OffMin
Assert.assertTrue(lcb.areFollowerTimesFaulty(l.getLightControlList()));
l.activateLight();
JUnitAppender.assertErrorMessage("Light has multiple actions for the same time in Light Controller ILL1 ON at 01:02, OFF at 03:04.");
JUnitAppender.assertErrorMessage("Light has multiple actions for the same time in Light Controller ILL1 ON at 00:00, OFF at 03:04.");
}
private int _listenerkicks;
// internal PCL event counter
private class ControlListen implements java.beans.PropertyChangeListener {
@Override
public void propertyChange(java.beans.PropertyChangeEvent e) {
_listenerkicks++;
// log.warn("{}",e);
}
}
private Light l;
private LightControl lc;
@BeforeEach
public void setUp() {
JUnitUtil.setUp();
jmri.util.JUnitUtil.resetInstanceManager();
jmri.util.JUnitUtil.initInternalTurnoutManager();
jmri.util.JUnitUtil.initInternalLightManager();
jmri.util.JUnitUtil.initInternalSensorManager();
_listenerkicks = 0;
l = InstanceManager.getDefault(jmri.LightManager.class).provideLight("L1");
lc = new DefaultLightControl(l);
}
@AfterEach
public void tearDown() {
JUnitUtil.tearDown();
l.deactivateLight();
l.dispose();
l = null;
lc = null;
}
// private static final Logger log = LoggerFactory.getLogger(LightControlTest.class);
}