JAL-3746 apply copyright to tests
[jalview.git] / test / jalview / datamodel / ConcurrentModificationTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ 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.datamodel;
22
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertNotSame;
25 import static org.testng.Assert.fail;
26
27 import java.util.ArrayList;
28 import java.util.ConcurrentModificationException;
29 import java.util.List;
30
31 import org.testng.annotations.BeforeMethod;
32 import org.testng.annotations.Test;
33
34 /**
35  * Not a test of code specific to Jalview, but some tests to verify Java
36  * behaviour under certain scenarios of concurrent modification of iterated
37  * lists or arrays
38  */
39 public class ConcurrentModificationTest
40 {
41   static int MAX = 10;
42
43   int[] intArray;
44
45   List<Integer> intList;
46
47   /**
48    * Setup: populate array and list with values 0,...,9
49    */
50   @BeforeMethod()
51   public void setUp()
52   {
53     intArray = new int[MAX];
54     intList = new ArrayList<Integer>();
55     for (int i = 0; i < MAX; i++)
56     {
57       intArray[i] = i;
58       intList.add(i);
59     }
60   }
61
62   /**
63    * Sanity check of values if no 'interference'
64    */
65   @Test
66   public void test_nullCase()
67   {
68     /*
69      * array iteration
70      */
71     int j = 0;
72     for (int i : intArray)
73     {
74       assertEquals(i, j);
75       j++;
76     }
77
78     /*
79      * list iteration
80      */
81     j = 0;
82     for (int i : intList)
83     {
84       assertEquals(i, j);
85       j++;
86     }
87   }
88
89   /**
90    * Test for the case where the array is reallocated and enlarged during the
91    * iteration. The for loop iteration is not affected.
92    */
93   @Test
94   public void testEnhancedForLoop_arrayExtended()
95   {
96     int j = 0;
97     for (int i : intArray)
98     {
99       if (j == 5)
100       {
101         intArray = new int[MAX + 1];
102       }
103       assertEquals(i, j);
104       j++;
105     }
106     assertEquals(j, MAX);
107   }
108
109   /**
110    * Test for the case where the array is nulled during the iteration. The for
111    * loop iteration is not affected.
112    */
113   @Test
114   public void testEnhancedForLoop_arrayNulled()
115   {
116     int j = 0;
117     for (int i : intArray)
118     {
119       if (j == 5)
120       {
121         intArray = null;
122       }
123       assertEquals(i, j);
124       j++;
125     }
126     assertEquals(j, MAX);
127   }
128
129   /**
130    * Test for the case where a value is changed before the iteration reaches it.
131    * The iteration reads the new value.
132    * <p>
133    * This is analagous to Jalview's consensus thread modifying entries in the
134    * AlignmentAnnotation.annotations array of Annotation[] while it is being
135    * read.
136    */
137   @Test
138   public void testEnhancedForLoop_arrayModified()
139   {
140     int j = 0;
141     for (int i : intArray)
142     {
143       if (j == 5)
144       {
145         intArray[5] = -1;
146         intArray[6] = -2;
147       }
148       /*
149        * the value 'just read' by the for loop is not affected;
150        * the next value read is affected
151        */
152       int expected = j == 6 ? -2 : j;
153       assertEquals(i, expected);
154       j++;
155     }
156     assertEquals(j, MAX);
157   }
158
159   /**
160    * Test for the case where a list entry is added during the iteration.
161    */
162   @Test
163   public void testEnhancedForLoop_listExtended()
164   {
165     int j = 0;
166     try
167     {
168       for (int i : intList)
169       {
170         if (j == 5)
171         {
172           intList.add(MAX + 1);
173         }
174         assertEquals(i, j);
175         j++;
176       }
177     } catch (ConcurrentModificationException e)
178     {
179       /*
180        * exception occurs on next loop iteration after 'concurrent'
181        * modification
182        */
183       assertEquals(j, 6);
184       return;
185     }
186     fail("Expected exception");
187   }
188
189   /**
190    * Test for the case where a list entry is modified during the iteration. No
191    * exception occurs.
192    */
193   @Test
194   public void testEnhancedForLoop_listModified()
195   {
196     int j = 0;
197     for (int i : intList)
198     {
199       if (j == 5)
200       {
201         intList.set(5, -1);
202         intList.set(6, -2);
203       }
204
205       /*
206        * the value 'just read' is not affected, the next value
207        * is read as modified, no exception
208        */
209       int expected = j == 6 ? -2 : j;
210       assertEquals(i, expected);
211       j++;
212     }
213     assertEquals(j, MAX);
214   }
215
216   /**
217    * Test for the case where the list is recreated during the iteration.
218    */
219   @Test
220   public void testEnhancedForLoop_listRenewed()
221   {
222     Object theList = intList;
223     int j = 0;
224     for (int i : intList)
225     {
226       if (j == 5)
227       {
228         /*
229          * recreate a new List object
230          */
231         setUp();
232         assertNotSame(theList, intList);
233       }
234       assertEquals(i, j);
235       j++;
236     }
237
238     /*
239      * no exception in the for loop; changing the object intList refers to
240      * does not affect the loop's iteration over the original object
241      */
242     assertEquals(j, MAX);
243   }
244 }