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
9package jsr166;
10
11import java.util.concurrent.atomic.AtomicMarkableReference;
12
13import junit.framework.Test;
14import junit.framework.TestSuite;
15
16public class AtomicMarkableReferenceTest extends JSR166TestCase {
17    // android-note: Removed because the CTS runner does a bad job of
18    // retrying tests that have suite() declarations.
19    //
20    // public static void main(String[] args) {
21    //     main(suite(), args);
22    // }
23    // public static Test suite() {
24    //     return new TestSuite(AtomicMarkableReferenceTest.class);
25    // }
26
27    /**
28     * constructor initializes to given reference and mark
29     */
30    public void testConstructor() {
31        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
32        assertSame(one, ai.getReference());
33        assertFalse(ai.isMarked());
34        AtomicMarkableReference a2 = new AtomicMarkableReference(null, true);
35        assertNull(a2.getReference());
36        assertTrue(a2.isMarked());
37    }
38
39    /**
40     * get returns the last values of reference and mark set
41     */
42    public void testGetSet() {
43        boolean[] mark = new boolean[1];
44        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
45        assertSame(one, ai.getReference());
46        assertFalse(ai.isMarked());
47        assertSame(one, ai.get(mark));
48        assertFalse(mark[0]);
49        ai.set(two, false);
50        assertSame(two, ai.getReference());
51        assertFalse(ai.isMarked());
52        assertSame(two, ai.get(mark));
53        assertFalse(mark[0]);
54        ai.set(one, true);
55        assertSame(one, ai.getReference());
56        assertTrue(ai.isMarked());
57        assertSame(one, ai.get(mark));
58        assertTrue(mark[0]);
59    }
60
61    /**
62     * attemptMark succeeds in single thread
63     */
64    public void testAttemptMark() {
65        boolean[] mark = new boolean[1];
66        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
67        assertFalse(ai.isMarked());
68        assertTrue(ai.attemptMark(one, true));
69        assertTrue(ai.isMarked());
70        assertSame(one, ai.get(mark));
71        assertTrue(mark[0]);
72    }
73
74    /**
75     * compareAndSet succeeds in changing values if equal to expected reference
76     * and mark else fails
77     */
78    public void testCompareAndSet() {
79        boolean[] mark = new boolean[1];
80        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
81        assertSame(one, ai.get(mark));
82        assertFalse(ai.isMarked());
83        assertFalse(mark[0]);
84
85        assertTrue(ai.compareAndSet(one, two, false, false));
86        assertSame(two, ai.get(mark));
87        assertFalse(mark[0]);
88
89        assertTrue(ai.compareAndSet(two, m3, false, true));
90        assertSame(m3, ai.get(mark));
91        assertTrue(mark[0]);
92
93        assertFalse(ai.compareAndSet(two, m3, true, true));
94        assertSame(m3, ai.get(mark));
95        assertTrue(mark[0]);
96    }
97
98    /**
99     * compareAndSet in one thread enables another waiting for reference value
100     * to succeed
101     */
102    public void testCompareAndSetInMultipleThreads() throws Exception {
103        final AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
104        Thread t = new Thread(new CheckedRunnable() {
105            public void realRun() {
106                while (!ai.compareAndSet(two, three, false, false))
107                    Thread.yield();
108            }});
109
110        t.start();
111        assertTrue(ai.compareAndSet(one, two, false, false));
112        t.join(LONG_DELAY_MS);
113        assertFalse(t.isAlive());
114        assertSame(three, ai.getReference());
115        assertFalse(ai.isMarked());
116    }
117
118    /**
119     * compareAndSet in one thread enables another waiting for mark value
120     * to succeed
121     */
122    public void testCompareAndSetInMultipleThreads2() throws Exception {
123        final AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
124        Thread t = new Thread(new CheckedRunnable() {
125            public void realRun() {
126                while (!ai.compareAndSet(one, one, true, false))
127                    Thread.yield();
128            }});
129
130        t.start();
131        assertTrue(ai.compareAndSet(one, one, false, true));
132        t.join(LONG_DELAY_MS);
133        assertFalse(t.isAlive());
134        assertSame(one, ai.getReference());
135        assertFalse(ai.isMarked());
136    }
137
138    /**
139     * repeated weakCompareAndSet succeeds in changing values when equal
140     * to expected
141     */
142    public void testWeakCompareAndSet() {
143        boolean[] mark = new boolean[1];
144        AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
145        assertSame(one, ai.get(mark));
146        assertFalse(ai.isMarked());
147        assertFalse(mark[0]);
148
149        do {} while (!ai.weakCompareAndSet(one, two, false, false));
150        assertSame(two, ai.get(mark));
151        assertFalse(mark[0]);
152
153        do {} while (!ai.weakCompareAndSet(two, m3, false, true));
154        assertSame(m3, ai.get(mark));
155        assertTrue(mark[0]);
156    }
157
158}
159