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
9package jsr166;
10
11import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
12
13import junit.framework.Test;
14import junit.framework.TestSuite;
15
16public 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
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    /**
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     */
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    /**
186     * 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    /**
214     * 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;
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     */
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}
346