Merge pull request #1753 from SiboVG/issue-1621
Write unit tests for flight events
This commit is contained in:
commit
b1777bb36b
@ -308,7 +308,7 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
*/
|
*/
|
||||||
public Status getStatus() {
|
public Status getStatus() {
|
||||||
mutex.verify();
|
mutex.verify();
|
||||||
if (status == Status.UPTODATE || status == Status.LOADED) {
|
if (isStatusUpToDate(status)) {
|
||||||
if (rocket.getFunctionalModID() != simulatedRocketID || !options.equals(simulatedConditions)) {
|
if (rocket.getFunctionalModID() != simulatedRocketID || !options.equals(simulatedConditions)) {
|
||||||
status = Status.OUTDATED;
|
status = Status.OUTDATED;
|
||||||
}
|
}
|
||||||
@ -331,6 +331,14 @@ public class Simulation implements ChangeSource, Cloneable {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true is the status indicates that the simulation data is up-to-date.
|
||||||
|
* @param status status of the simulation to check for if its data is up-to-date
|
||||||
|
*/
|
||||||
|
public static boolean isStatusUpToDate(Status status) {
|
||||||
|
return status == Status.UPTODATE || status == Status.LOADED || status == Status.EXTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,8 +6,6 @@ import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
|
|||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.simulation.exception.MotorIgnitionException;
|
import net.sf.openrocket.simulation.exception.MotorIgnitionException;
|
||||||
import net.sf.openrocket.simulation.exception.SimulationException;
|
import net.sf.openrocket.simulation.exception.SimulationException;
|
||||||
import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
|
|
||||||
import net.sf.openrocket.simulation.listeners.SimulationListener;
|
|
||||||
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
||||||
import net.sf.openrocket.util.TestRockets;
|
import net.sf.openrocket.util.TestRockets;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
@ -35,11 +33,9 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
simDisabled.getOptions().setISAAtmosphere(true);
|
simDisabled.getOptions().setISAAtmosphere(true);
|
||||||
simDisabled.getOptions().setTimeStep(0.05);
|
simDisabled.getOptions().setTimeStep(0.05);
|
||||||
|
|
||||||
SimulationListener simulationListener = new AbstractSimulationListener();
|
|
||||||
|
|
||||||
// Since there are no stages, the simulation should throw an exception.
|
// Since there are no stages, the simulation should throw an exception.
|
||||||
try {
|
try {
|
||||||
simDisabled.simulate(simulationListener);
|
simDisabled.simulate();
|
||||||
} catch (SimulationException e) {
|
} catch (SimulationException e) {
|
||||||
if (!(e instanceof MotorIgnitionException)) {
|
if (!(e instanceof MotorIgnitionException)) {
|
||||||
Assert.fail("Simulation should have thrown a MotorIgnitionException");
|
Assert.fail("Simulation should have thrown a MotorIgnitionException");
|
||||||
@ -56,7 +52,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
|
|
||||||
simDisabled.getActiveConfiguration().setAllStages(); // Re-enable all stages.
|
simDisabled.getActiveConfiguration().setAllStages(); // Re-enable all stages.
|
||||||
|
|
||||||
compareSims(simOriginal, simDisabled, simulationListener, delta);
|
compareSims(simOriginal, simDisabled, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,9 +79,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
simDisabled.getOptions().setISAAtmosphere(true);
|
simDisabled.getOptions().setISAAtmosphere(true);
|
||||||
simDisabled.getOptions().setTimeStep(0.05);
|
simDisabled.getOptions().setTimeStep(0.05);
|
||||||
|
|
||||||
SimulationListener simulationListener = new AbstractSimulationListener();
|
compareSims(simRemoved, simDisabled, delta);
|
||||||
|
|
||||||
compareSims(simRemoved, simDisabled, simulationListener, delta);
|
|
||||||
|
|
||||||
//// Test re-enableing the stage.
|
//// Test re-enableing the stage.
|
||||||
Rocket rocketOriginal = TestRockets.makeBeta();
|
Rocket rocketOriginal = TestRockets.makeBeta();
|
||||||
@ -96,7 +90,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
|
|
||||||
simDisabled.getActiveConfiguration().setAllStages();
|
simDisabled.getActiveConfiguration().setAllStages();
|
||||||
|
|
||||||
compareSims(simOriginal, simDisabled, simulationListener, delta);
|
compareSims(simOriginal, simDisabled, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -173,9 +167,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
simDisabled.getOptions().setISAAtmosphere(true);
|
simDisabled.getOptions().setISAAtmosphere(true);
|
||||||
simDisabled.getOptions().setTimeStep(0.05);
|
simDisabled.getOptions().setTimeStep(0.05);
|
||||||
|
|
||||||
SimulationListener simulationListener = new AbstractSimulationListener();
|
compareSims(simRemoved, simDisabled, delta);
|
||||||
|
|
||||||
compareSims(simRemoved, simDisabled, simulationListener, delta);
|
|
||||||
|
|
||||||
//// Test re-enableing the stage.
|
//// Test re-enableing the stage.
|
||||||
Rocket rocketOriginal = TestRockets.makeFalcon9Heavy();
|
Rocket rocketOriginal = TestRockets.makeFalcon9Heavy();
|
||||||
@ -186,7 +178,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
|
|
||||||
simDisabled.getActiveConfiguration().setAllStages();
|
simDisabled.getActiveConfiguration().setAllStages();
|
||||||
|
|
||||||
compareSims(simOriginal, simDisabled, simulationListener, delta);
|
compareSims(simOriginal, simDisabled, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,11 +206,9 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
simDisabled.getOptions().setISAAtmosphere(true);
|
simDisabled.getOptions().setISAAtmosphere(true);
|
||||||
simDisabled.getOptions().setTimeStep(0.05);
|
simDisabled.getOptions().setTimeStep(0.05);
|
||||||
|
|
||||||
SimulationListener simulationListener = new AbstractSimulationListener();
|
|
||||||
|
|
||||||
// There should be no motors left at this point, so a no motors exception should be thrown
|
// There should be no motors left at this point, so a no motors exception should be thrown
|
||||||
try {
|
try {
|
||||||
simRemoved.simulate(simulationListener);
|
simRemoved.simulate();
|
||||||
} catch (SimulationException e) {
|
} catch (SimulationException e) {
|
||||||
if (!(e instanceof MotorIgnitionException)) {
|
if (!(e instanceof MotorIgnitionException)) {
|
||||||
Assert.fail("Simulation failed: " + e);
|
Assert.fail("Simulation failed: " + e);
|
||||||
@ -226,7 +216,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
simDisabled.simulate(simulationListener);
|
simDisabled.simulate();
|
||||||
} catch (SimulationException e) {
|
} catch (SimulationException e) {
|
||||||
if (!(e instanceof MotorIgnitionException)) {
|
if (!(e instanceof MotorIgnitionException)) {
|
||||||
Assert.fail("Simulation failed: " + e);
|
Assert.fail("Simulation failed: " + e);
|
||||||
@ -242,7 +232,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
|
|
||||||
simDisabled.getActiveConfiguration().setAllStages();
|
simDisabled.getActiveConfiguration().setAllStages();
|
||||||
|
|
||||||
compareSims(simOriginal, simDisabled, simulationListener, delta);
|
compareSims(simOriginal, simDisabled, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -259,13 +249,11 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
* - groundHitVelocity
|
* - groundHitVelocity
|
||||||
* @param simExpected the expected simulation results
|
* @param simExpected the expected simulation results
|
||||||
* @param simActual the actual simulation results
|
* @param simActual the actual simulation results
|
||||||
* @param simulationListener the simulation listener to use for the comparison
|
|
||||||
* @param delta the error margin for the comparison (e.g. 0.05 = 5 % error margin)
|
* @param delta the error margin for the comparison (e.g. 0.05 = 5 % error margin)
|
||||||
*/
|
*/
|
||||||
private void compareSims(Simulation simExpected, Simulation simActual,
|
private void compareSims(Simulation simExpected, Simulation simActual, double delta) {
|
||||||
SimulationListener simulationListener, double delta) {
|
|
||||||
try {
|
try {
|
||||||
simExpected.simulate(simulationListener);
|
simExpected.simulate();
|
||||||
double maxAltitudeOriginal = simExpected.getSimulatedData().getMaxAltitude();
|
double maxAltitudeOriginal = simExpected.getSimulatedData().getMaxAltitude();
|
||||||
double maxVelocityOriginal = simExpected.getSimulatedData().getMaxVelocity();
|
double maxVelocityOriginal = simExpected.getSimulatedData().getMaxVelocity();
|
||||||
double maxMachNumberOriginal = simExpected.getSimulatedData().getMaxMachNumber();
|
double maxMachNumberOriginal = simExpected.getSimulatedData().getMaxMachNumber();
|
||||||
@ -274,7 +262,7 @@ public class DisableStageTest extends BaseTestCase {
|
|||||||
double launchRodVelocityOriginal = simExpected.getSimulatedData().getLaunchRodVelocity();
|
double launchRodVelocityOriginal = simExpected.getSimulatedData().getLaunchRodVelocity();
|
||||||
double deploymentVelocityOriginal = simExpected.getSimulatedData().getDeploymentVelocity();
|
double deploymentVelocityOriginal = simExpected.getSimulatedData().getDeploymentVelocity();
|
||||||
|
|
||||||
simActual.simulate(simulationListener);
|
simActual.simulate();
|
||||||
double maxAltitudeDisabled = simActual.getSimulatedData().getMaxAltitude();
|
double maxAltitudeDisabled = simActual.getSimulatedData().getMaxAltitude();
|
||||||
double maxVelocityDisabled = simActual.getSimulatedData().getMaxVelocity();
|
double maxVelocityDisabled = simActual.getSimulatedData().getMaxVelocity();
|
||||||
double maxMachNumberDisabled = simActual.getSimulatedData().getMaxMachNumber();
|
double maxMachNumberDisabled = simActual.getSimulatedData().getMaxMachNumber();
|
||||||
|
107
core/test/net/sf/openrocket/simulation/FlightEventsTest.java
Normal file
107
core/test/net/sf/openrocket/simulation/FlightEventsTest.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package net.sf.openrocket.simulation;
|
||||||
|
|
||||||
|
import net.sf.openrocket.document.Simulation;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
|
||||||
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
|
import net.sf.openrocket.simulation.exception.SimulationException;
|
||||||
|
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
||||||
|
import net.sf.openrocket.util.TestRockets;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to verify that simulations contain all the expected flight events.
|
||||||
|
*/
|
||||||
|
public class FlightEventsTest extends BaseTestCase {
|
||||||
|
/**
|
||||||
|
* Tests for a single stage design.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSingleStage() throws SimulationException {
|
||||||
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
Simulation sim = new Simulation(rocket);
|
||||||
|
sim.getOptions().setISAAtmosphere(true);
|
||||||
|
sim.getOptions().setTimeStep(0.05);
|
||||||
|
sim.setFlightConfigurationId(TestRockets.TEST_FCID_0);
|
||||||
|
|
||||||
|
sim.simulate();
|
||||||
|
|
||||||
|
// Test branch count
|
||||||
|
int branchCount = sim.getSimulatedData().getBranchCount();
|
||||||
|
assertEquals(" Single stage simulation invalid branch count", 1, branchCount);
|
||||||
|
|
||||||
|
FlightEvent.Type[] expectedEventTypes = {FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF,
|
||||||
|
FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT,
|
||||||
|
FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END};
|
||||||
|
|
||||||
|
// Test event count
|
||||||
|
FlightDataBranch branch = sim.getSimulatedData().getBranch(0);
|
||||||
|
List<FlightEvent> eventList = branch.getEvents();
|
||||||
|
List<FlightEvent.Type> eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList());
|
||||||
|
assertEquals(" Single stage simulation invalid number of events", expectedEventTypes.length, eventTypes.size());
|
||||||
|
|
||||||
|
// Test that all expected events are present, and in the right order
|
||||||
|
for (int i = 0; i < expectedEventTypes.length; i++) {
|
||||||
|
assertSame(" Flight type " + expectedEventTypes[i] + " not found in single stage simulation",
|
||||||
|
eventTypes.get(i), expectedEventTypes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for a multi-stage design.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testMultiStage() throws SimulationException {
|
||||||
|
Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
|
Simulation sim = new Simulation(rocket);
|
||||||
|
sim.getOptions().setISAAtmosphere(true);
|
||||||
|
sim.getOptions().setTimeStep(0.05);
|
||||||
|
rocket.getSelectedConfiguration().setAllStages();
|
||||||
|
FlightConfigurationId fcid = rocket.getSelectedConfiguration().getFlightConfigurationID();
|
||||||
|
sim.setFlightConfigurationId(fcid);
|
||||||
|
|
||||||
|
sim.simulate();
|
||||||
|
|
||||||
|
// Test branch count
|
||||||
|
int branchCount = sim.getSimulatedData().getBranchCount();
|
||||||
|
assertEquals(" Multi-stage simulation invalid branch count", 3, branchCount);
|
||||||
|
|
||||||
|
for (int b = 0; b < 3; b++) {
|
||||||
|
FlightEvent.Type[] expectedEventTypes;
|
||||||
|
switch (b) {
|
||||||
|
case 0:
|
||||||
|
expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.IGNITION,
|
||||||
|
FlightEvent.Type.LIFTOFF, FlightEvent.Type.LAUNCHROD, FlightEvent.Type.APOGEE, FlightEvent.Type.BURNOUT,
|
||||||
|
FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.EJECTION_CHARGE,
|
||||||
|
FlightEvent.Type.STAGE_SEPARATION, FlightEvent.Type.STAGE_SEPARATION, FlightEvent.Type.TUMBLE, FlightEvent.Type.GROUND_HIT,
|
||||||
|
FlightEvent.Type.SIMULATION_END};
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
expectedEventTypes = new FlightEvent.Type[]{FlightEvent.Type.TUMBLE, FlightEvent.Type.GROUND_HIT,
|
||||||
|
FlightEvent.Type.SIMULATION_END};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Invalid branch number " + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test event count
|
||||||
|
FlightDataBranch branch = sim.getSimulatedData().getBranch(b);
|
||||||
|
List<FlightEvent> eventList = branch.getEvents();
|
||||||
|
List<FlightEvent.Type> eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList());
|
||||||
|
assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events", expectedEventTypes.length, eventTypes.size());
|
||||||
|
|
||||||
|
// Test that all expected events are present, and in the right order
|
||||||
|
for (int i = 0; i < expectedEventTypes.length; i++) {
|
||||||
|
assertSame(" Flight type " + expectedEventTypes[i] + ", branch " + b + " not found in multi-stage simulation",
|
||||||
|
eventTypes.get(i), expectedEventTypes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -504,8 +504,7 @@ public class SimulationPanel extends JPanel {
|
|||||||
|
|
||||||
private void openDialog(final Simulation sim) {
|
private void openDialog(final Simulation sim) {
|
||||||
boolean plotMode = false;
|
boolean plotMode = false;
|
||||||
if (sim.hasSimulationData() && (sim.getStatus() == Status.UPTODATE || sim.getStatus() == Status.LOADED
|
if (sim.hasSimulationData() && Simulation.isStatusUpToDate(sim.getStatus())) {
|
||||||
|| sim.getStatus() == Status.EXTERNAL)) {
|
|
||||||
plotMode = true;
|
plotMode = true;
|
||||||
}
|
}
|
||||||
openDialog(plotMode, sim);
|
openDialog(plotMode, sim);
|
||||||
|
@ -60,7 +60,7 @@ import org.jfree.ui.RectangleInsets;
|
|||||||
import org.jfree.ui.TextAnchor;
|
import org.jfree.ui.TextAnchor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It should be possible to simplify this code quite a bit by using a single Renderer instance for
|
* TODO: It should be possible to simplify this code quite a bit by using a single Renderer instance for
|
||||||
* both datasets and the legend. But for now, the renderers are queried for the line color information
|
* both datasets and the legend. But for now, the renderers are queried for the line color information
|
||||||
* and this is held in the Legend.
|
* and this is held in the Legend.
|
||||||
*/
|
*/
|
||||||
|
@ -857,8 +857,8 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
// Re-run the present simulation(s)
|
// Re-run the present simulation(s)
|
||||||
List<Simulation> sims = new LinkedList<>();
|
List<Simulation> sims = new LinkedList<>();
|
||||||
for (Simulation sim : document.getSimulations()) {
|
for (Simulation sim : document.getSimulations()) {
|
||||||
if (sim.getStatus() == Simulation.Status.UPTODATE || sim.getStatus() == Simulation.Status.LOADED
|
if (Simulation.isStatusUpToDate(sim.getStatus()) ||
|
||||||
|| !document.getRocket().getFlightConfiguration(sim.getFlightConfigurationId()).hasMotors())
|
!document.getRocket().getFlightConfiguration(sim.getFlightConfigurationId()).hasMotors())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Find a Simulation based on the current flight configuration
|
// Find a Simulation based on the current flight configuration
|
||||||
|
@ -292,8 +292,7 @@ public class SimulationEditDialog extends JDialog {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
// If the simulation is out of date, run the simulation.
|
// If the simulation is out of date, run the simulation.
|
||||||
if (simulationList[0].getStatus() != Simulation.Status.UPTODATE &&
|
if (!Simulation.isStatusUpToDate(simulationList[0].getStatus())) {
|
||||||
simulationList[0].getStatus() != Simulation.Status.LOADED) {
|
|
||||||
new SimulationRunDialog(SimulationEditDialog.this.parentWindow, document, simulationList[0]).setVisible(true);
|
new SimulationRunDialog(SimulationEditDialog.this.parentWindow, document, simulationList[0]).setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user