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