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