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 junit.framework.*;
12 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
13 
14 public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase {
15     volatile Integer x = null;
16     Object z;
17     Integer w;
18     volatile int i;
19 
updaterFor(String fieldName)20     AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> updaterFor(String fieldName) {
21         return AtomicReferenceFieldUpdater.newUpdater
22             (AtomicReferenceFieldUpdaterTest.class, Integer.class, fieldName);
23     }
24 
25     /**
26      * Construction with non-existent field throws RuntimeException
27      */
testConstructor()28     public void testConstructor() {
29         try {
30             updaterFor("y");
31             shouldThrow();
32         } catch (RuntimeException success) {
33             assertNotNull(success.getCause());
34         }
35     }
36 
37     /**
38      * construction with field not of given type throws ClassCastException
39      */
testConstructor2()40     public void testConstructor2() {
41         try {
42             updaterFor("z");
43             shouldThrow();
44         } catch (ClassCastException success) {}
45     }
46 
47     /**
48      * Constructor with non-volatile field throws IllegalArgumentException
49      */
testConstructor3()50     public void testConstructor3() {
51         try {
52             updaterFor("w");
53             shouldThrow();
54         } catch (IllegalArgumentException success) {}
55     }
56 
57     /**
58      * Constructor with non-reference field throws ClassCastException
59      */
testConstructor4()60     public void testConstructor4() {
61         try {
62             updaterFor("i");
63             shouldThrow();
64         } catch (ClassCastException success) {}
65     }
66 
67     /**
68      * get returns the last value set or assigned
69      */
testGetSet()70     public void testGetSet() {
71         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
72         a = updaterFor("x");
73         x = one;
74         assertSame(one, a.get(this));
75         a.set(this, two);
76         assertSame(two, a.get(this));
77         a.set(this, m3);
78         assertSame(m3, a.get(this));
79     }
80 
81     /**
82      * get returns the last value lazySet by same thread
83      */
testGetLazySet()84     public void testGetLazySet() {
85         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
86         a = updaterFor("x");
87         x = one;
88         assertSame(one, a.get(this));
89         a.lazySet(this, two);
90         assertSame(two, a.get(this));
91         a.lazySet(this, m3);
92         assertSame(m3, a.get(this));
93     }
94 
95     /**
96      * compareAndSet succeeds in changing value if equal to expected else fails
97      */
testCompareAndSet()98     public void testCompareAndSet() {
99         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
100         a = updaterFor("x");
101         x = one;
102         assertTrue(a.compareAndSet(this, one, two));
103         assertTrue(a.compareAndSet(this, two, m4));
104         assertSame(m4, a.get(this));
105         assertFalse(a.compareAndSet(this, m5, seven));
106         assertFalse(seven == a.get(this));
107         assertTrue(a.compareAndSet(this, m4, seven));
108         assertSame(seven, a.get(this));
109     }
110 
111     /**
112      * compareAndSet in one thread enables another waiting for value
113      * to succeed
114      */
testCompareAndSetInMultipleThreads()115     public void testCompareAndSetInMultipleThreads() throws Exception {
116         x = one;
117         final AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
118         a = updaterFor("x");
119 
120         Thread t = new Thread(new CheckedRunnable() {
121             public void realRun() {
122                 while (!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three))
123                     Thread.yield();
124             }});
125 
126         t.start();
127         assertTrue(a.compareAndSet(this, one, two));
128         t.join(LONG_DELAY_MS);
129         assertFalse(t.isAlive());
130         assertSame(three, a.get(this));
131     }
132 
133     /**
134      * repeated weakCompareAndSet succeeds in changing value when equal
135      * to expected
136      */
testWeakCompareAndSet()137     public void testWeakCompareAndSet() {
138         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
139         a = updaterFor("x");
140         x = one;
141         while (!a.weakCompareAndSet(this, one, two));
142         while (!a.weakCompareAndSet(this, two, m4));
143         assertSame(m4, a.get(this));
144         while (!a.weakCompareAndSet(this, m4, seven));
145         assertSame(seven, a.get(this));
146     }
147 
148     /**
149      * getAndSet returns previous value and sets to given value
150      */
testGetAndSet()151     public void testGetAndSet() {
152         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
153         a = updaterFor("x");
154         x = one;
155         assertSame(one, a.getAndSet(this, zero));
156         assertSame(zero, a.getAndSet(this, m10));
157         assertSame(m10, a.getAndSet(this, 1));
158     }
159 
160 }
161