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 */
33
34import java.util.concurrent.CyclicBarrier;
35import java.util.concurrent.Executors;
36import java.util.concurrent.ExecutorService;
37import java.util.concurrent.atomic.LongAdder;
38
39import junit.framework.Test;
40import junit.framework.TestSuite;
41
42public class LongAdderTest extends JSR166TestCase {
43    public static void main(String[] args) {
44        main(suite(), args);
45    }
46    public static Test suite() {
47        return new TestSuite(LongAdderTest.class);
48    }
49
50    /**
51     * default constructed initializes to zero
52     */
53    public void testConstructor() {
54        LongAdder ai = new LongAdder();
55        assertEquals(0, ai.sum());
56    }
57
58    /**
59     * add adds given value to current, and sum returns current value
60     */
61    public void testAddAndSum() {
62        LongAdder ai = new LongAdder();
63        ai.add(2);
64        assertEquals(2, ai.sum());
65        ai.add(-4);
66        assertEquals(-2, ai.sum());
67    }
68
69    /**
70     * decrement decrements and sum returns current value
71     */
72    public void testDecrementAndsum() {
73        LongAdder ai = new LongAdder();
74        ai.decrement();
75        assertEquals(-1, ai.sum());
76        ai.decrement();
77        assertEquals(-2, ai.sum());
78    }
79
80    /**
81     * incrementAndGet increments and returns current value
82     */
83    public void testIncrementAndsum() {
84        LongAdder ai = new LongAdder();
85        ai.increment();
86        assertEquals(1, ai.sum());
87        ai.increment();
88        assertEquals(2, ai.sum());
89    }
90
91    /**
92     * reset() causes subsequent sum() to return zero
93     */
94    public void testReset() {
95        LongAdder ai = new LongAdder();
96        ai.add(2);
97        assertEquals(2, ai.sum());
98        ai.reset();
99        assertEquals(0, ai.sum());
100    }
101
102    /**
103     * sumThenReset() returns sum; subsequent sum() returns zero
104     */
105    public void testSumThenReset() {
106        LongAdder ai = new LongAdder();
107        ai.add(2);
108        assertEquals(2, ai.sum());
109        assertEquals(2, ai.sumThenReset());
110        assertEquals(0, ai.sum());
111    }
112
113    /**
114     * a deserialized serialized adder holds same value
115     */
116    public void testSerialization() throws Exception {
117        LongAdder x = new LongAdder();
118        LongAdder y = serialClone(x);
119        assertNotSame(x, y);
120        x.add(-22);
121        LongAdder z = serialClone(x);
122        assertNotSame(y, z);
123        assertEquals(-22, x.sum());
124        assertEquals(0, y.sum());
125        assertEquals(-22, z.sum());
126    }
127
128    /**
129     * toString returns current value.
130     */
131    public void testToString() {
132        LongAdder ai = new LongAdder();
133        assertEquals("0", ai.toString());
134        ai.increment();
135        assertEquals(Long.toString(1), ai.toString());
136    }
137
138    /**
139     * intValue returns current value.
140     */
141    public void testIntValue() {
142        LongAdder ai = new LongAdder();
143        assertEquals(0, ai.intValue());
144        ai.increment();
145        assertEquals(1, ai.intValue());
146    }
147
148    /**
149     * longValue returns current value.
150     */
151    public void testLongValue() {
152        LongAdder ai = new LongAdder();
153        assertEquals(0, ai.longValue());
154        ai.increment();
155        assertEquals(1, ai.longValue());
156    }
157
158    /**
159     * floatValue returns current value.
160     */
161    public void testFloatValue() {
162        LongAdder ai = new LongAdder();
163        assertEquals(0.0f, ai.floatValue());
164        ai.increment();
165        assertEquals(1.0f, ai.floatValue());
166    }
167
168    /**
169     * doubleValue returns current value.
170     */
171    public void testDoubleValue() {
172        LongAdder ai = new LongAdder();
173        assertEquals(0.0, ai.doubleValue());
174        ai.increment();
175        assertEquals(1.0, ai.doubleValue());
176    }
177
178    /**
179     * adds by multiple threads produce correct sum
180     */
181    public void testAddAndSumMT() throws Throwable {
182        final int incs = 1000000;
183        final int nthreads = 4;
184        final ExecutorService pool = Executors.newCachedThreadPool();
185        LongAdder a = new LongAdder();
186        CyclicBarrier barrier = new CyclicBarrier(nthreads + 1);
187        for (int i = 0; i < nthreads; ++i)
188            pool.execute(new AdderTask(a, barrier, incs));
189        barrier.await();
190        barrier.await();
191        long total = (long)nthreads * incs;
192        long sum = a.sum();
193        assertEquals(sum, total);
194        pool.shutdown();
195    }
196
197    static final class AdderTask implements Runnable {
198        final LongAdder adder;
199        final CyclicBarrier barrier;
200        final int incs;
201        volatile long result;
202        AdderTask(LongAdder adder, CyclicBarrier barrier, int incs) {
203            this.adder = adder;
204            this.barrier = barrier;
205            this.incs = incs;
206        }
207
208        public void run() {
209            try {
210                barrier.await();
211                LongAdder a = adder;
212                for (int i = 0; i < incs; ++i)
213                    a.add(1L);
214                result = a.sum();
215                barrier.await();
216            } catch (Throwable t) { throw new Error(t); }
217        }
218    }
219
220}
221