Skip to content

Commit

Permalink
test(agents): unit test for mapping and launching agents
Browse files Browse the repository at this point in the history
  • Loading branch information
kschrab committed Jan 24, 2025
1 parent 301fefc commit 2e50840
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.eclipse.mosaic.fed.application.ambassador.simulation.communication.ReceivedAcknowledgement;
import org.eclipse.mosaic.fed.application.ambassador.simulation.navigation.CentralNavigationComponent;
import org.eclipse.mosaic.fed.application.ambassador.simulation.perception.CentralPerceptionComponent;
import org.eclipse.mosaic.fed.application.app.TestAgentApplication;
import org.eclipse.mosaic.fed.application.app.TestApplicationWithSpy;
import org.eclipse.mosaic.fed.application.app.TestChargingStationApplication;
import org.eclipse.mosaic.fed.application.app.TestElectricVehicleApplication;
Expand Down Expand Up @@ -72,6 +73,7 @@
import org.eclipse.mosaic.rti.api.RtiAmbassador;
import org.eclipse.mosaic.rti.api.parameters.AmbassadorParameter;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Assert;
Expand Down Expand Up @@ -311,6 +313,35 @@ public void processInteraction_VehicleRegistration_VehicleWithElectricVehicleApp
);
}

/**
* The ApplicationAmbassador receives an AgentRegistration interaction with a AgentApplication.
* The application of the agent will be added to the simulator and initialized.
* After the simulation has been finished, the application will tear down.
*/
@Test
public void processInteraction_AgentRegistration() throws InternalFederateException, IOException {
final ApplicationAmbassador ambassador = createAmbassador();

// init ambassador
ambassador.initialize(0L, END_TIME);
assertEquals("Time advance should be requested for the end of the simulation", END_TIME, recentAdvanceTime);

TestAgentApplication app = testAddUnit(
ambassador,
"agent_0",
InteractionTestHelper.createAgentRegistrationInteraction("agent_0", 5, TestAgentApplication.class)
);

// verify that setUp has been called on the application of the unit
Mockito.verify(app.getApplicationSpy()).onStartup();

// tears down all applications
ambassador.processTimeAdvanceGrant(recentAdvanceTime);
ambassador.processTimeAdvanceGrant(END_TIME);
ambassador.finishSimulation();
Mockito.verify(app.getApplicationSpy()).onShutdown();
}


/**
* After a vehicle has been added to the ApplicationAmbassador, it receives an V2xMessageReception Interaction.
Expand Down Expand Up @@ -953,12 +984,13 @@ private <TEST_APP extends TestApplicationWithSpy<? extends Application>> TEST_AP
Assert.assertEquals(interaction.getTime(), recentAdvanceTime);
Assert.assertTrue(interactionTimeEquals(interaction.getTime()));
Assert.assertTrue(countStartApplicationEvents() > 0);
Assert.assertNotNull(UnitSimulator.UnitSimulator.getAllUnits().get(unitId));

// should initialize the application
ambassador.processTimeAdvanceGrant(recentAdvanceTime);

@SuppressWarnings("unchecked")
TEST_APP app = (TEST_APP) UnitSimulator.UnitSimulator.getAllUnits().get(unitId).getApplications().get(0);
TEST_APP app = (TEST_APP) Iterables.getFirst(UnitSimulator.UnitSimulator.getAllUnits().get(unitId).getApplications(), null);

// assert that the requested advance time of the ambassador did not change
Assert.assertEquals(interaction.getTime(), recentAdvanceTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.mosaic.fed.application.app.TestServerApplication;
import org.eclipse.mosaic.fed.application.app.TestTrafficLightApplication;
import org.eclipse.mosaic.fed.application.app.TestTrafficManagementCenterApplication;
import org.eclipse.mosaic.interactions.mapping.AgentRegistration;
import org.eclipse.mosaic.interactions.mapping.ChargingStationRegistration;
import org.eclipse.mosaic.interactions.mapping.RsuRegistration;
import org.eclipse.mosaic.interactions.mapping.ServerRegistration;
Expand All @@ -29,6 +30,7 @@
import org.eclipse.mosaic.interactions.mapping.VehicleRegistration;
import org.eclipse.mosaic.lib.enums.VehicleClass;
import org.eclipse.mosaic.lib.geo.GeoPoint;
import org.eclipse.mosaic.lib.math.SpeedUtils;
import org.eclipse.mosaic.lib.objects.trafficlight.TrafficLight;
import org.eclipse.mosaic.lib.objects.trafficlight.TrafficLightGroup;
import org.eclipse.mosaic.lib.objects.trafficlight.TrafficLightProgram;
Expand Down Expand Up @@ -150,6 +152,31 @@ public static VehicleRegistration createVehicleRegistrationInteraction(
);
}

/**
* Creates a {@link AgentRegistration}-interaction with the given parameters
* for an agent.
*
* @param id identifier of the agent
* @param startTimeInSeconds time of the interaction
* @param testClass application class
* @return the {@link VehicleRegistration}-interaction
*/
public static AgentRegistration createAgentRegistrationInteraction(
String id,
long startTimeInSeconds,
Class<? extends TestApplicationWithSpy<?>> testClass
) {
return new AgentRegistration(
startTimeInSeconds * TIME.SECOND,
id,
"group_0",
GeoPoint.ORIGO,
GeoPoint.ORIGO,
getApplications(testClass != null, testClass),
SpeedUtils.kmh2ms(3)
);
}

