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