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