64b15a6cb0643f00d8baade2a59fc526644a18c7
[jalview.git] / test / jalview / viewmodel / styles / ViewStyleTest.java
1 package jalview.viewmodel.styles;
2
3 import static org.testng.AssertJUnit.assertEquals;
4 import static org.testng.AssertJUnit.assertFalse;
5 import static org.testng.AssertJUnit.assertTrue;
6
7 import java.awt.Color;
8 import java.lang.reflect.Field;
9 import java.util.Random;
10
11 import org.testng.AssertJUnit;
12 import org.testng.annotations.Test;
13
14
15 public class ViewStyleTest
16 {
17
18   Random r = new Random();
19
20   /**
21    * This test uses reflection to set all fields on a ViewStyle, make a copy of
22    * it, and verify all fields match. This test should fail if a getter/setter
23    * pair are added to the class but missing in the copy constructor. Using
24    * reflection in the copy constructor itself is broken by obfuscation when the
25    * applet is built.
26    * 
27    * To prove this test works, simply comment out a line in the ViewStyle copy
28    * constructor, or add a new member field to ViewStyle.
29    * 
30    * @throws IllegalAccessException
31    * @throws IllegalArgumentException
32    */
33   @Test
34   public void testCopyConstructor() throws IllegalArgumentException,
35           IllegalAccessException
36   {
37     ViewStyle vs1 = new ViewStyle();
38     Field[] fields = ViewStyle.class.getDeclaredFields();
39     for (Field field : fields)
40     {
41       field.setAccessible(true);
42       if (!copyConstructorIgnores(field.getName()))
43       {
44         changeValue(vs1, field);
45       }
46     }
47
48     ViewStyle vs2 = new ViewStyle(vs1);
49
50     for (Field field1 : fields) {
51       final Object value1 = field1.get(vs1);
52       final Object value2 = field1.get(vs2);
53       String msg = "Mismatch in " + field1.getName() + "(" + value1 + "/"
54               + value2 + ") - not set in copy constructor?";
55       assertEquals(msg, value1, value2);
56     }
57     assertEquals("Hashcode not equals", vs1.hashCode(), vs2.hashCode());
58   }
59
60   /**
61    * Add any field names in here that we expect to be ignored by the copy
62    * constructor
63    * 
64    * @param name
65    * @return
66    */
67   private boolean copyConstructorIgnores(String name)
68   {
69     /*
70      * currently none!
71      */
72     return false;
73   }
74
75   /**
76    * Change the value of one field in a ViewStyle object
77    * 
78    * @param vs
79    * @param field
80    * @throws IllegalAccessException
81    */
82   protected void changeValue(ViewStyle vs, Field field)
83           throws IllegalAccessException
84   {
85     Class<?> type = field.getType();
86
87     if (type.equals(boolean.class) || type.equals(Boolean.class))
88     {
89       boolean value = (Boolean) field.get(vs);
90       // System.out.println("Setting " + field.getName() + " to " + !value);
91       field.set(vs, !value);
92     }
93     else if (type.equals(short.class) || type.equals(int.class)
94             || type.equals(long.class) || type.equals(float.class)
95             || type.equals(double.class))
96     {
97       final int value = (int) (1 + field.getDouble(vs));
98       // System.out.println("Setting " + field.getName() + " to " + value);
99       field.set(vs, value);
100     }
101     else if (type.equals(Integer.class))
102     {
103       field.set(vs, (int) (1 + getNumberValue(field, vs)));
104     }
105     else if (type.equals(Float.class))
106     {
107       field.set(vs, (float) (1f + getNumberValue(field, vs)));
108     }
109     else if (type.equals(Long.class))
110     {
111       field.set(vs, (long) (1L + getNumberValue(field, vs)));
112     }
113     else if (type.equals(Double.class))
114     {
115       field.set(vs, 1d + getNumberValue(field, vs));
116     }
117     else if (type.equals(Short.class))
118     {
119       field.set(vs, (short) (1 + getNumberValue(field, vs)));
120     }
121     else if (type.equals(Byte.class))
122     {
123       field.set(vs, (byte) (1 + getNumberValue(field, vs)));
124     }
125     else if (type.equals(Character.class))
126     {
127       field.set(vs, (char) (1 + getNumberValue(field, vs)));
128     }
129     else if (type.equals(String.class))
130     {
131       field.set(vs, "Joe" + field.get(vs));
132     }
133     else if (type.equals(Color.class))
134     {
135       field.set(vs, Color.RED.equals(field.get(vs)) ? Color.BLACK
136               : Color.RED);
137     }
138     else
139     {
140       AssertJUnit.fail("Unhandled field type (add to test): " + field.getName()
141               + ":" + type);
142     }
143   }
144
145   private double getNumberValue(Field field, ViewStyle vs)
146           throws IllegalArgumentException, IllegalAccessException
147   {
148     if (field.get(vs) == null)
149     {
150       return 0d;
151     }
152     return ((Number) field.get(vs)).doubleValue();
153   }
154
155   /**
156    * Test that the equals method compares every field by changing them one by
157    * one in a cloned ViewStyle.
158    * 
159    * This test will fail if a new field is added to ViewStyle but not to the
160    * comparisons in ViewStyle.equals().
161    * 
162    * To confirm that this test works, temporarily comment out one of the field
163    * comparisons in ViewStyle.equals()
164    * 
165    * @throws IllegalAccessException
166    * @throws IllegalArgumentException
167    */
168   @Test
169   public void testEquals() throws IllegalArgumentException,
170           IllegalAccessException
171   {
172     ViewStyle vs1 = new ViewStyle();
173     ViewStyle vs2 = new ViewStyle(vs1);
174
175     assertFalse(vs1.equals(null));
176     assertFalse(vs1.equals(this));
177     assertTrue(vs1.equals(vs2));
178     assertTrue(vs2.equals(vs1));
179
180     Field[] fields = ViewStyle.class.getDeclaredFields();
181     for (Field field : fields)
182     {
183       field.setAccessible(true);
184       Object oldValue = field.get(vs2);
185       changeValue(vs2, field);
186       assertFalse("equals method ignores " + field.getName(),
187               vs1.equals(vs2));
188
189       if (vs1.hashCode() == vs2.hashCode())
190       {
191         // uncomment next line to see which fields hashCode ignores
192         // System.out.println("hashCode ignores " + field.getName());
193       }
194       // restore original value before testing the next field
195       field.set(vs2, oldValue);
196     }
197   }
198 }