Files
JIMRI/java/test/jmri/implementation/AbstractSensorTestBase.java
T
2026-06-17 14:00:51 +02:00

262 lines
9.5 KiB
Java

package jmri.implementation;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.beans.PropertyChangeListener;
import jmri.JmriException;
import jmri.Sensor;
import jmri.util.JUnitUtil;
import org.junit.jupiter.api.*;
/**
* Abstract Base Class for Sensor tests in specific jmrix packages. This is not
* itself a test class, e.g. should not be added to a suite. Instead, this forms
* the base for test classes, including providing some common tests.
*
* @author Bob Jacobsen 2016 from AbstractLightTestBase (which was called AbstractLightTest at the time)
* @author Paul Bender Copyright (C) 2018
*/
public abstract class AbstractSensorTestBase {
// implementing classes must provide these these methods
// return number of listeners registered with the TrafficController
abstract public int numListeners();
abstract public void checkActiveMsgSent();
abstract public void checkInactiveMsgSent();
abstract public void checkStatusRequestMsgSent();
// implementing classes must provide this abstract member:
abstract public void setUp(); // load t with actual object; create scaffolds as needed
protected AbstractSensor t = null; // holds object under test; set by setUp()
protected boolean listenerResult = false;
protected class Listen implements PropertyChangeListener {
@Override
public void propertyChange(java.beans.PropertyChangeEvent e) {
listenerResult = true;
}
}
// start of common tests
// test creation - real work is in the setup() routine
@Test
public void testCreate() {
// initial state when created must be UNKNOWN
assertEquals( Sensor.UNKNOWN, t.getState(), "initial state 1 unknown");
assertEquals( "Unknown", t.describeState(t.getState()), "initial state 2");
}
@Test
public void testAddListener() throws JmriException {
t.addPropertyChangeListener(new Listen());
listenerResult = false;
t.setUserName("user id");
assertTrue( listenerResult, "listener invoked by setUserName");
listenerResult = false;
t.setState(Sensor.ACTIVE);
assertTrue( listenerResult, "listener invoked by setState");
}
@Test
public void testRemoveListener() {
Listen ln = new Listen();
t.addPropertyChangeListener(ln);
t.removePropertyChangeListener(ln);
listenerResult = false;
t.setUserName("user id");
assertFalse( listenerResult,
"listener should not have heard message after removeListener");
}
@Test
public void testDispose() throws JmriException {
t.setState(Sensor.ACTIVE); // in case registration with TrafficController is deferred to after first use
t.dispose();
assertEquals( 0, numListeners(), "controller listeners remaining");
}
@Test
public void testRemoveListenerOnDispose() {
assertEquals( 0, t.getNumPropertyChangeListeners(), "starts 0 listeners");
t.addPropertyChangeListener(new Listen());
assertEquals( 1, t.getNumPropertyChangeListeners(), "controller listener added");
t.dispose();
assertTrue( t.getNumPropertyChangeListeners() < 1, "controller listeners remaining < 1");
}
@Test
public void testCommandInactive() throws JmriException {
t.setState(Sensor.INACTIVE);
// check
assertEquals( Sensor.INACTIVE, t.getState(), "state 1");
assertEquals( "Inactive", t.describeState(t.getState()), "state 2");
}
@Test
public void testCommandActive() throws JmriException {
t.setState(Sensor.ACTIVE);
// check
assertEquals( Sensor.ACTIVE, t.getState(), "state 1");
assertEquals( "Active", t.describeState(t.getState()), "state 2");
}
@Test
public void testCommandSentActive() throws JmriException {
t.setState(Sensor.ACTIVE);
assertEquals( Sensor.ACTIVE, t.getState(), "Sensor goes active");
checkActiveMsgSent();
}
@Test
public void testCommandSentInactive() throws JmriException {
t.setState(Sensor.INACTIVE);
assertEquals( Sensor.INACTIVE, t.getState(), "sensor goes inactive");
checkInactiveMsgSent();
}
@Test
public void testInvertAfterInactive() throws JmriException {
assumeTrue(t.canInvert(), "Sensor does not invert");
t.setState(Sensor.INACTIVE);
t.setInverted(true);
// check
assertEquals( Sensor.ACTIVE, t.getState(), "state 1");
assertEquals( "Active", t.describeState(t.getState()), "state 2");
}
@Test
public void testInvertAfterActive() throws JmriException {
assumeTrue(t.canInvert(), "Sensor does not invert");
t.setState(Sensor.ACTIVE);
t.setInverted(true);
// check
assertEquals( Sensor.INACTIVE, t.getState(), "state 1");
assertEquals( "Inactive", t.describeState(t.getState()), "state 2");
}
@Test
public void testDebounceSettings() throws JmriException {
t.setSensorDebounceGoingActiveTimer(81L);
assertEquals( 81L, t.getSensorDebounceGoingActiveTimer(), "timer");
t.setSensorDebounceGoingInActiveTimer(31L);
assertEquals( 31L, t.getSensorDebounceGoingInActiveTimer(), "timer");
assertFalse( t.getUseDefaultTimerSettings(), "initial default");
t.setUseDefaultTimerSettings(true);
assertTrue( t.getUseDefaultTimerSettings(), "initial default");
}
@Test
public void testDebounce() throws JmriException {
t.setSensorDebounceGoingActiveTimer(81L);
assertEquals( 81L, t.getSensorDebounceGoingActiveTimer(), "timer");
t.setSensorDebounceGoingInActiveTimer(31L);
assertEquals( 31L, t.getSensorDebounceGoingInActiveTimer(), "timer");
assertEquals( Sensor.UNKNOWN, t.getState(), "initial state");
t.setOwnState(Sensor.ACTIVE); // next is considered to run immediately, before debounce
assertEquals( Sensor.UNKNOWN, t.getState(), "post-set state");
JUnitUtil.waitFor(()-> t.getState() == t.getRawState(), "raw state = state");
assertEquals( Sensor.ACTIVE, t.getState(), "2nd state");
t.setOwnState(Sensor.INACTIVE); // next is considered to run immediately, before debounce
assertEquals( Sensor.ACTIVE, t.getState(), "post-set state");
JUnitUtil.waitFor(()-> t.getState() == t.getRawState(), "raw state = state");
assertEquals( Sensor.INACTIVE, t.getState(), "Final state");
disposeAndWaitForDebounceThread(t);
}
private void disposeAndWaitForDebounceThread(AbstractSensor t) {
Thread debounce = t.thr;
t.dispose();
if ( debounce !=null ) {
JUnitUtil.waitFor( ()-> { return !debounce.isAlive(); }, debounce.getName() + " did not close");
}
}
@Test
public void testGetPullResistance(){
// default is off, override this test if this is supported.
assertEquals( Sensor.PullResistance.PULL_OFF, t.getPullResistance(), "Pull Direction");
}
@Test
public void testGetBeanType(){
assertEquals( t.getBeanType(), Bundle.getMessage("BeanNameSensor"), "bean type");
}
// Test outgoing status request
@Test
public void testSensorStatusRequest() {
t.requestUpdateFromLayout();
// check that the correct message was sent
checkStatusRequestMsgSent();
}
// Test the Sensor interface
@Test
public void testSensor() throws JmriException {
t.setState(Sensor.ON);
JUnitUtil.waitFor( ()-> t.getState() == Sensor.ON, "state = ON");
assertEquals( Sensor.ON, t.getState(), "Sensor is ON");
t.setState(Sensor.OFF);
JUnitUtil.waitFor( ()-> t.getState() == Sensor.OFF, "state = OFF");
assertEquals( Sensor.OFF, t.getState(), "Sensor is OFF");
t.setCommandedState(Sensor.ON);
JUnitUtil.waitFor( ()-> t.getState() == Sensor.ON, "state = ON");
assertEquals( Sensor.ON, t.getState(), "Sensor is ON");
t.setCommandedState(Sensor.OFF);
JUnitUtil.waitFor( ()-> t.getState() == Sensor.OFF, "state = OFF");
assertEquals( Sensor.OFF, t.getState(), "Sensor is OFF");
t.setState(Sensor.ON);
JUnitUtil.waitFor( ()-> t.getCommandedState() == Sensor.ON, "commanded state = ON");
assertEquals( Sensor.ON, t.getCommandedState(), "Sensor is ON");
t.setState(Sensor.OFF);
JUnitUtil.waitFor( ()-> t.getCommandedState() == Sensor.OFF, "commanded state = OFF");
assertEquals( Sensor.OFF, t.getCommandedState(), "Sensor is ON");
}
@Test
public void testSensorSetKnownState() throws JmriException {
// Assert.assertEquals("ACTIVE", t.describeState(Sensor.ACTIVE), t.describeState(t.getState()));
t.setKnownState(Sensor.ACTIVE);
assertEquals( Sensor.ACTIVE, t.getState(), "ACTIVE");
t.setKnownState(Sensor.INACTIVE);
assertEquals( Sensor.INACTIVE, t.getState(), "INACTIVE");
t.setKnownState(Sensor.UNKNOWN);
assertEquals( Sensor.UNKNOWN, t.getState(), "UNKNOWN");
// Reset known state to something normal
t.setKnownState(Sensor.ACTIVE);
assertEquals( Sensor.ACTIVE, t.getState(), "ACTIVE");
t.setKnownState(Sensor.INCONSISTENT);
assertEquals( Sensor.INCONSISTENT, t.getState(), "INCONSISTENT");
}
//dispose of t.
abstract public void tearDown();
}