Files
JIMRI/java/test/jmri/server/json/operations/JsonOperationsSocketServiceTest.java
2026-06-17 14:00:51 +02:00

608 lines
32 KiB
Java

package jmri.server.json.operations;
import static org.junit.jupiter.api.Assertions.*;
import java.beans.PropertyChangeEvent;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import org.junit.jupiter.api.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.NullNode;
import jmri.InstanceManager;
import jmri.JmriException;
import jmri.jmrit.operations.locations.Location;
import jmri.jmrit.operations.locations.LocationManager;
import jmri.jmrit.operations.rollingstock.cars.*;
import jmri.jmrit.operations.rollingstock.engines.EngineManager;
import jmri.jmrit.operations.trains.Train;
import jmri.jmrit.operations.trains.TrainManager;
import jmri.server.json.*;
import jmri.util.*;
public class JsonOperationsSocketServiceTest {
private JsonMockConnection connection;
private JsonOperationsSocketService service;
private ObjectMapper mapper;
private final Locale locale = Locale.ENGLISH;
@Test
public void testOnListCar() throws IOException, JmriException, JsonException {
service.onList(JsonOperations.CAR, mapper.createObjectNode(), new JsonRequest(locale, JSON.V5, JSON.GET, 0));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals(9, message.size());
assertEquals(JsonOperations.CAR, message.path(0).path(JSON.TYPE).asText());
assertEquals("CP777", message.path(0).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(1).path(JSON.TYPE).asText());
assertEquals("CP888", message.path(1).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(2).path(JSON.TYPE).asText());
assertEquals("CP99", message.path(2).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(3).path(JSON.TYPE).asText());
assertEquals("CPC10099", message.path(3).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(4).path(JSON.TYPE).asText());
assertEquals("CPC20099", message.path(4).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(5).path(JSON.TYPE).asText());
assertEquals("CPX10001", message.path(5).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(6).path(JSON.TYPE).asText());
assertEquals("CPX10002", message.path(6).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(7).path(JSON.TYPE).asText());
assertEquals("CPX20001", message.path(7).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.CAR, message.path(8).path(JSON.TYPE).asText());
assertEquals("CPX20002", message.path(8).path(JSON.DATA).path(JSON.NAME).asText());
// add car and assert new messages sent with 10 cars
CarManager manager = InstanceManager.getDefault(CarManager.class);
manager.newRS("GNWR", "300005");
message = connection.getMessage();
assertNotNull(message);
assertEquals( 10, message.size());
}
@Test
public void testGetCar() throws IOException, JmriException, JsonException {
CarManager manager = InstanceManager.getDefault(CarManager.class);
assertNull(manager.getById("GNWR300005"));
// get non-existent car
JsonException ex = assertThrows( JsonException.class, () ->
service.onMessage(JsonOperations.CAR, mapper.createObjectNode().put(JSON.NAME, "GNWR300005"),
new JsonRequest(locale, JSON.V5, JSON.GET, 42)),
"Expected exception not thrown");
assertEquals( 404, ex.getCode());
assertNull(manager.getById("GNWR300005"));
// create car
manager.newRS("GNWR", "300005");
assertNotNull(manager.getById("GNWR300005"));
// get existent car
service.onMessage(JsonOperations.CAR, mapper.createObjectNode().put(JSON.NAME, "GNWR300005"),
new JsonRequest(locale, JSON.V5, JSON.GET, 42));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.CAR, message.path(JSON.TYPE).asText());
assertEquals( "GNWR300005", message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "", message.path(JSON.DATA).path(JsonOperations.TYPE).asText());
// change car
manager.getById("GNWR300005").setTypeName("Boxcar");
message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.CAR, message.path(JSON.TYPE).asText());
assertEquals( "GNWR300005", message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "Boxcar", message.path(JSON.DATA).path(JsonOperations.TYPE).asText());
}
@Test
public void testEditCar() throws IOException, JmriException, JsonException {
CarManager manager = InstanceManager.getDefault(CarManager.class);
assertNull(manager.getById("GNWR300005"));
// creates car
service.onMessage(JsonOperations.CAR,
mapper.createObjectNode().put(JsonOperations.ROAD, "GNWR").put(JsonOperations.NUMBER, "300005"),
new JsonRequest(locale, JSON.V5, JSON.PUT, 42));
assertNotNull(manager.getById("GNWR300005"));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.CAR, message.path(JSON.TYPE).asText());
assertEquals( "", message.path(JSON.DATA).path(JsonOperations.TYPE).asText());
// makes change
service.onMessage(JsonOperations.CAR,
mapper.createObjectNode().put(JSON.NAME, "GNWR300005").put(JsonOperations.TYPE, "Boxcar"),
new JsonRequest(locale, JSON.V5, JSON.POST, 42));
message = connection.getMessage();
assertNotNull(message);
assertEquals( "Boxcar", message.path(JSON.DATA).path(JsonOperations.TYPE).asText());
// gets external change
manager.getById("GNWR300005").setTypeName("Flatcar");
message = connection.getMessage();
assertNotNull(message);
assertEquals( "Flatcar", message.path(JSON.DATA).path(JsonOperations.TYPE).asText());
// deletes car
service.onMessage(JsonOperations.CAR, mapper.createObjectNode().put(JSON.NAME, "GNWR300005"),
new JsonRequest(locale, JSON.V5, JSON.DELETE, 42));
assertNull(manager.getById("GNWR300005"));
}
@Test
public void testOnListEngine() throws IOException, JmriException, JsonException {
service.onList(JsonOperations.ENGINE, mapper.createObjectNode(), new JsonRequest(locale, JSON.V5, JSON.GET, 0));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals(4, message.size());
assertEquals(JsonOperations.ENGINE, message.path(0).path(JSON.TYPE).asText());
assertEquals("PC5016", message.path(0).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.ENGINE, message.path(1).path(JSON.TYPE).asText());
assertEquals("PC5019", message.path(1).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.ENGINE, message.path(2).path(JSON.TYPE).asText());
assertEquals("PC5524", message.path(2).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.ENGINE, message.path(3).path(JSON.TYPE).asText());
assertEquals("PC5559", message.path(3).path(JSON.DATA).path(JSON.NAME).asText());
// add engine and assert new messages sent with 10 engines
EngineManager manager = InstanceManager.getDefault(EngineManager.class);
manager.newRS("GNWR", "45");
message = connection.getMessage();
assertNotNull(message);
assertEquals( 5, message.size());
}
@Test
public void testGetEngine() throws IOException, JmriException, JsonException {
EngineManager manager = InstanceManager.getDefault(EngineManager.class);
assertNull(manager.getById("GNWR45"));
// get non-existent car
JsonException ex = assertThrows( JsonException.class, () ->
service.onMessage(JsonOperations.ENGINE, mapper.createObjectNode().put(JSON.NAME, "GNWR45"),
new JsonRequest(locale, JSON.V5, JSON.GET, 42)),
"Expected exception not thrown");
assertEquals( 404, ex.getCode());
assertNull(manager.getById("GNWR45"));
// create car
manager.newRS("GNWR", "45");
assertNotNull(manager.getById("GNWR45"));
// get existent car
service.onMessage(JsonOperations.ENGINE, mapper.createObjectNode().put(JSON.NAME, "GNWR45"),
new JsonRequest(locale, JSON.V5, JSON.GET, 42));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.ENGINE, message.path(JSON.TYPE).asText());
assertEquals( "GNWR45", message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "", message.path(JSON.DATA).path(JsonOperations.MODEL).asText());
// change car
manager.getById("GNWR45").setModel("MP15DC");
message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.ENGINE, message.path(JSON.TYPE).asText());
assertEquals( "GNWR45", message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "MP15DC", message.path(JSON.DATA).path(JsonOperations.MODEL).asText());
// capture error messages from using "unknown" engine model
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
}
@Test
public void testEditEngine() throws IOException, JmriException, JsonException {
EngineManager manager = InstanceManager.getDefault(EngineManager.class);
assertNull( manager.getById("GNWR45"));
// creates car
service.onMessage(JsonOperations.ENGINE,
mapper.createObjectNode().put(JsonOperations.ROAD, "GNWR").put(JsonOperations.NUMBER, "45"),
new JsonRequest(locale, JSON.V5, JSON.PUT, 42));
assertNotNull(manager.getById("GNWR45"));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.ENGINE, message.path(JSON.TYPE).asText());
assertEquals( "", message.path(JSON.DATA).path(JsonOperations.MODEL).asText());
// makes change
service.onMessage(JsonOperations.ENGINE,
mapper.createObjectNode().put(JSON.NAME, "GNWR45").put(JsonOperations.MODEL, "MP15DC"),
new JsonRequest(locale, JSON.V5, JSON.POST, 42));
message = connection.getMessage();
assertNotNull(message);
assertEquals( "MP15DC", message.path(JSON.DATA).path(JsonOperations.MODEL).asText());
// gets external change
manager.getById("GNWR45").setModel("");
message = connection.getMessage();
assertNotNull(message);
assertEquals( "", message.path(JSON.DATA).path(JsonOperations.MODEL).asText());
// deletes car
service.onMessage(JsonOperations.ENGINE, mapper.createObjectNode().put(JSON.NAME, "GNWR45"),
new JsonRequest(locale, JSON.V5, JSON.DELETE, 42));
assertNull(manager.getById("GNWR45"));
// capture error messages from using "unknown" engine model
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
JUnitAppender.assertErrorMessage("Rolling stock (GNWR 45) length () is not valid");
}
@Test
public void testOnListLocation() throws IOException, JmriException, JsonException {
service.onList(JSON.LOCATION, mapper.createObjectNode(),
new JsonRequest(locale, JSON.V5, JSON.GET, 0));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals(3, message.size());
assertEquals(JSON.LOCATION, message.path(0).path(JSON.TYPE).asText());
assertEquals("1", message.path(0).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JSON.LOCATION, message.path(1).path(JSON.TYPE).asText());
assertEquals("3", message.path(1).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JSON.LOCATION, message.path(2).path(JSON.TYPE).asText());
assertEquals("20", message.path(2).path(JSON.DATA).path(JSON.NAME).asText());
// add engine and assert new messages sent with 10 engines
LocationManager manager = InstanceManager.getDefault(LocationManager.class);
manager.newLocation("Acme Transfer");
message = connection.getMessage();
assertNotNull(message);
assertEquals( 4, message.size());
}
@Test
public void testGetLocation() throws IOException, JmriException, JsonException {
LocationManager manager = InstanceManager.getDefault(LocationManager.class);
assertNull(manager.getLocationByName("Acme Transfer"));
// get non-existent location
JsonException ex = assertThrows( JsonException.class, () ->
service.onMessage(JSON.LOCATION, mapper.createObjectNode().put(JSON.NAME, "Acme Transfer"),
new JsonRequest(locale, JSON.V5, JSON.GET, 42)),
"Expected exception not thrown");
assertEquals( 404, ex.getCode());
assertNull(manager.getLocationByName("Acme Transfer"));
// create location
Location location = manager.newLocation("Acme Transfer");
assertNotNull(location);
// get existent location
service.onMessage(JSON.LOCATION, mapper.createObjectNode().put(JSON.NAME, location.getId()),
new JsonRequest(locale, JSON.V5, JSON.GET, 42));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JSON.LOCATION, message.path(JSON.TYPE).asText());
assertEquals( location.getId(), message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// change location
location.setComment("Watch for coyotes");
message = connection.getMessage();
assertNotNull(message);
assertEquals( JSON.LOCATION, message.path(JSON.TYPE).asText());
assertEquals( location.getId(), message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "Watch for coyotes", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// silence expected error
JUnitAppender.assertErrorMessage("Unable to get location id [Acme Transfer].");
}
@Test
public void testEditLocation() throws IOException, JmriException, JsonException {
LocationManager manager = InstanceManager.getDefault(LocationManager.class);
assertNull(manager.getLocationByName("Acme Transfer"));
// creates location
service.onMessage(JSON.LOCATION, mapper.createObjectNode().put(JSON.USERNAME, "Acme Transfer"),
new JsonRequest(locale, JSON.V5, JSON.PUT, 42));
Location location = manager.getLocationByName("Acme Transfer");
assertNotNull(location);
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JSON.LOCATION, message.path(JSON.TYPE).asText());
assertEquals( "", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// makes change
service.onMessage(JSON.LOCATION,
mapper.createObjectNode().put(JSON.NAME, location.getId()).put(JSON.COMMENT, "Watch for coyotes"),
new JsonRequest(locale, JSON.V5, JSON.POST, 42));
message = connection.getMessage();
assertNotNull(message);
assertEquals( "Watch for coyotes", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// gets external change
location.setComment("");
message = connection.getMessage();
assertNotNull(message);
assertEquals( "", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// deletes location
service.onMessage(JSON.LOCATION, mapper.createObjectNode().put(JSON.NAME, location.getId()),
new JsonRequest(locale, JSON.V5, JSON.DELETE, 42));
assertNull(manager.getLocationById(location.getId()));
}
@Test
public void testOnListTrain() throws IOException, JmriException, JsonException {
service.onList(JsonOperations.TRAIN, mapper.createObjectNode(), new JsonRequest(locale, JSON.V5, JSON.GET, 0));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals(2, message.size());
assertEquals(JsonOperations.TRAIN, message.path(0).path(JSON.TYPE).asText());
assertEquals("1", message.path(0).path(JSON.DATA).path(JSON.NAME).asText());
assertEquals(JsonOperations.TRAIN, message.path(1).path(JSON.TYPE).asText());
assertEquals("2", message.path(1).path(JSON.DATA).path(JSON.NAME).asText());
// add engine and assert new messages sent with 10 engines
TrainManager manager = InstanceManager.getDefault(TrainManager.class);
manager.newTrain("Acme Transfer");
message = connection.getMessage();
assertNotNull(message);
assertEquals( 3, message.size());
}
@Test
public void testGetTrain() throws IOException, JmriException, JsonException {
TrainManager manager = InstanceManager.getDefault(TrainManager.class);
assertNull(manager.getTrainByName("Acme Transfer"));
// get non-existent train
JsonException ex = assertThrows( JsonException.class, () ->
service.onMessage(JSON.LOCATION, mapper.createObjectNode().put(JSON.NAME, "Acme Transfer"),
new JsonRequest(locale, JSON.V5, JSON.GET, 42)),
"Expected exception not thrown");
assertEquals( 404, ex.getCode());
assertNull(manager.getTrainByName("Acme Transfer"));
// create train
Train train = manager.newTrain("Acme Transfer");
assertNotNull(train);
// get existent location
service.onMessage(JsonOperations.TRAIN, mapper.createObjectNode().put(JSON.NAME, train.getId()),
new JsonRequest(locale, JSON.V5, JSON.GET, 42));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.TRAIN, message.path(JSON.TYPE).asText());
assertEquals( train.getId(), message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// change location
train.setComment("Watch for coyotes");
message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.TRAIN, message.path(JSON.TYPE).asText());
assertEquals( train.getId(), message.path(JSON.DATA).path(JSON.NAME).asText());
assertEquals( "Watch for coyotes", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// silence expected error
JUnitAppender.assertErrorMessage("Unable to get location id [Acme Transfer].");
}
@Test
public void testEditTrain() throws IOException, JmriException, JsonException {
JUnitOperationsUtil.loadTrains();
Location location1 = InstanceManager.getDefault(LocationManager.class).getLocationById("1");
Location location2 = InstanceManager.getDefault(LocationManager.class).getLocationById("3");
TrainManager manager = InstanceManager.getDefault(TrainManager.class);
Train train = manager.getTrainById("1");
assertTrue(train.build());
assertEquals( location1, train.getCurrentRouteLocation().getLocation());
assertNull(manager.getTrainByName("Acme Transfer"));
// creates train
JsonException ex = assertThrows( JsonException.class, () ->
service.onMessage(JsonOperations.TRAIN, mapper.createObjectNode().put(JSON.USERNAME, "Acme Transfer"),
new JsonRequest(locale, JSON.V5, JSON.PUT, 42)),
"Expected exception not thrown");
assertEquals( 405, ex.getCode());
assertNotNull(train);
service.onMessage(JsonOperations.TRAIN, mapper.createObjectNode().put(JSON.NAME, train.getId()),
new JsonRequest(locale, JSON.V5, JSON.GET, 42));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonOperations.TRAIN, message.path(JSON.TYPE).asText());
assertTrue(message.path(JSON.DATA).path(JSON.LOCATION).isEmpty());
// makes invalid change
ex = assertThrows( JsonException.class, () ->
service.onMessage(
JsonOperations.TRAIN, mapper.createObjectNode().put(JSON.NAME, train.getId())
.put(JSON.LOCATION, location1.getName()),
new JsonRequest(locale, JSON.V5, JSON.POST, 42)),
"Expected exception not thrown");
assertEquals( 428, ex.getCode());
assertEquals( "Unable to move train 1 to location North End Staging.", ex.getMessage());
// makes valid change
service.onMessage(JsonOperations.TRAIN, mapper.createObjectNode().put(JSON.NAME, train.getId())
.put(JSON.LOCATION, location2.getName()), new JsonRequest(locale, JSON.V5, JSON.POST, 42));
message = connection.getMessage();
assertNotNull(message);
assertEquals( location2.getName(), message.path(JSON.DATA).path(JSON.LOCATION).asText());
assertEquals( "Test comment for train STF", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// makes ignored change
service.onMessage(JsonOperations.TRAIN,
mapper.createObjectNode().put(JSON.NAME, train.getId()).put(JSON.COMMENT, "Watch for coyotes"),
new JsonRequest(locale, JSON.V5, JSON.POST, 42));
message = connection.getMessage();
assertNotNull(message);
assertEquals( location2.getName(), message.path(JSON.DATA).path(JSON.LOCATION).asText());
assertEquals( "Test comment for train STF", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// gets external change
train.setComment("Watch for coyotes");
message = connection.getMessage();
assertNotNull(message);
assertEquals( "Watch for coyotes", message.path(JSON.DATA).path(JSON.COMMENT).asText());
// terminates train
service.onMessage(JsonOperations.TRAIN,
mapper.createObjectNode().put(JSON.NAME, train.getId()).putNull(JSON.LOCATION),
new JsonRequest(locale, JSON.V5, JSON.POST, 42));
message = connection.getMessage();
assertNotNull(message);
assertFalse(message.path(JSON.DATA).path(JSON.LOCATION).isNull());
assertEquals( "", message.path(JSON.DATA).path(JSON.LOCATION).asText());
// deletes train
ex = assertThrows( JsonException.class, () ->
service.onMessage(JsonOperations.TRAIN, mapper.createObjectNode().put(JSON.NAME, train.getId()),
new JsonRequest(locale, JSON.V5, JSON.DELETE, 42)),
"Expected exception not thrown");
assertEquals( 405, ex.getCode());
assertEquals( "Deleting train is not allowed.", ex.getMessage());
assertNotNull(manager.getTrainById(train.getId()));
}
@Test
public void testOnMessageKernel() throws IOException, JmriException, JsonException {
JsonException ex = assertThrows( JsonException.class, () ->
service.onMessage(JsonOperations.KERNEL, mapper.createObjectNode().put(JSON.NAME, "non-existant"),
new JsonRequest(locale, JSON.V5, JSON.GET, 42)),
"Expected exception not thrown");
assertEquals(404, ex.getCode());
}
@Test
public void testOnListKernel() throws IOException, JmriException, JsonException {
service.onList(JsonOperations.KERNEL, mapper.createObjectNode(), new JsonRequest(locale, JSON.V5, JSON.GET, 0));
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals(1, message.size());
assertEquals(JsonOperations.KERNEL, message.path(0).path(JSON.TYPE).asText());
JsonNode kernel = message.path(0).path(JSON.DATA);
assertNotNull(kernel);
assertEquals(1, kernel.path(JsonOperations.CARS).size());
assertFalse(kernel.path(JsonOperations.LEAD).isMissingNode());
assertEquals(kernel.path(JsonOperations.LEAD), kernel.path(JsonOperations.CARS).path(0));
assertFalse(kernel.path(JSON.WEIGHT).isMissingNode());
assertEquals(0, kernel.path(JSON.WEIGHT).asInt());
assertEquals(94, kernel.path(JSON.LENGTH).asInt());
}
@Test
public void testOnMessageInvalidType() throws IOException, JmriException {
JsonException ex = assertThrows( JsonException.class, () ->
service.onMessage("invalid-type", NullNode.getInstance(),
new JsonRequest(locale, JSON.V5, JSON.GET, 0)),
"Expected exception not thrown");
assertEquals( 500, ex.getCode());
ex = assertThrows( JsonException.class, () ->
service.onMessage("invalid-type", NullNode.getInstance(),
new JsonRequest(locale, JSON.V5, JSON.DELETE, 0)),
"Expected exception not thrown");
assertEquals( 405, ex.getCode());
}
@Test
public void testOnListInvalidType() throws IOException, JmriException {
JsonException ex = assertThrows( JsonException.class, () ->
service.onList("invalid-type", NullNode.getInstance(),
new JsonRequest(locale, JSON.V5, JSON.GET, 0)),
"Expected exception not thrown");
assertEquals( 500, ex.getCode());
}
@Test
public void testBeanListenerFailures() {
InvalidJsonOperationsSocketService mock = new InvalidJsonOperationsSocketService(connection, new JsonOperationsHttpService(mapper));
Train train = InstanceManager.getDefault(TrainManager.class).getTrainById("1");
assertEquals( 0, mock.invalidBeanListeners.size());
assertEquals( 1, train.getPropertyChangeListeners().length);
InvalidJsonOperationsSocketService.InvalidBeanListener bl = mock.addInvalidBeanListener(train);
// add listener to test that an IOException removes the listener
// the listener would normally be added by onMessage, but that method creates
// a valid listener, and we are not interested in that
train.addPropertyChangeListener(bl);
assertEquals( 1, mock.invalidBeanListeners.size());
assertEquals( 2, train.getPropertyChangeListeners().length);
// throw JsonException on invalid type
bl.propertyChange("invalid-type", (PropertyChangeEvent) null);
assertEquals( 1, mock.invalidBeanListeners.size());
assertEquals( 2, train.getPropertyChangeListeners().length);
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonException.ERROR, message.path(JSON.TYPE).asText());
assertEquals( 500, message.path(JSON.DATA).path(JsonException.CODE).asInt());
assertEquals( "Internal invalid-type handling error. See JMRI logs for information.",
message.path(JSON.DATA).path(JsonException.MESSAGE).asText());
JUnitAppender.assertWarnMessageStartsWith("json error sending invalid-type:");
// throw IOException
connection.setThrowIOException(true);
assertEquals( 1, mock.invalidBeanListeners.size());
assertEquals( 2, train.getPropertyChangeListeners().length);
bl.propertyChange(JsonOperations.TRAIN, (PropertyChangeEvent) null);
assertEquals( 0, mock.invalidBeanListeners.size());
assertEquals( 1, train.getPropertyChangeListeners().length);
}
@Test
public void testManagerListenerFailures() {
InvalidJsonOperationsSocketService mock = new InvalidJsonOperationsSocketService(connection, new JsonOperationsHttpService(mapper));
TrainManager manager = InstanceManager.getDefault(TrainManager.class);
assertEquals( 0, manager.getPropertyChangeListeners().length);
// add listener to test that an IOException removes the listener
// the listener would normally be added by onList, but that method creates
// a valid listener, and we are not interested in that
manager.addPropertyChangeListener(mock.invalidBeansListener);
assertEquals( 1, manager.getPropertyChangeListeners().length);
// throw JsonException on invalid type
mock.invalidBeansListener.propertyChange("invalid-type");
assertEquals( 1, manager.getPropertyChangeListeners().length);
JsonNode message = connection.getMessage();
assertNotNull(message);
assertEquals( JsonException.ERROR, message.path(JSON.TYPE).asText());
assertEquals( 500, message.path(JSON.DATA).path(JsonException.CODE).asInt());
assertEquals( "Internal invalid-type handling error. See JMRI logs for information.",
message.path(JSON.DATA).path(JsonException.MESSAGE).asText());
JUnitAppender.assertWarnMessageStartsWith("json error sending invalid-type:");
// throw IOException
connection.setThrowIOException(true);
assertEquals( 1, manager.getPropertyChangeListeners().length);
mock.invalidBeansListener.propertyChange(JsonOperations.TRAIN);
assertEquals( 0, manager.getPropertyChangeListeners().length);
}
@BeforeEach
public void setUp() {
JUnitUtil.setUp();
JUnitUtil.initIdTagManager();
JUnitOperationsUtil.setupOperationsTests();
JUnitOperationsUtil.initOperationsData();
Kernel kernel = InstanceManager.getDefault(KernelManager.class).newKernel("test1");
InstanceManager.getDefault(CarManager.class).getById("CP99").setKernel(kernel);
mapper = new ObjectMapper();
connection = new JsonMockConnection((DataOutputStream) null);
service = new JsonOperationsSocketService(connection, new JsonOperationsHttpService(mapper));
}
@AfterEach
public void tearDown() {
service.onClose();
service = null;
connection = null;
mapper = null;
JUnitUtil.clearShutDownManager();
JUnitUtil.tearDown();
}
protected static class InvalidJsonOperationsSocketService extends JsonOperationsSocketService {
protected final HashMap<String, BeanListener<Train>> invalidBeanListeners = new HashMap<>();
protected final InvalidBeansListener invalidBeansListener = new InvalidBeansListener();
protected InvalidJsonOperationsSocketService(JsonMockConnection connection, JsonOperationsHttpService service) {
super(connection, service);
}
protected class InvalidBeanListener extends BeanListener<Train> {
InvalidBeanListener(Train bean) {
super(bean);
}
public void propertyChange(String type, PropertyChangeEvent evt) {
super.propertyChange(type, invalidBeanListeners);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
// do nothing, use #propertyChange(String, PropertyChangeEvent) in tests
}
}
protected InvalidBeanListener addInvalidBeanListener(Train bean) {
InvalidBeanListener l = new InvalidBeanListener(bean);
invalidBeanListeners.put(bean.getId(), l);
return l;
}
protected class InvalidBeansListener extends ManagerListener<TrainManager> {
protected InvalidBeansListener() {
super(InstanceManager.getDefault(TrainManager.class));
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
// do nothing, use #propertyChange(String) directly in tests
}
}
}
}