blob: 800a9c8ba46332f94723b1c6836d3bf0a519077c [file] [log] [blame]
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +00001/*
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
7package jsr166;
8
9import java.util.concurrent.CyclicBarrier;
10import java.util.concurrent.Executors;
11import java.util.concurrent.ExecutorService;
12import java.util.concurrent.atomic.LongAdder;
13
14import junit.framework.Test;
15import junit.framework.TestSuite;
16
17public 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}