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