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