blob: c9e32aaba525fa4a58dd8cdec2958389b32418bc [file] [log] [blame]
Calin Juravle8f0d92b2013-08-01 17:26:00 +01001/*
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
9package jsr166;
10
Calin Juravle8f0d92b2013-08-01 17:26:00 +010011import java.util.Arrays;
12import java.util.concurrent.atomic.AtomicIntegerArray;
13
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010014import junit.framework.Test;
15import junit.framework.TestSuite;
16
Calin Juravle8f0d92b2013-08-01 17:26:00 +010017public class AtomicIntegerArrayTest extends JSR166TestCase {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000018
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010019 // 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() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000026 // return new TestSuite(AtomicIntegerArrayTest.class);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010027 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010028
29 /**
30 * constructor creates array of given size with all elements zero
31 */
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 */
41 public void testConstructor2NPE() {
42 try {
43 int[] a = null;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010044 new AtomicIntegerArray(a);
Calin Juravle8f0d92b2013-08-01 17:26:00 +010045 shouldThrow();
46 } catch (NullPointerException success) {}
47 }
48
49 /**
50 * constructor with array is of same size and has all elements
51 */
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 */
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 */
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 */
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 */
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 */
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 */
168 public void testWeakCompareAndSet() {
169 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
170 for (int i = 0; i < SIZE; i++) {
171 aa.set(i, 1);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100172 do {} while (!aa.weakCompareAndSet(i, 1, 2));
173 do {} while (!aa.weakCompareAndSet(i, 2, -4));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100174 assertEquals(-4, aa.get(i));
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100175 do {} while (!aa.weakCompareAndSet(i, -4, 7));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100176 assertEquals(7, aa.get(i));
177 }
178 }
179
180 /**
181 * getAndSet returns previous value and sets to given value at given index
182 */
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 */
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 */
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 */
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 */
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 */
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 */
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
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100282 class Counter extends CheckedRunnable {
283 final AtomicIntegerArray aa;
284 volatile int counts;
285 Counter(AtomicIntegerArray a) { aa = a; }
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;
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000294 if (aa.compareAndSet(i, v, v - 1))
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100295 ++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 */
308 public void testCountingInMultipleThreads() throws InterruptedException {
309 final AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100310 int countdown = 10000;
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100311 for (int i = 0; i < SIZE; i++)
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100312 aa.set(i, countdown);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100313 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();
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100321 assertEquals(c1.counts+c2.counts, SIZE * countdown);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100322 }
323
324 /**
325 * a deserialized serialized array holds same values
326 */
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 */
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}