1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 */
22
23/*
24 * This file is available under and governed by the GNU General Public
25 * License version 2 only, as published by the Free Software Foundation.
26 * However, the following notice accompanied the original version of this
27 * file:
28 *
29 * Written by Doug Lea with assistance from members of JCP JSR-166
30 * Expert Group and released to the public domain, as explained at
31 * http://creativecommons.org/publicdomain/zero/1.0/
32 * Other contributors include Andrew Wright, Jeffrey Hayes,
33 * Pat Fisher, Mike Judd.
34 */
35
36import java.util.concurrent.atomic.AtomicLongFieldUpdater;
37
38import junit.framework.Test;
39import junit.framework.TestSuite;
40
41public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
42    volatile long x = 0;
43    protected volatile long protectedField;
44    private volatile long privateField;
45    long w;
46    float z;
47    public static void main(String[] args) {
48        main(suite(), args);
49    }
50    public static Test suite() {
51        return new TestSuite(AtomicLongFieldUpdaterTest.class);
52    }
53
54    // for testing subclass access
55    static class AtomicLongFieldUpdaterTestSubclass extends AtomicLongFieldUpdaterTest {
56        public void checkPrivateAccess() {
57            try {
58                AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
59                    AtomicLongFieldUpdater.newUpdater
60                    (AtomicLongFieldUpdaterTest.class, "privateField");
61                shouldThrow();
62            } catch (RuntimeException success) {
63                assertNotNull(success.getCause());
64            }
65        }
66
67        public void checkCompareAndSetProtectedSub() {
68            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
69                AtomicLongFieldUpdater.newUpdater
70                (AtomicLongFieldUpdaterTest.class, "protectedField");
71            this.protectedField = 1;
72            assertTrue(a.compareAndSet(this, 1, 2));
73            assertTrue(a.compareAndSet(this, 2, -4));
74            assertEquals(-4, a.get(this));
75            assertFalse(a.compareAndSet(this, -5, 7));
76            assertEquals(-4, a.get(this));
77            assertTrue(a.compareAndSet(this, -4, 7));
78            assertEquals(7, a.get(this));
79        }
80    }
81
82    static class UnrelatedClass {
83        public void checkPackageAccess(AtomicLongFieldUpdaterTest obj) {
84            obj.x = 72L;
85            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
86                AtomicLongFieldUpdater.newUpdater
87                (AtomicLongFieldUpdaterTest.class, "x");
88            assertEquals(72L, a.get(obj));
89            assertTrue(a.compareAndSet(obj, 72L, 73L));
90            assertEquals(73L, a.get(obj));
91        }
92
93        public void checkPrivateAccess(AtomicLongFieldUpdaterTest obj) {
94            try {
95                AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
96                    AtomicLongFieldUpdater.newUpdater
97                    (AtomicLongFieldUpdaterTest.class, "privateField");
98                throw new AssertionError("should throw");
99            } catch (RuntimeException success) {
100                assertNotNull(success.getCause());
101            }
102        }
103    }
104
105    AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> updaterFor(String fieldName) {
106        return AtomicLongFieldUpdater.newUpdater
107            (AtomicLongFieldUpdaterTest.class, fieldName);
108    }
109
110    /**
111     * Construction with non-existent field throws RuntimeException
112     */
113    public void testConstructor() {
114        try {
115            updaterFor("y");
116            shouldThrow();
117        } catch (RuntimeException success) {
118            assertNotNull(success.getCause());
119        }
120    }
121
122    /**
123     * construction with field not of given type throws IllegalArgumentException
124     */
125    public void testConstructor2() {
126        try {
127            updaterFor("z");
128            shouldThrow();
129        } catch (IllegalArgumentException success) {}
130    }
131
132    /**
133     * construction with non-volatile field throws IllegalArgumentException
134     */
135    public void testConstructor3() {
136        try {
137            updaterFor("w");
138            shouldThrow();
139        } catch (IllegalArgumentException success) {}
140    }
141
142    /**
143     * construction using private field from subclass throws RuntimeException
144     */
145    public void testPrivateFieldInSubclass() {
146        AtomicLongFieldUpdaterTestSubclass s =
147            new AtomicLongFieldUpdaterTestSubclass();
148        s.checkPrivateAccess();
149    }
150
151    /**
152     * construction from unrelated class; package access is allowed,
153     * private access is not
154     */
155    public void testUnrelatedClassAccess() {
156        new UnrelatedClass().checkPackageAccess(this);
157        new UnrelatedClass().checkPrivateAccess(this);
158    }
159
160    /**
161     * get returns the last value set or assigned
162     */
163    public void testGetSet() {
164        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
165        a = updaterFor("x");
166        x = 1;
167        assertEquals(1, a.get(this));
168        a.set(this, 2);
169        assertEquals(2, a.get(this));
170        a.set(this, -3);
171        assertEquals(-3, a.get(this));
172    }
173
174    /**
175     * get returns the last value lazySet by same thread
176     */
177    public void testGetLazySet() {
178        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
179        a = updaterFor("x");
180        x = 1;
181        assertEquals(1, a.get(this));
182        a.lazySet(this, 2);
183        assertEquals(2, a.get(this));
184        a.lazySet(this, -3);
185        assertEquals(-3, a.get(this));
186    }
187
188    /**
189     * compareAndSet succeeds in changing value if equal to expected else fails
190     */
191    public void testCompareAndSet() {
192        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
193        a = updaterFor("x");
194        x = 1;
195        assertTrue(a.compareAndSet(this, 1, 2));
196        assertTrue(a.compareAndSet(this, 2, -4));
197        assertEquals(-4, a.get(this));
198        assertFalse(a.compareAndSet(this, -5, 7));
199        assertEquals(-4, a.get(this));
200        assertTrue(a.compareAndSet(this, -4, 7));
201        assertEquals(7, a.get(this));
202    }
203
204    /**
205     * compareAndSet succeeds in changing protected field value if
206     * equal to expected else fails
207     */
208    public void testCompareAndSetProtected() {
209        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
210        a = updaterFor("protectedField");
211        protectedField = 1;
212        assertTrue(a.compareAndSet(this, 1, 2));
213        assertTrue(a.compareAndSet(this, 2, -4));
214        assertEquals(-4, a.get(this));
215        assertFalse(a.compareAndSet(this, -5, 7));
216        assertEquals(-4, a.get(this));
217        assertTrue(a.compareAndSet(this, -4, 7));
218        assertEquals(7, a.get(this));
219    }
220
221    /**
222     * compareAndSet succeeds in changing protected field value if
223     * equal to expected else fails
224     */
225    public void testCompareAndSetProtectedInSubclass() {
226        AtomicLongFieldUpdaterTestSubclass s =
227            new AtomicLongFieldUpdaterTestSubclass();
228        s.checkCompareAndSetProtectedSub();
229    }
230
231    /**
232     * compareAndSet in one thread enables another waiting for value
233     * to succeed
234     */
235    public void testCompareAndSetInMultipleThreads() throws Exception {
236        x = 1;
237        final AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
238        a = updaterFor("x");
239
240        Thread t = new Thread(new CheckedRunnable() {
241            public void realRun() {
242                while (!a.compareAndSet(AtomicLongFieldUpdaterTest.this, 2, 3))
243                    Thread.yield();
244            }});
245
246        t.start();
247        assertTrue(a.compareAndSet(this, 1, 2));
248        t.join(LONG_DELAY_MS);
249        assertFalse(t.isAlive());
250        assertEquals(3, a.get(this));
251    }
252
253    /**
254     * repeated weakCompareAndSet succeeds in changing value when equal
255     * to expected
256     */
257    public void testWeakCompareAndSet() {
258        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
259        a = updaterFor("x");
260        x = 1;
261        do {} while (!a.weakCompareAndSet(this, 1, 2));
262        do {} while (!a.weakCompareAndSet(this, 2, -4));
263        assertEquals(-4, a.get(this));
264        do {} while (!a.weakCompareAndSet(this, -4, 7));
265        assertEquals(7, a.get(this));
266    }
267
268    /**
269     * getAndSet returns previous value and sets to given value
270     */
271    public void testGetAndSet() {
272        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
273        a = updaterFor("x");
274        x = 1;
275        assertEquals(1, a.getAndSet(this, 0));
276        assertEquals(0, a.getAndSet(this, -10));
277        assertEquals(-10, a.getAndSet(this, 1));
278    }
279
280    /**
281     * getAndAdd returns previous value and adds given value
282     */
283    public void testGetAndAdd() {
284        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
285        a = updaterFor("x");
286        x = 1;
287        assertEquals(1, a.getAndAdd(this, 2));
288        assertEquals(3, a.get(this));
289        assertEquals(3, a.getAndAdd(this, -4));
290        assertEquals(-1, a.get(this));
291    }
292
293    /**
294     * getAndDecrement returns previous value and decrements
295     */
296    public void testGetAndDecrement() {
297        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
298        a = updaterFor("x");
299        x = 1;
300        assertEquals(1, a.getAndDecrement(this));
301        assertEquals(0, a.getAndDecrement(this));
302        assertEquals(-1, a.getAndDecrement(this));
303    }
304
305    /**
306     * getAndIncrement returns previous value and increments
307     */
308    public void testGetAndIncrement() {
309        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
310        a = updaterFor("x");
311        x = 1;
312        assertEquals(1, a.getAndIncrement(this));
313        assertEquals(2, a.get(this));
314        a.set(this, -2);
315        assertEquals(-2, a.getAndIncrement(this));
316        assertEquals(-1, a.getAndIncrement(this));
317        assertEquals(0, a.getAndIncrement(this));
318        assertEquals(1, a.get(this));
319    }
320
321    /**
322     * addAndGet adds given value to current, and returns current value
323     */
324    public void testAddAndGet() {
325        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
326        a = updaterFor("x");
327        x = 1;
328        assertEquals(3, a.addAndGet(this, 2));
329        assertEquals(3, a.get(this));
330        assertEquals(-1, a.addAndGet(this, -4));
331        assertEquals(-1, a.get(this));
332    }
333
334    /**
335     * decrementAndGet decrements and returns current value
336     */
337    public void testDecrementAndGet() {
338        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
339        a = updaterFor("x");
340        x = 1;
341        assertEquals(0, a.decrementAndGet(this));
342        assertEquals(-1, a.decrementAndGet(this));
343        assertEquals(-2, a.decrementAndGet(this));
344        assertEquals(-2, a.get(this));
345    }
346
347    /**
348     * incrementAndGet increments and returns current value
349     */
350    public void testIncrementAndGet() {
351        AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
352        a = updaterFor("x");
353        x = 1;
354        assertEquals(2, a.incrementAndGet(this));
355        assertEquals(2, a.get(this));
356        a.set(this, -2);
357        assertEquals(-1, a.incrementAndGet(this));
358        assertEquals(0, a.incrementAndGet(this));
359        assertEquals(1, a.incrementAndGet(this));
360        assertEquals(1, a.get(this));
361    }
362
363}
364