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