create changelog entry
[debian/openrocket] / core / test / net / sf / openrocket / rocketcomponent / ComponentCompare.java
1 package net.sf.openrocket.rocketcomponent;
2
3 import static org.junit.Assert.*;
4
5 import java.lang.reflect.Method;
6 import java.util.Iterator;
7 import java.util.regex.Pattern;
8
9 import net.sf.openrocket.util.BugException;
10
11 public class ComponentCompare {
12         
13         private static final Pattern GETTER_PATTERN = Pattern.compile("^(is|get)[A-Z].*+");
14         
15         private static final String[] IGNORED_METHODS = {
16                         "getClass", "getChildCount", "getChildren", "getNextComponent", "getID",
17                         "getPreviousComponent", "getParent", "getRocket", "getRoot", "getStage",
18                         "getStageNumber", "getComponentName",
19                         // Rocket specific methods:
20                         "getModID", "getMassModID", "getAerodynamicModID", "getTreeModID", "getFunctionalModID",
21                         "getMotorConfigurationIDs", "getDefaultConfiguration", "getMotorMounts"
22         };
23         
24         
25         /**
26          * Check whether the two components are <em>equal</em>.  Two components are considered
27          * equal if they are of the same type and all of their getXXX() and isXXX() methods
28          * return equal values.
29          * 
30          * @param c1    the first component to compare.
31          * @param c2    the second component to compare.
32          */
33         public static void assertEquality(RocketComponent c1, RocketComponent c2) {
34                 assertEquals(c1.getClass(), c2.getClass());
35                 
36                 // Same class + similar  ==  equal
37                 assertSimilarity(c1, c2);
38         }
39         
40         
41
42         public static void assertDeepEquality(RocketComponent c1, RocketComponent c2) {
43                 assertEquality(c1, c2);
44                 
45                 Iterator<RocketComponent> i1 = c1.getChildren().iterator();
46                 Iterator<RocketComponent> i2 = c2.getChildren().iterator();
47                 while (i1.hasNext()) {
48                         assertTrue("iterator continues", i2.hasNext());
49                         RocketComponent comp1 = i1.next();
50                         RocketComponent comp2 = i2.next();
51                         assertDeepEquality(comp1, comp2);
52                 }
53                 assertFalse("iterator end", i2.hasNext());
54         }
55         
56         
57
58         public static void assertDeepSimilarity(RocketComponent c1, RocketComponent c2,
59                         boolean allowNameDifference) {
60                 assertSimilarity(c1, c2, allowNameDifference);
61                 
62                 Iterator<RocketComponent> i1 = c1.getChildren().iterator();
63                 Iterator<RocketComponent> i2 = c2.getChildren().iterator();
64                 while (i1.hasNext()) {
65                         assertTrue("iterator continues", i2.hasNext());
66                         RocketComponent comp1 = i1.next();
67                         RocketComponent comp2 = i2.next();
68                         assertDeepSimilarity(comp1, comp2, allowNameDifference);
69                 }
70                 assertFalse("iterator end", i2.hasNext());
71         }
72         
73         
74
75         /**
76          * Check whether the two components are <em>similar</em>.  Two components are similar
77          * if each of the getXXX and isXXX methods that both object types have return
78          * equal values.  This does not check whether the two components are of the same type.
79          * 
80          * @param c1    the first component.
81          * @param c2    the second component.
82          */
83         public static void assertSimilarity(RocketComponent c1, RocketComponent c2) {
84                 assertSimilarity(c1, c2, false);
85         }
86         
87         /**
88          * Check whether the two components are <em>similar</em>, allowing a name difference.
89          * 
90          * @param c1    the first component.
91          * @param c2    the second component.
92          * @param allowNameDifference   whether to allow the components to have different names.
93          */
94         public static void assertSimilarity(RocketComponent c1, RocketComponent c2,
95                         boolean allowNameDifference) {
96                 Class<? extends RocketComponent> class1 = c1.getClass();
97                 Class<? extends RocketComponent> class2 = c2.getClass();
98                 
99                 mainloop: for (Method m1 : class1.getMethods()) {
100                         // Check for getter method
101                         String name = m1.getName();
102                         if (!GETTER_PATTERN.matcher(name).matches())
103                                 continue;
104                         
105                         // Ignore methods that take parameters
106                         if (m1.getParameterTypes().length != 0)
107                                 continue;
108                         
109                         // Ignore specific getters
110                         for (String ignore : IGNORED_METHODS) {
111                                 if (name.equals(ignore))
112                                         continue mainloop;
113                         }
114                         if (allowNameDifference && name.equals("getName"))
115                                 continue;
116                         
117
118                         // Check for method in other class
119                         Method m2;
120                         try {
121                                 m2 = class2.getMethod(name);
122                         } catch (NoSuchMethodException e) {
123                                 continue;
124                         }
125                         
126                         //                      System.out.println("Testing results of method " + name);
127                         
128                         // Run the methods
129                         Object result1, result2;
130                         try {
131                                 result1 = m1.invoke(c1);
132                                 result2 = m2.invoke(c2);
133                         } catch (Exception e) {
134                                 throw new BugException("Error executing method " + name, e);
135                         }
136                         
137                         if (result1 != null && result2 != null &&
138                                         result1.getClass().isArray() && result2.getClass().isArray()) {
139                                 assertArrayEquals("Comparing result of method " + name,
140                                                 (Object[]) result1, (Object[]) result2);
141                         } else {
142                                 assertEquals("Comparing result of method " + name, result1, result2);
143                         }
144                 }
145         }
146         
147 }