1 package net.sf.openrocket;
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotNull;
6 import static org.junit.Assert.assertTrue;
7 import static org.junit.Assert.fail;
9 import java.awt.event.ActionEvent;
10 import java.io.IOException;
11 import java.io.InputStream;
13 import javax.swing.Action;
15 import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
16 import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
17 import net.sf.openrocket.aerodynamics.FlightConditions;
18 import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
19 import net.sf.openrocket.document.OpenRocketDocument;
20 import net.sf.openrocket.document.Simulation;
21 import net.sf.openrocket.file.GeneralRocketLoader;
22 import net.sf.openrocket.file.RocketLoadException;
23 import net.sf.openrocket.file.motor.GeneralMotorLoader;
24 import net.sf.openrocket.gui.main.UndoRedoAction;
25 import net.sf.openrocket.l10n.ResourceBundleTranslator;
26 import net.sf.openrocket.masscalc.BasicMassCalculator;
27 import net.sf.openrocket.masscalc.MassCalculator;
28 import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
29 import net.sf.openrocket.motor.Motor;
30 import net.sf.openrocket.motor.ThrustCurveMotor;
31 import net.sf.openrocket.rocketcomponent.Configuration;
32 import net.sf.openrocket.rocketcomponent.EngineBlock;
33 import net.sf.openrocket.rocketcomponent.MassComponent;
34 import net.sf.openrocket.rocketcomponent.NoseCone;
35 import net.sf.openrocket.rocketcomponent.RocketComponent;
36 import net.sf.openrocket.simulation.FlightDataType;
37 import net.sf.openrocket.simulation.exception.SimulationException;
38 import net.sf.openrocket.startup.Application;
39 import net.sf.openrocket.util.Coordinate;
40 import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
42 import org.junit.BeforeClass;
43 import org.junit.Test;
46 * This class contains various integration tests that simulate user actions that
49 public class IntegrationTest extends BaseTestCase {
51 private OpenRocketDocument document;
52 private Action undoAction, redoAction;
54 private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
55 private MassCalculator massCalc = new BasicMassCalculator();
56 private Configuration config;
57 private FlightConditions conditions;
61 public static void initialize() {
62 ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
64 protected void loadMotors() {
65 GeneralMotorLoader loader = new GeneralMotorLoader();
66 InputStream is = this.getClass().getResourceAsStream("Estes_A8.rse");
67 assertNotNull("Problem in unit test, cannot find Estes_A8.rse", is);
69 for (Motor m : loader.load(is, "Estes_A8.rse")) {
70 addMotor((ThrustCurveMotor) m);
73 } catch (IOException e) {
75 fail("IOException: " + e);
80 assertEquals(1, db.getMotorSets().size());
81 Application.setMotorSetDatabase(db);
82 Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
86 * Tests loading a rocket design, modifying it, simulating it and the undo/redo
87 * mechanism in various combinations.
90 public void test1() throws RocketLoadException, IOException, SimulationException {
91 System.setProperty("openrocket.unittest", "true");
94 GeneralRocketLoader loader = new GeneralRocketLoader();
95 InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
96 assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
97 document = loader.load(is);
100 undoAction = UndoRedoAction.newUndoAction(document );
101 redoAction = UndoRedoAction.newRedoAction(document);
102 config = document.getSimulation(0).getConfiguration();
103 conditions = new FlightConditions(config);
107 checkUndoState(null, null);
110 // Compute cg+cp + altitude
111 checkCgCp(0.248, 0.0645, 0.320, 12.0);
116 document.addUndoPosition("Modify mass");
117 checkUndoState(null, null);
118 massComponent().setComponentMass(0.01);
119 checkUndoState("Modify mass", null);
122 // Check cg+cp + altitude
123 checkCgCp(0.230, 0.0745, 0.320, 12.0);
128 document.addUndoPosition("No change");
129 checkUndoState("Modify mass", null);
132 // Non-funcitonal change
133 document.addUndoPosition("Name change");
134 checkUndoState("Modify mass", null);
135 massComponent().setName("Foobar component");
136 checkUndoState("Name change", null);
140 checkCgCp(0.230, 0.0745, 0.320, 12.0);
143 // Aerodynamic modification
144 document.addUndoPosition("Remove component");
145 checkUndoState("Name change", null);
146 document.getRocket().getChild(0).removeChild(0);
147 checkUndoState("Remove component", null);
150 // Check cg+cp + altitude
151 checkCgCp(0.163, 0.0613, 0.275, 9.95);
155 // Undo "Remove component" change
156 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
157 assertTrue(document.getRocket().getChild(0).getChild(0) instanceof NoseCone);
158 checkUndoState("Name change", "Remove component");
161 // Check cg+cp + altitude
162 checkCgCp(0.230, 0.0745, 0.320, 12.0);
166 // Undo "Name change" change
167 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
168 assertEquals("Extra mass", massComponent().getName());
169 checkUndoState("Modify mass", "Name change");
173 checkCgCp(0.230, 0.0745, 0.320, 12.0);
176 // Undo "Modify mass" change
177 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
178 assertEquals(0, massComponent().getComponentMass(), 0);
179 checkUndoState(null, "Modify mass");
182 // Check cg+cp + altitude
183 checkCgCp(0.248, 0.0645, 0.320, 12.0);
187 // Redo "Modify mass" change
188 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
189 assertEquals(0.010, massComponent().getComponentMass(), 0.00001);
190 checkUndoState("Modify mass", "Name change");
193 // Check cg+cp + altitude
194 checkCgCp(0.230, 0.0745, 0.320, 12.0);
199 document.addUndoPosition("Modify mass2");
200 checkUndoState("Modify mass", "Name change");
201 massComponent().setComponentMass(0.015);
202 checkUndoState("Modify mass2", null);
205 // Check cg+cp + altitude
206 checkCgCp(0.223, 0.0795, 0.320, 12.0);
210 // Perform component movement
211 document.startUndo("Move component");
212 document.getRocket().freeze();
213 RocketComponent bodytube = document.getRocket().getChild(0).getChild(1);
214 RocketComponent innertube = bodytube.getChild(2);
215 RocketComponent engineblock = innertube.getChild(0);
216 assertTrue(innertube.removeChild(engineblock));
217 bodytube.addChild(engineblock, 0);
218 checkUndoState("Modify mass2", null);
219 document.getRocket().thaw();
220 checkUndoState("Move component", null);
224 // Check cg+cp + altitude
225 checkCgCp(0.221, 0.0797, 0.320, 12.0);
229 // Modify mass without setting undo description
230 massComponent().setComponentMass(0.020);
231 checkUndoState("Modify mass2", null);
234 // Check cg+cp + altitude
235 checkCgCp(0.215, 0.0847, 0.320, 12.0);
239 // Undo "Modify mass2" change
240 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
241 assertEquals(0.015, massComponent().getComponentMass(), 0.0000001);
242 checkUndoState("Move component", "Modify mass2");
245 // Check cg+cp + altitude
246 checkCgCp(0.221, 0.0797, 0.320, 12.0);
250 // Undo "Move component" change
251 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
252 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(2).getChild(0) instanceof EngineBlock);
253 checkUndoState("Modify mass2", "Move component");
256 // Check cg+cp + altitude
257 checkCgCp(0.223, 0.0795, 0.320, 12.0);
261 // Redo "Move component" change
262 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
263 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(0) instanceof EngineBlock);
264 checkUndoState("Move component", "Modify mass2");
267 // Check cg+cp + altitude
268 checkCgCp(0.221, 0.0797, 0.320, 12.0);
274 private String massComponentID = null;
276 private MassComponent massComponent() {
277 if (massComponentID == null) {
278 massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
280 return (MassComponent) document.getRocket().findComponent(massComponentID);
284 private void checkUndoState(String undoDesc, String redoDesc) {
285 if (undoDesc == null) {
286 assertEquals("Undo", undoAction.getValue(Action.NAME));
287 assertFalse(undoAction.isEnabled());
289 assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
290 assertTrue(undoAction.isEnabled());
292 if (redoDesc == null) {
293 assertEquals("Redo", redoAction.getValue(Action.NAME));
294 assertFalse(redoAction.isEnabled());
296 assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
297 assertTrue(redoAction.isEnabled());
302 private void checkCgCp(double cgx, double mass, double cpx, double cna) {
305 cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
306 assertEquals(cgx, cg.x, 0.001);
307 assertEquals(mass, cg.weight, 0.0005);
309 cp = aeroCalc.getWorstCP(config, conditions, null);
310 assertEquals(cpx, cp.x, 0.001);
311 assertEquals(cna, cp.weight, 0.1);
315 private void checkAlt(double expected) throws SimulationException {
316 Simulation simulation = document.getSimulation(0);
319 // Simulate + check altitude
320 simulation.simulate();
321 actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
322 assertEquals(expected, actual, 0.5);