235 lines
10 KiB
Java
235 lines
10 KiB
Java
package jmri.server.json.signalhead;
|
|
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
import java.io.DataOutputStream;
|
|
import java.io.IOException;
|
|
import java.util.Locale;
|
|
|
|
import jmri.InstanceManager;
|
|
import jmri.JmriException;
|
|
import jmri.SignalHead;
|
|
import jmri.SignalHeadManager;
|
|
import jmri.implementation.VirtualSignalHead;
|
|
import jmri.server.json.JSON;
|
|
import jmri.server.json.JsonException;
|
|
import jmri.server.json.JsonMockConnection;
|
|
import jmri.server.json.JsonRequest;
|
|
import jmri.util.JUnitAppender;
|
|
import jmri.util.JUnitUtil;
|
|
|
|
import org.junit.jupiter.api.*;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
|
/**
|
|
*
|
|
* @author Paul Bender
|
|
* @author Randall Wood
|
|
* @author Steve Todd
|
|
*/
|
|
public class JsonSignalHeadSocketServiceTest {
|
|
|
|
private final Locale locale = Locale.ENGLISH;
|
|
|
|
@Test
|
|
public void testSignalHeadChange() throws IOException, JmriException, JsonException {
|
|
//create a signal head for testing
|
|
String sysName = "IH1";
|
|
String userName = "SH1";
|
|
SignalHead s = new VirtualSignalHead(sysName, userName);
|
|
SignalHeadManager manager = InstanceManager.getDefault(SignalHeadManager.class);
|
|
manager.register(s);
|
|
assertNotNull(s);
|
|
assertEquals( 1, s.getNumPropertyChangeListeners(), "One listener");
|
|
|
|
JsonMockConnection connection = new JsonMockConnection((DataOutputStream) null);
|
|
connection.setVersion(JSON.V5);
|
|
TestJsonSignalHeadHttpService http = new TestJsonSignalHeadHttpService(connection.getObjectMapper());
|
|
JsonNode message = connection.getObjectMapper().createObjectNode().put(JSON.NAME, sysName);
|
|
JsonSignalHeadSocketService service = new JsonSignalHeadSocketService(connection, http);
|
|
service.onMessage(JsonSignalHead.SIGNAL_HEAD, message, new JsonRequest(locale, JSON.V5, JSON.POST, 42));
|
|
assertEquals( 2, s.getNumPropertyChangeListeners(), "Two listeners");
|
|
|
|
//signalhead defaults to Dark
|
|
message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertEquals(SignalHead.DARK, message.path(JSON.DATA).path(JSON.STATE).asInt());
|
|
|
|
//change to Green, and wait for change to show up, then verify
|
|
s.setAppearance(SignalHead.GREEN);
|
|
JUnitUtil.waitFor(() -> {
|
|
return s.getState() == SignalHead.GREEN;
|
|
}, "SignalHead is now GREEN");
|
|
message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertEquals(SignalHead.GREEN, message.path(JSON.DATA).path(JSON.STATE).asInt());
|
|
|
|
//change to Red, and wait for change to show up, then verify
|
|
s.setAppearance(SignalHead.RED);
|
|
JUnitUtil.waitFor(() -> {
|
|
return s.getState() == SignalHead.RED;
|
|
}, "SignalHead is now RED");
|
|
message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertEquals(SignalHead.RED, message.path(JSON.DATA).path(JSON.STATE).asInt());
|
|
|
|
// put a new signal head
|
|
JsonException ex = assertThrows( JsonException.class, () -> {
|
|
JsonNode messageEx = connection.getObjectMapper().createObjectNode().put(JSON.NAME, "something"); // does not matter
|
|
service.onMessage(JsonSignalHead.SIGNAL_HEAD, messageEx, new JsonRequest(locale, JSON.V5, JSON.PUT, 42));
|
|
});
|
|
assertEquals( 405, ex.getCode(), "Error code is HTTP Invalid Request");
|
|
assertEquals( "Putting signalHead is not allowed.", ex.getMessage(), "Error message");
|
|
|
|
// trap JsonException error
|
|
http.setThrowException(1);
|
|
s.setAppearance(SignalHead.GREEN);
|
|
JUnitUtil.waitFor(() -> {
|
|
return s.getState() == SignalHead.GREEN;
|
|
}, "SignalHead is now GREEN");
|
|
message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertEquals( 499, message.path(JSON.DATA).path(JsonException.CODE).asInt(), "Deliberately thrown error");
|
|
assertEquals( 2, s.getNumPropertyChangeListeners(), "Two listeners");
|
|
|
|
// trap IOException error
|
|
connection.setThrowIOException(true);
|
|
s.setAppearance(SignalHead.RED);
|
|
JUnitUtil.waitFor(() -> {
|
|
return s.getState() == SignalHead.RED;
|
|
}, "SignalHead is now RED");
|
|
assertEquals( 1, s.getNumPropertyChangeListeners(), "One listener");
|
|
}
|
|
|
|
@Test
|
|
public void testOnList() throws IOException, JmriException, JsonException {
|
|
//create a signal head for testing
|
|
String sysName = "IH1";
|
|
String userName = "SH1";
|
|
SignalHead s1 = new VirtualSignalHead(sysName, userName);
|
|
SignalHeadManager manager = InstanceManager.getDefault(SignalHeadManager.class);
|
|
manager.register(s1);
|
|
assertNotNull(s1);
|
|
assertEquals( 0, manager.getPropertyChangeListeners().length, "No listeners");
|
|
|
|
JsonMockConnection connection = new JsonMockConnection((DataOutputStream) null);
|
|
connection.setVersion(JSON.V5);
|
|
TestJsonSignalHeadHttpService http = new TestJsonSignalHeadHttpService(connection.getObjectMapper());
|
|
JsonSignalHeadSocketService service = new JsonSignalHeadSocketService(connection, http);
|
|
service.onList(JsonSignalHead.SIGNAL_HEAD, connection.getObjectMapper().createObjectNode(), new JsonRequest(locale, JSON.V5, JSON.GET, 0));
|
|
assertEquals( 1, manager.getPropertyChangeListeners().length, "One listener");
|
|
JsonNode message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertTrue(message.isArray());
|
|
|
|
SignalHead s2 = new VirtualSignalHead("IH2", "SH2");
|
|
manager.register(s2);
|
|
message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertTrue(message.isArray());
|
|
assertEquals( 2, message.size(), "Two SignalHeads");
|
|
|
|
manager.deregister(s1);
|
|
message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertTrue(message.isArray());
|
|
assertEquals( 1, message.size(), "One SignalHead");
|
|
|
|
// trap JsonException error
|
|
http.setThrowException(2);
|
|
manager.register(s1); // triggers two change reports
|
|
message = connection.getMessage();
|
|
assertNotNull(message);
|
|
assertEquals( 499, message.path(JSON.DATA).path(JsonException.CODE).asInt(), "Deliberately thrown error");
|
|
assertEquals( 1, manager.getPropertyChangeListeners().length, "One listener");
|
|
JUnitAppender.assertWarnMessage(
|
|
"json error sending SignalHeads: {\"type\":\"error\",\"data\":{\"code\":499,\"message\":\"Mock Exception\"}}");
|
|
JUnitAppender.assertWarnMessage(
|
|
"json error sending SignalHeads: {\"type\":\"error\",\"data\":{\"code\":499,\"message\":\"Mock Exception\"}}");
|
|
// trap IOException error
|
|
connection.setThrowIOException(true);
|
|
manager.deregister(s1); // an untrapped error will be thrown by the test
|
|
}
|
|
|
|
@Test
|
|
public void testOnMessageChange() throws IOException, JmriException, JsonException {
|
|
JsonNode message;
|
|
JsonMockConnection connection = new JsonMockConnection((DataOutputStream) null);
|
|
JsonSignalHeadSocketService service = new JsonSignalHeadSocketService(connection);
|
|
|
|
//create a signalhead for testing
|
|
String sysName = "IH1";
|
|
String userName = "SH1";
|
|
SignalHead s = new VirtualSignalHead(sysName, userName);
|
|
SignalHeadManager manager = InstanceManager.getDefault(SignalHeadManager.class);
|
|
manager.register(s);
|
|
assertNotNull(s);
|
|
assertEquals( 0, manager.getPropertyChangeListeners().length, "No listeners");
|
|
|
|
// SignalHead Yellow
|
|
message = connection.getObjectMapper().createObjectNode().put(JSON.NAME, userName)
|
|
.put(JSON.STATE, SignalHead.YELLOW);
|
|
service.onMessage(JsonSignalHead.SIGNAL_HEAD, message, new JsonRequest(locale, JSON.V5, JSON.POST, 42));
|
|
assertEquals(SignalHead.YELLOW, s.getState(), "state should be Yellow");
|
|
assertEquals( 0, manager.getPropertyChangeListeners().length, "No listeners");
|
|
assertEquals( 2, s.getNumPropertyChangeListeners(), "Two listeners");
|
|
|
|
// Try to set SignalHead to FLASHLUNAR, should throw error, remain at Yellow
|
|
JsonException ex = assertThrows( JsonException.class, () -> {
|
|
JsonNode messageEx = connection.getObjectMapper().createObjectNode().put(JSON.NAME, userName)
|
|
.put(JSON.STATE, SignalHead.FLASHLUNAR);
|
|
service.onMessage(JsonSignalHead.SIGNAL_HEAD, messageEx, new JsonRequest(locale, JSON.V5, JSON.POST, 42));
|
|
});
|
|
assertEquals( 400, ex.getCode(), "Error code is HTTP Method not allowed");
|
|
assertEquals( "Attempting to set object type signalHead to unknown state 128.",
|
|
ex.getMessage(), "Error message");
|
|
assertEquals(SignalHead.YELLOW, s.getAppearance()); //state should be Yellow
|
|
assertEquals( 0, manager.getPropertyChangeListeners().length, "No listeners");
|
|
assertEquals( 2, s.getNumPropertyChangeListeners(), "Two listeners");
|
|
|
|
service.onClose();
|
|
assertEquals( 1, s.getNumPropertyChangeListeners(), "One listener");
|
|
|
|
}
|
|
|
|
@BeforeEach
|
|
public void setUp() throws Exception {
|
|
JUnitUtil.setUp();
|
|
JUnitUtil.resetProfileManager();
|
|
JUnitUtil.initInternalSignalHeadManager();
|
|
}
|
|
|
|
@AfterEach
|
|
public void tearDown() throws Exception {
|
|
JUnitUtil.tearDown();
|
|
}
|
|
|
|
private static class TestJsonSignalHeadHttpService extends JsonSignalHeadHttpService {
|
|
|
|
private int throwException = 0;
|
|
|
|
TestJsonSignalHeadHttpService(ObjectMapper mapper) {
|
|
super(mapper);
|
|
}
|
|
|
|
@Override
|
|
public JsonNode doGet(String type, String name, JsonNode data, JsonRequest request) throws JsonException {
|
|
if (throwException > 0) {
|
|
throwException--;
|
|
throw new JsonException(499, "Mock Exception", request.id);
|
|
}
|
|
return super.doGet(type, name, data, request);
|
|
}
|
|
|
|
public void setThrowException(int throwException) {
|
|
this.throwException = throwException;
|
|
}
|
|
|
|
}
|
|
}
|