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
7package jsr166;
8
9import java.util.concurrent.Executors;
10import java.util.concurrent.ExecutorService;
11import java.util.concurrent.Phaser;
12import java.util.concurrent.atomic.LongAccumulator;
13
14import junit.framework.Test;
15import junit.framework.TestSuite;
16
17public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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;
145        AccTask(LongAccumulator acc, Phaser phaser, int incs) {
146            this.acc = acc;
147            this.phaser = phaser;
148            this.incs = incs;
149        }
150
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