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