1 /*
2  * Written by Doug Lea with assistance from members of JCP JSR-166
3  * Expert Group and released to the public domain, as explained at
4  * http://creativecommons.org/publicdomain/zero/1.0/
5  * Other contributors include Andrew Wright, Jeffrey Hayes,
6  * Pat Fisher, Mike Judd.
7  */
8 
9 package jsr166;
10 
11 import java.util.Arrays;
12 import java.util.concurrent.atomic.AtomicIntegerArray;
13 
14 import junit.framework.Test;
15 import junit.framework.TestSuite;
16 
17 public class AtomicIntegerArrayTest extends JSR166TestCase {
18 
19     // android-note: Removed because the CTS runner does a bad job of
20     // retrying tests that have suite() declarations.
21     //
22     // public static void main(String[] args) {
23     //     main(suite(), args);
24     // }
25     // public static Test suite() {
26     //     return new TestSuite(AtomicIntegerArrayTest.class);
27     // }
28 
29     /**
30      * constructor creates array of given size with all elements zero
31      */
testConstructor()32     public void testConstructor() {
33         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
34         for (int i = 0; i < SIZE; i++)
35             assertEquals(0, aa.get(i));
36     }
37 
38     /**
39      * constructor with null array throws NPE
40      */
testConstructor2NPE()41     public void testConstructor2NPE() {
42         try {
43             int[] a = null;
44             new AtomicIntegerArray(a);
45             shouldThrow();
46         } catch (NullPointerException success) {}
47     }
48 
49     /**
50      * constructor with array is of same size and has all elements
51      */
testConstructor2()52     public void testConstructor2() {
53         int[] a = { 17, 3, -42, 99, -7 };
54         AtomicIntegerArray aa = new AtomicIntegerArray(a);
55         assertEquals(a.length, aa.length());
56         for (int i = 0; i < a.length; i++)
57             assertEquals(a[i], aa.get(i));
58     }
59 
60     /**
61      * get and set for out of bound indices throw IndexOutOfBoundsException
62      */
testIndexing()63     public void testIndexing() {
64         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
65         for (int index : new int[] { -1, SIZE }) {
66             try {
67                 aa.get(index);
68                 shouldThrow();
69             } catch (IndexOutOfBoundsException success) {}
70             try {
71                 aa.set(index, 1);
72                 shouldThrow();
73             } catch (IndexOutOfBoundsException success) {}
74             try {
75                 aa.lazySet(index, 1);
76                 shouldThrow();
77             } catch (IndexOutOfBoundsException success) {}
78             try {
79                 aa.compareAndSet(index, 1, 2);
80                 shouldThrow();
81             } catch (IndexOutOfBoundsException success) {}
82             try {
83                 aa.weakCompareAndSet(index, 1, 2);
84                 shouldThrow();
85             } catch (IndexOutOfBoundsException success) {}
86             try {
87                 aa.getAndAdd(index, 1);
88                 shouldThrow();
89             } catch (IndexOutOfBoundsException success) {}
90             try {
91                 aa.addAndGet(index, 1);
92                 shouldThrow();
93             } catch (IndexOutOfBoundsException success) {}
94         }
95     }
96 
97     /**
98      * get returns the last value set at index
99      */
testGetSet()100     public void testGetSet() {
101         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
102         for (int i = 0; i < SIZE; i++) {
103             aa.set(i, 1);
104             assertEquals(1, aa.get(i));
105             aa.set(i, 2);
106             assertEquals(2, aa.get(i));
107             aa.set(i, -3);
108             assertEquals(-3, aa.get(i));
109         }
110     }
111 
112     /**
113      * get returns the last value lazySet at index by same thread
114      */
testGetLazySet()115     public void testGetLazySet() {
116         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
117         for (int i = 0; i < SIZE; i++) {
118             aa.lazySet(i, 1);
119             assertEquals(1, aa.get(i));
120             aa.lazySet(i, 2);
121             assertEquals(2, aa.get(i));
122             aa.lazySet(i, -3);
123             assertEquals(-3, aa.get(i));
124         }
125     }
126 
127     /**
128      * compareAndSet succeeds in changing value if equal to expected else fails
129      */
testCompareAndSet()130     public void testCompareAndSet() {
131         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
132         for (int i = 0; i < SIZE; i++) {
133             aa.set(i, 1);
134             assertTrue(aa.compareAndSet(i, 1, 2));
135             assertTrue(aa.compareAndSet(i, 2, -4));
136             assertEquals(-4, aa.get(i));
137             assertFalse(aa.compareAndSet(i, -5, 7));
138             assertEquals(-4, aa.get(i));
139             assertTrue(aa.compareAndSet(i, -4, 7));
140             assertEquals(7, aa.get(i));
141         }
142     }
143 
144     /**
145      * compareAndSet in one thread enables another waiting for value
146      * to succeed
147      */
testCompareAndSetInMultipleThreads()148     public void testCompareAndSetInMultipleThreads() throws Exception {
149         final AtomicIntegerArray a = new AtomicIntegerArray(1);
150         a.set(0, 1);
151         Thread t = new Thread(new CheckedRunnable() {
152             public void realRun() {
153                 while (!a.compareAndSet(0, 2, 3))
154                     Thread.yield();
155             }});
156 
157         t.start();
158         assertTrue(a.compareAndSet(0, 1, 2));
159         t.join(LONG_DELAY_MS);
160         assertFalse(t.isAlive());
161         assertEquals(3, a.get(0));
162     }
163 
164     /**
165      * repeated weakCompareAndSet succeeds in changing value when equal
166      * to expected
167      */
testWeakCompareAndSet()168     public void testWeakCompareAndSet() {
169         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
170         for (int i = 0; i < SIZE; i++) {
171             aa.set(i, 1);
172             do {} while (!aa.weakCompareAndSet(i, 1, 2));
173             do {} while (!aa.weakCompareAndSet(i, 2, -4));
174             assertEquals(-4, aa.get(i));
175             do {} while (!aa.weakCompareAndSet(i, -4, 7));
176             assertEquals(7, aa.get(i));
177         }
178     }
179 
180     /**
181      * getAndSet returns previous value and sets to given value at given index
182      */
testGetAndSet()183     public void testGetAndSet() {
184         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
185         for (int i = 0; i < SIZE; i++) {
186             aa.set(i, 1);
187             assertEquals(1, aa.getAndSet(i, 0));
188             assertEquals(0, aa.getAndSet(i, -10));
189             assertEquals(-10, aa.getAndSet(i, 1));
190         }
191     }
192 
193     /**
194      * getAndAdd returns previous value and adds given value
195      */
testGetAndAdd()196     public void testGetAndAdd() {
197         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
198         for (int i = 0; i < SIZE; i++) {
199             aa.set(i, 1);
200             assertEquals(1, aa.getAndAdd(i, 2));
201             assertEquals(3, aa.get(i));
202             assertEquals(3, aa.getAndAdd(i, -4));
203             assertEquals(-1, aa.get(i));
204         }
205     }
206 
207     /**
208      * getAndDecrement returns previous value and decrements
209      */
testGetAndDecrement()210     public void testGetAndDecrement() {
211         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
212         for (int i = 0; i < SIZE; i++) {
213             aa.set(i, 1);
214             assertEquals(1, aa.getAndDecrement(i));
215             assertEquals(0, aa.getAndDecrement(i));
216             assertEquals(-1, aa.getAndDecrement(i));
217         }
218     }
219 
220     /**
221      * getAndIncrement returns previous value and increments
222      */
testGetAndIncrement()223     public void testGetAndIncrement() {
224         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
225         for (int i = 0; i < SIZE; i++) {
226             aa.set(i, 1);
227             assertEquals(1, aa.getAndIncrement(i));
228             assertEquals(2, aa.get(i));
229             aa.set(i, -2);
230             assertEquals(-2, aa.getAndIncrement(i));
231             assertEquals(-1, aa.getAndIncrement(i));
232             assertEquals(0, aa.getAndIncrement(i));
233             assertEquals(1, aa.get(i));
234         }
235     }
236 
237     /**
238      * addAndGet adds given value to current, and returns current value
239      */
testAddAndGet()240     public void testAddAndGet() {
241         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
242         for (int i = 0; i < SIZE; i++) {
243             aa.set(i, 1);
244             assertEquals(3, aa.addAndGet(i, 2));
245             assertEquals(3, aa.get(i));
246             assertEquals(-1, aa.addAndGet(i, -4));
247             assertEquals(-1, aa.get(i));
248         }
249     }
250 
251     /**
252      * decrementAndGet decrements and returns current value
253      */
testDecrementAndGet()254     public void testDecrementAndGet() {
255         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
256         for (int i = 0; i < SIZE; i++) {
257             aa.set(i, 1);
258             assertEquals(0, aa.decrementAndGet(i));
259             assertEquals(-1, aa.decrementAndGet(i));
260             assertEquals(-2, aa.decrementAndGet(i));
261             assertEquals(-2, aa.get(i));
262         }
263     }
264 
265     /**
266      * incrementAndGet increments and returns current value
267      */
testIncrementAndGet()268     public void testIncrementAndGet() {
269         AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
270         for (int i = 0; i < SIZE; i++) {
271             aa.set(i, 1);
272             assertEquals(2, aa.incrementAndGet(i));
273             assertEquals(2, aa.get(i));
274             aa.set(i, -2);
275             assertEquals(-1, aa.incrementAndGet(i));
276             assertEquals(0, aa.incrementAndGet(i));
277             assertEquals(1, aa.incrementAndGet(i));
278             assertEquals(1, aa.get(i));
279         }
280     }
281 
282     class Counter extends CheckedRunnable {
283         final AtomicIntegerArray aa;
284         volatile int counts;
Counter(AtomicIntegerArray a)285         Counter(AtomicIntegerArray a) { aa = a; }
realRun()286         public void realRun() {
287             for (;;) {
288                 boolean done = true;
289                 for (int i = 0; i < aa.length(); i++) {
290                     int v = aa.get(i);
291                     assertTrue(v >= 0);
292                     if (v != 0) {
293                         done = false;
294                         if (aa.compareAndSet(i, v, v - 1))
295                             ++counts;
296                     }
297                 }
298                 if (done)
299                     break;
300             }
301         }
302     }
303 
304     /**
305      * Multiple threads using same array of counters successfully
306      * update a number of times equal to total count
307      */
testCountingInMultipleThreads()308     public void testCountingInMultipleThreads() throws InterruptedException {
309         final AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
310         int countdown = 10000;
311         for (int i = 0; i < SIZE; i++)
312             aa.set(i, countdown);
313         Counter c1 = new Counter(aa);
314         Counter c2 = new Counter(aa);
315         Thread t1 = new Thread(c1);
316         Thread t2 = new Thread(c2);
317         t1.start();
318         t2.start();
319         t1.join();
320         t2.join();
321         assertEquals(c1.counts+c2.counts, SIZE * countdown);
322     }
323 
324     /**
325      * a deserialized serialized array holds same values
326      */
testSerialization()327     public void testSerialization() throws Exception {
328         AtomicIntegerArray x = new AtomicIntegerArray(SIZE);
329         for (int i = 0; i < SIZE; i++)
330             x.set(i, -i);
331         AtomicIntegerArray y = serialClone(x);
332         assertNotSame(x, y);
333         assertEquals(x.length(), y.length());
334         for (int i = 0; i < SIZE; i++) {
335             assertEquals(x.get(i), y.get(i));
336         }
337     }
338 
339     /**
340      * toString returns current value.
341      */
testToString()342     public void testToString() {
343         int[] a = { 17, 3, -42, 99, -7 };
344         AtomicIntegerArray aa = new AtomicIntegerArray(a);
345         assertEquals(Arrays.toString(a), aa.toString());
346     }
347 
348 }
349