diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
index 3dd43b81b..0d3c657e6 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
@@ -253,9 +253,9 @@ class DocumentConfig {
 		setters.put("FinSet:cant", new DoubleSetter(
 				Reflection.findMethod(FinSet.class, "setCantAngle", double.class), Math.PI / 180.0));
 		setters.put("FinSet:tabheight", new DoubleSetter(
-				Reflection.findMethod(FinSet.class, "setTabHeight", double.class)));
+				Reflection.findMethod(FinSet.class, "setTabHeightNoValidate", double.class)));
 		setters.put("FinSet:tablength", new DoubleSetter(
-				Reflection.findMethod(FinSet.class, "setTabLength", double.class)));
+				Reflection.findMethod(FinSet.class, "setTabLengthNoValidate", double.class)));
 		setters.put("FinSet:tabposition", new FinTabPositionSetter());
 		setters.put("FinSet:filletradius", new DoubleSetter(
 				Reflection.findMethod(FinSet.class, "setFilletRadius", double.class)));
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/FinTabPositionSetter.java b/core/src/net/sf/openrocket/file/openrocket/importt/FinTabPositionSetter.java
index b0e3fda77..64072455f 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/FinTabPositionSetter.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/FinTabPositionSetter.java
@@ -11,7 +11,7 @@ import net.sf.openrocket.util.Reflection;
 class FinTabPositionSetter extends DoubleSetter {
 	
 	public FinTabPositionSetter() {
-		super(Reflection.findMethod(FinSet.class, "setTabOffset", double.class));
+		super(Reflection.findMethod(FinSet.class, "setTabOffsetNoValidate", double.class));
 	}
 	
 	@Override
@@ -50,4 +50,4 @@ class FinTabPositionSetter extends DoubleSetter {
 	}
 	
 	
-}
\ No newline at end of file
+}
diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java b/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java
index f2f9d7f64..ed84c8f3a 100644
--- a/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java
+++ b/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java
@@ -315,9 +315,9 @@ class FinSetHandler extends AbstractElementHandler {
 		result.setFinish(finish);
 		//All TTW tabs in Rocksim are relative to the front of the fin.
 		result.setTabOffsetMethod( AxialMethod.TOP);
-		result.setTabHeight(tabDepth);
-		result.setTabLength(tabLength);
-		result.setTabOffset(taboffset);
+		result.setTabHeightNoValidate(tabDepth);
+		result.setTabLengthNoValidate(tabLength);
+		result.setTabOffsetNoValidate(taboffset);
 		result.setBaseRotation(radialAngle);
 		result.setCrossSection(convertTipShapeCode(tipShapeCode));
 		result.setAxialMethod(axialMethod);
diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
index 57bb50b27..2b42be1e6 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
@@ -247,6 +247,24 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
 	public double getTabHeight() {
 		return tabHeight;
 	}
+
+	/**
+	 * wrapper to call setTabHeight without validating tab.
+	 * This is intended to be used when reading a rocket from a file,
+	 * since if the fin tab is read before the fin, validation will
+	 * reduce the tab length to the default fin length
+	 */
+	public void setTabHeightNoValidate(final double heightRequest) {
+		setTabHeight(heightRequest, false);
+	}
+
+	/**
+	 * wrapper to call setTabHeight and validate tab.
+	 * This is intended to be used from the GUI
+	 */
+	public void setTabHeight(final double heightRequest) {
+		setTabHeight(heightRequest, true);
+	}
 	
 	/**
 	 * Set the height from the fin's base at the reference point -- i.e. where the tab is located from.  If the tab is located via BOTTOM, then the back edge will be 
@@ -258,14 +276,16 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
 	 * @param newHeightRequest how deep the fin tab should project from the fin root, at the reference point 
 	 * 
 	 */
-	public void setTabHeight(final double newHeightRequest) {
-		if (MathUtil.equals(this.tabHeight, MathUtil.max(newHeightRequest, 0))){
+	private void setTabHeight(final double heightRequest, final boolean validate) {
+		if (MathUtil.equals(this.tabHeight, MathUtil.max(heightRequest, 0))){
 			return;
 		}
 		
-		this.tabHeight = newHeightRequest;
-		
-		validateFinTab();
+		tabHeight = heightRequest;
+
+		if (validate)
+			validateFinTab();
+
 		fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
 	}
 	
@@ -273,26 +293,74 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
 	public double getTabLength() {
 		return tabLength;
 	}
-	
-	public void setTabLength(double length) {
-		length = MathUtil.max(length, 0);
-		if (MathUtil.equals(this.tabLength, length))
+
+	/**
+	 * Wrapper to call setTabLength with no validation
+	 * This is only intended to be used when reading a
+	 * rocket from a file.  If the fin tab is read before
+	 * the fin, validation will reduce the length of the tab
+	 * to the default length of the fin
+	 */
+	public void setTabLengthNoValidate(final double lengthRequest) {
+		setTabLength(lengthRequest, false);
+	}
+
+	/**
+	 * Wrapper to call full setTabLength function, and validate
+	 * tab length
+	 */
+	public void setTabLength(final double lengthRequest) {
+		setTabLength(lengthRequest, true);
+	}
+
+	/**
+	 * set tab length and optionally validate parameters
+	 */
+	private void setTabLength(final double lengthRequest, final boolean validate) {
+		if (MathUtil.equals(tabLength, MathUtil.max(lengthRequest, 0))) {
 			return;
-		tabLength = length;
-		validateFinTab();
+		}
+		
+		tabLength = lengthRequest;
+		
+		if (validate) {
+			validateFinTab();
+		}
+		
 		fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
 	}
 
-	/** 
-	 * internally, set the internal  
-	 * 
-	 * @param newOffset new requested shift of tab -- from
+	/**
+	 * wrapper to call setTabOffset without validating tab.
+	 * This is intended to be used when reading a rocket from a file,
+	 * since if the fin tab is read before the fin, validation will
+	 * reduce the tab length to the default fin length
 	 */
-	public void setTabOffset( final double newOffset) {
-		this.tabOffset = newOffset;
-		this.tabPosition = this.tabOffsetMethod.getAsPosition( newOffset, this.tabLength, this.length);
+	public void setTabOffsetNoValidate(final double offsetRequest) {
+		setTabOffset(offsetRequest, false);
+	}
 
-		validateFinTab();
+	/**
+	 * wrapper to call setTabOffset and validate tab.
+	 * This is intended to be used in the gui
+	 */
+	public void setTabOffset(final double offsetRequest) {
+		setTabOffset(offsetRequest, true);
+	}
+	
+	/** 
+	 * internally, set the internal offset and optionally validate tab
+	 * 
+	 * @param offsetRequest new requested shift of tab -- from
+	 * @param validate wehther or not to validate
+	 */
+	private void setTabOffset( final double offsetRequest, final boolean validate) {
+		tabOffset = offsetRequest;
+		tabPosition = tabOffsetMethod.getAsPosition( tabOffset, tabLength, length);
+
+		if (validate) {
+			validateFinTab();
+		}
 		fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
 	}
 	
diff --git a/core/src/net/sf/openrocket/util/#TestRockets.java# b/core/src/net/sf/openrocket/util/#TestRockets.java#
new file mode 100644
index 000000000..2213a18ad
--- /dev/null
+++ b/core/src/net/sf/openrocket/util/#TestRockets.java#
@@ -0,0 +1,1633 @@
+package net.sf.openrocket.util;
+
+import java.util.Random;
+
+import net.sf.openrocket.appearance.Appearance;
+import net.sf.openrocket.file.openrocket.OpenRocketSaver;
+import net.sf.openrocket.database.Databases;
+import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.document.OpenRocketDocumentFactory;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.material.Material.Type;
+import net.sf.openrocket.motor.Manufacturer;
+import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.motor.MotorConfiguration;
+import net.sf.openrocket.motor.ThrustCurveMotor;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.preset.ComponentPresetFactory;
+import net.sf.openrocket.preset.InvalidComponentPresetException;
+import net.sf.openrocket.preset.TypedPropertyMap;
+import net.sf.openrocket.rocketcomponent.AxialStage;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.Bulkhead;
+import net.sf.openrocket.rocketcomponent.CenteringRing;
+import net.sf.openrocket.rocketcomponent.ClusterConfiguration;
+import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
+import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
+import net.sf.openrocket.rocketcomponent.EngineBlock;
+import net.sf.openrocket.rocketcomponent.ExternalComponent;
+import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
+import net.sf.openrocket.rocketcomponent.FinSet;
+import net.sf.openrocket.rocketcomponent.FinSet.CrossSection;
+import net.sf.openrocket.rocketcomponent.FlightConfiguration;
+import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
+import net.sf.openrocket.rocketcomponent.FreeformFinSet;
+import net.sf.openrocket.rocketcomponent.InnerTube;
+import net.sf.openrocket.rocketcomponent.InternalComponent;
+import net.sf.openrocket.rocketcomponent.LaunchLug;
+import net.sf.openrocket.rocketcomponent.MassComponent;
+import net.sf.openrocket.rocketcomponent.NoseCone;
+import net.sf.openrocket.rocketcomponent.Parachute;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
+import net.sf.openrocket.rocketcomponent.PodSet;
+import net.sf.openrocket.rocketcomponent.RecoveryDevice;
+import net.sf.openrocket.rocketcomponent.ReferenceType;
+import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.rocketcomponent.ShockCord;
+import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
+import net.sf.openrocket.rocketcomponent.Transition;
+import net.sf.openrocket.rocketcomponent.Transition.Shape;
+import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
+import net.sf.openrocket.rocketcomponent.TubeCoupler;
+import net.sf.openrocket.rocketcomponent.position.*;
+import net.sf.openrocket.simulation.customexpression.CustomExpression;
+import net.sf.openrocket.simulation.exception.SimulationException;
+import net.sf.openrocket.simulation.extension.impl.ScriptingExtension;
+import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
+import net.sf.openrocket.simulation.listeners.SimulationListener;
+import net.sf.openrocket.startup.Application;
+
+public class TestRockets {
+	
+	private final String key;
+	private final Random rnd;
+	
+	
+	public TestRockets(String key) {
+		
+		if (key == null) {
+			Random myRnd = new Random();
+			StringBuilder sb = new StringBuilder();
+			for (int i = 0; i < 6; i++) {
+				int n = myRnd.nextInt(62);
+				if (n < 10) {
+					sb.append((char) ('0' + n));
+				} else if (n < 36) {
+					sb.append((char) ('A' + n - 10));
+				} else {
+					sb.append((char) ('a' + n - 36));
+				}
+			}
+			key = sb.toString();
+		}
+		
+		this.key = key;
+		this.rnd = new Random(key.hashCode());
+		
+	}
+	
+	// Minimal motor without any useful numbers data
+	private static ThrustCurveMotor getTestMotor() {
+		return new ThrustCurveMotor.Builder()
+				.setManufacturer(Manufacturer.getManufacturer("A"))
+				.setDesignation("F12X")
+				.setDescription("Desc")
+				.setMotorType(Motor.Type.UNKNOWN)
+				.setStandardDelays(new double[] {})
+				.setDiameter(0.024)
+				.setLength(0.07)
+				.setTimePoints(new double[] { 0, 1, 2 })
+				.setThrustPoints(new double[] { 0, 1, 0 })
+				.setCGPoints(new Coordinate[] { Coordinate.NUL, Coordinate.NUL, Coordinate.NUL })
+				.setDigest("digestA")
+				.build();
+	} 
+	
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	private static Motor generateMotor_A8_18mm(){
+		return new ThrustCurveMotor.Builder()
+				.setManufacturer(Manufacturer.getManufacturer("Estes"))
+				.setDesignation("A8")
+				.setDescription(" SU Black Powder")
+				.setMotorType(Motor.Type.SINGLE)
+				.setStandardDelays(new double[] {0,3,5})
+				.setDiameter(0.018)
+				.setLength(0.070)
+				.setTimePoints(new double[] { 0, 1, 2 })
+				.setThrustPoints(new double[] { 0, 9, 0 })
+				.setCGPoints(new Coordinate[] {
+						new Coordinate(0.035, 0, 0, 0.0164),new Coordinate(.035, 0, 0, 0.0145),new Coordinate(.035, 0, 0, 0.0131)})
+				.setDigest("digest A8 test")
+				.build();
+	}
+	
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	private static Motor generateMotor_B4_18mm(){
+		return new ThrustCurveMotor.Builder()
+				.setManufacturer(Manufacturer.getManufacturer("Estes"))
+				.setDesignation("B4")
+				.setDescription(" SU Black Powder")
+				.setMotorType(Motor.Type.SINGLE)
+				.setStandardDelays(new double[] {0,3,5})
+				.setDiameter(0.018)
+				.setLength(0.070)
+				.setTimePoints(new double[] { 0, 1, 2 })
+				.setThrustPoints(new double[] { 0, 11.4, 0 })
+				.setCGPoints(new Coordinate[] {
+						new Coordinate(0.035, 0, 0, 0.0195),new Coordinate(.035, 0, 0, 0.0155),new Coordinate(.035, 0, 0, 0.013)})
+				.setDigest("digest B4 test")
+				.build();
+	}
+	
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	private static Motor generateMotor_C6_18mm(){
+		return new ThrustCurveMotor.Builder()
+				.setManufacturer(Manufacturer.getManufacturer("Estes"))
+				.setDesignation("C6")
+				.setDescription(" SU Black Powder")
+				.setMotorType(Motor.Type.SINGLE)
+				.setStandardDelays(new double[] {0,3,5,7})
+				.setDiameter(0.018)
+				.setLength(0.070)
+				.setTimePoints(new double[] { 0, 1, 2 })
+				.setThrustPoints(new double[] { 0, 6, 0 })
+				.setCGPoints(new Coordinate[] {
+						new Coordinate(0.035, 0, 0, 0.0227),new Coordinate(.035, 0, 0, 0.0165),new Coordinate(.035, 0, 0, 0.012)})
+				.setDigest("digest C6 test")
+				.build();
+	}
+	
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	private static Motor generateMotor_D21_18mm(){
+		return new ThrustCurveMotor.Builder()
+				.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
+				.setDesignation("D21")
+				.setDescription("Desc")
+				.setMotorType(Motor.Type.SINGLE)
+				.setStandardDelays(new double[] {})
+				.setDiameter(0.018)
+				.setLength(0.070)
+				.setTimePoints(new double[] { 0, 1, 2 })
+				.setThrustPoints(new double[] { 0, 32, 0 })
+				.setCGPoints(new Coordinate[] {
+						new Coordinate(.035, 0, 0, 0.025),new Coordinate(.035, 0, 0, .020),new Coordinate(.035, 0, 0, 0.0154)})
+				.setDigest("digest D21 test")
+				.build();
+	}
+	
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	private static Motor generateMotor_M1350_75mm(){
+		return new ThrustCurveMotor.Builder()
+				.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
+				.setDesignation("M1350")
+				.setDescription("Desc")
+				.setMotorType(Motor.Type.SINGLE)
+				.setStandardDelays(new double[] {})
+				.setDiameter(0.075)
+				.setLength(0.622)
+				.setTimePoints(new double[] { 0, 1, 2 })
+				.setThrustPoints(new double[] { 0, 1357, 0 })
+				.setCGPoints(new Coordinate[] {
+						new Coordinate(.311, 0, 0, 4.808),new Coordinate(.311, 0, 0, 3.389),new Coordinate(.311, 0, 0, 1.970)})
+				.setDigest("digest M1350 test")
+				.build();
+	}
+	
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	private static Motor generateMotor_G77_29mm(){
+		return new ThrustCurveMotor.Builder()
+				.setManufacturer(Manufacturer.getManufacturer("AeroTech"))
+				.setDesignation("G77")
+				.setDescription("Desc")
+				.setMotorType(Motor.Type.SINGLE)
+				.setStandardDelays(new double[] {4,7,10})
+				.setDiameter(0.029)
+				.setLength(0.124)
+				.setTimePoints(new double[] { 0, 1, 2 })
+				.setThrustPoints(new double[] { 0, 1, 0 })
+				.setCGPoints(new Coordinate[] {
+						new Coordinate(.062, 0, 0, 0.123),new Coordinate(.062, 0, 0, .0935),new Coordinate(.062, 0, 0, 0.064)})
+				.setDigest("digest G77 test")
+				.build();
+	}
+	
+	/**
+	 * Create a new test rocket based on the value 'key'.  The rocket utilizes most of the 
+	 * properties and features available.  The same key always returns the same rocket,
+	 * but different key values produce slightly different rockets.  A key value of
+	 * null generates a rocket using a random key.
+	 * 
+	 * The rocket created by this method is not fly-worthy.  It is also NOT guaranteed
+	 * that later versions would produce exactly the same rocket!
+	 * 
+	 * @return		a rocket design.
+	 */
+	public Rocket makeTestRocket() {
+		
+		Rocket rocket = new Rocket();
+		setBasics(rocket);
+		rocket.setCustomReferenceLength(rnd(0.05));
+		rocket.setDesigner("Designer " + key);
+		rocket.setReferenceType((ReferenceType) randomEnum(ReferenceType.class));
+		rocket.setRevision("Rocket revision " + key);
+		rocket.setName(key);
+		
+		AxialStage stage = new AxialStage();
+		setBasics(stage);
+		rocket.addChild(stage);
+		
+		NoseCone nose = new NoseCone();
+		setBasics(stage);
+		nose.setAftRadius(rnd(0.03));
+		nose.setAftRadiusAutomatic(rnd.nextBoolean());
+		nose.setAftShoulderCapped(rnd.nextBoolean());
+		nose.setAftShoulderLength(rnd(0.02));
+		nose.setAftShoulderRadius(rnd(0.02));
+		nose.setAftShoulderThickness(rnd(0.002));
+		nose.setClipped(rnd.nextBoolean());
+		nose.setThickness(rnd(0.002));
+		nose.setFilled(rnd.nextBoolean());
+		nose.setForeRadius(rnd(0.1)); // Unset
+		nose.setLength(rnd(0.15));
+		nose.setShapeParameter(rnd(0.5));
+		nose.setType((Shape) randomEnum(Shape.class));
+		stage.addChild(nose);
+		
+		Transition shoulder = new Transition();
+		setBasics(shoulder);
+		shoulder.setAftRadius(rnd(0.06));
+		shoulder.setAftRadiusAutomatic(rnd.nextBoolean());
+		shoulder.setAftShoulderCapped(rnd.nextBoolean());
+		shoulder.setAftShoulderLength(rnd(0.02));
+		shoulder.setAftShoulderRadius(rnd(0.05));
+		shoulder.setAftShoulderThickness(rnd(0.002));
+		shoulder.setClipped(rnd.nextBoolean());
+		shoulder.setThickness(rnd(0.002));
+		shoulder.setFilled(rnd.nextBoolean());
+		shoulder.setForeRadius(rnd(0.03));
+		shoulder.setForeRadiusAutomatic(rnd.nextBoolean());
+		shoulder.setForeShoulderCapped(rnd.nextBoolean());
+		shoulder.setForeShoulderLength(rnd(0.02));
+		shoulder.setForeShoulderRadius(rnd(0.02));
+		shoulder.setForeShoulderThickness(rnd(0.002));
+		shoulder.setLength(rnd(0.15));
+		shoulder.setShapeParameter(rnd(0.5));
+		shoulder.setThickness(rnd(0.003));
+		shoulder.setType((Shape) randomEnum(Shape.class));
+		stage.addChild(shoulder);
+		
+		BodyTube body = new BodyTube();
+		setBasics(body);
+		body.setThickness(rnd(0.002));
+		body.setFilled(rnd.nextBoolean());
+		body.setLength(rnd(0.3));
+		//body.setMotorMount(rnd.nextBoolean());
+		body.setMotorOverhang(rnd.nextGaussian() * 0.03);
+		body.setOuterRadius(rnd(0.06));
+		body.setOuterRadiusAutomatic(rnd.nextBoolean());
+		stage.addChild(body);
+		
+		Transition boattail = new Transition();
+		setBasics(boattail);
+		boattail.setAftRadius(rnd(0.03));
+		boattail.setAftRadiusAutomatic(rnd.nextBoolean());
+		boattail.setAftShoulderCapped(rnd.nextBoolean());
+		boattail.setAftShoulderLength(rnd(0.02));
+		boattail.setAftShoulderRadius(rnd(0.02));
+		boattail.setAftShoulderThickness(rnd(0.002));
+		boattail.setClipped(rnd.nextBoolean());
+		boattail.setThickness(rnd(0.002));
+		boattail.setFilled(rnd.nextBoolean());
+		boattail.setForeRadius(rnd(0.06));
+		boattail.setForeRadiusAutomatic(rnd.nextBoolean());
+		boattail.setForeShoulderCapped(rnd.nextBoolean());
+		boattail.setForeShoulderLength(rnd(0.02));
+		boattail.setForeShoulderRadius(rnd(0.05));
+		boattail.setForeShoulderThickness(rnd(0.002));
+		boattail.setLength(rnd(0.15));
+		boattail.setShapeParameter(rnd(0.5));
+		boattail.setThickness(rnd(0.003));
+		boattail.setType((Shape) randomEnum(Shape.class));
+		stage.addChild(boattail);
+		
+		MassComponent mass = new MassComponent();
+		setBasics(mass);
+		mass.setComponentMass(rnd(0.05));
+		mass.setLength(rnd(0.05));
+		mass.setRadialDirection(rnd(100));
+		mass.setRadialPosition(rnd(0.02));
+		mass.setRadius(rnd(0.05));
+		nose.addChild(mass);
+		
+		rocket.enableEvents();
+		return rocket;
+	}
+	
+	
+	private void setBasics(RocketComponent c) {
+		c.setComment(c.getComponentName() + " comment " + key);
+		c.setName(c.getComponentName() + " name " + key);
+		
+		c.setCGOverridden(rnd.nextBoolean());
+		c.setMassOverridden(rnd.nextBoolean());
+		c.setOverrideCGX(rnd(0.2));
+		c.setOverrideMass(rnd(0.05));
+		c.setOverrideSubcomponents(rnd.nextBoolean());
+		
+		if (c.isMassive()) {
+			// Only massive components are drawn
+			c.setColor(randomColor());
+			c.setLineStyle((LineStyle) randomEnum(LineStyle.class));
+		}
+		
+		if (c instanceof ExternalComponent) {
+			ExternalComponent e = (ExternalComponent) c;
+			e.setFinish((Finish) randomEnum(Finish.class));
+			double d = rnd(100);
+			e.setMaterial(Databases.findMaterial(Type.BULK, "Testmat " + d, d));
+		}
+		
+		if (c instanceof InternalComponent) {
+			InternalComponent i = (InternalComponent) c;
+			i.setAxialMethod((AxialMethod) randomEnum(AxialMethod.class));
+			i.setAxialOffset(rnd(0.3));
+		}
+	}
+	
+	private double rnd(double scale) {
+		return (rnd.nextDouble() * 0.2 + 0.9) * scale;
+	}
+	
+	private Color randomColor() {
+		return new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
+	}
+	
+	private > Enum randomEnum(Class c) {
+		Enum[] values = c.getEnumConstants();
+		if (values.length == 0)
+			return null;
+			
+		return values[rnd.nextInt(values.length)];
+	}
+	
+	final static FlightConfigurationId ESTES_ALPHA_III_FCID[] = { 
+			null, // treat the array as 1-indexed.   
+			new FlightConfigurationId("test_config #1: A8-0"), 
+			new FlightConfigurationId("test_config #2: B4-3"),
+			new FlightConfigurationId("test_config #3: C6-3"),
+			new FlightConfigurationId("test_config #4: C6-5"),
+			new FlightConfigurationId("test_config #5: C6-7"),
+	};
+	
+	// This is a Estes Alpha III 
+	// http://www.rocketreviews.com/alpha-iii---estes-221256.html
+	// It is picked as a standard, simple, validation rocket. 
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	public static final Rocket makeEstesAlphaIII(){
+		Rocket rocket = new Rocket();
+		FlightConfigurationId fcid[] = new FlightConfigurationId[5];
+		fcid[0] = rocket.createFlightConfiguration( ESTES_ALPHA_III_FCID[1] );
+		fcid[1] = rocket.createFlightConfiguration( ESTES_ALPHA_III_FCID[2] );
+		fcid[2] = rocket.createFlightConfiguration( ESTES_ALPHA_III_FCID[3] );
+		fcid[3] = rocket.createFlightConfiguration( ESTES_ALPHA_III_FCID[4] );
+		fcid[4] = rocket.createFlightConfiguration( ESTES_ALPHA_III_FCID[5] );
+		
+		
+		rocket.setName("Estes Alpha III / Code Verification Rocket");
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage");
+		rocket.addChild(stage);
+				
+		double noseconeLength = 0.07;
+		double noseconeRadius = 0.012;
+		NoseCone nosecone = new NoseCone(Transition.Shape.OGIVE, noseconeLength, noseconeRadius);
+		nosecone.setAftShoulderLength(0.02);
+		nosecone.setAftShoulderRadius(0.011);
+		nosecone.setName("Nose Cone");
+		stage.addChild(nosecone);
+		
+		double bodytubeLength = 0.20;
+		double bodytubeRadius = 0.012;
+		double bodytubeThickness = 0.0003;
+		BodyTube bodytube = new BodyTube(bodytubeLength, bodytubeRadius, bodytubeThickness);
+		bodytube.setName("Body Tube");
+		stage.addChild(bodytube);
+		
+		TrapezoidFinSet finset;
+		{
+			int finCount = 3;
+			double finRootChord = .05;
+			double finTipChord = .03;
+			double finSweep = 0.02;
+			double finHeight = 0.05;
+			finset = new TrapezoidFinSet(finCount, finRootChord, finTipChord, finSweep, finHeight);
+			finset.setThickness( 0.0032);
+			finset.setAxialMethod(AxialMethod.BOTTOM);
+			finset.setName("3 Fin Set");
+			bodytube.addChild(finset);
+			
+			LaunchLug lug = new LaunchLug();
+			lug.setName("Launch Lugs");
+			lug.setAxialMethod(AxialMethod.TOP);
+			lug.setAxialOffset(0.111);
+			lug.setLength(0.050);
+			lug.setOuterRadius(0.0022);
+			lug.setInnerRadius(0.0020);
+			bodytube.addChild(lug);
+			
+			InnerTube inner = new InnerTube();
+			inner.setAxialMethod(AxialMethod.TOP);
+			inner.setAxialOffset(0.133);
+			inner.setLength(0.07);
+			inner.setOuterRadius(0.009);
+			inner.setThickness(0.0003);
+			inner.setMotorMount(true);
+			inner.setName("Motor Mount Tube");
+			bodytube.addChild(inner);
+			
+			{
+				// MotorBlock 
+				EngineBlock thrustBlock= new EngineBlock();
+				thrustBlock.setAxialMethod(AxialMethod.TOP);
+				thrustBlock.setAxialOffset(0.0);
+				thrustBlock.setLength(0.005);
+				thrustBlock.setOuterRadius(0.009);
+				thrustBlock.setThickness(0.0008);
+				thrustBlock.setName("Engine Block");
+				inner.addChild(thrustBlock);
+				inner.setMotorMount( true);
+				
+				{
+					MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[0]);
+					Motor mtr =	TestRockets.generateMotor_A8_18mm();
+					motorConfig.setMotor( mtr);
+					motorConfig.setEjectionDelay(0.0);
+					inner.setMotorConfig( motorConfig, fcid[0]);
+				}
+				{
+					MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[1]);
+					Motor mtr =	TestRockets.generateMotor_B4_18mm();
+					motorConfig.setMotor( mtr);
+					motorConfig.setEjectionDelay(3.0);
+					inner.setMotorConfig( motorConfig, fcid[1]);
+				}
+				{
+					MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[2]);
+					Motor mtr =	TestRockets.generateMotor_C6_18mm();
+					motorConfig.setEjectionDelay(3.0);
+					motorConfig.setMotor( mtr);
+					inner.setMotorConfig( motorConfig, fcid[2]);
+				}
+				{
+					MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[3]);
+					Motor mtr =	TestRockets.generateMotor_C6_18mm();
+					motorConfig.setEjectionDelay(5.0);
+					motorConfig.setMotor( mtr);
+					inner.setMotorConfig( motorConfig, fcid[3]);
+				}
+				{
+					MotorConfiguration motorConfig = new MotorConfiguration(inner,fcid[4]);
+					Motor mtr =	TestRockets.generateMotor_C6_18mm();
+					motorConfig.setEjectionDelay(7.0);
+					motorConfig.setMotor( mtr);
+					inner.setMotorConfig( motorConfig, fcid[4]);
+				}
+			}
+		
+			// parachute
+			Parachute chute = new Parachute();
+			chute.setAxialMethod(AxialMethod.TOP);
+			chute.setName("Parachute");
+			chute.setAxialOffset(0.028);
+			chute.setOverrideMass(0.002);
+			chute.setMassOverridden(true);
+			bodytube.addChild(chute);
+			
+			// bulkhead x2
+			CenteringRing centerings = new CenteringRing();
+			centerings.setName("Centering Rings");
+			centerings.setAxialMethod(AxialMethod.TOP);
+			centerings.setAxialOffset(0.14);
+			centerings.setLength(0.006);
+			centerings.setInstanceCount(2);
+			centerings.setInstanceSeparation(0.035);
+			bodytube.addChild(centerings);
+		}
+		
+		Material material = Application.getPreferences().getDefaultComponentMaterial(null, Material.Type.BULK);
+		nosecone.setMaterial(material);
+		bodytube.setMaterial(material);
+		finset.setMaterial(material);
+		
+		
+		// preserve default default configuration of rocket -- to test what the default is set to upon initialization.
+		
+		rocket.enableEvents();
+		return rocket;
+	}
+	
+	// This is an extra stage tacked onto the end of an Estes Alpha III 
+	// http://www.rocketreviews.com/alpha-iii---estes-221256.html
+	// 
+	// This function is used for unit, integration tests, DO NOT CHANGE WITHOUT UPDATING TESTS
+	public static final Rocket makeBeta(){
+		Rocket rocket = makeEstesAlphaIII();
+		rocket.setName("Kit-bash Beta");
+		
+		AxialStage sustainerStage = (AxialStage)rocket.getChild(0);
+		sustainerStage.setName( "Sustainer Stage");
+		BodyTube sustainerBody = (BodyTube)sustainerStage.getChild(1);
+		final double sustainerRadius = sustainerBody.getAftRadius();
+		final double sustainerThickness = sustainerBody.getThickness();
+		
+		AxialStage boosterStage = new AxialStage();
+		boosterStage.setName("Booster Stage");
+		rocket.addChild( boosterStage );
+		{
+			BodyTube boosterBody = new BodyTube(0.06, sustainerRadius, sustainerThickness);
+			boosterBody.setName("Booster Body");
+			boosterStage.addChild( boosterBody);
+			{
+				TubeCoupler coupler = new TubeCoupler();
+				coupler.setName("Coupler");
+				coupler.setOuterRadiusAutomatic(true);
+				coupler.setThickness( sustainerThickness );
+				coupler.setLength(0.03);
+				coupler.setAxialMethod(AxialMethod.TOP);
+				coupler.setAxialOffset(-0.015);
+				boosterBody.addChild(coupler);
+				
+				int finCount = 3;
+				double finRootChord = .05;
+				double finTipChord = .03;
+				double finSweep = 0.02;
+				double finHeight = 0.05;
+				FinSet finset = new TrapezoidFinSet(finCount, finRootChord, finTipChord, finSweep, finHeight);
+				finset.setName("Booster Fins");
+				finset.setThickness( 0.0032);
+				finset.setAxialMethod(AxialMethod.BOTTOM);
+				finset.setAxialOffset(0.);
+				boosterBody.addChild(finset);
+
+				// Motor mount
+				InnerTube boosterMMT = new InnerTube();
+				boosterMMT.setName("Booster MMT");
+				boosterMMT.setAxialOffset(0.005);
+				boosterMMT.setAxialMethod(AxialMethod.BOTTOM);
+				boosterMMT.setOuterRadius(0.019 / 2);
+				boosterMMT.setInnerRadius(0.018 / 2);
+				boosterMMT.setLength(0.05);
+				boosterMMT.setMotorMount(true);
+				{
+					MotorConfiguration motorConfig= new MotorConfiguration(boosterMMT, ESTES_ALPHA_III_FCID[1] );
+					Motor mtr = generateMotor_D21_18mm();
+					motorConfig.setMotor(mtr);
+					boosterMMT.setMotorConfig( motorConfig, ESTES_ALPHA_III_FCID[1]);
+				}
+				boosterBody.addChild(boosterMMT);
+			}
+		}
+
+		rocket.setSelectedConfiguration( ESTES_ALPHA_III_FCID[1] );
+		rocket.getSelectedConfiguration().setAllStages();
+		rocket.enableEvents();
+		
+		return rocket;
+	}
+	
+	public static Rocket makeBigBlue() {
+		Rocket rocket;
+		AxialStage stage;
+		NoseCone nosecone;
+		BodyTube bodytube;
+		FreeformFinSet finset;
+		MassComponent mcomp;
+		
+		rocket = new Rocket();
+		stage = new AxialStage();
+		stage.setName("Stage1");
+		
+		nosecone = new NoseCone(Transition.Shape.ELLIPSOID, 0.105, 0.033);
+		nosecone.setThickness(0.001);
+		bodytube = new BodyTube(0.69, 0.033, 0.001);
+		
+		finset = new FreeformFinSet();
+		final Coordinate[] finPoints = {
+				new Coordinate(0, 0),
+				new Coordinate(0.115, 0.072),
+				new Coordinate(0.255, 0.072),
+				new Coordinate(0.255, 0.037),
+				new Coordinate(0.150, 0)};
+		finset.setPoints(finPoints);
+
+		finset.setThickness(0.003);
+		finset.setFinCount(4);
+		
+		finset.setCantAngle(0 * Math.PI / 180);
+		//System.err.println("Fin cant angle: " + (finset.getCantAngle() * 180 / Math.PI));
+		
+		mcomp = new MassComponent(0.2, 0.03, 0.045 + 0.060);
+		mcomp.setAxialMethod(AxialMethod.TOP);
+		mcomp.setAxialOffset(0);
+		
+		// Stage construction
+		rocket.addChild(stage);
+		rocket.setPerfectFinish(false);
+		
+		// Component construction
+		stage.addChild(nosecone);
+		stage.addChild(bodytube);
+		
+		bodytube.addChild(finset);
+		
+		bodytube.addChild(mcomp);
+		
+		//		Material material = new Material("Test material", 500);
+		//		nosecone.setMaterial(material);
+		//		bodytube.setMaterial(material);
+		//		finset.setMaterial(material);
+		
+//		FlightConfiguration config = rocket.getDefaultConfiguration();
+//		FlightConfigurationID fcid = config.getFlightConfigurationID();
+//		config.setAllStages();
+		
+		//		Motor m = Application.getMotorSetDatabase().findMotors(null, null, "F12J", Double.NaN, Double.NaN).get(0);
+		//		bodytube.setMotor(id, m);
+		//		bodytube.setMotorOverhang(0.005);
+		
+		rocket.enableEvents();
+		return rocket;
+	}
+	
+	
+	
+	
+	public static Rocket makeIsoHaisu() {
+		Rocket rocket;
+		AxialStage stage;
+		NoseCone nosecone;
+		BodyTube tube1, tube2, tube3;
+		TrapezoidFinSet finset;
+		TrapezoidFinSet auxfinset;
+		@SuppressWarnings("unused")
+		MassComponent mcomp;
+		
+		final double R = 0.07;
+		
+		rocket = new Rocket();
+		stage = new AxialStage();
+		stage.setName("Stage1");
+		
+		nosecone = new NoseCone(Transition.Shape.OGIVE, 0.53, R);
+		nosecone.setThickness(0.005);
+		nosecone.setMassOverridden(true);
+		nosecone.setOverrideMass(0.588);
+		stage.addChild(nosecone);
+		
+		tube1 = new BodyTube(0.505, R, 0.005);
+		tube1.setMassOverridden(true);
+		tube1.setOverrideMass(0.366);
+		stage.addChild(tube1);
+		
+		tube2 = new BodyTube(0.605, R, 0.005);
+		tube2.setMassOverridden(true);
+		tube2.setOverrideMass(0.427);
+		stage.addChild(tube2);
+		
+		tube3 = new BodyTube(1.065, R, 0.005);
+		tube3.setMassOverridden(true);
+		tube3.setOverrideMass(0.730);
+		stage.addChild(tube3);
+		
+		LaunchLug lug = new LaunchLug();
+		tube1.addChild(lug);
+		
+		TubeCoupler coupler = new TubeCoupler();
+		coupler.setOuterRadiusAutomatic(true);
+		coupler.setThickness(0.005);
+		coupler.setLength(0.28);
+		coupler.setMassOverridden(true);
+		coupler.setOverrideMass(0.360);
+		coupler.setAxialMethod(AxialMethod.BOTTOM);
+		coupler.setAxialOffset(-0.14);
+		tube1.addChild(coupler);
+		
+		// Parachute
+		MassComponent mass = new MassComponent(0.05, 0.05, 0.280);
+		mass.setAxialMethod(AxialMethod.TOP);
+		mass.setAxialOffset(0.2);
+		tube1.addChild(mass);
+		
+		// Cord
+		mass = new MassComponent(0.05, 0.05, 0.125);
+		mass.setAxialMethod(AxialMethod.TOP);
+		mass.setAxialOffset(0.2);
+		tube1.addChild(mass);
+		
+		// Payload
+		mass = new MassComponent(0.40, R, 1.500);
+		mass.setAxialMethod(AxialMethod.TOP);
+		mass.setAxialOffset(0.25);
+		tube1.addChild(mass);
+		
+		auxfinset = new TrapezoidFinSet();
+		auxfinset.setName("CONTROL");
+		auxfinset.setFinCount(2);
+		auxfinset.setRootChord(0.05);
+		auxfinset.setTipChord(0.05);
+		auxfinset.setHeight(0.10);
+		auxfinset.setSweep(0);
+		auxfinset.setThickness(0.008);
+		auxfinset.setCrossSection(CrossSection.AIRFOIL);
+		auxfinset.setAxialMethod(AxialMethod.TOP);
+		auxfinset.setAxialOffset(0.28);
+		auxfinset.setBaseRotation(Math.PI / 2);
+		tube1.addChild(auxfinset);
+		
+		coupler = new TubeCoupler();
+		coupler.setOuterRadiusAutomatic(true);
+		coupler.setLength(0.28);
+		coupler.setAxialMethod(AxialMethod.TOP);
+		coupler.setAxialOffset(0.47);
+		coupler.setMassOverridden(true);
+		coupler.setOverrideMass(0.360);
+		tube2.addChild(coupler);
+		
+		// Parachute
+		mass = new MassComponent(0.1, 0.05, 0.028);
+		mass.setAxialMethod(AxialMethod.TOP);
+		mass.setAxialOffset(0.14);
+		tube2.addChild(mass);
+		
+		Bulkhead bulk = new Bulkhead();
+		bulk.setOuterRadiusAutomatic(true);
+		bulk.setMassOverridden(true);
+		bulk.setOverrideMass(0.050);
+		bulk.setAxialMethod(AxialMethod.TOP);
+		bulk.setAxialOffset(0.27);
+		tube2.addChild(bulk);
+		
+		// Chord
+		mass = new MassComponent(0.1, 0.05, 0.125);
+		mass.setAxialMethod(AxialMethod.TOP);
+		mass.setAxialOffset(0.19);
+		tube2.addChild(mass);
+		
+		InnerTube inner = new InnerTube();
+		inner.setOuterRadius(0.08 / 2);
+		inner.setInnerRadius(0.0762 / 2);
+		inner.setLength(0.86);
+		inner.setMassOverridden(true);
+		inner.setOverrideMass(0.388);
+		tube3.addChild(inner);
+		
+		CenteringRing center = new CenteringRing();
+		center.setInnerRadiusAutomatic(true);
+		center.setOuterRadiusAutomatic(true);
+		center.setLength(0.005);
+		center.setMassOverridden(true);
+		center.setOverrideMass(0.038);
+		center.setAxialMethod(AxialMethod.BOTTOM);
+		center.setAxialOffset(0);
+		tube3.addChild(center);
+		
+		center = new CenteringRing();
+		center.setInnerRadiusAutomatic(true);
+		center.setOuterRadiusAutomatic(true);
+		center.setLength(0.005);
+		center.setMassOverridden(true);
+		center.setOverrideMass(0.038);
+		center.setAxialMethod(AxialMethod.TOP);
+		center.setAxialOffset(0.28);
+		tube3.addChild(center);
+		
+		center = new CenteringRing();
+		center.setInnerRadiusAutomatic(true);
+		center.setOuterRadiusAutomatic(true);
+		center.setLength(0.005);
+		center.setMassOverridden(true);
+		center.setOverrideMass(0.038);
+		center.setAxialMethod(AxialMethod.TOP);
+		center.setAxialOffset(0.83);
+		tube3.addChild(center);
+		
+		finset = new TrapezoidFinSet();
+		finset.setRootChord(0.495);
+		finset.setTipChord(0.1);
+		finset.setHeight(0.185);
+		finset.setThickness(0.005);
+		finset.setSweep(0.3);
+		finset.setAxialMethod(AxialMethod.BOTTOM);
+		finset.setAxialOffset(-0.03);
+		finset.setBaseRotation(Math.PI / 2);
+		tube3.addChild(finset);
+		
+		finset.setCantAngle(0 * Math.PI / 180);
+		//System.err.println("Fin cant angle: " + (finset.getCantAngle() * 180 / Math.PI));
+		
+		// Stage construction
+		rocket.addChild(stage);
+		rocket.setPerfectFinish(false);
+		
+		FlightConfiguration config = rocket.getSelectedConfiguration();
+//		FlightConfigurationID fcid = config.getFlightConfigurationID();
+
+		//		Motor m = Application.getMotorSetDatabase().findMotors(null, null, "L540", Double.NaN, Double.NaN).get(0);
+		//		tube3.setMotor(id, m);
+		//		tube3.setMotorOverhang(0.02);
+		
+		//		tube3.setIgnitionEvent(MotorMount.IgnitionEvent.NEVER);
+		
+		config.setAllStages();
+		rocket.enableEvents();
+		return rocket;
+	}
+	
+	public final static String FALCON_9H_FCID_1="test_config #1: [ M1350, G77]";
+	public final static int FALCON_9H_PAYLOAD_STAGE_NUMBER=0;
+	public final static int FALCON_9H_CORE_STAGE_NUMBER=1;
+	public final static int FALCON_9H_BOOSTER_STAGE_NUMBER=2;
+	
+	
+	
+	// This function is used for unit, integration tests, DO NOT CHANGE (without updating tests).
+	// Comments starting with cp: are center of pressure calculations
+	// for components of the rocket.  Note that a cp: without a weight
+	// has a weight of 0 (see for example body tubes) -- included for
+	// completeness.
+	// Instanced components (ie components on the side boosters) have
+	// a cp: for each instance.
+	// The unit tests change the number of fins on the side boosters;
+	// cp: comments are shown for 1-fin, 2-fin, and 3-fin cases
+	public static Rocket makeFalcon9Heavy() {
+		Rocket rocket = new Rocket();
+		rocket.setName("Falcon9H Scale Rocket");
+
+		FlightConfigurationId selFCID = rocket.createFlightConfiguration( new FlightConfigurationId( FALCON_9H_FCID_1 ));
+        rocket.setSelectedConfiguration(selFCID);
+
+		// ====== Payload Stage ======
+		// ====== ====== ====== ======
+		AxialStage payloadStage = new AxialStage();
+		payloadStage.setName("Payload Fairing Stage");
+		rocket.addChild(payloadStage);
+
+		{
+			NoseCone payloadFairingNoseCone = new NoseCone(Transition.Shape.POWER, 0.118, 0.052);
+			payloadFairingNoseCone.setName("PL Fairing Nose");
+			payloadFairingNoseCone.setThickness(0.001);
+			payloadFairingNoseCone.setShapeParameter(0.5);
+			//payloadFairingNoseCone.setLength(0.118);
+			//payloadFairingNoseCone.setAftRadius(0.052);
+			payloadFairingNoseCone.setAftShoulderRadius( 0.051 );
+	        payloadFairingNoseCone.setAftShoulderLength( 0.02 );
+	        payloadFairingNoseCone.setAftShoulderThickness( 0.001 );
+	        payloadFairingNoseCone.setAftShoulderCapped( false );
+	        payloadStage.addChild(payloadFairingNoseCone);
+			// cp:(0.05900,0.00000,0.00000,w=2.00000)
+			
+			BodyTube payloadBody = new BodyTube(0.132, 0.052, 0.001);
+			payloadBody.setName("PL Fairing Body");
+			payloadStage.addChild(payloadBody);
+			// cp:(0.18400,0.00000,0.00000)
+			
+			Transition payloadFairingTail = new Transition();
+			payloadFairingTail.setName("PL Fairing Transition");
+			payloadFairingTail.setLength(0.014);
+			payloadFairingTail.setThickness(0.002);
+			payloadFairingTail.setForeRadiusAutomatic(true);
+			payloadFairingTail.setAftRadiusAutomatic(true);
+			payloadStage.addChild(payloadFairingTail);
+			// cp:(0.25665,0.00000,0.00000,w=-0.90366)
+			
+			BodyTube upperStageBody= new BodyTube(0.18, 0.0385, 0.001);
+			upperStageBody.setName("Upper Stage Body ");
+			payloadStage.addChild( upperStageBody);
+			// cp:(0.35400,0.00000,0.00000)
+			
+			{
+				// Parachute
+				Parachute upperChute= new Parachute();
+				upperChute.setName("Parachute");
+				upperChute.setAxialMethod(AxialMethod.MIDDLE);
+				upperChute.setAxialOffset(0.0);
+				upperChute.setDiameter(0.3);
+				upperChute.setLineCount(6);
+				upperChute.setLineLength(0.3);
+				upperStageBody.addChild( upperChute);
+				
+				// Cord
+				ShockCord cord = new ShockCord();
+				cord.setName("Shock Cord");
+				cord.setAxialMethod(AxialMethod.BOTTOM);
+				cord.setAxialOffset(0.0);
+				cord.setCordLength(0.4);
+		    	upperStageBody.addChild( cord);
+			}
+			
+			BodyTube interstage= new BodyTube(0.12, 0.0385, 0.001);
+			interstage.setName("Interstage");
+			payloadStage.addChild( interstage);
+			// cp:(0.50400,0.00000,0.00000)
+		}
+
+		// ====== Core Stage ====== 
+		// ====== ====== ====== ======
+		AxialStage coreStage = new AxialStage();
+		coreStage.setName("Core Stage");
+		rocket.addChild(coreStage);
+
+		{
+			BodyTube coreBody = new BodyTube(0.8, 0.0385, 0.001);
+			// 74 mm inner dia
+			coreBody.setName("Core Stage Body");
+			coreBody.setMotorMount(true);
+			coreStage.addChild( coreBody);
+			// cp:(0.96400,0.00000,0.00000)
+			{
+				MotorConfiguration coreMotorConfig = new MotorConfiguration(coreBody, selFCID);
+				Motor mtr = TestRockets.generateMotor_M1350_75mm();
+				coreMotorConfig.setMotor( mtr);
+				coreBody.setMotorMount( true);
+				FlightConfigurationId motorConfigId = selFCID;
+				coreBody.setMotorConfig( coreMotorConfig, motorConfigId);	 
+			
+				// ====== Booster Stage Set ======
+				// ====== ====== ====== ======
+				ParallelStage boosterStage = new ParallelStage();
+				boosterStage.setName("Booster Stage");
+				coreBody.addChild( boosterStage);
+				boosterStage.setAxialMethod(AxialMethod.BOTTOM);
+				boosterStage.setAxialOffset(0.0);
+				boosterStage.setInstanceCount(2);
+				boosterStage.setRadius( RadiusMethod.SURFACE, 0.0 );
+				boosterStage.setAngleMethod( AngleMethod.RELATIVE );
+				
+				{
+					NoseCone boosterCone = new NoseCone(Transition.Shape.POWER, 0.08, 0.0385);
+					boosterCone.setShapeParameter(0.5);
+					boosterCone.setName("Booster Nose");
+					boosterCone.setThickness(0.002);
+					//payloadFairingNoseCone.setLength(0.118);
+					//payloadFairingNoseCone.setAftRadius(0.052);
+					boosterCone.setAftShoulderRadius( 0.051 );
+					boosterCone.setAftShoulderLength( 0.02 );
+					boosterCone.setAftShoulderThickness( 0.001 );
+					boosterCone.setAftShoulderCapped( false );
+					boosterStage.addChild( boosterCone);
+					// cp:(0.52400,0.07700,0.00000,w=1.09634)
+					// cp:(0.52400,-0.07700,0.00000,w=1.09634)
+					
+					BodyTube boosterBody = new BodyTube(0.8, 0.0385, 0.001);
+					boosterBody.setName("Booster Body");
+					boosterBody.setOuterRadiusAutomatic(true);
+					boosterStage.addChild( boosterBody);
+					// cp:(0.96400,0.07700,0.00000)
+					// cp:(0.96400,-0.07700,0.00000)
+					{
+						InnerTube boosterMotorTubes = new InnerTube();
+						boosterMotorTubes.setName("Booster Motor Tubes");
+						boosterMotorTubes.setLength(0.15);
+						boosterMotorTubes.setOuterRadius(0.015); // => 29mm motors
+						boosterMotorTubes.setThickness(0.0005);
+						boosterMotorTubes.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[5]); // 4-ring
+						//boosterMotorTubes.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[13]); // 9-star
+						boosterMotorTubes.setClusterScale(1.0);
+						boosterBody.addChild( boosterMotorTubes);
+						
+						MotorConfiguration boosterMotorConfig = new MotorConfiguration( boosterMotorTubes, selFCID);
+						Motor boosterMotor = TestRockets.generateMotor_G77_29mm();
+						boosterMotorConfig.setMotor( boosterMotor );
+						boosterMotorTubes.setMotorConfig( boosterMotorConfig, motorConfigId);
+						boosterMotorTubes.setMotorOverhang(0.01234);
+						
+						TrapezoidFinSet boosterFins = new TrapezoidFinSet();
+						boosterBody.addChild(boosterFins);
+						boosterFins.setName("Booster Fins");
+						boosterFins.setFinCount(3);
+						boosterFins.setBaseRotation( Math.PI / 4);
+						boosterFins.setThickness(0.003);
+						boosterFins.setCrossSection(CrossSection.ROUNDED);
+						boosterFins.setRootChord(0.32);
+						boosterFins.setTipChord(0.12);
+						boosterFins.setHeight(0.12);
+						boosterFins.setSweep(0.18);
+						boosterFins.setAxialMethod(AxialMethod.BOTTOM);
+						boosterFins.setAxialOffset(0.0);
+						// cp:(1.17873,0.10422,0.02722,w=6.07405) (1 fin case)
+						// cp:(1.17873,-0.10422,-0.02722,w=6.07405) (1 fin case)
+						// cp:(1.17873,0.10422,0.02722,w=12.14810) (2 fin case)
+						// cp:(1.17873,-0.10422,-0.02722,w=12.14810) (2 fin case)
+						// cp:(1.17873,0.00000,0.00000,w=9.11107) (3 fin case)
+						// cp:(1.17873,0.00000,0.00000,w=9.11107) (3 fin case)
+					}
+				}
+				
+			}
+		}
+		
+		rocket.enableEvents();
+		rocket.setSelectedConfiguration( selFCID);
+		rocket.getFlightConfiguration( selFCID).setAllStages();
+		
+		return rocket;
+	}
+
+	// This is a simple four-fin rocket with large endplates on the
+	// fins, for testing CG and CP calculations with fins on pods.
+	// not a complete rocket (no motor mount nor recovery system)
+
+	// it's parameterized to make things easy to change, but be sure
+	// to adjust the unit test to match!
+	public static Rocket makeEndPlateRocket() {
+		
+		// rocket design parameters
+		double radius = 0.01; // note this is diameter/2!
+		int finCount = 4;     // also determines pod count
+		
+		// nose cone
+		double noseThick = 0.002;
+		double noseLength = 0.05;
+		
+		// body tube
+		double bodyWallThick = 0.002;
+		double bodyLength = 0.254;
+
+		// main body tube fins
+		int bodyFinCount = 4;
+		double bodyFinRootChord = 0.05;
+		double bodyFinTipChord = bodyFinRootChord;
+		double bodyFinHeight = 0.025;
+		double bodyFinSweep = 0.0;
+		AxialMethod bodyFinAxialMethod = AxialMethod.BOTTOM;
+		double bodyFinAxialOffset = 0.0;
+		double bodyFinThickness = 0.003;
+				
+		// pods for end plates
+		int podSetCount = bodyFinCount;
+		double podSetOffset = bodyFinHeight;
+		AxialMethod podSetAxialMethod = bodyFinAxialMethod;
+		double podSetAxialOffset = 0.0;
+
+		// "phantom" tube on pods to give us somewhere to connect end
+		// plates
+		double phantomLength = bodyFinTipChord;
+		double phantomRadius = 0;
+		double phantomWallThickness = 0;
+
+		// end plates
+		int endPlateCount = 2;
+		double endPlateRootChord = bodyFinTipChord;
+		double endPlateTipChord = endPlateRootChord;
+		double endPlateSweep = 0.0;
+		double endPlateThickness = bodyFinThickness;
+		double endPlateHeight = bodyFinHeight;
+		double endPlateRotation = Math.PI/2.0;
+		AxialMethod endPlateAxialMethod = AxialMethod.BOTTOM;
+		double endPlateAxialOffset = 0;
+	
+		// create bare rocket
+		Rocket rocket = new Rocket();
+		rocket.enableEvents();
+		rocket.setName("End Plate Test");
+
+		// rocket has one stage
+		AxialStage sustainer = new AxialStage();
+		rocket.addChild(sustainer);
+		sustainer.setName("Sustainer");
+		
+		// nose cone
+		NoseCone noseCone = new NoseCone(Transition.Shape.OGIVE, noseLength, radius);
+		sustainer.addChild(noseCone);
+		noseCone.setName("Nose Cone");
+		// cp:(0.02303,0.00000,0.00000,w=2.00000)
+
+		// body tube
+		BodyTube bodyTube = new BodyTube(bodyLength, radius, bodyWallThick);
+		sustainer.addChild(bodyTube);
+		bodyTube.setName("Body tube");
+		// cp:(0.17700,0.00000,0.00000)
+		
+		// Trapezoidal fin set on body tube
+		TrapezoidFinSet bodyFinSet = new TrapezoidFinSet(bodyFinCount, bodyFinRootChord, bodyFinTipChord, bodyFinSweep, bodyFinHeight);
+		bodyTube.addChild(bodyFinSet);
+		bodyFinSet.setName("Body Tube FinSet");
+		bodyFinSet.setAxialMethod(bodyFinAxialMethod);
+		bodyFinSet.setAxialOffset(bodyFinAxialOffset);
+		bodyFinSet.setThickness(bodyFinThickness);
+		// cp:(0.26650,0.00000,0.00000,w=15.24857)
+
+		// Pod set to put an end plate on each fin
+		PodSet podSet = new PodSet();
+		bodyTube.addChild(podSet);
+		podSet.setName("Pod Set");
+		podSet.setInstanceCount(podSetCount);
+		podSet.setRadiusOffset(podSetOffset);
+		podSet.setAxialMethod(podSetAxialMethod);
+		podSet.setAxialOffset(podSetAxialOffset);
+
+		// 0-diameter "body tube" to give us something to hook the
+		// endplates to.  Note that this causes a "thick fins"
+		// warning.
+		BodyTube phantom = new BodyTube(phantomLength, phantomRadius, phantomWallThickness);
+		podSet.addChild(phantom);
+		phantom.setName("Phantom");
+		// cp:(0.25400,0.03540,0.00000)
+		// cp:(0.25400,0.00000,0.03540)
+		// cp:(0.25400,-0.03540,0.00000)
+		// cp:(0.25400,-0.00000,-0.03540)
+
+		// end plates
+		TrapezoidFinSet endPlate = new TrapezoidFinSet(endPlateCount, endPlateRootChord, endPlateTipChord, endPlateSweep, endPlateHeight);
+		phantom.addChild(endPlate);
+		endPlate.setName("End plates");
+		endPlate.setBaseRotation(endPlateRotation);
+		endPlate.setAxialMethod(endPlateAxialMethod);
+		endPlate.setAxialOffset(endPlateAxialOffset);
+		endPlate.setThickness(endPlateThickness);
+		// cp:(0.26650,0.03540,0.00000,w=0.00000)
+		// cp:(0.26650,0.00000,0.03540,w=11.86000)
+		// cp:(0.26650,-0.03540,0.00000,w=0.00000)
+		// cp:(0.26650,-0.00000,-0.03540,w=11.86000)
+		
+		// Total cp:(0.25461,-0.00000,0.00000,w=40.96857)
+
+		return rocket;
+	}
+	
+	/*
+	 * Create a new file version 1.00 rocket
+	 */
+	public static OpenRocketDocument makeTestRocket_v100() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v100");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		stage.addChild(bodyTube);
+		
+		rocket.addChild(stage);
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.01 rocket with finTabs
+	 */
+	public static OpenRocketDocument makeTestRocket_v101_withFinTabs() {
+		
+		Rocket rocket = new Rocket();
+		rocket.setName("v101_withFinTabs");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		stage.addChild(bodyTube);
+		
+		// make fins with fin tabs and add to body tube
+		TrapezoidFinSet fins = new TrapezoidFinSet();
+		fins.setFinCount(3);
+		fins.setFinShape(1.0, 1.0, 0.0, 1.0, .005);
+		fins.setTabHeight(0.25);
+		fins.setTabLength(0.25, true);
+		bodyTube.addChild(fins);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.01 rocket with tube coupler child
+	 */
+	public static OpenRocketDocument makeTestRocket_v101_withTubeCouplerChild() {
+		
+		Rocket rocket = new Rocket();
+		rocket.setName("v101_withTubeCouplerChild");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		stage.addChild(bodyTube);
+		
+		// make tube coupler with centering ring, add to stage
+		TubeCoupler tubeCoupler = new TubeCoupler();
+		CenteringRing centeringRing = new CenteringRing();
+		tubeCoupler.addChild(centeringRing);
+		bodyTube.addChild(tubeCoupler);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.04 rocket with motor in flight config
+	 */
+	public static OpenRocketDocument makeTestRocket_v104_withMotor() {
+		
+		Rocket rocket = new Rocket();
+		rocket.setName("v104_withMotorConfig");
+		FlightConfiguration config = rocket.getSelectedConfiguration();
+		FlightConfigurationId fcid = config.getFlightConfigurationID();
+		config.setName("F12X");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		stage.addChild(bodyTube);
+		
+		// make inner tube with motor mount flag set
+		InnerTube innerTube = new InnerTube();
+		bodyTube.addChild(innerTube);
+		
+		// create motor config and add a motor to it
+		ThrustCurveMotor motor = getTestMotor();
+		MotorConfiguration motorConfig = new MotorConfiguration(innerTube, fcid);
+		motorConfig.setMotor(motor);
+		motorConfig.setEjectionDelay(5);
+		
+		// add motor config to inner tube (motor mount)
+		innerTube.setMotorConfig( motorConfig, fcid);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.04 rocket with simulation data
+	 */
+	public static OpenRocketDocument makeTestRocket_v104_withSimulationData() {
+		
+		Rocket rocket = new Rocket();
+		rocket.setName("v104_withSimulationData");
+		FlightConfiguration config = rocket.getSelectedConfiguration();
+		FlightConfigurationId fcid = config.getFlightConfigurationID();
+		config.setName("F12X");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		stage.addChild(bodyTube);
+		
+		// make inner tube with motor mount flag set
+		InnerTube innerTube = new InnerTube();
+		bodyTube.addChild(innerTube);
+		
+		// create motor config and add a motor to it
+		ThrustCurveMotor motor = getTestMotor();
+		MotorConfiguration motorConfig = new MotorConfiguration(innerTube, fcid);
+		motorConfig.setMotor(motor);
+		motorConfig.setEjectionDelay(5);
+		
+		// add motor config to inner tube (motor mount)
+		innerTube.setMotorConfig(motorConfig, fcid);
+				
+		OpenRocketDocument rocketDoc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+		
+		// create simulation data
+		Simulation simulation1 = new Simulation(rocket);
+		simulation1.setFlightConfigurationId(fcid);
+		
+		rocketDoc.addSimulation(simulation1);
+		Simulation simulation2 = new Simulation(rocket);
+		rocketDoc.addSimulation(simulation2);
+		
+		rocket.enableEvents();
+		return rocketDoc;
+	}
+	
+	/*
+	 * Create a new file version 1.05 rocket with custom expression 
+	 */
+	public static OpenRocketDocument makeTestRocket_v105_withCustomExpression() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v105_withCustomExpression");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube();
+		stage.addChild(bodyTube);
+		
+		OpenRocketDocument rocketDoc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+		
+		CustomExpression expression = new CustomExpression(rocketDoc, "name", "symbol", "unit", "expression");
+		rocketDoc.addCustomExpression(expression);
+		
+		rocket.enableEvents();
+		return rocketDoc;
+	}
+	
+	/*
+	 * Create a new file version 1.05 rocket with component preset
+	 */
+	public static OpenRocketDocument makeTestRocket_v105_withComponentPreset() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v105_withComponentPreset");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube();
+		
+		TypedPropertyMap presetspec = new TypedPropertyMap();
+		presetspec.put(ComponentPreset.TYPE, ComponentPreset.Type.BODY_TUBE);
+		presetspec.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer("manufacturer"));
+		presetspec.put(ComponentPreset.PARTNO, "partno");
+		presetspec.put(ComponentPreset.LENGTH, 2.0);
+		presetspec.put(ComponentPreset.OUTER_DIAMETER, 2.0);
+		presetspec.put(ComponentPreset.INNER_DIAMETER, 1.0);
+		presetspec.put(ComponentPreset.MASS, 100.0);
+		ComponentPreset preset;
+		try {
+			preset = ComponentPresetFactory.create(presetspec);
+			bodyTube.loadPreset(preset);
+			stage.addChild(bodyTube);
+		} catch (InvalidComponentPresetException e) {
+			// should never happen
+			e.printStackTrace();
+		}
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.05 rocket with lower stage recovery device
+	 */
+	public static OpenRocketDocument makeTestRocket_v105_withLowerStageRecoveryDevice() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v105_withLowerStageRecoveryDevice");
+		
+		// make 1st stage
+		AxialStage stage1 = new AxialStage();
+		stage1.setName("Stage1");
+		rocket.addChild(stage1);
+		
+		// make 1st stage body tube
+		BodyTube bodyTube1 = new BodyTube(5, 1, 0.05);
+		stage1.addChild(bodyTube1);
+		
+		// make 1st stage recovery device with deployment config in default
+		RecoveryDevice parachute = new Parachute();
+		DeploymentConfiguration deploymentConfig = new DeploymentConfiguration();
+		deploymentConfig.setDeployEvent(DeployEvent.LOWER_STAGE_SEPARATION);
+		parachute.getDeploymentConfigurations().setDefault(deploymentConfig);
+		bodyTube1.addChild(parachute);
+		
+		// make 2nd stage
+		AxialStage stage2 = new AxialStage();
+		stage2.setName("Stage2");
+		rocket.addChild(stage2);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.06 rocket with appearance
+	 */
+	public static OpenRocketDocument makeTestRocket_v106_withAppearance() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v106_withAppearance");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube with an appearance setting
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		Appearance appearance = new Appearance(new Color(100, 25, 50), 1, null);
+		bodyTube.setAppearance(appearance);
+		stage.addChild(bodyTube);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.06 rocket with flight configuration with motor mount ignition configuration
+	 */
+	public static OpenRocketDocument makeTestRocket_v106_withMotorMountIgnitionConfig() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v106_withwithMotorMountIgnitionConfig");
+		FlightConfigurationId fcid = new FlightConfigurationId();
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		stage.addChild(bodyTube);
+		
+		// make inner tube with motor mount flag set
+		InnerTube innerTube = new InnerTube();
+		bodyTube.addChild(innerTube);
+		
+		// make inner tube with motor mount flag set
+		MotorConfiguration motorConfig = new MotorConfiguration(innerTube, fcid);
+		Motor mtr = getTestMotor();
+		motorConfig.setMotor( mtr);
+		innerTube.setMotorConfig(motorConfig,fcid);
+		
+		// set ignition parameters for motor mount
+		// inst.setIgnitionEvent( IgnitionEvent.AUTOMATIC);
+		motorConfig.setIgnitionDelay(2);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.06 rocket with flight configuration with recovery device deployment configuration non-default
+	 */
+	public static OpenRocketDocument makeTestRocket_v106_withRecoveryDeviceDeploymentConfig() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v106_withRecoveryDeviceDeploymentConfig");
+		FlightConfigurationId testFCID = new FlightConfigurationId("testParachute");
+		
+		// make stage
+		AxialStage stage = new AxialStage();
+		stage.setName("Stage1");
+		rocket.addChild(stage);
+		
+		// make body tube 
+		BodyTube bodyTube = new BodyTube(12, 1, 0.05);
+		stage.addChild(bodyTube);
+		
+		// make recovery device with deployment config
+		RecoveryDevice parachute = new Parachute();
+		DeploymentConfiguration deploymentConfig = new DeploymentConfiguration();
+		deploymentConfig.setDeployAltitude(1000);
+		parachute.getDeploymentConfigurations().set(testFCID, deploymentConfig);
+		bodyTube.addChild(parachute);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	/*
+	 * Create a new file version 1.06 rocket with flight configuration with stage separation configuration
+	 */
+	public static OpenRocketDocument makeTestRocket_v106_withStageSeparationConfig() {
+		Rocket rocket = new Rocket();
+		rocket.setName("v106_withStageSeparationConfig");
+		FlightConfigurationId fcid = new FlightConfigurationId("3SecondDelay");
+		// make 1st stage
+		AxialStage stage1 = new AxialStage();
+		stage1.setName("Stage1");
+		rocket.addChild(stage1);
+		
+		// make 1st stage body tube
+		BodyTube bodyTube1 = new BodyTube(5, 1, 0.05);
+		stage1.addChild(bodyTube1);
+		
+		// make1st stage  recovery device 
+		RecoveryDevice parachute = new Parachute();
+		bodyTube1.addChild(parachute);
+		
+		// set stage separation configuration
+		StageSeparationConfiguration stageSepConfig = new StageSeparationConfiguration();
+		stageSepConfig.setSeparationDelay(3);
+		stage1.getSeparationConfigurations().set(fcid, stageSepConfig);
+		
+		// make 2nd stage
+		AxialStage stage2 = new AxialStage();
+		stage2.setName("Stage2");
+		rocket.addChild(stage2);
+		
+		// make 2st stage body tube
+		BodyTube bodyTube2 = new BodyTube(12, 1, 0.05);
+		stage2.addChild(bodyTube2);
+		
+		rocket.enableEvents();
+		return OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+	}
+	
+	
+	public static OpenRocketDocument makeTestRocket_v107_withSimulationExtension(String script) {
+		Rocket rocket = makeEstesAlphaIII();
+		OpenRocketDocument document = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+		Simulation sim = new Simulation(rocket);
+		ScriptingExtension ext = new ScriptingExtension();
+		ext.setEnabled(true);
+		ext.setLanguage("JavaScript");
+		ext.setScript(script);
+		sim.getSimulationExtensions().add(ext);
+		document.addSimulation(sim);
+		
+		rocket.enableEvents();
+		return document;
+	}
+	
+	public static OpenRocketDocument makeTestRocket_v108_withBoosters() {
+		Rocket rocket = makeFalcon9Heavy();
+		OpenRocketDocument document = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+			
+		return document;
+	}
+	
+	/*
+	 * Create a new test rocket for testing OpenRocketSaver.estimateFileSize()
+	 */
+	public static OpenRocketDocument makeTestRocket_for_estimateFileSize() {
+		Rocket rocket = new Rocket();
+		rocket.setName("for_estimateFileSize");
+		
+		// make 1st stage
+		AxialStage stage1 = new AxialStage();
+		stage1.setName("Stage1");
+		rocket.addChild(stage1);
+		
+		// make 1st stage body tube
+		BodyTube bodyTube1 = new BodyTube(5, 1, 0.05);
+		stage1.addChild(bodyTube1);
+		
+		TrapezoidFinSet fins1 = new TrapezoidFinSet();
+		fins1.setFinCount(3);
+		fins1.setFinShape(1.5, 1.5, 0.0, 1.5, .005);
+		bodyTube1.addChild(fins1);
+		
+		// make 1st stage recovery device with deployment config in default
+		RecoveryDevice parachute = new Parachute();
+		DeploymentConfiguration deploymentConfig = new DeploymentConfiguration();
+		deploymentConfig.setDeployEvent(DeployEvent.LOWER_STAGE_SEPARATION);
+		deploymentConfig.setDeployEvent(DeployEvent.ALTITUDE);
+		parachute.getDeploymentConfigurations().setDefault(deploymentConfig);
+		bodyTube1.addChild(parachute);
+		
+		// make 2nd stage
+		AxialStage stage2 = new AxialStage();
+		stage2.setName("Stage2");
+		rocket.addChild(stage2);
+		
+		// make 2nd stage nose cone
+		NoseCone noseCone = new NoseCone(Transition.Shape.OGIVE, 6 * 0.5, 0.5);
+		stage2.addChild(noseCone);
+		
+		// make 2nd stage body tube
+		BodyTube bodyTube2 = new BodyTube(15, 1, 0.05);
+		stage2.addChild(bodyTube2);
+		
+		// make 2nd stage fins
+		TrapezoidFinSet fins2 = new TrapezoidFinSet();
+		fins2.setFinCount(3);
+		fins2.setFinShape(1.0, 1.0, 0.0, 1.0, .005);
+		bodyTube2.addChild(fins2);
+		
+		OpenRocketDocument rocketDoc = OpenRocketDocumentFactory.createDocumentFromRocket(rocket);
+		
+		// create simulation data
+		Simulation simulation1 = new Simulation(rocket);
+		simulation1.getOptions().setISAAtmosphere(false); // helps cover code in saveComponent()
+		simulation1.getOptions().setTimeStep(0.05);
+		rocketDoc.addSimulation(simulation1);
+		
+		Simulation simulation2 = new Simulation(rocket);
+		simulation2.getOptions().setISAAtmosphere(true); // helps cover code in saveComponent()
+		simulation2.getOptions().setTimeStep(0.05);
+		rocketDoc.addSimulation(simulation2);
+		
+		SimulationListener simulationListener = new AbstractSimulationListener();
+		try {
+			simulation1.simulate(simulationListener);
+			simulation2.simulate(simulationListener);
+		} catch (SimulationException e) {
+			// do nothing, we don't care
+		}
+		
+		rocket.enableEvents();
+		return rocketDoc;
+	}
+	
+}