/**
* Creates a {@link VehicleRegistration}-interaction with the given parameters
* for an electric car.
Expand Down Expand Up @@ -246,4 +273,6 @@ private static List<String> getApplications(boolean withApp, Class<?> appClass)
return Collections.emptyList();
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2025 Fraunhofer FOKUS and others. All rights reserved.
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contact: [email protected]
*/

package org.eclipse.mosaic.fed.application.app;

import org.eclipse.mosaic.fed.application.app.api.Application;
import org.eclipse.mosaic.fed.application.app.api.OperatingSystemAccess;
import org.eclipse.mosaic.fed.application.app.api.os.AgentOperatingSystem;
import org.eclipse.mosaic.lib.util.scheduling.Event;

import org.mockito.Mockito;

public class TestAgentApplication extends AbstractApplication<AgentOperatingSystem>
implements TestApplicationWithSpy<OperatingSystemAccess<AgentOperatingSystem>>, Application {

private final OperatingSystemAccess<AgentOperatingSystem> thisApplicationSpy;

public TestAgentApplication() {
thisApplicationSpy = Mockito.mock(OperatingSystemAccess.class);
}

@Override
public OperatingSystemAccess<AgentOperatingSystem> getApplicationSpy() {
return thisApplicationSpy;
}

@Override
public void onStartup() {
thisApplicationSpy.onStartup();
}

@Override
public void onShutdown() {
thisApplicationSpy.onShutdown();
}

@Override
public void processEvent(Event event) throws Exception {
thisApplicationSpy.processEvent(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ public class SpawningFramework {
private final Map<String, List<CPrototype>> typeDistributions = new HashMap<>();
private final Map<String, TrafficLightSpawner> tls = new HashMap<>();
private final List<VehicleFlowGenerator> vehicleFlowGenerators = new ArrayList<>();
private final List<AgentSpawner> agents = new ArrayList<>();
private final List<AgentSpawner> agentSpawners = new ArrayList<>();
private final List<RoadSideUnitSpawner> rsus = new ArrayList<>();
private final List<TrafficManagementCenterSpawner> tmcs = new ArrayList<>();
private final List<ServerSpawner> servers = new ArrayList<>();
private final List<ChargingStationSpawner> chargingStations = new ArrayList<>();
private final List<Spawner> spawners = new ArrayList<>();
private final List<Spawner> staticSpawners = new ArrayList<>();
private final CMappingConfiguration config;

private ScenarioTrafficLightRegistration scenarioTrafficLightRegistration;
Expand Down Expand Up @@ -135,23 +135,13 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration,
}
}

if (mappingConfiguration.agents != null) {
for (CAgent agentConfiguration : mappingConfiguration.agents) {
if (agentConfiguration != null) {
AgentSpawner agentSpawner = new AgentSpawner(agentConfiguration);
agents.add(agentSpawner);
spawners.add(agentSpawner);
}
}
}

// RSUs
if (mappingConfiguration.rsus != null) {
for (CRoadSideUnit roadSideUnitConfiguration : mappingConfiguration.rsus) {
if (roadSideUnitConfiguration != null) {
RoadSideUnitSpawner roadSideUnitSpawner = new RoadSideUnitSpawner(roadSideUnitConfiguration);
rsus.add(roadSideUnitSpawner);
spawners.add(roadSideUnitSpawner);
staticSpawners.add(roadSideUnitSpawner);
}
}
}
Expand All @@ -162,7 +152,7 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration,
TrafficManagementCenterSpawner trafficManagementCenterSpawner =
new TrafficManagementCenterSpawner(trafficManagementCenterConfiguration);
tmcs.add(trafficManagementCenterSpawner);
spawners.add(trafficManagementCenterSpawner);
staticSpawners.add(trafficManagementCenterSpawner);
}
}
}
Expand All @@ -172,7 +162,7 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration,
if (serverConfiguration != null) {
ServerSpawner serverSpawner = new ServerSpawner(serverConfiguration);
servers.add(serverSpawner);
spawners.add(serverSpawner);
staticSpawners.add(serverSpawner);
}
}
}
Expand All @@ -183,7 +173,7 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration,
ChargingStationSpawner chargingStationSpawner =
new ChargingStationSpawner(chargingStationConfiguration);
chargingStations.add(chargingStationSpawner);
spawners.add(chargingStationSpawner);
staticSpawners.add(chargingStationSpawner);
}
}
}
Expand All @@ -206,8 +196,14 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration,
spawnersExist = generateVehicleFlows(mappingConfiguration.vehicles, mappingConfiguration.config, rng);
}

