package org.opentrafficsim.sim0mq.publisher; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.Serializable; import java.rmi.RemoteException; import javax.naming.NamingException; import org.djunits.unit.AccelerationUnit; import org.djunits.unit.DirectionUnit; import org.djunits.unit.LengthUnit; import org.djunits.unit.SpeedUnit; import org.djunits.unit.TimeUnit; import org.djunits.value.vdouble.scalar.Acceleration; import org.djunits.value.vdouble.scalar.Direction; import org.djunits.value.vdouble.scalar.Length; import org.djunits.value.vdouble.scalar.Speed; import org.djunits.value.vdouble.scalar.Time; import org.djunits.value.vdouble.vector.PositionVector; import org.djutils.event.EventInterface; import org.djutils.event.EventListenerInterface; import org.djutils.event.EventProducerInterface; import org.djutils.event.TimedEvent; import org.djutils.event.TimedEventType; import org.djutils.metadata.MetaData; import org.djutils.metadata.ObjectDescriptor; import org.djutils.serialization.SerializationException; import org.junit.Test; import org.mockito.Mockito; import org.opentrafficsim.core.dsol.OTSReplication; import org.opentrafficsim.core.dsol.OTSSimulatorInterface; import org.opentrafficsim.core.geometry.OTSGeometryException; import org.opentrafficsim.core.geometry.OTSLine3D; import org.opentrafficsim.core.geometry.OTSPoint3D; import org.opentrafficsim.core.gtu.GTUException; import org.opentrafficsim.core.gtu.GTUType; import org.opentrafficsim.core.network.LinkType; import org.opentrafficsim.core.network.NetworkException; import org.opentrafficsim.core.perception.HistoryManagerDEVS; import org.opentrafficsim.road.gtu.lane.LaneBasedGTU; import org.opentrafficsim.road.network.OTSRoadNetwork; import org.opentrafficsim.road.network.lane.CrossSectionLink; import org.opentrafficsim.road.network.lane.Lane; import org.opentrafficsim.road.network.lane.LaneType; import org.opentrafficsim.road.network.lane.OTSRoadNode; import org.opentrafficsim.road.network.lane.Stripe; import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy; import org.sim0mq.Sim0MQException; import nl.tudelft.simulation.dsol.SimRuntimeException; import nl.tudelft.simulation.dsol.simulators.SimulatorInterface; import nl.tudelft.simulation.language.d3.DirectedPoint; /** * Unit tests. *
* Copyright (c) 2020-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* $LastChangedDate: 2020-02-13 11:08:16 +0100 (Thu, 13 Feb 2020) $, @version $Revision: 6383 $, by $Author: pknoppers $, * @author Peter Knoppers */ public class TransceiverTest { /** Storage for the last ACK or NACK value submitted to the ReturnWrapper. */ @SuppressWarnings("checkstyle:visibilitymodifier") Boolean lastAckNack = null; /** Storage for the last payload submitted to the ReturnWrapper. */ @SuppressWarnings("checkstyle:visibilitymodifier") Object[] lastPayload = null; /** Storage for last content submitted to notify method in EventListenerInterface. */ @SuppressWarnings("checkstyle:visibilitymodifier") Serializable lastContent = null; /** Time stamp of last notify event. */ @SuppressWarnings("checkstyle:visibilitymodifier") Time lastTime = null; /** * Test the GTUIdTransceiver and the GTUTransceiver. * @throws RemoteException if the happens, this test has failed * @throws SerializationException on error * @throws Sim0MQException on error * @throws NetworkException on error * @throws OTSGeometryException on error * @throws NamingException on error * @throws SimRuntimeException on error * @throws GTUException on error */ @Test public void testGTUIdTransceiver() throws RemoteException, Sim0MQException, SerializationException, NetworkException, OTSGeometryException, SimRuntimeException, NamingException, GTUException { ReturnWrapper storeLastResult = new ReturnWrapper() { @Override public void encodeReplyAndTransmit(final Boolean ackNack, final Object[] payload) { TransceiverTest.this.lastAckNack = ackNack; TransceiverTest.this.lastPayload = payload; } }; try { new GTUIdTransceiver(null); fail("null argument should have thrown an exception"); } catch (NullPointerException npe) { // Ignore expected exception } OTSSimulatorInterface simulator = MockDEVSSimulator.createMock(); OTSRoadNetwork network = new OTSRoadNetwork("test network for TransceiverTest", true, simulator); GTUIdTransceiver gtuIdTransceiver = new GTUIdTransceiver(network); assertEquals("getId returns correct id", "GTU id transceiver", gtuIdTransceiver.getId()); assertEquals("address has 0 entries", 0, gtuIdTransceiver.getAddressFields().size()); assertEquals("result has one field", 1, gtuIdTransceiver.getResultFields().size()); assertEquals("type of the result field is String", String[].class, gtuIdTransceiver.getResultFields().getObjectClass(0)); assertEquals("description of the result field", "String array filled with all currently valid GTU ids", gtuIdTransceiver.getResultFields().getObjectDescription(0)); try { gtuIdTransceiver.getResultFields().getObjectClass(1); fail("Bad index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } try { gtuIdTransceiver.getResultFields().getObjectClass(-1); fail("Bad index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } try { gtuIdTransceiver.getResultFields().getObjectDescription(1); fail("Bad index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } try { gtuIdTransceiver.getResultFields().getObjectDescription(-1); fail("Bad index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } for (int i = -1; i <= 1; i++) { try { gtuIdTransceiver.getIdSource(i, storeLastResult); fail("any address level should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } } Object[] result = gtuIdTransceiver.get(null, storeLastResult); assertNotNull("result should not be null", result); assertEquals("length of result should be 0", 0, result.length); assertNull("Bad address", checkAckNack(gtuIdTransceiver, new Object[] {"this is a bad address"}, false, "wrong length")); GTUType gtuType = new GTUType("gtuType 1", network); LaneBasedGTU gtu1 = new MyMockGTU("gtu 1", gtuType, new DirectedPoint(1, 10, 100, 1, 1, 1), new Speed(1, SpeedUnit.KM_PER_HOUR), new Acceleration(1, AccelerationUnit.METER_PER_SECOND_2), simulator).getMock(); network.addGTU(gtu1); result = gtuIdTransceiver.get(null, storeLastResult); assertEquals("length of result is now 1", 1, result.length); assertTrue("result contains a string", result[0] instanceof String); assertEquals("result[0] is name of our mocked GTU", "gtu 1", result[0]); LaneBasedGTU gtu2 = new MyMockGTU("gtu 2", gtuType, new DirectedPoint(2, 20, 200, 2, 2, 2), new Speed(2, SpeedUnit.KM_PER_HOUR), new Acceleration(2, AccelerationUnit.METER_PER_SECOND_2), simulator).getMock(); network.addGTU(gtu2); result = gtuIdTransceiver.get(new Object[0], storeLastResult); assertEquals("length of result is now 2", 2, result.length); for (int i = 0; i < 2; i++) { assertTrue("result contains a string", result[i] instanceof String); // Order is not guaranteed; the network maintains the GTUs in a LinkedHashMap int count = 0; String lookingFor = String.format("gtu %d", i + 1); for (int j = 0; j < 2; j++) { if (lookingFor.equals(result[j])) { count++; } } assertEquals("found gtu i once", 1, count); } // Make the GTUTransceiver GTUTransceiver gtuTransceiver = new GTUTransceiver(network, gtuIdTransceiver); assertEquals("GTUTransceiver returns correct id", "GTU transceiver", gtuTransceiver.getId()); assertEquals("getIdSource returns gtuIdTransceiver", gtuIdTransceiver, gtuTransceiver.getIdSource(0, null)); try { gtuTransceiver.getIdSource(1, storeLastResult); fail("Invalid index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } try { gtuTransceiver.getIdSource(-1, storeLastResult); fail("Invalid index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } assertEquals("address field 0", "GTU id", gtuTransceiver.getAddressFields().getObjectDescription(0)); try { gtuTransceiver.getAddressFields().getObjectDescription(1); fail("Invalid index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } try { gtuTransceiver.getAddressFields().getObjectDescription(-1); fail("Invalid index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } assertEquals("address field class", String.class, gtuTransceiver.getAddressFields().getObjectClass(0)); try { gtuTransceiver.getAddressFields().getObjectClass(1); fail("Invalid index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } try { gtuTransceiver.getAddressFields().getObjectClass(-1); fail("Invalid index should have thrown an IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ioobe) { // Ignore expected exception } for (int i = 0; i < 2; i++) { Object[] gtuResult = gtuTransceiver.get(new Object[] {result[i]}, storeLastResult); assertNotNull("result is not null", gtuResult); assertEquals("result has 6 fields", 6, gtuResult.length); assertEquals("first field is a String", String.class, gtuResult[0].getClass()); assertEquals("gtuResult is gtu with expected id", result[i], gtuResult[0]); LaneBasedGTU gtu = (LaneBasedGTU) network.getGTU(((String) gtuResult[0])); assertNotNull("GTU is in the network", gtu); assertTrue("field 1 is id of a GTUType", gtuResult[1] instanceof String); assertEquals("gtu type matches", gtuType.getId(), gtuResult[1]); assertEquals("x matches", gtu.getLocation().x, ((PositionVector) gtuResult[2]).get(0).si, 0.0000); assertEquals("y matches", gtu.getLocation().y, ((PositionVector) gtuResult[2]).get(1).si, 0.0000); assertEquals("z matches", gtu.getLocation().z, ((PositionVector) gtuResult[2]).get(2).si, 0.0000); assertEquals("direction matches", new Direction(gtu.getLocation().getRotZ(), DirectionUnit.EAST_DEGREE).si, ((Direction) gtuResult[3]).si, 0.0001); assertEquals("speed", gtu.getSpeed(), gtuResult[4]); assertEquals("acceleration", gtu.getAcceleration(), gtuResult[5]); } assertNull("gtuTransceiver returns null for non-existend ID", gtuTransceiver.get(new Object[] {"NONEXISTENTGTU"}, storeLastResult)); gtuTransceiver.get(new Object[] {123}, storeLastResult); assertTrue("toString returns something descriptive", gtuTransceiver.toString().contains("Transceiver")); NodeIdTransceiver nit = new NodeIdTransceiver(network); assertTrue("toString of node id transceiver returns something descriptive", nit.toString().startsWith("NodeIdTransceiver")); LinkIdTransceiver lit = new LinkIdTransceiver(network); assertTrue("toString of link id transceiver returns something descriptive", lit.toString().startsWith("LinkIdTransceiver")); // Give the network two nodes and a link with a lane - A lot of code is required to create a lane :-( OTSPoint3D node1Point = new OTSPoint3D(10, 20, 30); OTSRoadNode node1 = new OTSRoadNode(network, "node 1", node1Point, Direction.ZERO); OTSRoadNode node2 = new OTSRoadNode(network, "node 2", new OTSPoint3D(110, 20, 30), Direction.ZERO); LinkType roadLinkType = network.getLinkType(LinkType.DEFAULTS.ROAD); CrossSectionLink link = new CrossSectionLink(network, "1 to 2", node1, node2, roadLinkType, new OTSLine3D(node1.getPoint(), node2.getPoint()), LaneKeepingPolicy.KEEPRIGHT); LaneType laneType = network.getLaneType(LaneType.DEFAULTS.RESIDENTIAL_ROAD_LANE); OTSReplication replication = Mockito.mock(OTSReplication.class); HistoryManagerDEVS hmd = Mockito.mock(HistoryManagerDEVS.class); Mockito.when(hmd.now()).thenReturn(Time.ZERO); Mockito.when(replication.getHistoryManager(simulator)).thenReturn(hmd); Mockito.when(simulator.getReplication()).thenReturn(replication); Lane lane = new Lane(link, "lane", Length.ZERO, Length.ZERO, new Length(3, LengthUnit.METER), new Length(3, LengthUnit.METER), laneType, new Speed(50, SpeedUnit.KM_PER_HOUR)); Stripe stripe = new Stripe(link, Length.ZERO, Length.ZERO, new Length(20, LengthUnit.DECIMETER)); String stripeId = stripe.getId(); LinkGTUIdTransceiver linkgit = new LinkGTUIdTransceiver(network); assertTrue("toString of LinkGTUIdTransceiver returns something descriptive", linkgit.toString().startsWith("LinkGTUIdTransceiver")); assertFalse("LinkGTUIdTransceiver does not have an id source", linkgit.hasIdSource()); assertNull("Bad address", checkAckNack(linkgit, new Object[] {"bad", "address"}, false, "need id of a link")); assertNull("Non existing link", checkAckNack(linkgit, new Object[] {"Non existing link"}, false, "Network does not contain a link with id")); this.lastAckNack = null; result = linkgit.get(new Object[] {"1 to 2"}, storeLastResult); assertNotNull(result); assertEquals("result is empty array", 0, result.length); assertNull(this.lastAckNack); LaneGTUIdTransceiver lanegit = new LaneGTUIdTransceiver(network); assertTrue("toString of LaneGTUIdTransceiver returns something descriptive", lanegit.toString().startsWith("LaneGTUIdTransceiver")); assertFalse("LaneGTUIdTransceiver does not have an Id source", lanegit.hasIdSource()); assertNull("Bad address", checkAckNack(lanegit, new Object[] {"this", "is", "a", "bad", "address"}, false, "need id of a link and id of a CrossSectionElement")); assertNull("Non existing link", checkAckNack(lanegit, new Object[] {"Non existing link", "Non existing lane"}, false, "Network does not contain a link with id")); assertNull("Existing link but non existing lane", checkAckNack(lanegit, new Object[] {"1 to 2", "Non existing lane"}, false, "does not contain a cross section element with id")); assertNull("Existing link, but non a lane", checkAckNack(lanegit, new Object[] {"1 to 2", stripeId}, false, "is not a lane")); this.lastAckNack = null; result = lanegit.get(new Object[] {"1 to 2", "lane"}, storeLastResult); assertNull("Existing link and lane should not have sent a NACK or ACK", this.lastAckNack); assertEquals("Existing link and lane should have sent empty array", 0, result.length); // Put one of the GTUs on the lane lane.addGTU(gtu1, 0.3); this.lastAckNack = null; result = linkgit.get(new Object[] {"1 to 2"}, storeLastResult); assertNotNull(result); assertEquals("result is array with one entry", 1, result.length); assertEquals("content of entry is id of gtu1", gtu1.getId(), result[0]); assertNull(this.lastAckNack); result = lanegit.get(new Object[] {"1 to 2", "lane"}, storeLastResult); assertNull("Existing link and lane should not have sent a NACK or ACK", this.lastAckNack); assertEquals("Existing link and lane should have sent empty array", 1, result.length); assertEquals("content of entry is id of gtu1", gtu1.getId(), result[0]); assertNull(this.lastAckNack); Mockito.when(simulator.isInitialized()).thenReturn(false); SimulatorStateTransceiver sst = new SimulatorStateTransceiver(simulator); result = sst.get(null, storeLastResult); assertEquals("get returned one element Object array", 1, result.length); assertEquals("Mock simulator pretends not to have been initialized", "Not (yet) initialized", result[0]); Mockito.when(simulator.isInitialized()).thenReturn(true); // Next statement is not really needed; just making sure Mockito.when(simulator.isStartingOrRunning()).thenReturn(false); result = sst.get(null, storeLastResult); assertEquals("get returned one element Object array", 1, result.length); assertEquals("Mock simulator pretends be in stopped state", "Stopping or stopped", result[0]); Mockito.when(simulator.isStartingOrRunning()).thenReturn(true); result = sst.get(null, storeLastResult); assertEquals("get returned one element Object array", 1, result.length); assertEquals("Mock simulator pretends be in stopped state", "Starting or running", result[0]); LookupEventProducerInterface lepi = sst.getLookupEventProducerInterface(); EventProducerInterface epi = lepi.lookup(null, storeLastResult); TimedEvent