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 */ 6 7 package jsr166; 8 9 import java.util.concurrent.CyclicBarrier; 10 import java.util.concurrent.Executors; 11 import java.util.concurrent.ExecutorService; 12 import java.util.concurrent.atomic.DoubleAdder; 13 14 import junit.framework.Test; 15 import junit.framework.TestSuite; 16 17 public class DoubleAdderTest extends JSR166TestCase { 18 // android-note: Removed because the CTS runner does a bad job of 19 // retrying tests that have suite() declarations. 20 // 21 // public static void main(String[] args) { 22 // main(suite(), args); 23 // } 24 // public static Test suite() { 25 // return new TestSuite(DoubleAdderTest.class); 26 // } 27 28 /** 29 * default constructed initializes to zero 30 */ testConstructor()31 public void testConstructor() { 32 DoubleAdder ai = new DoubleAdder(); 33 assertEquals(0.0, ai.sum()); 34 } 35 36 /** 37 * add adds given value to current, and sum returns current value 38 */ testAddAndSum()39 public void testAddAndSum() { 40 DoubleAdder ai = new DoubleAdder(); 41 ai.add(2.0); 42 assertEquals(2.0, ai.sum()); 43 ai.add(-4.0); 44 assertEquals(-2.0, ai.sum()); 45 } 46 47 /** 48 * reset() causes subsequent sum() to return zero 49 */ testReset()50 public void testReset() { 51 DoubleAdder ai = new DoubleAdder(); 52 ai.add(2.0); 53 assertEquals(2.0, ai.sum()); 54 ai.reset(); 55 assertEquals(0.0, ai.sum()); 56 } 57 58 /** 59 * sumThenReset() returns sum; subsequent sum() returns zero 60 */ testSumThenReset()61 public void testSumThenReset() { 62 DoubleAdder ai = new DoubleAdder(); 63 ai.add(2.0); 64 assertEquals(2.0, ai.sum()); 65 assertEquals(2.0, ai.sumThenReset()); 66 assertEquals(0.0, ai.sum()); 67 } 68 69 /** 70 * a deserialized serialized adder holds same value 71 */ testSerialization()72 public void testSerialization() throws Exception { 73 DoubleAdder x = new DoubleAdder(); 74 DoubleAdder y = serialClone(x); 75 assertNotSame(x, y); 76 x.add(-22.0); 77 DoubleAdder z = serialClone(x); 78 assertEquals(-22.0, x.sum()); 79 assertEquals(0.0, y.sum()); 80 assertEquals(-22.0, z.sum()); 81 } 82 83 /** 84 * toString returns current value. 85 */ testToString()86 public void testToString() { 87 DoubleAdder ai = new DoubleAdder(); 88 assertEquals(Double.toString(0.0), ai.toString()); 89 ai.add(1.0); 90 assertEquals(Double.toString(1.0), ai.toString()); 91 } 92 93 /** 94 * intValue returns current value. 95 */ testIntValue()96 public void testIntValue() { 97 DoubleAdder ai = new DoubleAdder(); 98 assertEquals(0, ai.intValue()); 99 ai.add(1.0); 100 assertEquals(1, ai.intValue()); 101 } 102 103 /** 104 * longValue returns current value. 105 */ testLongValue()106 public void testLongValue() { 107 DoubleAdder ai = new DoubleAdder(); 108 assertEquals(0, ai.longValue()); 109 ai.add(1.0); 110 assertEquals(1, ai.longValue()); 111 } 112 113 /** 114 * floatValue returns current value. 115 */ testFloatValue()116 public void testFloatValue() { 117 DoubleAdder ai = new DoubleAdder(); 118 assertEquals(0.0f, ai.floatValue()); 119 ai.add(1.0); 120 assertEquals(1.0f, ai.floatValue()); 121 } 122 123 /** 124 * doubleValue returns current value. 125 */ testDoubleValue()126 public void testDoubleValue() { 127 DoubleAdder ai = new DoubleAdder(); 128 assertEquals(0.0, ai.doubleValue()); 129 ai.add(1.0); 130 assertEquals(1.0, ai.doubleValue()); 131 } 132 133 /** 134 * adds by multiple threads produce correct sum 135 */ testAddAndSumMT()136 public void testAddAndSumMT() throws Throwable { 137 final int incs = 1000000; 138 final int nthreads = 4; 139 final ExecutorService pool = Executors.newCachedThreadPool(); 140 DoubleAdder a = new DoubleAdder(); 141 CyclicBarrier barrier = new CyclicBarrier(nthreads + 1); 142 for (int i = 0; i < nthreads; ++i) 143 pool.execute(new AdderTask(a, barrier, incs)); 144 barrier.await(); 145 barrier.await(); 146 double total = (long)nthreads * incs; 147 double sum = a.sum(); 148 assertEquals(sum, total); 149 pool.shutdown(); 150 } 151 152 static final class AdderTask implements Runnable { 153 final DoubleAdder adder; 154 final CyclicBarrier barrier; 155 final int incs; 156 volatile double result; AdderTask(DoubleAdder adder, CyclicBarrier barrier, int incs)157 AdderTask(DoubleAdder adder, CyclicBarrier barrier, int incs) { 158 this.adder = adder; 159 this.barrier = barrier; 160 this.incs = incs; 161 } 162 run()163 public void run() { 164 try { 165 barrier.await(); 166 DoubleAdder a = adder; 167 for (int i = 0; i < incs; ++i) 168 a.add(1.0); 169 result = a.sum(); 170 barrier.await(); 171 } catch (Throwable t) { throw new Error(t); } 172 } 173 } 174 175 } 176