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