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.ThreadLocalRandom;
10import java.util.concurrent.atomic.AtomicInteger;
11import java.util.concurrent.atomic.LongAdder;
12
13import junit.framework.Test;
14import junit.framework.TestSuite;
15
16public class ThreadLocalRandom8Test extends JSR166TestCase {
17
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(ThreadLocalRandom8Test.class);
26    // }
27
28    // max sampled int bound
29    static final int MAX_INT_BOUND = (1 << 26);
30
31    // max sampled long bound
32    static final long MAX_LONG_BOUND = (1L << 42);
33
34    // Number of replications for other checks
35    static final int REPS =
36        Integer.getInteger("ThreadLocalRandom8Test.reps", 4);
37
38    /**
39     * Invoking sized ints, long, doubles, with negative sizes throws
40     * IllegalArgumentException
41     */
42    public void testBadStreamSize() {
43        ThreadLocalRandom r = ThreadLocalRandom.current();
44        Runnable[] throwingActions = {
45            () -> r.ints(-1L),
46            () -> r.ints(-1L, 2, 3),
47            () -> r.longs(-1L),
48            () -> r.longs(-1L, -1L, 1L),
49            () -> r.doubles(-1L),
50            () -> r.doubles(-1L, .5, .6),
51        };
52        assertThrows(IllegalArgumentException.class, throwingActions);
53    }
54
55    /**
56     * Invoking bounded ints, long, doubles, with illegal bounds throws
57     * IllegalArgumentException
58     */
59    public void testBadStreamBounds() {
60        ThreadLocalRandom r = ThreadLocalRandom.current();
61        Runnable[] throwingActions = {
62            () -> r.ints(2, 1),
63            () -> r.ints(10, 42, 42),
64            () -> r.longs(-1L, -1L),
65            () -> r.longs(10, 1L, -2L),
66            () -> r.doubles(0.0, 0.0),
67            () -> r.doubles(10, .5, .4),
68        };
69        assertThrows(IllegalArgumentException.class, throwingActions);
70    }
71
72    /**
73     * A parallel sized stream of ints generates the given number of values
74     */
75    public void testIntsCount() {
76        LongAdder counter = new LongAdder();
77        ThreadLocalRandom r = ThreadLocalRandom.current();
78        long size = 0;
79        for (int reps = 0; reps < REPS; ++reps) {
80            counter.reset();
81            r.ints(size).parallel().forEach(x -> counter.increment());
82            assertEquals(size, counter.sum());
83            size += 524959;
84        }
85    }
86
87    /**
88     * A parallel sized stream of longs generates the given number of values
89     */
90    public void testLongsCount() {
91        LongAdder counter = new LongAdder();
92        ThreadLocalRandom r = ThreadLocalRandom.current();
93        long size = 0;
94        for (int reps = 0; reps < REPS; ++reps) {
95            counter.reset();
96            r.longs(size).parallel().forEach(x -> counter.increment());
97            assertEquals(size, counter.sum());
98            size += 524959;
99        }
100    }
101
102    /**
103     * A parallel sized stream of doubles generates the given number of values
104     */
105    public void testDoublesCount() {
106        LongAdder counter = new LongAdder();
107        ThreadLocalRandom r = ThreadLocalRandom.current();
108        long size = 0;
109        for (int reps = 0; reps < REPS; ++reps) {
110            counter.reset();
111            r.doubles(size).parallel().forEach(x -> counter.increment());
112            assertEquals(size, counter.sum());
113            size += 524959;
114        }
115    }
116
117    /**
118     * Each of a parallel sized stream of bounded ints is within bounds
119     */
120    public void testBoundedInts() {
121        AtomicInteger fails = new AtomicInteger(0);
122        ThreadLocalRandom r = ThreadLocalRandom.current();
123        long size = 12345L;
124        for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
125            for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
126                final int lo = least, hi = bound;
127                r.ints(size, lo, hi).parallel().forEach(
128                    x -> {
129                        if (x < lo || x >= hi)
130                            fails.getAndIncrement(); });
131            }
132        }
133        assertEquals(0, fails.get());
134    }
135
136    /**
137     * Each of a parallel sized stream of bounded longs is within bounds
138     */
139    public void testBoundedLongs() {
140        AtomicInteger fails = new AtomicInteger(0);
141        ThreadLocalRandom r = ThreadLocalRandom.current();
142        long size = 123L;
143        for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
144            for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
145                final long lo = least, hi = bound;
146                r.longs(size, lo, hi).parallel().forEach(
147                    x -> {
148                        if (x < lo || x >= hi)
149                            fails.getAndIncrement(); });
150            }
151        }
152        assertEquals(0, fails.get());
153    }
154
155    /**
156     * Each of a parallel sized stream of bounded doubles is within bounds
157     */
158    public void testBoundedDoubles() {
159        AtomicInteger fails = new AtomicInteger(0);
160        ThreadLocalRandom r = ThreadLocalRandom.current();
161        long size = 456;
162        for (double least = 0.00011; least < 1.0e20; least *= 9) {
163            for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
164                final double lo = least, hi = bound;
165                r.doubles(size, lo, hi).parallel().forEach(
166                    x -> {
167                        if (x < lo || x >= hi)
168                            fails.getAndIncrement(); });
169            }
170        }
171        assertEquals(0, fails.get());
172    }
173
174    /**
175     * A parallel unsized stream of ints generates at least 100 values
176     */
177    public void testUnsizedIntsCount() {
178        LongAdder counter = new LongAdder();
179        ThreadLocalRandom r = ThreadLocalRandom.current();
180        long size = 100;
181        r.ints().limit(size).parallel().forEach(x -> counter.increment());
182        assertEquals(size, counter.sum());
183    }
184
185    /**
186     * A parallel unsized stream of longs generates at least 100 values
187     */
188    public void testUnsizedLongsCount() {
189        LongAdder counter = new LongAdder();
190        ThreadLocalRandom r = ThreadLocalRandom.current();
191        long size = 100;
192        r.longs().limit(size).parallel().forEach(x -> counter.increment());
193        assertEquals(size, counter.sum());
194    }
195
196    /**
197     * A parallel unsized stream of doubles generates at least 100 values
198     */
199    public void testUnsizedDoublesCount() {
200        LongAdder counter = new LongAdder();
201        ThreadLocalRandom r = ThreadLocalRandom.current();
202        long size = 100;
203        r.doubles().limit(size).parallel().forEach(x -> counter.increment());
204        assertEquals(size, counter.sum());
205    }
206
207    /**
208     * A sequential unsized stream of ints generates at least 100 values
209     */
210    public void testUnsizedIntsCountSeq() {
211        LongAdder counter = new LongAdder();
212        ThreadLocalRandom r = ThreadLocalRandom.current();
213        long size = 100;
214        r.ints().limit(size).forEach(x -> counter.increment());
215        assertEquals(size, counter.sum());
216    }
217
218    /**
219     * A sequential unsized stream of longs generates at least 100 values
220     */
221    public void testUnsizedLongsCountSeq() {
222        LongAdder counter = new LongAdder();
223        ThreadLocalRandom r = ThreadLocalRandom.current();
224        long size = 100;
225        r.longs().limit(size).forEach(x -> counter.increment());
226        assertEquals(size, counter.sum());
227    }
228
229    /**
230     * A sequential unsized stream of doubles generates at least 100 values
231     */
232    public void testUnsizedDoublesCountSeq() {
233        LongAdder counter = new LongAdder();
234        ThreadLocalRandom r = ThreadLocalRandom.current();
235        long size = 100;
236        r.doubles().limit(size).forEach(x -> counter.increment());
237        assertEquals(size, counter.sum());
238    }
239
240}
241