Files
JIMRI/java/test/jmri/jmrix/dccpp/DCCppProgrammerTest.java
T
2026-06-17 14:00:51 +02:00

425 lines
17 KiB
Java

package jmri.jmrix.dccpp;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import jmri.*;
import jmri.util.JUnitUtil;
import org.junit.jupiter.api.*;
/**
* DCCppProgrammerTest.java
*
* JUnit tests for the DCCppProgrammer class
*
* @author Bob Jacobsen
* @author Mark Underwood (C) 2015
*/
public class DCCppProgrammerTest extends jmri.jmrix.AbstractProgrammerTest {
static final int RESTART_TIME = 20;
private DCCppInterfaceScaffold t = null;
private ProgListenerScaffold l = null;
private DCCppProgrammer p = null;
@Test
@Override
public void testDefault() {
assertEquals( ProgrammingMode.DIRECTBYTEMODE, programmer.getMode(),
"Check Default");
}
@Override
@Test
public void testDefaultViaBestMode() {
assertEquals( ProgrammingMode.DIRECTBYTEMODE,
((DCCppProgrammer) programmer).getBestMode(), "Check Default");
}
@Test
@Override
public void testSetGetMode() {
Throwable throwable = assertThrows( IllegalArgumentException.class,
() -> programmer.setMode(ProgrammingMode.REGISTERMODE));
assertNotNull(throwable.getMessage());
}
@Override
@Test
public void testGetCanWriteAddress() {
assertFalse( programmer.getCanWrite("1234"), "can write address");
}
@Override
@Test
public void testGetWriteConfirmMode() {
assertEquals( Programmer.WriteConfirmMode.DecoderReply,
programmer.getWriteConfirmMode("1234"), "Write Confirm Mode");
}
@Test
public void testWriteCvSequence() throws JmriException {
// and do the write
p.writeCV("29", 34, l);
// check "prog mode" message sent
assertEquals( 1, t.outbound.size(), "mode message sent");
assertEquals( "W 29 34 0 87", t.outbound.elementAt(0).toString(),
"write message contents");
// send reply
DCCppReply mr1 = DCCppReply.parseDCCppReply("r 0|87|29 34");
t.sendTestMessage(mr1);
// At this point, the standard DCC++ programmer
// should send a result to the programmer listeners, and
// wait for either the next read/write request or for the
// traffic controller to exit from service mode. We just
// need to wait a few seconds and see that the listener we
// registered earlier received the values we expected.
JUnitUtil.waitFor(() -> !(l.getRcvdInvoked() == 0), "Rcvd not invoked");
assertNotEquals( 0, l.getRcvdInvoked(), "Receive Called by Programmer");
assertEquals( 34, l.getRcvdValue(), "Direct mode received value");
}
@Test
@Disabled("test body is commented out")
public void testWriteRegisterSequence() throws JmriException {
/*
// infrastructure objects
DCCppInterfaceScaffold t = new DCCppInterfaceScaffold(new DCCppCommandStation());
jmri.ProgListenerScaffold l = new jmri.ProgListenerScaffold();
DCCppProgrammer p = new DCCppProgrammer(t) {
protected synchronized void restartTimer(int delay) {
super.restartTimer(RESTART_TIME);
}
};
// set register mode
p.setMode(ProgrammingMode.REGISTERMODE);
// and do the write
p.writeCV("29", 12, l);
// check "prog mode" message sent
Assert.assertEquals("read message sent", 1, t.outbound.size());
Assert.assertEquals("write message contents", "23 12 05 0C 38", t.outbound.elementAt(0).toString());
// send reply
DCCppReply mr1 = new DCCppReply();
mr1.setElement(0, 0x61);
mr1.setElement(1, 0x02);
mr1.setElement(2, 0x63);
t.sendTestMessage(mr1);
Assert.assertEquals("inquire message sent", 2, t.outbound.size());
Assert.assertEquals("inquire message contents", "21 10 31", t.outbound.elementAt(1).toString());
// send a result string
DCCppReply mr2 = new DCCppReply();
mr2.setElement(0, 0x63);
mr2.setElement(1, 0x10);
mr2.setElement(2, 0x05);
mr2.setElement(3, 0x0C);
mr2.setElement(4, 0x7A);
t.sendTestMessage(mr2);
// At this point, the standard XpressNet programmer
// should send a result to the programmer listeners, and
// wait for either the next read/write request or for the
// traffic controller to exit from service mode. We just
// need to wait a few seconds and see that the listener we
// registered earlier received the values we expected.
JUnitUtil.waitFor(() -> { return !(l.getRcvdInvoked() == 0); });
//failure in this test occurs with the next line.
Assert.assertFalse("Receive Called by Programmer", l.getRcvdInvoked() == 0);
Assert.assertEquals("Register mode received value", 12, l.getRcvdValue());
*/
}
@Test
public void testReadCvSequence() throws JmriException {
// and do the read
p.readCV("29", l);
// check "prog mode" message sent
assertEquals( 1, t.outbound.size(), "mode message sent");
assertEquals( "R 29 0 82", t.outbound.elementAt(0).toString(), "read message contents");
// send reply
DCCppReply mr1 = DCCppReply.parseDCCppReply("r 0|82|29 12");
t.sendTestMessage(mr1);
// At this point, the standard DCC++ programmer
// should send a result to the programmer listeners, and
// wait for either the next read/write request or for the
// traffic controller to exit from service mode. We just
// need to wait a few seconds and see that the listener we
// registered earlier received the values we expected.
JUnitUtil.waitFor(() -> !(l.getRcvdInvoked() == 0), "Rcvd not invoked");
assertNotEquals( 0, l.getRcvdInvoked(), "Receive Called by Programmer");
assertEquals( 12, l.getRcvdValue(), "Register mode received value");
}
@Test
public void testReadCvWithStartValSequence() throws JmriException {
t.terminateThreads();
p.dispose();
l = null;
t = null;
p = null;
// infrastructure objects
DCCppCommandStation cs = new DCCppCommandStation();
cs.setVersion("3.0.0"); //set the version to support startVal
assertEquals( "3.0.0", cs.getVersion());
t = new DCCppInterfaceScaffold(cs);
l = new ProgListenerScaffold();
p = new DCCppProgrammer(t) {
@Override
protected synchronized void restartTimer(int delay) {
super.restartTimer(RESTART_TIME);
}
};
// and do the read, with 12 as startVal
p.readCV("29", l, 12);
// check "prog mode" message sent
assertEquals( 1, t.outbound.size(), "mode message sent");
assertEquals( "V 29 12", t.outbound.elementAt(0).toString(), "read message contents");
// send reply
DCCppReply mr1 = DCCppReply.parseDCCppReply("v 29 12");
t.sendTestMessage(mr1);
// At this point, the standard DCC++ programmer
// should send a result to the programmer listeners, and
// wait for either the next read/write request or for the
// traffic controller to exit from service mode. We just
// need to wait a few seconds and see that the listener we
// registered earlier received the values we expected.
JUnitUtil.waitFor(() -> !(l.getRcvdInvoked() == 0), "Rcvd not invoked");
//failure in this test occurs with the next line.
assertNotEquals( 0, l.getRcvdInvoked());
assertEquals( 12, l.getRcvdValue(), "Register mode received value");
}
@Test
@Disabled("test is commented out")
public void testReadRegisterSequence() throws JmriException {
/*
// infrastructure objects
DCCppInterfaceScaffold t = new DCCppInterfaceScaffold(new DCCppCommandStation());
jmri.ProgListenerScaffold l = new jmri.ProgListenerScaffold();
DCCppProgrammer p = new DCCppProgrammer(t) {
protected synchronized void restartTimer(int delay) {
super.restartTimer(RESTART_TIME);
}
};
// set register mode
p.setMode(ProgrammingMode.REGISTERMODE);
// and do the read
p.readCV("29", l);
// check "prog mode" message sent
Assert.assertEquals("mode message sent", 1, t.outbound.size());
Assert.assertEquals("read message contents", "22 11 05 36", t.outbound.elementAt(0).toString());
// send reply (enter service mode )
DCCppReply mr1 = new DCCppReply();
mr1.setElement(0, 0x61);
mr1.setElement(1, 0x02);
mr1.setElement(2, 0x63);
t.sendTestMessage(mr1);
Assert.assertEquals("inquire message sent", 2, t.outbound.size());
Assert.assertEquals("inquire message contents", "21 10 31", t.outbound.elementAt(1).toString());
// send a result string
DCCppReply mr2 = new DCCppReply();
mr2.setElement(0, 0x63);
mr2.setElement(1, 0x10);
mr2.setElement(2, 0x05);
mr2.setElement(3, 0x22);
mr2.setElement(4, 0x54);
t.sendTestMessage(mr2);
// At this point, the standard XpressNet programmer
// should send a result to the programmer listeners, and
// wait for either the next read/write request or for the
// traffic controller to exit from service mode. We just
// need to wait a few seconds and see that the listener we
// registered earlier received the values we expected.
JUnitUtil.waitFor(() -> { return !(l.getRcvdInvoked() == 0); });
//failure in this test occurs with the next line.
Assert.assertFalse("Receive Called by Programmer", l.getRcvdInvoked() == 0);
Assert.assertEquals("Register mode received value", 34, l.getRcvdValue());
*/
}
// this test is the same as the testWriteCvSequence test, but
// it checks the sequence for CVs greater than 256, which use
// different XpressNet commands.
@Test
public void testWriteHighCvSequence() throws JmriException {
// and do the write
p.writeCV("300", 34, l);
// check "prog mode" message sent
assertEquals( 1, t.outbound.size(), "mode message sent");
assertEquals( "W 300 34 0 87", t.outbound.elementAt(0).toString(), "write message contents");
// send reply
DCCppReply mr1 = DCCppReply.parseDCCppReply("r 0|87|300 34");
t.sendTestMessage(mr1);
// At this point, the standard DCC++ programmer
// should send a result to the programmer listeners, and
// wait for either the next read/write request or for the
// traffic controller to exit from service mode. We just
// need to wait a few seconds and see that the listener we
// registered earlier received the values we expected.
JUnitUtil.waitFor(() -> !(l.getRcvdInvoked() == 0), "Rcvd not invoked");
assertNotEquals( 0, l.getRcvdInvoked(), "Receive Called by Programmer");
assertEquals( 34, l.getRcvdValue(), "Direct mode received value");
}
// this test is the same as the testReadCvSequence test, but
// it checks the sequence for CVs greater than 256, which use
// different XpressNet commands.
@Test
public void testReadCvHighSequence() throws JmriException {
// and do the read
p.readCV("300", l);
// check "prog mode" message sent
assertEquals( 1, t.outbound.size(), "mode message sent");
assertEquals( "R 300 0 82", t.outbound.elementAt(0).toString(), "read message contents");
// send reply
DCCppReply mr1 = DCCppReply.parseDCCppReply("r 0|82|300 34");
t.sendTestMessage(mr1);
// At this point, the standard DCC++ programmer
// should send a result to the programmer listeners, and
// wait for either the next read/write request or for the
// traffic controller to exit from service mode. We just
// need to wait a few seconds and see that the listener we
// registered earlier received the values we expected.
JUnitUtil.waitFor(() -> !(l.getRcvdInvoked() == 0), "Rcvd not invoked");
assertNotEquals( 0, l.getRcvdInvoked(), "Receive Called by Programmer");
assertEquals( 34, l.getRcvdValue(), "Direct mode received value");
}
// Test to make sure the getCanWrite(int,string) function works correctly
// TODO: Fix test to verify exception thrown for Register and paged modes.
@Test
@Override
public void testGetCanWrite() {
//p.setMode(ProgrammingMode.REGISTERMODE);
//Assert.assertTrue("DCC++ Base Station can write CV3 in Register Mode", p.getCanWrite("3"));
//p.setMode(ProgrammingMode.PAGEMODE);
//Assert.assertTrue("DCC++ Base Station Can Write CV3 in paged mode", p.getCanWrite("3"));
p.setMode(ProgrammingMode.DIRECTBYTEMODE);
assertTrue( p.getCanWrite("3"), "DCC++ Base Station Can Write CV3 in direct byte mode");
// p.setMode(ProgrammingMode.DIRECTBITMODE);
// Assert.assertFalse("DCC++ Base Station Can Not Write CV3 in direct bit mode", p.getCanWrite("3"));
//p.setMode(ProgrammingMode.REGISTERMODE);
//Assert.assertFalse("DCC++ Base Station Can not Write CV300 in register mode", p.getCanWrite("300"));
//p.setMode(ProgrammingMode.PAGEMODE);
//Assert.assertFalse("DCC++ Base Station Can not Write CV300 in paged mode", p.getCanWrite("300"));
p.setMode(ProgrammingMode.DIRECTBYTEMODE);
assertTrue( p.getCanWrite("300"), "DCC++ Base Station Can Write CV300 in direct byte mode");
// p.setMode(ProgrammingMode.DIRECTBITMODE);
// Assert.assertFalse("DCC++ Base Station Can Not Write CV300 in direct bit mode", p.getCanWrite("300"));
p.setMode(ProgrammingMode.DIRECTBYTEMODE);
assertFalse( p.getCanWrite("3000"), "DCC++ Base Station Can Not Write CV3000 in direct byte mode");
// p.setMode(ProgrammingMode.DIRECTBITMODE);
// Assert.assertFalse("DCC++ Base Station Can Not Write CV3000 in direct bit mode", p.getCanWrite("3000"));
}
// Test to make sure the getCanRead(int,string) function works correctly
// TODO: Fix test to verify exception thrown for Register and paged modes.
@Test
@Override
public void testGetCanRead() {
//p.setMode(ProgrammingMode.REGISTERMODE);
//Assert.assertTrue("DCC++ Base Station Can Read CV3 in register mode", p.getCanRead("3"));
//p.setMode(ProgrammingMode.PAGEMODE);
//Assert.assertTrue("DCC++ Base Station Can Read CV3 in paged mode", p.getCanRead("3"));
p.setMode(ProgrammingMode.DIRECTBYTEMODE);
assertTrue( p.getCanRead("3"), "DCC++ Base Station Can Read CV3 in direct byte mode");
// p.setMode(ProgrammingMode.DIRECTBITMODE);
// Assert.assertFalse("DCC++ Base Station Can Not Read CV3 in direct bit mode", p.getCanRead("3"));
//p.setMode(ProgrammingMode.REGISTERMODE);
//Assert.assertFalse("DCC++ Base Station Can not Read CV300 in register mode", p.getCanRead("300"));
//p.setMode(ProgrammingMode.PAGEMODE);
//Assert.assertFalse("DCC++ Base Station Can not Read CV300 in paged mode", p.getCanRead("300"));
p.setMode(ProgrammingMode.DIRECTBYTEMODE);
assertTrue( p.getCanRead("300"), "DCC++ Base Station Can Read CV300 in direct byte mode");
// p.setMode(ProgrammingMode.DIRECTBITMODE);
// Assert.assertFalse("DCC++ Base Station Can Not Read CV300 in direct bit mode", p.getCanRead("300"));
p.setMode(ProgrammingMode.DIRECTBYTEMODE);
assertFalse( p.getCanRead("3000"), "DCC++ Base Station Can not Read CV3000 in direct byte mode");
// p.setMode(ProgrammingMode.DIRECTBITMODE);
// Assert.assertFalse("DCC++ Base Station Can not Read CV3000 in direct bit mode", p.getCanRead("3000"));
}
@Override
@BeforeEach
public void setUp() {
JUnitUtil.setUp();
// infrastructure objects
t = new DCCppInterfaceScaffold(new DCCppCommandStation());
l = new ProgListenerScaffold();
p = new DCCppProgrammer(t) {
@Override
protected synchronized void restartTimer(int delay) {
super.restartTimer(RESTART_TIME);
}
};
programmer = p;
}
@Override
@AfterEach
public void tearDown() {
p.dispose();
t.terminateThreads();
t = null;
l = null;
p = null;
JUnitUtil.tearDown();
}
}