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