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 junit.framework.*;
12import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
13
14public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
15    volatile int x = 0;
16    int w;
17    long z;
18
19    AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> updaterFor(String fieldName) {
20        return AtomicIntegerFieldUpdater.newUpdater
21            (AtomicIntegerFieldUpdaterTest.class, fieldName);
22    }
23
24    /**
25     * Construction with non-existent field throws RuntimeException
26     */
27    public void testConstructor() {
28        try {
29            updaterFor("y");
30            shouldThrow();
31        } catch (RuntimeException success) {
32            assertNotNull(success.getCause());
33        }
34    }
35
36    /**
37     * construction with field not of given type throws IllegalArgumentException
38     */
39    public void testConstructor2() {
40        try {
41            updaterFor("z");
42            shouldThrow();
43        } catch (IllegalArgumentException success) {}
44    }
45
46    /**
47     * construction with non-volatile field throws IllegalArgumentException
48     */
49    public void testConstructor3() {
50        try {
51            updaterFor("w");
52            shouldThrow();
53        } catch (IllegalArgumentException success) {}
54    }
55
56    /**
57     * get returns the last value set or assigned
58     */
59    public void testGetSet() {
60        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
61        a = updaterFor("x");
62        x = 1;
63        assertEquals(1, a.get(this));
64        a.set(this, 2);
65        assertEquals(2, a.get(this));
66        a.set(this, -3);
67        assertEquals(-3, a.get(this));
68    }
69
70    /**
71     * get returns the last value lazySet by same thread
72     */
73    public void testGetLazySet() {
74        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
75        a = updaterFor("x");
76        x = 1;
77        assertEquals(1, a.get(this));
78        a.lazySet(this, 2);
79        assertEquals(2, a.get(this));
80        a.lazySet(this, -3);
81        assertEquals(-3, a.get(this));
82    }
83
84    /**
85     * compareAndSet succeeds in changing value if equal to expected else fails
86     */
87    public void testCompareAndSet() {
88        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
89        a = updaterFor("x");
90        x = 1;
91        assertTrue(a.compareAndSet(this, 1, 2));
92        assertTrue(a.compareAndSet(this, 2, -4));
93        assertEquals(-4, a.get(this));
94        assertFalse(a.compareAndSet(this, -5, 7));
95        assertEquals(-4, a.get(this));
96        assertTrue(a.compareAndSet(this, -4, 7));
97        assertEquals(7, a.get(this));
98    }
99
100    /**
101     * compareAndSet in one thread enables another waiting for value
102     * to succeed
103     */
104    public void testCompareAndSetInMultipleThreads() throws Exception {
105        x = 1;
106        final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
107        a = updaterFor("x");
108
109        Thread t = new Thread(new CheckedRunnable() {
110            public void realRun() {
111                while (!a.compareAndSet(AtomicIntegerFieldUpdaterTest.this, 2, 3))
112                    Thread.yield();
113            }});
114
115        t.start();
116        assertTrue(a.compareAndSet(this, 1, 2));
117        t.join(LONG_DELAY_MS);
118        assertFalse(t.isAlive());
119        assertEquals(3, a.get(this));
120    }
121
122    /**
123     * repeated weakCompareAndSet succeeds in changing value when equal
124     * to expected
125     */
126    public void testWeakCompareAndSet() {
127        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
128        a = updaterFor("x");
129        x = 1;
130        while (!a.weakCompareAndSet(this, 1, 2));
131        while (!a.weakCompareAndSet(this, 2, -4));
132        assertEquals(-4, a.get(this));
133        while (!a.weakCompareAndSet(this, -4, 7));
134        assertEquals(7, a.get(this));
135    }
136
137    /**
138     * getAndSet returns previous value and sets to given value
139     */
140    public void testGetAndSet() {
141        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
142        a = updaterFor("x");
143        x = 1;
144        assertEquals(1, a.getAndSet(this, 0));
145        assertEquals(0, a.getAndSet(this, -10));
146        assertEquals(-10, a.getAndSet(this, 1));
147    }
148
149    /**
150     * getAndAdd returns previous value and adds given value
151     */
152    public void testGetAndAdd() {
153        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
154        a = updaterFor("x");
155        x = 1;
156        assertEquals(1, a.getAndAdd(this, 2));
157        assertEquals(3, a.get(this));
158        assertEquals(3, a.getAndAdd(this, -4));
159        assertEquals(-1, a.get(this));
160    }
161
162    /**
163     * getAndDecrement returns previous value and decrements
164     */
165    public void testGetAndDecrement() {
166        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
167        a = updaterFor("x");
168        x = 1;
169        assertEquals(1, a.getAndDecrement(this));
170        assertEquals(0, a.getAndDecrement(this));
171        assertEquals(-1, a.getAndDecrement(this));
172    }
173
174    /**
175     * getAndIncrement returns previous value and increments
176     */
177    public void testGetAndIncrement() {
178        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
179        a = updaterFor("x");
180        x = 1;
181        assertEquals(1, a.getAndIncrement(this));
182        assertEquals(2, a.get(this));
183        a.set(this, -2);
184        assertEquals(-2, a.getAndIncrement(this));
185        assertEquals(-1, a.getAndIncrement(this));
186        assertEquals(0, a.getAndIncrement(this));
187        assertEquals(1, a.get(this));
188    }
189
190    /**
191     * addAndGet adds given value to current, and returns current value
192     */
193    public void testAddAndGet() {
194        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
195        a = updaterFor("x");
196        x = 1;
197        assertEquals(3, a.addAndGet(this, 2));
198        assertEquals(3, a.get(this));
199        assertEquals(-1, a.addAndGet(this, -4));
200        assertEquals(-1, a.get(this));
201    }
202
203    /**
204     * decrementAndGet decrements and returns current value
205     */
206    public void testDecrementAndGet() {
207        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
208        a = updaterFor("x");
209        x = 1;
210        assertEquals(0, a.decrementAndGet(this));
211        assertEquals(-1, a.decrementAndGet(this));
212        assertEquals(-2, a.decrementAndGet(this));
213        assertEquals(-2, a.get(this));
214    }
215
216    /**
217     * incrementAndGet increments and returns current value
218     */
219    public void testIncrementAndGet() {
220        AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
221        a = updaterFor("x");
222        x = 1;
223        assertEquals(2, a.incrementAndGet(this));
224        assertEquals(2, a.get(this));
225        a.set(this, -2);
226        assertEquals(-1, a.incrementAndGet(this));
227        assertEquals(0, a.incrementAndGet(this));
228        assertEquals(1, a.incrementAndGet(this));
229        assertEquals(1, a.get(this));
230    }
231
232}
233