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.AtomicLong;
12
13import junit.framework.Test;
14import junit.framework.TestSuite;
15
16public class AtomicLongTest 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(AtomicLongTest.class);
25    // }
26
27    final long[] VALUES = {
28        Long.MIN_VALUE,
29        Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE,
30        Long.MAX_VALUE,
31    };
32
33    /**
34     * constructor initializes to given value
35     */
36    public void testConstructor() {
37        AtomicLong ai = new AtomicLong(1);
38        assertEquals(1, ai.get());
39    }
40
41    /**
42     * default constructed initializes to zero
43     */
44    public void testConstructor2() {
45        AtomicLong ai = new AtomicLong();
46        assertEquals(0, ai.get());
47    }
48
49    /**
50     * get returns the last value set
51     */
52    public void testGetSet() {
53        AtomicLong ai = new AtomicLong(1);
54        assertEquals(1, ai.get());
55        ai.set(2);
56        assertEquals(2, ai.get());
57        ai.set(-3);
58        assertEquals(-3, ai.get());
59    }
60
61    /**
62     * get returns the last value lazySet in same thread
63     */
64    public void testGetLazySet() {
65        AtomicLong ai = new AtomicLong(1);
66        assertEquals(1, ai.get());
67        ai.lazySet(2);
68        assertEquals(2, ai.get());
69        ai.lazySet(-3);
70        assertEquals(-3, ai.get());
71    }
72
73    /**
74     * compareAndSet succeeds in changing value if equal to expected else fails
75     */
76    public void testCompareAndSet() {
77        AtomicLong ai = new AtomicLong(1);
78        assertTrue(ai.compareAndSet(1, 2));
79        assertTrue(ai.compareAndSet(2, -4));
80        assertEquals(-4, ai.get());
81        assertFalse(ai.compareAndSet(-5, 7));
82        assertEquals(-4, ai.get());
83        assertTrue(ai.compareAndSet(-4, 7));
84        assertEquals(7, ai.get());
85    }
86
87    /**
88     * compareAndSet in one thread enables another waiting for value
89     * to succeed
90     */
91    public void testCompareAndSetInMultipleThreads() throws Exception {
92        final AtomicLong ai = new AtomicLong(1);
93        Thread t = new Thread(new CheckedRunnable() {
94            public void realRun() {
95                while (!ai.compareAndSet(2, 3))
96                    Thread.yield();
97            }});
98
99        t.start();
100        assertTrue(ai.compareAndSet(1, 2));
101        t.join(LONG_DELAY_MS);
102        assertFalse(t.isAlive());
103        assertEquals(3, ai.get());
104    }
105
106    /**
107     * repeated weakCompareAndSet succeeds in changing value when equal
108     * to expected
109     */
110    public void testWeakCompareAndSet() {
111        AtomicLong ai = new AtomicLong(1);
112        do {} while (!ai.weakCompareAndSet(1, 2));
113        do {} while (!ai.weakCompareAndSet(2, -4));
114        assertEquals(-4, ai.get());
115        do {} while (!ai.weakCompareAndSet(-4, 7));
116        assertEquals(7, ai.get());
117    }
118
119    /**
120     * getAndSet returns previous value and sets to given value
121     */
122    public void testGetAndSet() {
123        AtomicLong ai = new AtomicLong(1);
124        assertEquals(1, ai.getAndSet(0));
125        assertEquals(0, ai.getAndSet(-10));
126        assertEquals(-10, ai.getAndSet(1));
127    }
128
129    /**
130     * getAndAdd returns previous value and adds given value
131     */
132    public void testGetAndAdd() {
133        AtomicLong ai = new AtomicLong(1);
134        assertEquals(1, ai.getAndAdd(2));
135        assertEquals(3, ai.get());
136        assertEquals(3, ai.getAndAdd(-4));
137        assertEquals(-1, ai.get());
138    }
139
140    /**
141     * getAndDecrement returns previous value and decrements
142     */
143    public void testGetAndDecrement() {
144        AtomicLong ai = new AtomicLong(1);
145        assertEquals(1, ai.getAndDecrement());
146        assertEquals(0, ai.getAndDecrement());
147        assertEquals(-1, ai.getAndDecrement());
148    }
149
150    /**
151     * getAndIncrement returns previous value and increments
152     */
153    public void testGetAndIncrement() {
154        AtomicLong ai = new AtomicLong(1);
155        assertEquals(1, ai.getAndIncrement());
156        assertEquals(2, ai.get());
157        ai.set(-2);
158        assertEquals(-2, ai.getAndIncrement());
159        assertEquals(-1, ai.getAndIncrement());
160        assertEquals(0, ai.getAndIncrement());
161        assertEquals(1, ai.get());
162    }
163
164    /**
165     * addAndGet adds given value to current, and returns current value
166     */
167    public void testAddAndGet() {
168        AtomicLong ai = new AtomicLong(1);
169        assertEquals(3, ai.addAndGet(2));
170        assertEquals(3, ai.get());
171        assertEquals(-1, ai.addAndGet(-4));
172        assertEquals(-1, ai.get());
173    }
174
175    /**
176     * decrementAndGet decrements and returns current value
177     */
178    public void testDecrementAndGet() {
179        AtomicLong ai = new AtomicLong(1);
180        assertEquals(0, ai.decrementAndGet());
181        assertEquals(-1, ai.decrementAndGet());
182        assertEquals(-2, ai.decrementAndGet());
183        assertEquals(-2, ai.get());
184    }
185
186    /**
187     * incrementAndGet increments and returns current value
188     */
189    public void testIncrementAndGet() {
190        AtomicLong ai = new AtomicLong(1);
191        assertEquals(2, ai.incrementAndGet());
192        assertEquals(2, ai.get());
193        ai.set(-2);
194        assertEquals(-1, ai.incrementAndGet());
195        assertEquals(0, ai.incrementAndGet());
196        assertEquals(1, ai.incrementAndGet());
197        assertEquals(1, ai.get());
198    }
199
200    /**
201     * a deserialized serialized atomic holds same value
202     */
203    public void testSerialization() throws Exception {
204        AtomicLong x = new AtomicLong();
205        AtomicLong y = serialClone(x);
206        assertNotSame(x, y);
207        x.set(-22);
208        AtomicLong z = serialClone(x);
209        assertNotSame(y, z);
210        assertEquals(-22, x.get());
211        assertEquals(0, y.get());
212        assertEquals(-22, z.get());
213    }
214
215    /**
216     * toString returns current value.
217     */
218    public void testToString() {
219        AtomicLong ai = new AtomicLong();
220        assertEquals("0", ai.toString());
221        for (long x : VALUES) {
222            ai.set(x);
223            assertEquals(Long.toString(x), ai.toString());
224        }
225    }
226
227    /**
228     * intValue returns current value.
229     */
230    public void testIntValue() {
231        AtomicLong ai = new AtomicLong();
232        assertEquals(0, ai.intValue());
233        for (long x : VALUES) {
234            ai.set(x);
235            assertEquals((int)x, ai.intValue());
236        }
237    }
238
239    /**
240     * longValue returns current value.
241     */
242    public void testLongValue() {
243        AtomicLong ai = new AtomicLong();
244        assertEquals(0L, ai.longValue());
245        for (long x : VALUES) {
246            ai.set(x);
247            assertEquals(x, ai.longValue());
248        }
249    }
250
251    /**
252     * floatValue returns current value.
253     */
254    public void testFloatValue() {
255        AtomicLong ai = new AtomicLong();
256        assertEquals(0.0f, ai.floatValue());
257        for (long x : VALUES) {
258            ai.set(x);
259            assertEquals((float)x, ai.floatValue());
260        }
261    }
262
263    /**
264     * doubleValue returns current value.
265     */
266    public void testDoubleValue() {
267        AtomicLong ai = new AtomicLong();
268        assertEquals(0.0d, ai.doubleValue());
269        for (long x : VALUES) {
270            ai.set(x);
271            assertEquals((double)x, ai.doubleValue());
272        }
273    }
274
275}
276