if (mappingConfiguration.vehicles == null || !spawnersExist) {
LOG.info("No vehicle spawners defined in mapping config. Only external vehicles will be simulated.");
// Agent spawners
if (mappingConfiguration.agents != null) {
for (CAgent agentConfiguration : mappingConfiguration.agents) {
if (agentConfiguration != null) {
agentSpawners.add(new AgentSpawner(agentConfiguration));
spawnersExist = true;
}
}
}

// OD-Matrices
Expand All @@ -224,6 +220,11 @@ public SpawningFramework(CMappingAmbassador mappingConfiguration,
boolean fixedOrder = mappingConfiguration.config != null && mappingConfiguration.config.fixedOrder;
for (OriginDestinationVehicleFlowGenerator mapper : matrices) {
mapper.generateVehicleStreams(this, rng, flowNoise, fixedOrder);
spawnersExist = true;
}

if (!spawnersExist) {
LOG.info("No vehicle spawners defined in mapping config. Only external vehicles will be simulated.");
}

// Use the prototype configurations to complete the spawner-definitions:
Expand Down Expand Up @@ -415,7 +416,7 @@ private void completeSpawnerDefinitions() {
}
}

for (AgentSpawner spawner : agents) {
for (AgentSpawner spawner : agentSpawners) {
spawner.fillInPrototype(getPrototypeByName(spawner.getPrototypeName()));

if (config != null) {
Expand Down Expand Up @@ -494,11 +495,19 @@ void timeAdvance(long time, RtiAmbassador rti, RandomNumberGenerator rng) throws
immobileUnitsInitialized = true;
}

Iterator<VehicleFlowGenerator> iterator = vehicleFlowGenerators.iterator();
while (iterator.hasNext()) {
VehicleFlowGenerator vehicleFlowGenerator = iterator.next();
Iterator<VehicleFlowGenerator> vehicleFlowIt = vehicleFlowGenerators.iterator();
while (vehicleFlowIt.hasNext()) {
VehicleFlowGenerator vehicleFlowGenerator = vehicleFlowIt.next();
if (vehicleFlowGenerator.timeAdvance(this)) {
iterator.remove();
vehicleFlowIt.remove();
}
}

Iterator<AgentSpawner> agentSpawnerIt = agentSpawners.iterator();
while (agentSpawnerIt.hasNext()) {
AgentSpawner agentSpawner = agentSpawnerIt.next();
if (agentSpawner.timeAdvance(this)) {
agentSpawnerIt.remove();
}
}
}
Expand Down Expand Up @@ -553,7 +562,7 @@ private void initTrafficLights(long time, RtiAmbassador rti, RandomNumberGenerat

private void initImmobileUnits() throws InternalFederateException {
// First time-advance. We need to process RSUs, ChargingStations, TMCs and Servers:
for (Spawner spawner : spawners) {
for (Spawner spawner : staticSpawners) {
spawner.init(this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ public void configure(CMappingConfiguration mappingParameterizationConfiguration
}
}

public void init(SpawningFramework spawningFramework) throws InternalFederateException {
public boolean timeAdvance(SpawningFramework spawningFramework) throws InternalFederateException {
if (spawningFramework.getTime() < startingTime) {
return false;
}

final String name = UnitNameGenerator.nextAgentName();
final AgentRegistration interaction = new AgentRegistration(
startingTime, name, group, origin, destination, getApplications(), defaultIfNull(walkingSpeed, DEFAULT_WALKING_SPEED)
Expand All @@ -75,6 +79,7 @@ startingTime, name, group, origin, destination, getApplications(), defaultIfNull
LOG.error("Exception while sending Interaction in AgentSpawner.init()");
throw new InternalFederateException("Exception while sending Interaction in AgentSpawner.init()", e);
}
return true;
}

@Override
Expand Down
Loading

0 comments on commit 2e50840

Please sign in to comment.