Home | History | Annotate | Download | only in jsr166
      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      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    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;
    157         AdderTask(DoubleAdder adder, CyclicBarrier barrier, int incs) {
    158             this.adder = adder;
    159             this.barrier = barrier;
    160             this.incs = incs;
    161         }
    162 
    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