blob: c8d38567286c2f2feecb7f37c7561704b4058ff7 [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.concurrent.atomic.AtomicIntegerFieldUpdater;
12
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010013import junit.framework.Test;
14import junit.framework.TestSuite;
15
Calin Juravle8f0d92b2013-08-01 17:26:00 +010016public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
17 volatile int x = 0;
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000018 protected volatile int protectedField;
19 private volatile int privateField;
Calin Juravle8f0d92b2013-08-01 17:26:00 +010020 int w;
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000021 float z;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010022 // android-note: Removed because the CTS runner does a bad job of
23 // retrying tests that have suite() declarations.
24 //
25 // public static void main(String[] args) {
26 // main(suite(), args);
27 // }
28 // public static Test suite() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000029 // return new TestSuite(AtomicIntegerFieldUpdaterTest.class);
30 // }
31
32 // for testing subclass access
33 // android-note: Removed because android doesn't restrict reflection access
34 // static class AtomicIntegerFieldUpdaterTestSubclass extends AtomicIntegerFieldUpdaterTest {
35 // public void checkPrivateAccess() {
36 // try {
37 // AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
38 // AtomicIntegerFieldUpdater.newUpdater
39 // (AtomicIntegerFieldUpdaterTest.class, "privateField");
40 // shouldThrow();
41 // } catch (RuntimeException success) {
42 // assertNotNull(success.getCause());
43 // }
44 // }
45
46 // public void checkCompareAndSetProtectedSub() {
47 // AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
48 // AtomicIntegerFieldUpdater.newUpdater
49 // (AtomicIntegerFieldUpdaterTest.class, "protectedField");
50 // this.protectedField = 1;
51 // assertTrue(a.compareAndSet(this, 1, 2));
52 // assertTrue(a.compareAndSet(this, 2, -4));
53 // assertEquals(-4, a.get(this));
54 // assertFalse(a.compareAndSet(this, -5, 7));
55 // assertEquals(-4, a.get(this));
56 // assertTrue(a.compareAndSet(this, -4, 7));
57 // assertEquals(7, a.get(this));
58 // }
59 // }
60
61 // static class UnrelatedClass {
62 // public void checkPackageAccess(AtomicIntegerFieldUpdaterTest obj) {
63 // obj.x = 72;
64 // AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
65 // AtomicIntegerFieldUpdater.newUpdater
66 // (AtomicIntegerFieldUpdaterTest.class, "x");
67 // assertEquals(72, a.get(obj));
68 // assertTrue(a.compareAndSet(obj, 72, 73));
69 // assertEquals(73, a.get(obj));
70 // }
71
72 // public void checkPrivateAccess(AtomicIntegerFieldUpdaterTest obj) {
73 // try {
74 // AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a =
75 // AtomicIntegerFieldUpdater.newUpdater
76 // (AtomicIntegerFieldUpdaterTest.class, "privateField");
77 // throw new AssertionError("should throw");
78 // } catch (RuntimeException success) {
79 // assertNotNull(success.getCause());
80 // }
81 // }
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010082 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010083
84 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> updaterFor(String fieldName) {
85 return AtomicIntegerFieldUpdater.newUpdater
86 (AtomicIntegerFieldUpdaterTest.class, fieldName);
87 }
88
89 /**
90 * Construction with non-existent field throws RuntimeException
91 */
92 public void testConstructor() {
93 try {
94 updaterFor("y");
95 shouldThrow();
96 } catch (RuntimeException success) {
97 assertNotNull(success.getCause());
98 }
99 }
100
101 /**
102 * construction with field not of given type throws IllegalArgumentException
103 */
104 public void testConstructor2() {
105 try {
106 updaterFor("z");
107 shouldThrow();
108 } catch (IllegalArgumentException success) {}
109 }
110
111 /**
112 * construction with non-volatile field throws IllegalArgumentException
113 */
114 public void testConstructor3() {
115 try {
116 updaterFor("w");
117 shouldThrow();
118 } catch (IllegalArgumentException success) {}
119 }
120
121 /**
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000122 * construction using private field from subclass throws RuntimeException
123 */
124 // android-note: Removed because android doesn't restrict reflection access
125 // public void testPrivateFieldInSubclass() {
126 // AtomicIntegerFieldUpdaterTestSubclass s =
127 // new AtomicIntegerFieldUpdaterTestSubclass();
128 // s.checkPrivateAccess();
129 // }
130
131 /**
132 * construction from unrelated class; package access is allowed,
133 * private access is not
134 */
135 // android-note: Removed because android doesn't restrict reflection access
136 // public void testUnrelatedClassAccess() {
137 // new UnrelatedClass().checkPackageAccess(this);
138 // new UnrelatedClass().checkPrivateAccess(this);
139 // }
140
141 /**
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100142 * get returns the last value set or assigned
143 */
144 public void testGetSet() {
145 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
146 a = updaterFor("x");
147 x = 1;
148 assertEquals(1, a.get(this));
149 a.set(this, 2);
150 assertEquals(2, a.get(this));
151 a.set(this, -3);
152 assertEquals(-3, a.get(this));
153 }
154
155 /**
156 * get returns the last value lazySet by same thread
157 */
158 public void testGetLazySet() {
159 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
160 a = updaterFor("x");
161 x = 1;
162 assertEquals(1, a.get(this));
163 a.lazySet(this, 2);
164 assertEquals(2, a.get(this));
165 a.lazySet(this, -3);
166 assertEquals(-3, a.get(this));
167 }
168
169 /**
170 * compareAndSet succeeds in changing value if equal to expected else fails
171 */
172 public void testCompareAndSet() {
173 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
174 a = updaterFor("x");
175 x = 1;
176 assertTrue(a.compareAndSet(this, 1, 2));
177 assertTrue(a.compareAndSet(this, 2, -4));
178 assertEquals(-4, a.get(this));
179 assertFalse(a.compareAndSet(this, -5, 7));
180 assertEquals(-4, a.get(this));
181 assertTrue(a.compareAndSet(this, -4, 7));
182 assertEquals(7, a.get(this));
183 }
184
185 /**
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000186 * compareAndSet succeeds in changing protected field value if
187 * equal to expected else fails
188 */
189 public void testCompareAndSetProtected() {
190 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
191 a = updaterFor("protectedField");
192 protectedField = 1;
193 assertTrue(a.compareAndSet(this, 1, 2));
194 assertTrue(a.compareAndSet(this, 2, -4));
195 assertEquals(-4, a.get(this));
196 assertFalse(a.compareAndSet(this, -5, 7));
197 assertEquals(-4, a.get(this));
198 assertTrue(a.compareAndSet(this, -4, 7));
199 assertEquals(7, a.get(this));
200 }
201
202 /**
203 * compareAndSet succeeds in changing protected field value if
204 * equal to expected else fails
205 */
206 // android-note: Removed because android doesn't restrict reflection access
207 // public void testCompareAndSetProtectedInSubclass() {
208 // AtomicIntegerFieldUpdaterTestSubclass s =
209 // new AtomicIntegerFieldUpdaterTestSubclass();
210 // s.checkCompareAndSetProtectedSub();
211 // }
212
213 /**
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100214 * compareAndSet in one thread enables another waiting for value
215 * to succeed
216 */
217 public void testCompareAndSetInMultipleThreads() throws Exception {
218 x = 1;
219 final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
220 a = updaterFor("x");
221
222 Thread t = new Thread(new CheckedRunnable() {
223 public void realRun() {
224 while (!a.compareAndSet(AtomicIntegerFieldUpdaterTest.this, 2, 3))
225 Thread.yield();
226 }});
227
228 t.start();
229 assertTrue(a.compareAndSet(this, 1, 2));
230 t.join(LONG_DELAY_MS);
231 assertFalse(t.isAlive());
232 assertEquals(3, a.get(this));
233 }
234
235 /**
236 * repeated weakCompareAndSet succeeds in changing value when equal
237 * to expected
238 */
239 public void testWeakCompareAndSet() {
240 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
241 a = updaterFor("x");
242 x = 1;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100243 do {} while (!a.weakCompareAndSet(this, 1, 2));
244 do {} while (!a.weakCompareAndSet(this, 2, -4));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100245 assertEquals(-4, a.get(this));
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100246 do {} while (!a.weakCompareAndSet(this, -4, 7));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100247 assertEquals(7, a.get(this));
248 }
249
250 /**
251 * getAndSet returns previous value and sets to given value
252 */
253 public void testGetAndSet() {
254 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
255 a = updaterFor("x");
256 x = 1;
257 assertEquals(1, a.getAndSet(this, 0));
258 assertEquals(0, a.getAndSet(this, -10));
259 assertEquals(-10, a.getAndSet(this, 1));
260 }
261
262 /**
263 * getAndAdd returns previous value and adds given value
264 */
265 public void testGetAndAdd() {
266 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
267 a = updaterFor("x");
268 x = 1;
269 assertEquals(1, a.getAndAdd(this, 2));
270 assertEquals(3, a.get(this));
271 assertEquals(3, a.getAndAdd(this, -4));
272 assertEquals(-1, a.get(this));
273 }
274
275 /**
276 * getAndDecrement returns previous value and decrements
277 */
278 public void testGetAndDecrement() {
279 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
280 a = updaterFor("x");
281 x = 1;
282 assertEquals(1, a.getAndDecrement(this));
283 assertEquals(0, a.getAndDecrement(this));
284 assertEquals(-1, a.getAndDecrement(this));
285 }
286
287 /**
288 * getAndIncrement returns previous value and increments
289 */
290 public void testGetAndIncrement() {
291 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
292 a = updaterFor("x");
293 x = 1;
294 assertEquals(1, a.getAndIncrement(this));
295 assertEquals(2, a.get(this));
296 a.set(this, -2);
297 assertEquals(-2, a.getAndIncrement(this));
298 assertEquals(-1, a.getAndIncrement(this));
299 assertEquals(0, a.getAndIncrement(this));
300 assertEquals(1, a.get(this));
301 }
302
303 /**
304 * addAndGet adds given value to current, and returns current value
305 */
306 public void testAddAndGet() {
307 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
308 a = updaterFor("x");
309 x = 1;
310 assertEquals(3, a.addAndGet(this, 2));
311 assertEquals(3, a.get(this));
312 assertEquals(-1, a.addAndGet(this, -4));
313 assertEquals(-1, a.get(this));
314 }
315
316 /**
317 * decrementAndGet decrements and returns current value
318 */
319 public void testDecrementAndGet() {
320 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
321 a = updaterFor("x");
322 x = 1;
323 assertEquals(0, a.decrementAndGet(this));
324 assertEquals(-1, a.decrementAndGet(this));
325 assertEquals(-2, a.decrementAndGet(this));
326 assertEquals(-2, a.get(this));
327 }
328
329 /**
330 * incrementAndGet increments and returns current value
331 */
332 public void testIncrementAndGet() {
333 AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
334 a = updaterFor("x");
335 x = 1;
336 assertEquals(2, a.incrementAndGet(this));
337 assertEquals(2, a.get(this));
338 a.set(this, -2);
339 assertEquals(-1, a.incrementAndGet(this));
340 assertEquals(0, a.incrementAndGet(this));
341 assertEquals(1, a.incrementAndGet(this));
342 assertEquals(1, a.get(this));
343 }
344
345}