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