updates for 0.9.4
[debian/openrocket] / test / net / sf / openrocket / rocketcomponent / ComponentCompare.java
diff --git a/test/net/sf/openrocket/rocketcomponent/ComponentCompare.java b/test/net/sf/openrocket/rocketcomponent/ComponentCompare.java
new file mode 100644 (file)
index 0000000..a9fb278
--- /dev/null
@@ -0,0 +1,146 @@
+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);
+                       }
+               }
+       }
+
+}