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 
  34 import java.util.concurrent.Executors;
  35 import java.util.concurrent.ExecutorService;
  36 import java.util.concurrent.Phaser;
  37 import java.util.concurrent.ThreadLocalRandom;
  38 import java.util.concurrent.atomic.DoubleAccumulator;
  39 
  40 import junit.framework.Test;
  41 import junit.framework.TestSuite;
  42 
  43 public class DoubleAccumulatorTest extends JSR166TestCase {
  44     public static void main(String[] args) {
  45         main(suite(), args);
  46     }
  47     public static Test suite() {
  48         return new TestSuite(DoubleAccumulatorTest.class);
  49     }
  50 
  51     /**
  52      * new instance initialized to supplied identity
  53      */
  54     public void testConstructor() {
  55         for (double identity : new double[] {
  56                  Double.NEGATIVE_INFINITY,
  57                  Double.POSITIVE_INFINITY,
  58                  Double.MIN_VALUE,
  59                  Double.MAX_VALUE,
  60                  0.0,
  61              })
  62             assertEquals(identity,
  63                          new DoubleAccumulator(Double::max, identity).get());
  64     }
  65 
  66     /**
  67      * accumulate accumulates given value to current, and get returns current value
  68      */
  69     public void testAccumulateAndGet() {
  70         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
  71         acc.accumulate(2.0);
  72         assertEquals(2.0, acc.get());
  73         acc.accumulate(-4.0);
  74         assertEquals(2.0, acc.get());
  75         acc.accumulate(4.0);
  76         assertEquals(4.0, acc.get());
  77     }
  78 
  79     /**
  80      * reset() causes subsequent get() to return zero
  81      */
  82     public void testReset() {
  83         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
  84         acc.accumulate(2.0);
  85         assertEquals(2.0, acc.get());
  86         acc.reset();
  87         assertEquals(0.0, acc.get());
  88     }
  89 
  90     /**
  91      * getThenReset() returns current value; subsequent get() returns zero
  92      */
  93     public void testGetThenReset() {
  94         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
  95         acc.accumulate(2.0);
  96         assertEquals(2.0, acc.get());
  97         assertEquals(2.0, acc.getThenReset());
  98         assertEquals(0.0, acc.get());
  99     }
 100 
 101     /**
 102      * toString returns current value.
 103      */
 104     public void testToString() {
 105         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
 106         assertEquals("0.0", acc.toString());
 107         acc.accumulate(1.0);
 108         assertEquals(Double.toString(1.0), acc.toString());
 109     }
 110 
 111     /**
 112      * intValue returns current value.
 113      */
 114     public void testIntValue() {
 115         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
 116         assertEquals(0, acc.intValue());
 117         acc.accumulate(1.0);
 118         assertEquals(1, acc.intValue());
 119     }
 120 
 121     /**
 122      * longValue returns current value.
 123      */
 124     public void testLongValue() {
 125         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
 126         assertEquals(0, acc.longValue());
 127         acc.accumulate(1.0);
 128         assertEquals(1, acc.longValue());
 129     }
 130 
 131     /**
 132      * floatValue returns current value.
 133      */
 134     public void testFloatValue() {
 135         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
 136         assertEquals(0.0f, acc.floatValue());
 137         acc.accumulate(1.0);
 138         assertEquals(1.0f, acc.floatValue());
 139     }
 140 
 141     /**
 142      * doubleValue returns current value.
 143      */
 144     public void testDoubleValue() {
 145         DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
 146         assertEquals(0.0, acc.doubleValue());
 147         acc.accumulate(1.0);
 148         assertEquals(1.0, acc.doubleValue());
 149     }
 150 
 151     /**
 152      * accumulates by multiple threads produce correct result
 153      */
 154     public void testAccumulateAndGetMT() {
 155         final DoubleAccumulator acc
 156             = new DoubleAccumulator((x, y) -> x + y, 0.0);
 157         final int nThreads = ThreadLocalRandom.current().nextInt(1, 5);
 158         final Phaser phaser = new Phaser(nThreads + 1);
 159         final int incs = expensiveTests ? 1_000_000 : 100_000;
 160         final double total = nThreads * incs/2.0 * (incs - 1); // Gauss
 161         final Runnable task = () -> {
 162             phaser.arriveAndAwaitAdvance();
 163             for (int i = 0; i < incs; i++) {
 164                 acc.accumulate((double) i);
 165                 assertTrue(acc.get() <= total);
 166             }
 167             phaser.arrive();
 168         };
 169         final ExecutorService p = Executors.newCachedThreadPool();
 170         try (PoolCleaner cleaner = cleaner(p)) {
 171             for (int i = nThreads; i-->0; )
 172                 p.execute(task);
 173             phaser.arriveAndAwaitAdvance();
 174             phaser.arriveAndAwaitAdvance();
 175             assertEquals(total, acc.get());
 176         }
 177     }
 178 
 179 }