moving to core/
[debian/openrocket] / core / test / net / sf / openrocket / IntegrationTest.java
1 package net.sf.openrocket;
2
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;
8
9 import java.awt.event.ActionEvent;
10 import java.io.IOException;
11 import java.io.InputStream;
12
13 import javax.swing.Action;
14
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;
41
42 import org.junit.BeforeClass;
43 import org.junit.Test;
44
45 /**
46  * This class contains various integration tests that simulate user actions that
47  * might be performed.
48  */
49 public class IntegrationTest extends BaseTestCase {
50         
51         private OpenRocketDocument document;
52         private Action undoAction, redoAction;
53         
54         private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
55         private MassCalculator massCalc = new BasicMassCalculator();
56         private Configuration config;
57         private FlightConditions conditions;
58         
59         
60         @BeforeClass
61         public static void initialize() {
62                 ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
63                         @Override
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);
68                                 try {
69                                         for (Motor m : loader.load(is, "Estes_A8.rse")) {
70                                                 addMotor((ThrustCurveMotor) m);
71                                         }
72                                         is.close();
73                                 } catch (IOException e) {
74                                         e.printStackTrace();
75                                         fail("IOException: " + e);
76                                 }
77                         }
78                 };
79                 db.startLoading();
80                 assertEquals(1, db.getMotorSets().size());
81                 Application.setMotorSetDatabase(db);
82                 Application.setBaseTranslator(new ResourceBundleTranslator("l10n.messages"));
83         }
84         
85         /**
86          * Tests loading a rocket design, modifying it, simulating it and the undo/redo
87          * mechanism in various combinations.
88          */
89         @Test
90         public void test1() throws RocketLoadException, IOException, SimulationException {
91                 System.setProperty("openrocket.unittest", "true");
92                 
93                 // Load the rocket
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);
98                 is.close();
99                 
100                 undoAction = UndoRedoAction.newUndoAction(document );
101                 redoAction = UndoRedoAction.newRedoAction(document);
102                 config = document.getSimulation(0).getConfiguration();
103                 conditions = new FlightConditions(config);
104                 
105
106                 // Test undo state
107                 checkUndoState(null, null);
108                 
109
110                 // Compute cg+cp + altitude
111                 checkCgCp(0.248, 0.0645, 0.320, 12.0);
112                 checkAlt(48.2);
113                 
114
115                 // Mass modification
116                 document.addUndoPosition("Modify mass");
117                 checkUndoState(null, null);
118                 massComponent().setComponentMass(0.01);
119                 checkUndoState("Modify mass", null);
120                 
121
122                 // Check cg+cp + altitude
123                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
124                 checkAlt(37.2);
125                 
126
127                 // Non-change
128                 document.addUndoPosition("No change");
129                 checkUndoState("Modify mass", null);
130                 
131
132                 // Non-funcitonal change
133                 document.addUndoPosition("Name change");
134                 checkUndoState("Modify mass", null);
135                 massComponent().setName("Foobar component");
136                 checkUndoState("Name change", null);
137                 
138
139                 // Check cg+cp
140                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
141                 
142
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);
148                 
149
150                 // Check cg+cp + altitude
151                 checkCgCp(0.163, 0.0613, 0.275, 9.95);
152                 checkAlt(45.0);
153                 
154
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");
159                 
160
161                 // Check cg+cp + altitude
162                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
163                 checkAlt(37.2);
164                 
165
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");
170                 
171
172                 // Check cg+cp
173                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
174                 
175
176                 // Undo "Modify mass" change
177                 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
178                 assertEquals(0, massComponent().getComponentMass(), 0);
179                 checkUndoState(null, "Modify mass");
180                 
181
182                 // Check cg+cp + altitude
183                 checkCgCp(0.248, 0.0645, 0.320, 12.0);
184                 checkAlt(48.2);
185                 
186
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");
191                 
192
193                 // Check cg+cp + altitude
194                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
195                 checkAlt(37.2);
196                 
197
198                 // Mass modification
199                 document.addUndoPosition("Modify mass2");
200                 checkUndoState("Modify mass", "Name change");
201                 massComponent().setComponentMass(0.015);
202                 checkUndoState("Modify mass2", null);
203                 
204
205                 // Check cg+cp + altitude
206                 checkCgCp(0.223, 0.0795, 0.320, 12.0);
207                 checkAlt(32.7);
208                 
209
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);
221                 document.stopUndo();
222                 
223
224                 // Check cg+cp + altitude
225                 checkCgCp(0.221, 0.0797, 0.320, 12.0);
226                 checkAlt(32.7);
227                 
228
229                 // Modify mass without setting undo description
230                 massComponent().setComponentMass(0.020);
231                 checkUndoState("Modify mass2", null);
232                 
233
234                 // Check cg+cp + altitude
235                 checkCgCp(0.215, 0.0847, 0.320, 12.0);
236                 checkAlt(29.0);
237                 
238
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");
243                 
244
245                 // Check cg+cp + altitude
246                 checkCgCp(0.221, 0.0797, 0.320, 12.0);
247                 checkAlt(32.7);
248                 
249
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");
254                 
255
256                 // Check cg+cp + altitude
257                 checkCgCp(0.223, 0.0795, 0.320, 12.0);
258                 checkAlt(32.7);
259                 
260
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");
265                 
266
267                 // Check cg+cp + altitude
268                 checkCgCp(0.221, 0.0797, 0.320, 12.0);
269                 checkAlt(32.7);
270                 
271
272         }
273         
274         private String massComponentID = null;
275         
276         private MassComponent massComponent() {
277                 if (massComponentID == null) {
278                         massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
279                 }
280                 return (MassComponent) document.getRocket().findComponent(massComponentID);
281         }
282         
283         
284         private void checkUndoState(String undoDesc, String redoDesc) {
285                 if (undoDesc == null) {
286                         assertEquals("Undo", undoAction.getValue(Action.NAME));
287                         assertFalse(undoAction.isEnabled());
288                 } else {
289                         assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
290                         assertTrue(undoAction.isEnabled());
291                 }
292                 if (redoDesc == null) {
293                         assertEquals("Redo", redoAction.getValue(Action.NAME));
294                         assertFalse(redoAction.isEnabled());
295                 } else {
296                         assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
297                         assertTrue(redoAction.isEnabled());
298                 }
299         }
300         
301         
302         private void checkCgCp(double cgx, double mass, double cpx, double cna) {
303                 Coordinate cg, cp;
304                 
305                 cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
306                 assertEquals(cgx, cg.x, 0.001);
307                 assertEquals(mass, cg.weight, 0.0005);
308                 
309                 cp = aeroCalc.getWorstCP(config, conditions, null);
310                 assertEquals(cpx, cp.x, 0.001);
311                 assertEquals(cna, cp.weight, 0.1);
312         }
313         
314         
315         private void checkAlt(double expected) throws SimulationException {
316                 Simulation simulation = document.getSimulation(0);
317                 double actual;
318                 
319                 // Simulate + check altitude
320                 simulation.simulate();
321                 actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
322                 assertEquals(expected, actual, 0.5);
323         }
324         
325 }