bug fix + more logging
[debian/openrocket] / test / net / sf / openrocket / IntegrationTest.java
1 package net.sf.openrocket;
2
3 import static org.junit.Assert.*;
4
5 import java.awt.event.ActionEvent;
6 import java.io.IOException;
7 import java.io.InputStream;
8
9 import javax.swing.Action;
10
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;
34
35 import org.junit.BeforeClass;
36 import org.junit.Test;
37
38 /**
39  * This class contains various integration tests that simulate user actions that
40  * might be performed.
41  */
42 public class IntegrationTest {
43         
44         private OpenRocketDocument document;
45         private Action undoAction, redoAction;
46         
47         private AerodynamicCalculator aeroCalc = new BarrowmanCalculator();
48         private MassCalculator massCalc = new BasicMassCalculator();
49         private Configuration config;
50         private FlightConditions conditions;
51         
52         
53         @BeforeClass
54         public static void initialize() {
55                 ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {
56                         @Override
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);
61                                 try {
62                                         for (Motor m : loader.load(is, "Estes_A8.rse")) {
63                                                 addMotor((ThrustCurveMotor) m);
64                                         }
65                                         is.close();
66                                 } catch (IOException e) {
67                                         e.printStackTrace();
68                                         fail("IOException: " + e);
69                                 }
70                         }
71                 };
72                 db.startLoading();
73                 assertEquals(1, db.getMotorSets().size());
74                 Application.setMotorSetDatabase(db);
75         }
76         
77         /**
78          * Tests loading a rocket design, modifying it, simulating it and the undo/redo
79          * mechanism in various combinations.
80          */
81         @Test
82         public void test1() throws RocketLoadException, IOException, SimulationException {
83                 System.setProperty("openrocket.unittest", "true");
84                 
85                 // Load the rocket
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);
90                 is.close();
91                 
92                 undoAction = document.getUndoAction();
93                 redoAction = document.getRedoAction();
94                 config = document.getSimulation(0).getConfiguration();
95                 conditions = new FlightConditions(config);
96                 
97
98                 // Test undo state
99                 checkUndoState(null, null);
100                 
101
102                 // Compute cg+cp + altitude
103                 checkCgCp(0.248, 0.0645, 0.320, 12.0);
104                 checkAlt(48.2);
105                 
106
107                 // Mass modification
108                 document.addUndoPosition("Modify mass");
109                 checkUndoState(null, null);
110                 massComponent().setComponentMass(0.01);
111                 checkUndoState("Modify mass", null);
112                 
113
114                 // Check cg+cp + altitude
115                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
116                 checkAlt(37.2);
117                 
118
119                 // Non-change
120                 document.addUndoPosition("No change");
121                 checkUndoState("Modify mass", null);
122                 
123
124                 // Non-funcitonal change
125                 document.addUndoPosition("Name change");
126                 checkUndoState("Modify mass", null);
127                 massComponent().setName("Foobar component");
128                 checkUndoState("Name change", null);
129                 
130
131                 // Check cg+cp
132                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
133                 
134
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);
140                 
141
142                 // Check cg+cp + altitude
143                 checkCgCp(0.163, 0.0613, 0.275, 9.95);
144                 checkAlt(45.0);
145                 
146
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");
151                 
152
153                 // Check cg+cp + altitude
154                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
155                 checkAlt(37.2);
156                 
157
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");
162                 
163
164                 // Check cg+cp
165                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
166                 
167
168                 // Undo "Modify mass" change
169                 undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
170                 assertEquals(0, massComponent().getComponentMass(), 0);
171                 checkUndoState(null, "Modify mass");
172                 
173
174                 // Check cg+cp + altitude
175                 checkCgCp(0.248, 0.0645, 0.320, 12.0);
176                 checkAlt(48.2);
177                 
178
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");
183                 
184
185                 // Check cg+cp + altitude
186                 checkCgCp(0.230, 0.0745, 0.320, 12.0);
187                 checkAlt(37.2);
188                 
189
190                 // Mass modification
191                 document.addUndoPosition("Modify mass2");
192                 checkUndoState("Modify mass", "Name change");
193                 massComponent().setComponentMass(0.015);
194                 checkUndoState("Modify mass2", null);
195                 
196
197                 // Check cg+cp + altitude
198                 checkCgCp(0.223, 0.0795, 0.320, 12.0);
199                 checkAlt(32.7);
200                 
201
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);
213                 document.stopUndo();
214                 
215
216                 // Check cg+cp + altitude
217                 checkCgCp(0.221, 0.0797, 0.320, 12.0);
218                 checkAlt(32.7);
219                 
220
221                 // Modify mass without setting undo description
222                 massComponent().setComponentMass(0.020);
223                 checkUndoState("Modify mass2", null);
224                 
225
226                 // Check cg+cp + altitude
227                 checkCgCp(0.215, 0.0847, 0.320, 12.0);
228                 checkAlt(29.0);
229                 
230
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");
235                 
236
237                 // Check cg+cp + altitude
238                 checkCgCp(0.221, 0.0797, 0.320, 12.0);
239                 checkAlt(32.7);
240                 
241
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");
246                 
247
248                 // Check cg+cp + altitude
249                 checkCgCp(0.223, 0.0795, 0.320, 12.0);
250                 checkAlt(32.7);
251                 
252
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");
257                 
258
259                 // Check cg+cp + altitude
260                 checkCgCp(0.221, 0.0797, 0.320, 12.0);
261                 checkAlt(32.7);
262                 
263
264         }
265         
266         private String massComponentID = null;
267         
268         private MassComponent massComponent() {
269                 if (massComponentID == null) {
270                         massComponentID = document.getRocket().getChild(0).getChild(1).getChild(0).getID();
271                 }
272                 return (MassComponent) document.getRocket().findComponent(massComponentID);
273         }
274         
275         
276         private void checkUndoState(String undoDesc, String redoDesc) {
277                 if (undoDesc == null) {
278                         assertEquals("Undo", undoAction.getValue(Action.NAME));
279                         assertFalse(undoAction.isEnabled());
280                 } else {
281                         assertEquals("Undo (" + undoDesc + ")", undoAction.getValue(Action.NAME));
282                         assertTrue(undoAction.isEnabled());
283                 }
284                 if (redoDesc == null) {
285                         assertEquals("Redo", redoAction.getValue(Action.NAME));
286                         assertFalse(redoAction.isEnabled());
287                 } else {
288                         assertEquals("Redo (" + redoDesc + ")", redoAction.getValue(Action.NAME));
289                         assertTrue(redoAction.isEnabled());
290                 }
291         }
292         
293         
294         private void checkCgCp(double cgx, double mass, double cpx, double cna) {
295                 Coordinate cg, cp;
296                 
297                 cg = massCalc.getCG(config, MassCalcType.LAUNCH_MASS);
298                 assertEquals(cgx, cg.x, 0.001);
299                 assertEquals(mass, cg.weight, 0.0005);
300                 
301                 cp = aeroCalc.getWorstCP(config, conditions, null);
302                 assertEquals(cpx, cp.x, 0.001);
303                 assertEquals(cna, cp.weight, 0.1);
304         }
305         
306         
307         private void checkAlt(double expected) throws SimulationException {
308                 Simulation simulation = document.getSimulation(0);
309                 double actual;
310                 
311                 // Simulate + check altitude
312                 simulation.simulate();
313                 actual = simulation.getSimulatedData().getBranch(0).getMaximum(FlightDataType.TYPE_ALTITUDE);
314                 assertEquals(expected, actual, 0.5);
315         }
316         
317 }