blob: a662e11d7685a2590d9c842288ad720ec6730ee8 [file] [log] [blame]
Calin Juravle8f0d92b2013-08-01 17:26:00 +01001/*
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
9package jsr166;
10
Calin Juravle8f0d92b2013-08-01 17:26:00 +010011import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
12
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010013import junit.framework.Test;
14import junit.framework.TestSuite;
15
Calin Juravle8f0d92b2013-08-01 17:26:00 +010016public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase {
17 volatile Integer x = null;
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000018 protected volatile Integer protectedField;
19 private volatile Integer privateField;
Calin Juravle8f0d92b2013-08-01 17:26:00 +010020 Object z;
21 Integer w;
22 volatile int i;
23
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010024 // 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() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000031 // return new TestSuite(AtomicReferenceFieldUpdaterTest.class);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010032 // }
33
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000034 // for testing subclass access
Pete Gillinfbdae2c2018-03-20 14:55:37 +000035 static class AtomicReferenceFieldUpdaterTestSubclass extends AtomicReferenceFieldUpdaterTest {
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 }
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000046
Pete Gillinfbdae2c2018-03-20 14:55:37 +000047 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 }
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000061
Pete Gillinfbdae2c2018-03-20 14:55:37 +000062 static class UnrelatedClass {
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 }
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000072
Pete Gillinfbdae2c2018-03-20 14:55:37 +000073 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 }
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000084
85 static AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> updaterFor(String fieldName) {
Calin Juravle8f0d92b2013-08-01 17:26:00 +010086 return AtomicReferenceFieldUpdater.newUpdater
87 (AtomicReferenceFieldUpdaterTest.class, Integer.class, fieldName);
88 }
89
90 /**
91 * Construction with non-existent field throws RuntimeException
92 */
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 */
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 */
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 */
125 public void testConstructor4() {
126 try {
127 updaterFor("i");
128 shouldThrow();
129 } catch (ClassCastException success) {}
130 }
131
132 /**
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000133 * construction using private field from subclass throws RuntimeException
134 */
Pete Gillinfbdae2c2018-03-20 14:55:37 +0000135 public void testPrivateFieldInSubclass() {
136 AtomicReferenceFieldUpdaterTestSubclass s =
137 new AtomicReferenceFieldUpdaterTestSubclass();
138 s.checkPrivateAccess();
139 }
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000140
141 /**
142 * construction from unrelated class; package access is allowed,
143 * private access is not
144 */
Pete Gillinfbdae2c2018-03-20 14:55:37 +0000145 public void testUnrelatedClassAccess() {
146 new UnrelatedClass().checkPackageAccess(this);
147 new UnrelatedClass().checkPrivateAccess(this);
148 }
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000149
150 /**
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100151 * get returns the last value set or assigned
152 */
153 public void testGetSet() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100154 AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100155 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 */
167 public void testGetLazySet() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100168 AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100169 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 */
181 public void testCompareAndSet() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100182 AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100183 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 */
198 public void testCompareAndSetInMultipleThreads() throws Exception {
199 x = one;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100200 final AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100201 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 */
220 public void testWeakCompareAndSet() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100221 AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100222 a = updaterFor("x");
223 x = one;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100224 do {} while (!a.weakCompareAndSet(this, one, two));
225 do {} while (!a.weakCompareAndSet(this, two, m4));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100226 assertSame(m4, a.get(this));
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100227 do {} while (!a.weakCompareAndSet(this, m4, seven));
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100228 assertSame(seven, a.get(this));
229 }
230
231 /**
232 * getAndSet returns previous value and sets to given value
233 */
234 public void testGetAndSet() {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +0100235 AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100236 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}