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