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.DatabaseMotorFinder;
18 import net.sf.openrocket.file.GeneralRocketLoader;
19 import net.sf.openrocket.file.RocketLoadException;
20 import net.sf.openrocket.file.motor.GeneralMotorLoader;
21 import net.sf.openrocket.gui.main.UndoRedoAction;
22 import net.sf.openrocket.l10n.ResourceBundleTranslator;
23 import net.sf.openrocket.masscalc.BasicMassCalculator;
24 import net.sf.openrocket.masscalc.MassCalculator;
25 import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
26 import net.sf.openrocket.motor.Motor;
27 import net.sf.openrocket.motor.ThrustCurveMotor;
28 import net.sf.openrocket.rocketcomponent.Configuration;
29 import net.sf.openrocket.rocketcomponent.EngineBlock;
30 import net.sf.openrocket.rocketcomponent.MassComponent;
31 import net.sf.openrocket.rocketcomponent.NoseCone;
32 import net.sf.openrocket.rocketcomponent.RocketComponent;
33 import net.sf.openrocket.simulation.FlightDataType;
34 import net.sf.openrocket.simulation.exception.SimulationException;
35 import net.sf.openrocket.startup.Application;
36 import net.sf.openrocket.util.Coordinate;
37 import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
43 * This class contains various integration tests that simulate user actions that
46 public class IntegrationTest extends BaseTestCase {
48 private OpenRocketDocument document;
49 private Action undoAction, redoAction;
51 private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
52 private MassCalculator massCalc = new BasicMassCalculator();
53 private Configuration config;
54 private FlightConditions conditions;
58 public static void initialize() {
59 ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
61 protected void loadMotors() {
62 GeneralMotorLoader loader = new GeneralMotorLoader();
63 InputStream is = this.getClass().getResourceAsStream("Estes_A8.rse");
64 assertNotNull("Problem in unit test, cannot find Estes_A8.rse", is);
66 for (Motor m : loader.load(is, "Estes_A8.rse")) {
67 addMotor((ThrustCurveMotor) m);
70 } catch (IOException e) {
72 fail("IOException: " + e);
77 assertEquals(1, db.getMotorSets().size());
78 Application.setMotorSetDatabase(db);
79 Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
83 * Tests loading a rocket design, modifying it, simulating it and the undo/redo
84 * mechanism in various combinations.
87 public void test1() throws RocketLoadException, IOException, SimulationException {
88 System.setProperty("openrocket.unittest", "true");
91 GeneralRocketLoader loader = new GeneralRocketLoader();
92 InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
93 assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
94 document = loader.load(is, new DatabaseMotorFinder());
97 undoAction = UndoRedoAction.newUndoAction(document);
98 redoAction = UndoRedoAction.newRedoAction(document);
99 config = document.getSimulation(0).getConfiguration();
100 conditions = new FlightConditions(config);
104 checkUndoState(null, null);
107 // Compute cg+cp + altitude
108 checkCgCp(0.248, 0.0645, 0.320, 12.0);
113 document.addUndoPosition("Modify mass");
114 checkUndoState(null, null);
115 massComponent().setComponentMass(0.01);
116 checkUndoState("Modify mass", null);
119 // Check cg+cp + altitude
120 checkCgCp(0.230, 0.0745, 0.320, 12.0);
125 document.addUndoPosition("No change");
126 checkUndoState("Modify mass", null);
129 // Non-funcitonal change
130 document.addUndoPosition("Name change");
131 checkUndoState("Modify mass", null);
132 massComponent().setName("Foobar component");
133 checkUndoState("Name change", null);
137 checkCgCp(0.230, 0.0745, 0.320, 12.0);
140 // Aerodynamic modification
141 document.addUndoPosition("Remove component");
142 checkUndoState("Name change", null);
143 document.getRocket().getChild(0).removeChild(0);
144 checkUndoState("Remove component", null);
147 // Check cg+cp + altitude
148 checkCgCp(0.163, 0.0613, 0.275, 9.95);
152 // Undo "Remove component" change
153 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
154 assertTrue(document.getRocket().getChild(0).getChild(0) instanceof NoseCone);
155 checkUndoState("Name change", "Remove component");
158 // Check cg+cp + altitude
159 checkCgCp(0.230, 0.0745, 0.320, 12.0);
163 // Undo "Name change" change
164 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
165 assertEquals("Extra mass", massComponent().getName());
166 checkUndoState("Modify mass", "Name change");
170 checkCgCp(0.230, 0.0745, 0.320, 12.0);
173 // Undo "Modify mass" change
174 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
175 assertEquals(0, massComponent().getComponentMass(), 0);
176 checkUndoState(null, "Modify mass");
179 // Check cg+cp + altitude
180 checkCgCp(0.248, 0.0645, 0.320, 12.0);
184 // Redo "Modify mass" change
185 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
186 assertEquals(0.010, massComponent().getComponentMass(), 0.00001);
187 checkUndoState("Modify mass", "Name change");
190 // Check cg+cp + altitude
191 checkCgCp(0.230, 0.0745, 0.320, 12.0);
196 document.addUndoPosition("Modify mass2");
197 checkUndoState("Modify mass", "Name change");
198 massComponent().setComponentMass(0.015);
199 checkUndoState("Modify mass2", null);
202 // Check cg+cp + altitude
203 checkCgCp(0.223, 0.0795, 0.320, 12.0);
207 // Perform component movement
208 document.startUndo("Move component");
209 document.getRocket().freeze();
210 RocketComponent bodytube = document.getRocket().getChild(0).getChild(1);
211 RocketComponent innertube = bodytube.getChild(2);
212 RocketComponent engineblock = innertube.getChild(0);
213 assertTrue(innertube.removeChild(engineblock));
214 bodytube.addChild(engineblock, 0);
215 checkUndoState("Modify mass2", null);
216 document.getRocket().thaw();
217 checkUndoState("Move component", null);
221 // Check cg+cp + altitude
222 checkCgCp(0.221, 0.0797, 0.320, 12.0);
226 // Modify mass without setting undo description
227 massComponent().setComponentMass(0.020);
228 checkUndoState("Modify mass2", null);
231 // Check cg+cp + altitude
232 checkCgCp(0.215, 0.0847, 0.320, 12.0);
236 // Undo "Modify mass2" change
237 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
238 assertEquals(0.015, massComponent().getComponentMass(), 0.0000001);
239 checkUndoState("Move component", "Modify mass2");
242 // Check cg+cp + altitude
243 checkCgCp(0.221, 0.0797, 0.320, 12.0);
247 // Undo "Move component" change
248 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
249 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(2).getChild(0) instanceof EngineBlock);
250 checkUndoState("Modify mass2", "Move component");
253 // Check cg+cp + altitude
254 checkCgCp(0.223, 0.0795, 0.320, 12.0);
258 // Redo "Move component" change
259 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
260 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(0) instanceof EngineBlock);
261 checkUndoState("Move component", "Modify mass2");
264 // Check cg+cp + altitude
265 checkCgCp(0.221, 0.0797, 0.320, 12.0);
271 private String massComponentID = null;
273 private MassComponent massComponent() {
274 if (massComponentID == null) {
275 massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
277 return (MassComponent) document.getRocket().findComponent(massComponentID);
281 private void checkUndoState(String undoDesc, String redoDesc) {
282 if (undoDesc == null) {
283 assertEquals("Undo", undoAction.getValue(Action.NAME));
284 assertFalse(undoAction.isEnabled());
286 assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
287 assertTrue(undoAction.isEnabled());
289 if (redoDesc == null) {
290 assertEquals("Redo", redoAction.getValue(Action.NAME));
291 assertFalse(redoAction.isEnabled());
293 assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
294 assertTrue(redoAction.isEnabled());
299 private void checkCgCp(double cgx, double mass, double cpx, double cna) {
302 cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
303 assertEquals(cgx, cg.x, 0.001);
304 assertEquals(mass, cg.weight, 0.0005);
306 cp = aeroCalc.getWorstCP(config, conditions, null);
307 assertEquals(cpx, cp.x, 0.001);
308 assertEquals(cna, cp.weight, 0.1);
312 private void checkAlt(double expected) throws SimulationException {
313 Simulation simulation = document.getSimulation(0);
316 // Simulate + check altitude
317 simulation.simulate();
318 actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
319 assertEquals(expected, actual, 0.5);