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.l10n.ResourceBundleTranslator;
21 import net.sf.openrocket.masscalc.BasicMassCalculator;
22 import net.sf.openrocket.masscalc.MassCalculator;
23 import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
24 import net.sf.openrocket.motor.Motor;
25 import net.sf.openrocket.motor.ThrustCurveMotor;
26 import net.sf.openrocket.rocketcomponent.Configuration;
27 import net.sf.openrocket.rocketcomponent.EngineBlock;
28 import net.sf.openrocket.rocketcomponent.MassComponent;
29 import net.sf.openrocket.rocketcomponent.NoseCone;
30 import net.sf.openrocket.rocketcomponent.RocketComponent;
31 import net.sf.openrocket.simulation.FlightDataType;
32 import net.sf.openrocket.simulation.exception.SimulationException;
33 import net.sf.openrocket.startup.Application;
34 import net.sf.openrocket.util.Coordinate;
36 import org.junit.BeforeClass;
37 import org.junit.Test;
40 * This class contains various integration tests that simulate user actions that
43 public class IntegrationTest {
45 private OpenRocketDocument document;
46 private Action undoAction, redoAction;
48 private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
49 private MassCalculator massCalc = new BasicMassCalculator();
50 private Configuration config;
51 private FlightConditions conditions;
55 public static void initialize() {
56 ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
58 protected void loadMotors() {
59 GeneralMotorLoader loader = new GeneralMotorLoader();
60 InputStream is = this.getClass().getResourceAsStream("Estes_A8.rse");
61 assertNotNull("Problem in unit test, cannot find Estes_A8.rse", is);
63 for (Motor m : loader.load(is, "Estes_A8.rse")) {
64 addMotor((ThrustCurveMotor) m);
67 } catch (IOException e) {
69 fail("IOException: " + e);
74 assertEquals(1, db.getMotorSets().size());
75 Application.setMotorSetDatabase(db);
76 Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
80 * Tests loading a rocket design, modifying it, simulating it and the undo/redo
81 * mechanism in various combinations.
84 public void test1() throws RocketLoadException, IOException, SimulationException {
85 System.setProperty("openrocket.unittest", "true");
88 GeneralRocketLoader loader = new GeneralRocketLoader();
89 InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
90 assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
91 document = loader.load(is);
94 undoAction = document.getUndoAction();
95 redoAction = document.getRedoAction();
96 config = document.getSimulation(0).getConfiguration();
97 conditions = new FlightConditions(config);
101 checkUndoState(null, null);
104 // Compute cg+cp + altitude
105 checkCgCp(0.248, 0.0645, 0.320, 12.0);
110 document.addUndoPosition("Modify mass");
111 checkUndoState(null, null);
112 massComponent().setComponentMass(0.01);
113 checkUndoState("Modify mass", null);
116 // Check cg+cp + altitude
117 checkCgCp(0.230, 0.0745, 0.320, 12.0);
122 document.addUndoPosition("No change");
123 checkUndoState("Modify mass", null);
126 // Non-funcitonal change
127 document.addUndoPosition("Name change");
128 checkUndoState("Modify mass", null);
129 massComponent().setName("Foobar component");
130 checkUndoState("Name change", null);
134 checkCgCp(0.230, 0.0745, 0.320, 12.0);
137 // Aerodynamic modification
138 document.addUndoPosition("Remove component");
139 checkUndoState("Name change", null);
140 document.getRocket().getChild(0).removeChild(0);
141 checkUndoState("Remove component", null);
144 // Check cg+cp + altitude
145 checkCgCp(0.163, 0.0613, 0.275, 9.95);
149 // Undo "Remove component" change
150 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
151 assertTrue(document.getRocket().getChild(0).getChild(0) instanceof NoseCone);
152 checkUndoState("Name change", "Remove component");
155 // Check cg+cp + altitude
156 checkCgCp(0.230, 0.0745, 0.320, 12.0);
160 // Undo "Name change" change
161 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
162 assertEquals("Extra mass", massComponent().getName());
163 checkUndoState("Modify mass", "Name change");
167 checkCgCp(0.230, 0.0745, 0.320, 12.0);
170 // Undo "Modify mass" change
171 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
172 assertEquals(0, massComponent().getComponentMass(), 0);
173 checkUndoState(null, "Modify mass");
176 // Check cg+cp + altitude
177 checkCgCp(0.248, 0.0645, 0.320, 12.0);
181 // Redo "Modify mass" change
182 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
183 assertEquals(0.010, massComponent().getComponentMass(), 0.00001);
184 checkUndoState("Modify mass", "Name change");
187 // Check cg+cp + altitude
188 checkCgCp(0.230, 0.0745, 0.320, 12.0);
193 document.addUndoPosition("Modify mass2");
194 checkUndoState("Modify mass", "Name change");
195 massComponent().setComponentMass(0.015);
196 checkUndoState("Modify mass2", null);
199 // Check cg+cp + altitude
200 checkCgCp(0.223, 0.0795, 0.320, 12.0);
204 // Perform component movement
205 document.startUndo("Move component");
206 document.getRocket().freeze();
207 RocketComponent bodytube = document.getRocket().getChild(0).getChild(1);
208 RocketComponent innertube = bodytube.getChild(2);
209 RocketComponent engineblock = innertube.getChild(0);
210 assertTrue(innertube.removeChild(engineblock));
211 bodytube.addChild(engineblock, 0);
212 checkUndoState("Modify mass2", null);
213 document.getRocket().thaw();
214 checkUndoState("Move component", null);
218 // Check cg+cp + altitude
219 checkCgCp(0.221, 0.0797, 0.320, 12.0);
223 // Modify mass without setting undo description
224 massComponent().setComponentMass(0.020);
225 checkUndoState("Modify mass2", null);
228 // Check cg+cp + altitude
229 checkCgCp(0.215, 0.0847, 0.320, 12.0);
233 // Undo "Modify mass2" change
234 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
235 assertEquals(0.015, massComponent().getComponentMass(), 0.0000001);
236 checkUndoState("Move component", "Modify mass2");
239 // Check cg+cp + altitude
240 checkCgCp(0.221, 0.0797, 0.320, 12.0);
244 // Undo "Move component" change
245 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
246 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(2).getChild(0) instanceof EngineBlock);
247 checkUndoState("Modify mass2", "Move component");
250 // Check cg+cp + altitude
251 checkCgCp(0.223, 0.0795, 0.320, 12.0);
255 // Redo "Move component" change
256 redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
257 assertTrue(document.getRocket().getChild(0).getChild(1).getChild(0) instanceof EngineBlock);
258 checkUndoState("Move component", "Modify mass2");
261 // Check cg+cp + altitude
262 checkCgCp(0.221, 0.0797, 0.320, 12.0);
268 private String massComponentID = null;
270 private MassComponent massComponent() {
271 if (massComponentID == null) {
272 massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
274 return (MassComponent) document.getRocket().findComponent(massComponentID);
278 private void checkUndoState(String undoDesc, String redoDesc) {
279 if (undoDesc == null) {
280 assertEquals("Undo", undoAction.getValue(Action.NAME));
281 assertFalse(undoAction.isEnabled());
283 assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
284 assertTrue(undoAction.isEnabled());
286 if (redoDesc == null) {
287 assertEquals("Redo", redoAction.getValue(Action.NAME));
288 assertFalse(redoAction.isEnabled());
290 assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
291 assertTrue(redoAction.isEnabled());
296 private void checkCgCp(double cgx, double mass, double cpx, double cna) {
299 cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
300 assertEquals(cgx, cg.x, 0.001);
301 assertEquals(mass, cg.weight, 0.0005);
303 cp = aeroCalc.getWorstCP(config, conditions, null);
304 assertEquals(cpx, cp.x, 0.001);
305 assertEquals(cna, cp.weight, 0.1);
309 private void checkAlt(double expected) throws SimulationException {
310 Simulation simulation = document.getSimulation(0);
313 // Simulate + check altitude
314 simulation.simulate();
315 actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
316 assertEquals(expected, actual, 0.5);