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