1 package net.sf.openrocket;
3 import static org.junit.Assert.*;
5 import java.awt.event.ActionEvent;
6 import java.io.IOException;
7 import java.io.InputStream;
9 import javax.swing.Action;
11 import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
12 import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
13 import net.sf.openrocket.aerodynamics.FlightConditions;
14 import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
15 import net.sf.openrocket.document.OpenRocketDocument;
16 import net.sf.openrocket.document.Simulation;
17 import net.sf.openrocket.file.GeneralRocketLoader;
18 import net.sf.openrocket.file.RocketLoadException;
19 import net.sf.openrocket.file.motor.GeneralMotorLoader;
20 import net.sf.openrocket.masscalc.BasicMassCalculator;
21 import net.sf.openrocket.masscalc.MassCalculator;
22 import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
23 import net.sf.openrocket.motor.Motor;
24 import net.sf.openrocket.motor.ThrustCurveMotor;
25 import net.sf.openrocket.rocketcomponent.Configuration;
26 import net.sf.openrocket.rocketcomponent.EngineBlock;
27 import net.sf.openrocket.rocketcomponent.MassComponent;
28 import net.sf.openrocket.rocketcomponent.NoseCone;
29 import net.sf.openrocket.rocketcomponent.RocketComponent;
30 import net.sf.openrocket.simulation.FlightDataType;
31 import net.sf.openrocket.simulation.exception.SimulationException;
32 import net.sf.openrocket.startup.Application;
33 import net.sf.openrocket.util.Coordinate;
35 import org.junit.BeforeClass;
36 import org.junit.Test;
39 * This class contains various integration tests that simulate user actions that
42 public class IntegrationTest {
44 private OpenRocketDocument document;
45 private Action undoAction, redoAction;
47 private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
48 private MassCalculator massCalc = new BasicMassCalculator();
49 private Configuration config;
50 private FlightConditions conditions;
54 public static void initialize() {
55 ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
57 protected void loadMotors() {
58 GeneralMotorLoader loader = new GeneralMotorLoader();
59 InputStream is = this.getClass().getResourceAsStream("Estes_A8.rse");
60 assertNotNull("Problem in unit test, cannot find Estes_A8.rse", is);
62 for (Motor m : loader.load(is, "Estes_A8.rse")) {
63 addMotor((ThrustCurveMotor) m);
66 } catch (IOException e) {
68 fail("IOException: " + e);
73 assertEquals(1, db.getMotorSets().size());
74 Application.setMotorSetDatabase(db);
78 * Tests loading a rocket design, modifying it, simulating it and the undo/redo
79 * mechanism in various combinations.
82 public void test1() throws RocketLoadException, IOException, SimulationException {
83 System.setProperty("openrocket.unittest", "true");
86 GeneralRocketLoader loader = new GeneralRocketLoader();
87 InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
88 assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
89 document = loader.load(is);
92 undoAction = document.getUndoAction();
93 redoAction = document.getRedoAction();
94 config = document.getSimulation(0).getConfiguration();
95 conditions = new FlightConditions(config);
99 checkUndoState(null, null);
102 // Compute cg+cp + altitude
103 checkCgCp(0.248, 0.0645, 0.320, 12.0);
108 document.addUndoPosition("Modify mass");
109 checkUndoState(null, null);
110 massComponent().setComponentMass(0.01);
111 checkUndoState("Modify mass", null);
114 // Check cg+cp + altitude
115 checkCgCp(0.230, 0.0745, 0.320, 12.0);
120 document.addUndoPosition("No change");
121 checkUndoState("Modify mass", null);
124 // Non-funcitonal change
125 document.addUndoPosition("Name change");
126 checkUndoState("Modify mass", null);
127 massComponent().setName("Foobar component");
128 checkUndoState("Name change", null);
132 checkCgCp(0.230, 0.0745, 0.320, 12.0);
135 // Aerodynamic modification
136 document.addUndoPosition("Remove component");
137 checkUndoState("Name change", null);
138 document.getRocket().getChild(0).removeChild(0);
139 checkUndoState("Remove component", null);
142 // Check cg+cp + altitude
143 checkCgCp(0.163, 0.0613, 0.275, 9.95);
147 // Undo "Remove component" change
148 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
149 assertTrue(document.getRocket().getChild(0).getChild(0) instanceof NoseCone);
150 checkUndoState("Name change", "Remove component");
153 // Check cg+cp + altitude
154 checkCgCp(0.230, 0.0745, 0.320, 12.0);
158 // Undo "Name change" change
159 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
160 assertEquals("Extra mass", massComponent().getName());
161 checkUndoState("Modify mass", "Name change");
165 checkCgCp(0.230, 0.0745, 0.320, 12.0);
168 // Undo "Modify mass" change
169 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
170 assertEquals(0, massComponent().getComponentMass(), 0);
171 checkUndoState(null, "Modify mass");
174 // Check cg+cp + altitude
175 checkCgCp(0.248, 0.0645, 0.320, 12.0);
179 // Redo "Modify mass" change
180 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
181 assertEquals(0.010, massComponent().getComponentMass(), 0.00001);
182 checkUndoState("Modify mass", "Name change");
185 // Check cg+cp + altitude
186 checkCgCp(0.230, 0.0745, 0.320, 12.0);
191 document.addUndoPosition("Modify mass2");
192 checkUndoState("Modify mass", "Name change");
193 massComponent().setComponentMass(0.015);
194 checkUndoState("Modify mass2", null);
197 // Check cg+cp + altitude
198 checkCgCp(0.223, 0.0795, 0.320, 12.0);
202 // Perform component movement
203 document.startUndo("Move component");
204 document.getRocket().freeze();
205 RocketComponent bodytube = document.getRocket().getChild(0).getChild(1);
206 RocketComponent innertube = bodytube.getChild(2);
207 RocketComponent engineblock = innertube.getChild(0);
208 assertTrue(innertube.removeChild(engineblock));
209 bodytube.addChild(engineblock, 0);
210 checkUndoState("Modify mass2", null);
211 document.getRocket().thaw();
212 checkUndoState("Move component", null);
216 // Check cg+cp + altitude
217 checkCgCp(0.221, 0.0797, 0.320, 12.0);
221 // Modify mass without setting undo description
222 massComponent().setComponentMass(0.020);
223 checkUndoState("Modify mass2", null);
226 // Check cg+cp + altitude
227 checkCgCp(0.215, 0.0847, 0.320, 12.0);
231 // Undo "Modify mass2" change
232 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
233 assertEquals(0.015, massComponent().getComponentMass(), 0.0000001);
234 checkUndoState("Move component", "Modify mass2");
237 // Check cg+cp + altitude
238 checkCgCp(0.221, 0.0797, 0.320, 12.0);
242 // Undo "Move component" change
243 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
244 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(2).getChild(0) instanceof EngineBlock);
245 checkUndoState("Modify mass2", "Move component");
248 // Check cg+cp + altitude
249 checkCgCp(0.223, 0.0795, 0.320, 12.0);
253 // Redo "Move component" change
254 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
255 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(0) instanceof EngineBlock);
256 checkUndoState("Move component", "Modify mass2");
259 // Check cg+cp + altitude
260 checkCgCp(0.221, 0.0797, 0.320, 12.0);
264 private String massComponentID = null;
266 private MassComponent massComponent() {
267 if (massComponentID == null) {
268 massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
270 return (MassComponent) document.getRocket().findComponent(massComponentID);
274 private void checkUndoState(String undoDesc, String redoDesc) {
275 if (undoDesc == null) {
276 assertEquals("Undo", undoAction.getValue(Action.NAME));
277 assertFalse(undoAction.isEnabled());
279 assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
280 assertTrue(undoAction.isEnabled());
282 if (redoDesc == null) {
283 assertEquals("Redo", redoAction.getValue(Action.NAME));
284 assertFalse(redoAction.isEnabled());
286 assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
287 assertTrue(redoAction.isEnabled());
292 private void checkCgCp(double cgx, double mass, double cpx, double cna) {
295 cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
296 assertEquals(cgx, cg.x, 0.001);
297 assertEquals(mass, cg.weight, 0.0005);
299 cp = aeroCalc.getWorstCP(config, conditions, null);
300 assertEquals(cpx, cp.x, 0.001);
301 assertEquals(cna, cp.weight, 0.1);
305 private void checkAlt(double expected) throws SimulationException {
306 Simulation simulation = document.getSimulation(0);
309 // Simulate + check altitude
310 simulation.simulate();
311 actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
312 assertEquals(expected, actual, 0.5);