1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 */
22
23/*
24 * This file is available under and governed by the GNU General Public
25 * License version 2 only, as published by the Free Software Foundation.
26 * However, the following notice accompanied the original version of this
27 * file:
28 *
29 * Written by Doug Lea with assistance from members of JCP JSR-166
30 * Expert Group and released to the public domain, as explained at
31 * http://creativecommons.org/publicdomain/zero/1.0/
32 * Other contributors include Andrew Wright, Jeffrey Hayes,
33 * Pat Fisher, Mike Judd.
34 */
35
36import java.util.concurrent.atomic.AtomicLong;
37
38import junit.framework.Test;
39import junit.framework.TestSuite;
40
41public class AtomicLongTest extends JSR166TestCase {
42    public static void main(String[] args) {
43        main(suite(), args);
44    }
45    public static Test suite() {
46        return new TestSuite(AtomicLongTest.class);
47    }
48
49    final long[] VALUES = {
50        Long.MIN_VALUE,
51        Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE,
52        Long.MAX_VALUE,
53    };
54
55    /**
56     * constructor initializes to given value
57     */
58    public void testConstructor() {
59        AtomicLong ai = new AtomicLong(1);
60        assertEquals(1, ai.get());
61    }
62
63    /**
64     * default constructed initializes to zero
65     */
66    public void testConstructor2() {
67        AtomicLong ai = new AtomicLong();
68        assertEquals(0, ai.get());
69    }
70
71    /**
72     * get returns the last value set
73     */
74    public void testGetSet() {
75        AtomicLong ai = new AtomicLong(1);
76        assertEquals(1, ai.get());
77        ai.set(2);
78        assertEquals(2, ai.get());
79        ai.set(-3);
80        assertEquals(-3, ai.get());
81    }
82
83    /**
84     * get returns the last value lazySet in same thread
85     */
86    public void testGetLazySet() {
87        AtomicLong ai = new AtomicLong(1);
88        assertEquals(1, ai.get());
89        ai.lazySet(2);
90        assertEquals(2, ai.get());
91        ai.lazySet(-3);
92        assertEquals(-3, ai.get());
93    }
94
95    /**
96     * compareAndSet succeeds in changing value if equal to expected else fails
97     */
98    public void testCompareAndSet() {
99        AtomicLong ai = new AtomicLong(1);
100        assertTrue(ai.compareAndSet(1, 2));
101        assertTrue(ai.compareAndSet(2, -4));
102        assertEquals(-4, ai.get());
103        assertFalse(ai.compareAndSet(-5, 7));
104        assertEquals(-4, ai.get());
105        assertTrue(ai.compareAndSet(-4, 7));
106        assertEquals(7, ai.get());
107    }
108
109    /**
110     * compareAndSet in one thread enables another waiting for value
111     * to succeed
112     */
113    public void testCompareAndSetInMultipleThreads() throws Exception {
114        final AtomicLong ai = new AtomicLong(1);
115        Thread t = new Thread(new CheckedRunnable() {
116            public void realRun() {
117                while (!ai.compareAndSet(2, 3))
118                    Thread.yield();
119            }});
120
121        t.start();
122        assertTrue(ai.compareAndSet(1, 2));
123        t.join(LONG_DELAY_MS);
124        assertFalse(t.isAlive());
125        assertEquals(3, ai.get());
126    }
127
128    /**
129     * repeated weakCompareAndSet succeeds in changing value when equal
130     * to expected
131     */
132    public void testWeakCompareAndSet() {
133        AtomicLong ai = new AtomicLong(1);
134        do {} while (!ai.weakCompareAndSet(1, 2));
135        do {} while (!ai.weakCompareAndSet(2, -4));
136        assertEquals(-4, ai.get());
137        do {} while (!ai.weakCompareAndSet(-4, 7));
138        assertEquals(7, ai.get());
139    }
140
141    /**
142     * getAndSet returns previous value and sets to given value
143     */
144    public void testGetAndSet() {
145        AtomicLong ai = new AtomicLong(1);
146        assertEquals(1, ai.getAndSet(0));
147        assertEquals(0, ai.getAndSet(-10));
148        assertEquals(-10, ai.getAndSet(1));
149    }
150
151    /**
152     * getAndAdd returns previous value and adds given value
153     */
154    public void testGetAndAdd() {
155        AtomicLong ai = new AtomicLong(1);
156        assertEquals(1, ai.getAndAdd(2));
157        assertEquals(3, ai.get());
158        assertEquals(3, ai.getAndAdd(-4));
159        assertEquals(-1, ai.get());
160    }
161
162    /**
163     * getAndDecrement returns previous value and decrements
164     */
165    public void testGetAndDecrement() {
166        AtomicLong ai = new AtomicLong(1);
167        assertEquals(1, ai.getAndDecrement());
168        assertEquals(0, ai.getAndDecrement());
169        assertEquals(-1, ai.getAndDecrement());
170    }
171
172    /**
173     * getAndIncrement returns previous value and increments
174     */
175    public void testGetAndIncrement() {
176        AtomicLong ai = new AtomicLong(1);
177        assertEquals(1, ai.getAndIncrement());
178        assertEquals(2, ai.get());
179        ai.set(-2);
180        assertEquals(-2, ai.getAndIncrement());
181        assertEquals(-1, ai.getAndIncrement());
182        assertEquals(0, ai.getAndIncrement());
183        assertEquals(1, ai.get());
184    }
185
186    /**
187     * addAndGet adds given value to current, and returns current value
188     */
189    public void testAddAndGet() {
190        AtomicLong ai = new AtomicLong(1);
191        assertEquals(3, ai.addAndGet(2));
192        assertEquals(3, ai.get());
193        assertEquals(-1, ai.addAndGet(-4));
194        assertEquals(-1, ai.get());
195    }
196
197    /**
198     * decrementAndGet decrements and returns current value
199     */
200    public void testDecrementAndGet() {
201        AtomicLong ai = new AtomicLong(1);
202        assertEquals(0, ai.decrementAndGet());
203        assertEquals(-1, ai.decrementAndGet());
204        assertEquals(-2, ai.decrementAndGet());
205        assertEquals(-2, ai.get());
206    }
207
208    /**
209     * incrementAndGet increments and returns current value
210     */
211    public void testIncrementAndGet() {
212        AtomicLong ai = new AtomicLong(1);
213        assertEquals(2, ai.incrementAndGet());
214        assertEquals(2, ai.get());
215        ai.set(-2);
216        assertEquals(-1, ai.incrementAndGet());
217        assertEquals(0, ai.incrementAndGet());
218        assertEquals(1, ai.incrementAndGet());
219        assertEquals(1, ai.get());
220    }
221
222    /**
223     * a deserialized/reserialized atomic holds same value
224     */
225    public void testSerialization() throws Exception {
226        AtomicLong x = new AtomicLong();
227        AtomicLong y = serialClone(x);
228        assertNotSame(x, y);
229        x.set(-22);
230        AtomicLong z = serialClone(x);
231        assertNotSame(y, z);
232        assertEquals(-22, x.get());
233        assertEquals(0, y.get());
234        assertEquals(-22, z.get());
235    }
236
237    /**
238     * toString returns current value.
239     */
240    public void testToString() {
241        AtomicLong ai = new AtomicLong();
242        assertEquals("0", ai.toString());
243        for (long x : VALUES) {
244            ai.set(x);
245            assertEquals(Long.toString(x), ai.toString());
246        }
247    }
248
249    /**
250     * intValue returns current value.
251     */
252    public void testIntValue() {
253        AtomicLong ai = new AtomicLong();
254        assertEquals(0, ai.intValue());
255        for (long x : VALUES) {
256            ai.set(x);
257            assertEquals((int)x, ai.intValue());
258        }
259    }
260
261    /**
262     * longValue returns current value.
263     */
264    public void testLongValue() {
265        AtomicLong ai = new AtomicLong();
266        assertEquals(0L, ai.longValue());
267        for (long x : VALUES) {
268            ai.set(x);
269            assertEquals(x, ai.longValue());
270        }
271    }
272
273    /**
274     * floatValue returns current value.
275     */
276    public void testFloatValue() {
277        AtomicLong ai = new AtomicLong();
278        assertEquals(0.0f, ai.floatValue());
279        for (long x : VALUES) {
280            ai.set(x);
281            assertEquals((float)x, ai.floatValue());
282        }
283    }
284
285    /**
286     * doubleValue returns current value.
287     */
288    public void testDoubleValue() {
289        AtomicLong ai = new AtomicLong();
290        assertEquals(0.0d, ai.doubleValue());
291        for (long x : VALUES) {
292            ai.set(x);
293            assertEquals((double)x, ai.doubleValue());
294        }
295    }
296
297}
298