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