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