--- /dev/null
+package net.sf.openrocket.rocketcomponent;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+public class ComponentCompare {
+
+ private static final Pattern GETTER_PATTERN = Pattern.compile("^(is|get)[A-Z].*+");
+
+ private static final String[] IGNORED_METHODS = {
+ "getClass", "getChildCount", "getChildren", "getNextComponent", "getID",
+ "getPreviousComponent", "getParent", "getRocket", "getRoot", "getStage",
+ "getStageNumber", "getComponentName",
+ // Rocket specific methods:
+ "getModID", "getMassModID", "getAerodynamicModID", "getTreeModID", "getFunctionalModID",
+ "getMotorConfigurationIDs", "getDefaultConfiguration"
+ };
+
+
+ /**
+ * Check whether the two components are <em>equal</em>. Two components are considered
+ * equal if they are of the same type and all of their getXXX() and isXXX() methods
+ * return equal values.
+ *
+ * @param c1 the first component to compare.
+ * @param c2 the second component to compare.
+ */
+ public static void assertEquality(RocketComponent c1, RocketComponent c2) {
+ assertEquals(c1.getClass(), c2.getClass());
+
+ // Same class + similar == equal
+ assertSimilarity(c1, c2);
+ }
+
+
+
+ public static void assertDeepEquality(RocketComponent c1, RocketComponent c2) {
+ assertEquality(c1, c2);
+
+ Iterator<RocketComponent> i1 = c1.iterator();
+ Iterator<RocketComponent> i2 = c2.iterator();
+ while (i1.hasNext()) {
+ assertTrue("iterator continues", i2.hasNext());
+ RocketComponent comp1 = i1.next();
+ RocketComponent comp2 = i2.next();
+ assertDeepEquality(comp1, comp2);
+ }
+ assertFalse("iterator end", i2.hasNext());
+ }
+
+
+
+ public static void assertDeepSimilarity(RocketComponent c1, RocketComponent c2,
+ boolean allowNameDifference) {
+ assertSimilarity(c1, c2, allowNameDifference);
+
+ Iterator<RocketComponent> i1 = c1.iterator();
+ Iterator<RocketComponent> i2 = c2.iterator();
+ while (i1.hasNext()) {
+ assertTrue("iterator continues", i2.hasNext());
+ RocketComponent comp1 = i1.next();
+ RocketComponent comp2 = i2.next();
+ assertDeepSimilarity(comp1, comp2, allowNameDifference);
+ }
+ assertFalse("iterator end", i2.hasNext());
+ }
+
+
+
+ /**
+ * Check whether the two components are <em>similar</em>. Two components are similar
+ * if each of the getXXX and isXXX methods that both object types have return
+ * equal values. This does not check whether the two components are of the same type.
+ *
+ * @param c1 the first component.
+ * @param c2 the second component.
+ */
+ public static void assertSimilarity(RocketComponent c1, RocketComponent c2) {
+ assertSimilarity(c1, c2, false);
+ }
+
+ /**
+ * Check whether the two components are <em>similar</em>, allowing a name difference.
+ *
+ * @param c1 the first component.
+ * @param c2 the second component.
+ * @param allowNameDifference whether to allow the components to have different names.
+ */
+ public static void assertSimilarity(RocketComponent c1, RocketComponent c2,
+ boolean allowNameDifference) {
+ Class<? extends RocketComponent> class1 = c1.getClass();
+ Class<? extends RocketComponent> class2 = c2.getClass();
+
+ mainloop:
+ for (Method m1: class1.getMethods()) {
+ // Check for getter method
+ String name = m1.getName();
+ if (!GETTER_PATTERN.matcher(name).matches())
+ continue;
+
+ // Ignore methods that take parameters
+ if (m1.getParameterTypes().length != 0)
+ continue;
+
+ // Ignore specific getters
+ for (String ignore: IGNORED_METHODS) {
+ if (name.equals(ignore))
+ continue mainloop;
+ }
+ if (allowNameDifference && name.equals("getName"))
+ continue;
+
+
+ // Check for method in other class
+ Method m2;
+ try {
+ m2 = class2.getMethod(name);
+ } catch (NoSuchMethodException e) {
+ continue;
+ }
+
+// System.out.println("Testing results of method " + name);
+
+ // Run the methods
+ Object result1, result2;
+ try {
+ result1 = m1.invoke(c1);
+ result2 = m2.invoke(c2);
+ } catch (Exception e) {
+ throw new RuntimeException("Error executing method " + name, e);
+ }
+
+ if (result1 != null && result2 != null &&
+ result1.getClass().isArray() && result2.getClass().isArray()) {
+ assertArrayEquals("Comparing result of method " + name,
+ (Object[])result1, (Object[])result2);
+ } else {
+ assertEquals("Comparing result of method " + name, result1, result2);
+ }
+ }
+ }
+
+}