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