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