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.concurrent.atomic.AtomicIntegerFieldUpdater;
12 
13 import junit.framework.Test;
14 import junit.framework.TestSuite;
15 
16 public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
17     volatile int x = 0;
18     protected volatile int protectedField;
19     private volatile int privateField;
20     int w;
21     float z;
22     // 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() {
29     //     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     //     }
82     // }
83 
updaterFor(String fieldName)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      */
testConstructor()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      */
testConstructor2()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      */
testConstructor3()114     public void testConstructor3() {
115         try {
116             updaterFor("w");
117             shouldThrow();
118         } catch (IllegalArgumentException success) {}
119     }
120 
121     /**
122      * 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     /**
142      * get returns the last value set or assigned
143      */
testGetSet()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      */
testGetLazySet()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      */
testCompareAndSet()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     /**
186      * compareAndSet succeeds in changing protected field value if
187      * equal to expected else fails
188      */
testCompareAndSetProtected()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     /**
214      * compareAndSet in one thread enables another waiting for value
215      * to succeed
216      */
testCompareAndSetInMultipleThreads()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      */
testWeakCompareAndSet()239     public void testWeakCompareAndSet() {
240         AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
241         a = updaterFor("x");
242         x = 1;
243         do {} while (!a.weakCompareAndSet(this, 1, 2));
244         do {} while (!a.weakCompareAndSet(this, 2, -4));
245         assertEquals(-4, a.get(this));
246         do {} while (!a.weakCompareAndSet(this, -4, 7));
247         assertEquals(7, a.get(this));
248     }
249 
250     /**
251      * getAndSet returns previous value and sets to given value
252      */
testGetAndSet()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      */
testGetAndAdd()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      */
testGetAndDecrement()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      */
testGetAndIncrement()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      */
testAddAndGet()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      */
testDecrementAndGet()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      */
testIncrementAndGet()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 }
346