LongAccumulatorTest.java revision 13564:1f4febd3c93d
1219820Sjeff/*
2219820Sjeff * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3219820Sjeff *
4219820Sjeff * This code is free software; you can redistribute it and/or modify it
5219820Sjeff * under the terms of the GNU General Public License version 2 only, as
6219820Sjeff * published by the Free Software Foundation.
7219820Sjeff *
8219820Sjeff * This code is distributed in the hope that it will be useful, but WITHOUT
9219820Sjeff * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10219820Sjeff * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11219820Sjeff * version 2 for more details (a copy is included in the LICENSE file that
12219820Sjeff * accompanied this code).
13219820Sjeff *
14219820Sjeff * You should have received a copy of the GNU General Public License version
15219820Sjeff * 2 along with this work; if not, write to the Free Software Foundation,
16219820Sjeff * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17219820Sjeff *
18219820Sjeff * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19219820Sjeff * or visit www.oracle.com if you need additional information or have any
20219820Sjeff * questions.
21219820Sjeff */
22219820Sjeff
23219820Sjeff/*
24219820Sjeff * This file is available under and governed by the GNU General Public
25219820Sjeff * License version 2 only, as published by the Free Software Foundation.
26219820Sjeff * However, the following notice accompanied the original version of this
27219820Sjeff * file:
28219820Sjeff *
29219820Sjeff * Written by Doug Lea with assistance from members of JCP JSR-166
30219820Sjeff * Expert Group and released to the public domain, as explained at
31219820Sjeff * http://creativecommons.org/publicdomain/zero/1.0/
32219820Sjeff */
33219820Sjeff
34219820Sjeffimport java.util.concurrent.Executors;
35219820Sjeffimport java.util.concurrent.ExecutorService;
36219820Sjeffimport java.util.concurrent.Phaser;
37219820Sjeffimport java.util.concurrent.atomic.LongAccumulator;
38219820Sjeff
39219820Sjeffimport junit.framework.Test;
40219820Sjeffimport junit.framework.TestSuite;
41219820Sjeff
42219820Sjeffpublic class LongAccumulatorTest extends JSR166TestCase {
43219820Sjeff    public static void main(String[] args) {
44219820Sjeff        main(suite(), args);
45219820Sjeff    }
46219820Sjeff    public static Test suite() {
47219820Sjeff        return new TestSuite(LongAccumulatorTest.class);
48219820Sjeff    }
49219820Sjeff
50219820Sjeff    /**
51219820Sjeff     * default constructed initializes to zero
52219820Sjeff     */
53219820Sjeff    public void testConstructor() {
54219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
55219820Sjeff        assertEquals(0, ai.get());
56219820Sjeff    }
57219820Sjeff
58219820Sjeff    /**
59219820Sjeff     * accumulate accumulates given value to current, and get returns current value
60219820Sjeff     */
61219820Sjeff    public void testAccumulateAndGet() {
62219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
63219820Sjeff        ai.accumulate(2);
64219820Sjeff        assertEquals(2, ai.get());
65219820Sjeff        ai.accumulate(-4);
66219820Sjeff        assertEquals(2, ai.get());
67219820Sjeff        ai.accumulate(4);
68219820Sjeff        assertEquals(4, ai.get());
69219820Sjeff    }
70219820Sjeff
71219820Sjeff    /**
72219820Sjeff     * reset() causes subsequent get() to return zero
73219820Sjeff     */
74219820Sjeff    public void testReset() {
75219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
76219820Sjeff        ai.accumulate(2);
77219820Sjeff        assertEquals(2, ai.get());
78219820Sjeff        ai.reset();
79219820Sjeff        assertEquals(0, ai.get());
80219820Sjeff    }
81219820Sjeff
82219820Sjeff    /**
83219820Sjeff     * getThenReset() returns current value; subsequent get() returns zero
84219820Sjeff     */
85219820Sjeff    public void testGetThenReset() {
86219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
87219820Sjeff        ai.accumulate(2);
88219820Sjeff        assertEquals(2, ai.get());
89219820Sjeff        assertEquals(2, ai.getThenReset());
90219820Sjeff        assertEquals(0, ai.get());
91219820Sjeff    }
92219820Sjeff
93219820Sjeff    /**
94219820Sjeff     * toString returns current value.
95219820Sjeff     */
96219820Sjeff    public void testToString() {
97219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
98219820Sjeff        assertEquals("0", ai.toString());
99219820Sjeff        ai.accumulate(1);
100219820Sjeff        assertEquals(Long.toString(1), ai.toString());
101219820Sjeff    }
102219820Sjeff
103219820Sjeff    /**
104219820Sjeff     * intValue returns current value.
105219820Sjeff     */
106219820Sjeff    public void testIntValue() {
107219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
108219820Sjeff        assertEquals(0, ai.intValue());
109219820Sjeff        ai.accumulate(1);
110219820Sjeff        assertEquals(1, ai.intValue());
111219820Sjeff    }
112219820Sjeff
113219820Sjeff    /**
114219820Sjeff     * longValue returns current value.
115219820Sjeff     */
116219820Sjeff    public void testLongValue() {
117219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
118219820Sjeff        assertEquals(0, ai.longValue());
119219820Sjeff        ai.accumulate(1);
120219820Sjeff        assertEquals(1, ai.longValue());
121219820Sjeff    }
122219820Sjeff
123219820Sjeff    /**
124219820Sjeff     * floatValue returns current value.
125219820Sjeff     */
126219820Sjeff    public void testFloatValue() {
127219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
128219820Sjeff        assertEquals(0.0f, ai.floatValue());
129219820Sjeff        ai.accumulate(1);
130219820Sjeff        assertEquals(1.0f, ai.floatValue());
131219820Sjeff    }
132219820Sjeff
133219820Sjeff    /**
134219820Sjeff     * doubleValue returns current value.
135219820Sjeff     */
136219820Sjeff    public void testDoubleValue() {
137219820Sjeff        LongAccumulator ai = new LongAccumulator(Long::max, 0L);
138219820Sjeff        assertEquals(0.0, ai.doubleValue());
139219820Sjeff        ai.accumulate(1);
140219820Sjeff        assertEquals(1.0, ai.doubleValue());
141219820Sjeff    }
142219820Sjeff
143219820Sjeff    /**
144219820Sjeff     * accumulates by multiple threads produce correct result
145219820Sjeff     */
146219820Sjeff    public void testAccumulateAndGetMT() {
147219820Sjeff        final int incs = 1000000;
148219820Sjeff        final int nthreads = 4;
149219820Sjeff        final ExecutorService pool = Executors.newCachedThreadPool();
150219820Sjeff        LongAccumulator a = new LongAccumulator(Long::max, 0L);
151219820Sjeff        Phaser phaser = new Phaser(nthreads + 1);
152219820Sjeff        for (int i = 0; i < nthreads; ++i)
153219820Sjeff            pool.execute(new AccTask(a, phaser, incs));
154219820Sjeff        phaser.arriveAndAwaitAdvance();
155219820Sjeff        phaser.arriveAndAwaitAdvance();
156219820Sjeff        long expected = incs - 1;
157219820Sjeff        long result = a.get();
158219820Sjeff        assertEquals(expected, result);
159219820Sjeff        pool.shutdown();
160219820Sjeff    }
161219820Sjeff
162219820Sjeff    static final class AccTask implements Runnable {
163219820Sjeff        final LongAccumulator acc;
164219820Sjeff        final Phaser phaser;
165219820Sjeff        final int incs;
166219820Sjeff        volatile long result;
167219820Sjeff        AccTask(LongAccumulator acc, Phaser phaser, int incs) {
168219820Sjeff            this.acc = acc;
169219820Sjeff            this.phaser = phaser;
170219820Sjeff            this.incs = incs;
171219820Sjeff        }
172219820Sjeff
173219820Sjeff        public void run() {
174219820Sjeff            phaser.arriveAndAwaitAdvance();
175219820Sjeff            LongAccumulator a = acc;
176219820Sjeff            for (int i = 0; i < incs; ++i)
177219820Sjeff                a.accumulate(i);
178219820Sjeff            result = a.get();
179219820Sjeff            phaser.arrive();
180219820Sjeff        }
181219820Sjeff    }
182219820Sjeff
183219820Sjeff}
184219820Sjeff