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.AtomicReferenceFieldUpdater;
12 
13 import junit.framework.Test;
14 import junit.framework.TestSuite;
15 
16 public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase {
17     volatile Integer x = null;
18     protected volatile Integer protectedField;
19     private volatile Integer privateField;
20     Object z;
21     Integer w;
22     volatile int i;
23 
24     // android-note: Removed because the CTS runner does a bad job of
25     // retrying tests that have suite() declarations.
26     //
27     // public static void main(String[] args) {
28     //     main(suite(), args);
29     // }
30     // public static Test suite() {
31     //     return new TestSuite(AtomicReferenceFieldUpdaterTest.class);
32     // }
33 
34     // for testing subclass access
35     static class AtomicReferenceFieldUpdaterTestSubclass extends AtomicReferenceFieldUpdaterTest {
checkPrivateAccess()36         public void checkPrivateAccess() {
37             try {
38                 AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
39                     AtomicReferenceFieldUpdater.newUpdater
40                     (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
41                 shouldThrow();
42             } catch (RuntimeException success) {
43                 assertNotNull(success.getCause());
44             }
45         }
46 
checkCompareAndSetProtectedSub()47         public void checkCompareAndSetProtectedSub() {
48             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
49                 AtomicReferenceFieldUpdater.newUpdater
50                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "protectedField");
51             this.protectedField = one;
52             assertTrue(a.compareAndSet(this, one, two));
53             assertTrue(a.compareAndSet(this, two, m4));
54             assertSame(m4, a.get(this));
55             assertFalse(a.compareAndSet(this, m5, seven));
56             assertFalse(seven == a.get(this));
57             assertTrue(a.compareAndSet(this, m4, seven));
58             assertSame(seven, a.get(this));
59         }
60     }
61 
62     static class UnrelatedClass {
checkPackageAccess(AtomicReferenceFieldUpdaterTest obj)63         public void checkPackageAccess(AtomicReferenceFieldUpdaterTest obj) {
64             obj.x = one;
65             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
66                 AtomicReferenceFieldUpdater.newUpdater
67                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
68             assertSame(one, a.get(obj));
69             assertTrue(a.compareAndSet(obj, one, two));
70             assertSame(two, a.get(obj));
71         }
72 
checkPrivateAccess(AtomicReferenceFieldUpdaterTest obj)73         public void checkPrivateAccess(AtomicReferenceFieldUpdaterTest obj) {
74             try {
75                 AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
76                     AtomicReferenceFieldUpdater.newUpdater
77                     (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
78                 throw new AssertionError("should throw");
79             } catch (RuntimeException success) {
80                 assertNotNull(success.getCause());
81             }
82         }
83     }
84 
updaterFor(String fieldName)85     static AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> updaterFor(String fieldName) {
86         return AtomicReferenceFieldUpdater.newUpdater
87             (AtomicReferenceFieldUpdaterTest.class, Integer.class, fieldName);
88     }
89 
90     /**
91      * Construction with non-existent field throws RuntimeException
92      */
testConstructor()93     public void testConstructor() {
94         try {
95             updaterFor("y");
96             shouldThrow();
97         } catch (RuntimeException success) {
98             assertNotNull(success.getCause());
99         }
100     }
101 
102     /**
103      * construction with field not of given type throws ClassCastException
104      */
testConstructor2()105     public void testConstructor2() {
106         try {
107             updaterFor("z");
108             shouldThrow();
109         } catch (ClassCastException success) {}
110     }
111 
112     /**
113      * Constructor with non-volatile field throws IllegalArgumentException
114      */
testConstructor3()115     public void testConstructor3() {
116         try {
117             updaterFor("w");
118             shouldThrow();
119         } catch (IllegalArgumentException success) {}
120     }
121 
122     /**
123      * Constructor with non-reference field throws ClassCastException
124      */
testConstructor4()125     public void testConstructor4() {
126         try {
127             updaterFor("i");
128             shouldThrow();
129         } catch (ClassCastException success) {}
130     }
131 
132     /**
133      * construction using private field from subclass throws RuntimeException
134      */
testPrivateFieldInSubclass()135     public void testPrivateFieldInSubclass() {
136         AtomicReferenceFieldUpdaterTestSubclass s =
137             new AtomicReferenceFieldUpdaterTestSubclass();
138         s.checkPrivateAccess();
139     }
140 
141     /**
142      * construction from unrelated class; package access is allowed,
143      * private access is not
144      */
testUnrelatedClassAccess()145     public void testUnrelatedClassAccess() {
146         new UnrelatedClass().checkPackageAccess(this);
147         new UnrelatedClass().checkPrivateAccess(this);
148     }
149 
150     /**
151      * get returns the last value set or assigned
152      */
testGetSet()153     public void testGetSet() {
154         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
155         a = updaterFor("x");
156         x = one;
157         assertSame(one, a.get(this));
158         a.set(this, two);
159         assertSame(two, a.get(this));
160         a.set(this, m3);
161         assertSame(m3, a.get(this));
162     }
163 
164     /**
165      * get returns the last value lazySet by same thread
166      */
testGetLazySet()167     public void testGetLazySet() {
168         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
169         a = updaterFor("x");
170         x = one;
171         assertSame(one, a.get(this));
172         a.lazySet(this, two);
173         assertSame(two, a.get(this));
174         a.lazySet(this, m3);
175         assertSame(m3, a.get(this));
176     }
177 
178     /**
179      * compareAndSet succeeds in changing value if equal to expected else fails
180      */
testCompareAndSet()181     public void testCompareAndSet() {
182         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
183         a = updaterFor("x");
184         x = one;
185         assertTrue(a.compareAndSet(this, one, two));
186         assertTrue(a.compareAndSet(this, two, m4));
187         assertSame(m4, a.get(this));
188         assertFalse(a.compareAndSet(this, m5, seven));
189         assertFalse(seven == a.get(this));
190         assertTrue(a.compareAndSet(this, m4, seven));
191         assertSame(seven, a.get(this));
192     }
193 
194     /**
195      * compareAndSet in one thread enables another waiting for value
196      * to succeed
197      */
testCompareAndSetInMultipleThreads()198     public void testCompareAndSetInMultipleThreads() throws Exception {
199         x = one;
200         final AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
201         a = updaterFor("x");
202 
203         Thread t = new Thread(new CheckedRunnable() {
204             public void realRun() {
205                 while (!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three))
206                     Thread.yield();
207             }});
208 
209         t.start();
210         assertTrue(a.compareAndSet(this, one, two));
211         t.join(LONG_DELAY_MS);
212         assertFalse(t.isAlive());
213         assertSame(three, a.get(this));
214     }
215 
216     /**
217      * repeated weakCompareAndSet succeeds in changing value when equal
218      * to expected
219      */
testWeakCompareAndSet()220     public void testWeakCompareAndSet() {
221         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
222         a = updaterFor("x");
223         x = one;
224         do {} while (!a.weakCompareAndSet(this, one, two));
225         do {} while (!a.weakCompareAndSet(this, two, m4));
226         assertSame(m4, a.get(this));
227         do {} while (!a.weakCompareAndSet(this, m4, seven));
228         assertSame(seven, a.get(this));
229     }
230 
231     /**
232      * getAndSet returns previous value and sets to given value
233      */
testGetAndSet()234     public void testGetAndSet() {
235         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
236         a = updaterFor("x");
237         x = one;
238         assertSame(one, a.getAndSet(this, zero));
239         assertSame(zero, a.getAndSet(this, m10));
240         assertSame(m10, a.getAndSet(this, 1));
241     }
242 
243 }
244