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