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