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